Commit | Line | Data |
---|---|---|
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 | ||
15 | static 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 | ||
43 | int 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 | } |