sparc64: Create and use psycho_pbm_init_common().
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / sparc64 / kernel / psycho_common.c
CommitLineData
a21cff3e
DM
1/* psycho_common.c: Code common to PSYCHO and derivative PCI controllers.
2 *
3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
4 */
5#include <linux/kernel.h>
6
7#include <asm/upa.h>
8
9#include "pci_impl.h"
10#include "psycho_common.h"
11
12#define PSYCHO_IOMMU_TAG 0xa580UL
13#define PSYCHO_IOMMU_DATA 0xa600UL
14
15static void psycho_iommu_flush(struct pci_pbm_info *pbm)
16{
17 int i;
18
19 for (i = 0; i < 16; i++) {
20 unsigned long off = i * 8;
21
22 upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_TAG + off);
23 upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_DATA + off);
24 }
25}
26
27#define PSYCHO_IOMMU_CONTROL 0x0200UL
28#define PSYCHO_IOMMU_CTRL_TSBSZ 0x0000000000070000UL
29#define PSYCHO_IOMMU_TSBSZ_1K 0x0000000000000000UL
30#define PSYCHO_IOMMU_TSBSZ_2K 0x0000000000010000UL
31#define PSYCHO_IOMMU_TSBSZ_4K 0x0000000000020000UL
32#define PSYCHO_IOMMU_TSBSZ_8K 0x0000000000030000UL
33#define PSYCHO_IOMMU_TSBSZ_16K 0x0000000000040000UL
34#define PSYCHO_IOMMU_TSBSZ_32K 0x0000000000050000UL
35#define PSYCHO_IOMMU_TSBSZ_64K 0x0000000000060000UL
36#define PSYCHO_IOMMU_TSBSZ_128K 0x0000000000070000UL
37#define PSYCHO_IOMMU_CTRL_TBWSZ 0x0000000000000004UL
38#define PSYCHO_IOMMU_CTRL_DENAB 0x0000000000000002UL
39#define PSYCHO_IOMMU_CTRL_ENAB 0x0000000000000001UL
40#define PSYCHO_IOMMU_FLUSH 0x0210UL
41#define PSYCHO_IOMMU_TSBBASE 0x0208UL
42
43int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize,
44 u32 dvma_offset, u32 dma_mask,
45 unsigned long write_complete_offset)
46{
47 struct iommu *iommu = pbm->iommu;
48 u64 control;
49 int err;
50
51 iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL;
52 iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE;
53 iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH;
54 iommu->iommu_tags = pbm->controller_regs + PSYCHO_IOMMU_TAG;
55 iommu->write_complete_reg = (pbm->controller_regs +
56 write_complete_offset);
57
58 iommu->iommu_ctxflush = 0;
59
60 control = upa_readq(iommu->iommu_control);
61 control |= PSYCHO_IOMMU_CTRL_DENAB;
62 upa_writeq(control, iommu->iommu_control);
63
64 psycho_iommu_flush(pbm);
65
66 /* Leave diag mode enabled for full-flushing done in pci_iommu.c */
67 err = iommu_table_init(iommu, tsbsize * 1024 * 8,
68 dvma_offset, dma_mask, pbm->numa_node);
69 if (err)
70 return err;
71
72 upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase);
73
74 control = upa_readq(iommu->iommu_control);
75 control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
76 control |= PSYCHO_IOMMU_CTRL_ENAB;
77
78 switch (tsbsize) {
79 case 64:
80 control |= PSYCHO_IOMMU_TSBSZ_64K;
81 break;
82 case 128:
83 control |= PSYCHO_IOMMU_TSBSZ_128K;
84 break;
85 default:
86 return -EINVAL;
87 }
88
89 upa_writeq(control, iommu->iommu_control);
90
91 return 0;
92
93}
1c03a55c
DM
94
95void psycho_pbm_init_common(struct pci_pbm_info *pbm, struct of_device *op,
96 const char *chip_name, int chip_type)
97{
98 struct device_node *dp = op->node;
99
100 pbm->name = dp->full_name;
101 pbm->numa_node = -1;
102 pbm->chip_type = chip_type;
103 pbm->chip_version = of_getintprop_default(dp, "version#", 0);
104 pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0);
105 pbm->op = op;
106 pbm->pci_ops = &sun4u_pci_ops;
107 pbm->config_space_reg_bits = 8;
108 pbm->index = pci_num_pbms++;
109 pci_get_pbm_props(pbm);
110 pci_determine_mem_io_space(pbm);
111
112 printk(KERN_INFO "%s: %s PCI Bus Module ver[%x:%x]\n",
113 pbm->name, chip_name,
114 pbm->chip_version, pbm->chip_revision);
115}