diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/wsp/Kconfig | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/wsp/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/wsp/psr2.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/wsp/wsp.h | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/wsp/wsp_pci.c | 1133 | ||||
-rw-r--r-- | arch/powerpc/platforms/wsp/wsp_pci.h | 268 |
6 files changed, 1412 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/wsp/Kconfig b/arch/powerpc/platforms/wsp/Kconfig index d051581e9ebf..f4fb837873fb 100644 --- a/arch/powerpc/platforms/wsp/Kconfig +++ b/arch/powerpc/platforms/wsp/Kconfig | |||
@@ -4,6 +4,9 @@ config PPC_WSP | |||
4 | select PPC_SCOM | 4 | select PPC_SCOM |
5 | select PPC_XICS | 5 | select PPC_XICS |
6 | select PPC_ICP_NATIVE | 6 | select PPC_ICP_NATIVE |
7 | select PCI | ||
8 | select PPC_IO_WORKAROUNDS if PCI | ||
9 | select PPC_INDIRECT_PIO if PCI | ||
7 | default n | 10 | default n |
8 | 11 | ||
9 | menu "WSP platform selection" | 12 | menu "WSP platform selection" |
diff --git a/arch/powerpc/platforms/wsp/Makefile b/arch/powerpc/platforms/wsp/Makefile index 095be73d6cd4..84519f8d8945 100644 --- a/arch/powerpc/platforms/wsp/Makefile +++ b/arch/powerpc/platforms/wsp/Makefile | |||
@@ -4,3 +4,4 @@ obj-y += setup.o ics.o | |||
4 | obj-$(CONFIG_PPC_PSR2) += psr2.o opb_pic.o | 4 | obj-$(CONFIG_PPC_PSR2) += psr2.o opb_pic.o |
5 | obj-$(CONFIG_PPC_WSP) += scom_wsp.o | 5 | obj-$(CONFIG_PPC_WSP) += scom_wsp.o |
6 | obj-$(CONFIG_SMP) += smp.o scom_smp.o | 6 | obj-$(CONFIG_SMP) += smp.o scom_smp.o |
7 | obj-$(CONFIG_PCI) += wsp_pci.o | ||
diff --git a/arch/powerpc/platforms/wsp/psr2.c b/arch/powerpc/platforms/wsp/psr2.c index 40f28916ff6c..166f2e4b4bee 100644 --- a/arch/powerpc/platforms/wsp/psr2.c +++ b/arch/powerpc/platforms/wsp/psr2.c | |||
@@ -63,6 +63,10 @@ static void __init psr2_setup_arch(void) | |||
63 | #ifdef CONFIG_SMP | 63 | #ifdef CONFIG_SMP |
64 | a2_setup_smp(); | 64 | a2_setup_smp(); |
65 | #endif | 65 | #endif |
66 | #ifdef CONFIG_PCI | ||
67 | wsp_setup_pci(); | ||
68 | #endif | ||
69 | |||
66 | } | 70 | } |
67 | 71 | ||
68 | static int __init psr2_probe(void) | 72 | static int __init psr2_probe(void) |
diff --git a/arch/powerpc/platforms/wsp/wsp.h b/arch/powerpc/platforms/wsp/wsp.h index 7c3e087fd2f2..33479818f62a 100644 --- a/arch/powerpc/platforms/wsp/wsp.h +++ b/arch/powerpc/platforms/wsp/wsp.h | |||
@@ -3,6 +3,9 @@ | |||
3 | 3 | ||
4 | #include <asm/wsp.h> | 4 | #include <asm/wsp.h> |
5 | 5 | ||
6 | /* Devtree compatible strings for major devices */ | ||
7 | #define PCIE_COMPATIBLE "ibm,wsp-pciex" | ||
8 | |||
6 | extern void wsp_setup_pci(void); | 9 | extern void wsp_setup_pci(void); |
7 | extern void scom_init_wsp(void); | 10 | extern void scom_init_wsp(void); |
8 | 11 | ||
diff --git a/arch/powerpc/platforms/wsp/wsp_pci.c b/arch/powerpc/platforms/wsp/wsp_pci.c new file mode 100644 index 000000000000..e0262cd0e2d3 --- /dev/null +++ b/arch/powerpc/platforms/wsp/wsp_pci.c | |||
@@ -0,0 +1,1133 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Ben Herrenschmidt, IBM Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #define DEBUG | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/bootmem.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/debugfs.h> | ||
21 | |||
22 | #include <asm/sections.h> | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/prom.h> | ||
25 | #include <asm/pci-bridge.h> | ||
26 | #include <asm/machdep.h> | ||
27 | #include <asm/ppc-pci.h> | ||
28 | #include <asm/iommu.h> | ||
29 | #include <asm/io-workarounds.h> | ||
30 | |||
31 | #include "wsp.h" | ||
32 | #include "wsp_pci.h" | ||
33 | #include "msi.h" | ||
34 | |||
35 | |||
36 | /* Max number of TVTs for one table. Only 32-bit tables can use | ||
37 | * multiple TVTs and so the max currently supported is thus 8 | ||
38 | * since only 2G of DMA space is supported | ||
39 | */ | ||
40 | #define MAX_TABLE_TVT_COUNT 8 | ||
41 | |||
42 | struct wsp_dma_table { | ||
43 | struct list_head link; | ||
44 | struct iommu_table table; | ||
45 | struct wsp_phb *phb; | ||
46 | struct page *tces[MAX_TABLE_TVT_COUNT]; | ||
47 | }; | ||
48 | |||
49 | /* We support DMA regions from 0...2G in 32bit space (no support for | ||
50 | * 64-bit DMA just yet). Each device gets a separate TCE table (TVT | ||
51 | * entry) with validation enabled (though not supported by SimiCS | ||
52 | * just yet). | ||
53 | * | ||
54 | * To simplify things, we divide this 2G space into N regions based | ||
55 | * on the constant below which could be turned into a tunable eventually | ||
56 | * | ||
57 | * We then assign dynamically those regions to devices as they show up. | ||
58 | * | ||
59 | * We use a bitmap as an allocator for these. | ||
60 | * | ||
61 | * Tables are allocated/created dynamically as devices are discovered, | ||
62 | * multiple TVT entries are used if needed | ||
63 | * | ||
64 | * When 64-bit DMA support is added we should simply use a separate set | ||
65 | * of larger regions (the HW supports 64 TVT entries). We can | ||
66 | * additionally create a bypass region in 64-bit space for performances | ||
67 | * though that would have a cost in term of security. | ||
68 | * | ||
69 | * If you set NUM_DMA32_REGIONS to 1, then a single table is shared | ||
70 | * for all devices and bus/dev/fn validation is disabled | ||
71 | * | ||
72 | * Note that a DMA32 region cannot be smaller than 256M so the max | ||
73 | * supported here for now is 8. We don't yet support sharing regions | ||
74 | * between multiple devices so the max number of devices supported | ||
75 | * is MAX_TABLE_TVT_COUNT. | ||
76 | */ | ||
77 | #define NUM_DMA32_REGIONS 1 | ||
78 | |||
79 | struct wsp_phb { | ||
80 | struct pci_controller *hose; | ||
81 | |||
82 | /* Lock controlling access to the list of dma tables. | ||
83 | * It does -not- protect against dma_* operations on | ||
84 | * those tables, those should be stopped before an entry | ||
85 | * is removed from the list. | ||
86 | * | ||
87 | * The lock is also used for error handling operations | ||
88 | */ | ||
89 | spinlock_t lock; | ||
90 | struct list_head dma_tables; | ||
91 | unsigned long dma32_map; | ||
92 | unsigned long dma32_base; | ||
93 | unsigned int dma32_num_regions; | ||
94 | unsigned long dma32_region_size; | ||
95 | |||
96 | /* Debugfs stuff */ | ||
97 | struct dentry *ddir; | ||
98 | |||
99 | struct list_head all; | ||
100 | }; | ||
101 | static LIST_HEAD(wsp_phbs); | ||
102 | |||
103 | //#define cfg_debug(fmt...) pr_debug(fmt) | ||
104 | #define cfg_debug(fmt...) | ||
105 | |||
106 | |||
107 | static int wsp_pcie_read_config(struct pci_bus *bus, unsigned int devfn, | ||
108 | int offset, int len, u32 *val) | ||
109 | { | ||
110 | struct pci_controller *hose; | ||
111 | int suboff; | ||
112 | u64 addr; | ||
113 | |||
114 | hose = pci_bus_to_host(bus); | ||
115 | if (hose == NULL) | ||
116 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
117 | if (offset >= 0x1000) | ||
118 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
119 | addr = PCIE_REG_CA_ENABLE | | ||
120 | ((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT | | ||
121 | ((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT | | ||
122 | ((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT; | ||
123 | suboff = offset & 3; | ||
124 | |||
125 | /* | ||
126 | * Note: the caller has already checked that offset is | ||
127 | * suitably aligned and that len is 1, 2 or 4. | ||
128 | */ | ||
129 | |||
130 | switch (len) { | ||
131 | case 1: | ||
132 | addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT; | ||
133 | out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr); | ||
134 | *val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA) | ||
135 | >> (suboff << 3)) & 0xff; | ||
136 | cfg_debug("read 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n", | ||
137 | bus->number, devfn >> 3, devfn & 7, | ||
138 | offset, suboff, addr, *val); | ||
139 | break; | ||
140 | case 2: | ||
141 | addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT; | ||
142 | out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr); | ||
143 | *val = (in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA) | ||
144 | >> (suboff << 3)) & 0xffff; | ||
145 | cfg_debug("read 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n", | ||
146 | bus->number, devfn >> 3, devfn & 7, | ||
147 | offset, suboff, addr, *val); | ||
148 | break; | ||
149 | default: | ||
150 | addr |= 0xful << PCIE_REG_CA_BE_SHIFT; | ||
151 | out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr); | ||
152 | *val = in_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA); | ||
153 | cfg_debug("read 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n", | ||
154 | bus->number, devfn >> 3, devfn & 7, | ||
155 | offset, suboff, addr, *val); | ||
156 | break; | ||
157 | } | ||
158 | return PCIBIOS_SUCCESSFUL; | ||
159 | } | ||
160 | |||
161 | static int wsp_pcie_write_config(struct pci_bus *bus, unsigned int devfn, | ||
162 | int offset, int len, u32 val) | ||
163 | { | ||
164 | struct pci_controller *hose; | ||
165 | int suboff; | ||
166 | u64 addr; | ||
167 | |||
168 | hose = pci_bus_to_host(bus); | ||
169 | if (hose == NULL) | ||
170 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
171 | if (offset >= 0x1000) | ||
172 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
173 | addr = PCIE_REG_CA_ENABLE | | ||
174 | ((u64)bus->number) << PCIE_REG_CA_BUS_SHIFT | | ||
175 | ((u64)devfn) << PCIE_REG_CA_FUNC_SHIFT | | ||
176 | ((u64)offset & ~3) << PCIE_REG_CA_REG_SHIFT; | ||
177 | suboff = offset & 3; | ||
178 | |||
179 | /* | ||
180 | * Note: the caller has already checked that offset is | ||
181 | * suitably aligned and that len is 1, 2 or 4. | ||
182 | */ | ||
183 | switch (len) { | ||
184 | case 1: | ||
185 | addr |= (0x8ul >> suboff) << PCIE_REG_CA_BE_SHIFT; | ||
186 | val <<= suboff << 3; | ||
187 | out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr); | ||
188 | out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val); | ||
189 | cfg_debug("write 1 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%02x\n", | ||
190 | bus->number, devfn >> 3, devfn & 7, | ||
191 | offset, suboff, addr, val); | ||
192 | break; | ||
193 | case 2: | ||
194 | addr |= (0xcul >> suboff) << PCIE_REG_CA_BE_SHIFT; | ||
195 | val <<= suboff << 3; | ||
196 | out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr); | ||
197 | out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val); | ||
198 | cfg_debug("write 2 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%04x\n", | ||
199 | bus->number, devfn >> 3, devfn & 7, | ||
200 | offset, suboff, addr, val); | ||
201 | break; | ||
202 | default: | ||
203 | addr |= 0xful << PCIE_REG_CA_BE_SHIFT; | ||
204 | out_be64(hose->cfg_data + PCIE_REG_CONFIG_ADDRESS, addr); | ||
205 | out_le32(hose->cfg_data + PCIE_REG_CONFIG_DATA, val); | ||
206 | cfg_debug("write 4 %02x:%02x:%02x + %02x/%x addr=0x%llx val=%08x\n", | ||
207 | bus->number, devfn >> 3, devfn & 7, | ||
208 | offset, suboff, addr, val); | ||
209 | break; | ||
210 | } | ||
211 | return PCIBIOS_SUCCESSFUL; | ||
212 | } | ||
213 | |||
214 | static struct pci_ops wsp_pcie_pci_ops = | ||
215 | { | ||
216 | .read = wsp_pcie_read_config, | ||
217 | .write = wsp_pcie_write_config, | ||
218 | }; | ||
219 | |||
220 | #define TCE_SHIFT 12 | ||
221 | #define TCE_PAGE_SIZE (1 << TCE_SHIFT) | ||
222 | #define TCE_PCI_WRITE 0x2 /* write from PCI allowed */ | ||
223 | #define TCE_PCI_READ 0x1 /* read from PCI allowed */ | ||
224 | #define TCE_RPN_MASK 0x3fffffffffful /* 42-bit RPN (4K pages) */ | ||
225 | #define TCE_RPN_SHIFT 12 | ||
226 | |||
227 | //#define dma_debug(fmt...) pr_debug(fmt) | ||
228 | #define dma_debug(fmt...) | ||
229 | |||
230 | static int tce_build_wsp(struct iommu_table *tbl, long index, long npages, | ||
231 | unsigned long uaddr, enum dma_data_direction direction, | ||
232 | struct dma_attrs *attrs) | ||
233 | { | ||
234 | struct wsp_dma_table *ptbl = container_of(tbl, | ||
235 | struct wsp_dma_table, | ||
236 | table); | ||
237 | u64 proto_tce; | ||
238 | u64 *tcep; | ||
239 | u64 rpn; | ||
240 | |||
241 | proto_tce = TCE_PCI_READ; | ||
242 | #ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS | ||
243 | proto_tce |= TCE_PCI_WRITE; | ||
244 | #else | ||
245 | if (direction != DMA_TO_DEVICE) | ||
246 | proto_tce |= TCE_PCI_WRITE; | ||
247 | #endif | ||
248 | |||
249 | /* XXX Make this faster by factoring out the page address for | ||
250 | * within a TCE table | ||
251 | */ | ||
252 | while (npages--) { | ||
253 | /* We don't use it->base as the table can be scattered */ | ||
254 | tcep = (u64 *)page_address(ptbl->tces[index >> 16]); | ||
255 | tcep += (index & 0xffff); | ||
256 | |||
257 | /* can't move this out since we might cross LMB boundary */ | ||
258 | rpn = __pa(uaddr) >> TCE_SHIFT; | ||
259 | *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; | ||
260 | |||
261 | dma_debug("[DMA] TCE %p set to 0x%016llx (dma addr: 0x%lx)\n", | ||
262 | tcep, *tcep, (tbl->it_offset + index) << IOMMU_PAGE_SHIFT); | ||
263 | |||
264 | uaddr += TCE_PAGE_SIZE; | ||
265 | index++; | ||
266 | } | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static void tce_free_wsp(struct iommu_table *tbl, long index, long npages) | ||
271 | { | ||
272 | struct wsp_dma_table *ptbl = container_of(tbl, | ||
273 | struct wsp_dma_table, | ||
274 | table); | ||
275 | #ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS | ||
276 | struct pci_controller *hose = ptbl->phb->hose; | ||
277 | #endif | ||
278 | u64 *tcep; | ||
279 | |||
280 | /* XXX Make this faster by factoring out the page address for | ||
281 | * within a TCE table. Also use line-kill option to kill multiple | ||
282 | * TCEs at once | ||
283 | */ | ||
284 | while (npages--) { | ||
285 | /* We don't use it->base as the table can be scattered */ | ||
286 | tcep = (u64 *)page_address(ptbl->tces[index >> 16]); | ||
287 | tcep += (index & 0xffff); | ||
288 | dma_debug("[DMA] TCE %p cleared\n", tcep); | ||
289 | *tcep = 0; | ||
290 | #ifndef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS | ||
291 | /* Don't write there since it would pollute other MMIO accesses */ | ||
292 | out_be64(hose->cfg_data + PCIE_REG_TCE_KILL, | ||
293 | PCIE_REG_TCEKILL_SINGLE | PCIE_REG_TCEKILL_PS_4K | | ||
294 | (__pa(tcep) & PCIE_REG_TCEKILL_ADDR_MASK)); | ||
295 | #endif | ||
296 | index++; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | static struct wsp_dma_table *wsp_pci_create_dma32_table(struct wsp_phb *phb, | ||
301 | unsigned int region, | ||
302 | struct pci_dev *validate) | ||
303 | { | ||
304 | struct pci_controller *hose = phb->hose; | ||
305 | unsigned long size = phb->dma32_region_size; | ||
306 | unsigned long addr = phb->dma32_region_size * region + phb->dma32_base; | ||
307 | struct wsp_dma_table *tbl; | ||
308 | int tvts_per_table, i, tvt, nid; | ||
309 | unsigned long flags; | ||
310 | |||
311 | nid = of_node_to_nid(phb->hose->dn); | ||
312 | |||
313 | /* Calculate how many TVTs are needed */ | ||
314 | tvts_per_table = size / 0x10000000; | ||
315 | if (tvts_per_table == 0) | ||
316 | tvts_per_table = 1; | ||
317 | |||
318 | /* Calculate the base TVT index. We know all tables have the same | ||
319 | * size so we just do a simple multiply here | ||
320 | */ | ||
321 | tvt = region * tvts_per_table; | ||
322 | |||
323 | pr_debug(" Region : %d\n", region); | ||
324 | pr_debug(" DMA range : 0x%08lx..0x%08lx\n", addr, addr + size - 1); | ||
325 | pr_debug(" Number of TVTs : %d\n", tvts_per_table); | ||
326 | pr_debug(" Base TVT : %d\n", tvt); | ||
327 | pr_debug(" Node : %d\n", nid); | ||
328 | |||
329 | tbl = kzalloc_node(sizeof(struct wsp_dma_table), GFP_KERNEL, nid); | ||
330 | if (!tbl) | ||
331 | return ERR_PTR(-ENOMEM); | ||
332 | tbl->phb = phb; | ||
333 | |||
334 | /* Create as many TVTs as needed, each represents 256M at most */ | ||
335 | for (i = 0; i < tvts_per_table; i++) { | ||
336 | u64 tvt_data1, tvt_data0; | ||
337 | |||
338 | /* Allocate table. We use a 4K TCE size for now always so | ||
339 | * one table is always 8 * (258M / 4K) == 512K | ||
340 | */ | ||
341 | tbl->tces[i] = alloc_pages_node(nid, GFP_KERNEL, get_order(0x80000)); | ||
342 | if (tbl->tces[i] == NULL) | ||
343 | goto fail; | ||
344 | memset(page_address(tbl->tces[i]), 0, 0x80000); | ||
345 | |||
346 | pr_debug(" TCE table %d at : %p\n", i, page_address(tbl->tces[i])); | ||
347 | |||
348 | /* Table size. We currently set it to be the whole 256M region */ | ||
349 | tvt_data0 = 2ull << IODA_TVT0_TCE_TABLE_SIZE_SHIFT; | ||
350 | /* IO page size set to 4K */ | ||
351 | tvt_data1 = 1ull << IODA_TVT1_IO_PAGE_SIZE_SHIFT; | ||
352 | /* Shift in the address */ | ||
353 | tvt_data0 |= __pa(page_address(tbl->tces[i])) << IODA_TVT0_TTA_SHIFT; | ||
354 | |||
355 | /* Validation stuff. We only validate fully bus/dev/fn for now | ||
356 | * one day maybe we can group devices but that isn't the case | ||
357 | * at the moment | ||
358 | */ | ||
359 | if (validate) { | ||
360 | tvt_data0 |= IODA_TVT0_BUSNUM_VALID_MASK; | ||
361 | tvt_data0 |= validate->bus->number; | ||
362 | tvt_data1 |= IODA_TVT1_DEVNUM_VALID; | ||
363 | tvt_data1 |= ((u64)PCI_SLOT(validate->devfn)) | ||
364 | << IODA_TVT1_DEVNUM_VALUE_SHIFT; | ||
365 | tvt_data1 |= IODA_TVT1_FUNCNUM_VALID; | ||
366 | tvt_data1 |= ((u64)PCI_FUNC(validate->devfn)) | ||
367 | << IODA_TVT1_FUNCNUM_VALUE_SHIFT; | ||
368 | } | ||
369 | |||
370 | /* XX PE number is always 0 for now */ | ||
371 | |||
372 | /* Program the values using the PHB lock */ | ||
373 | spin_lock_irqsave(&phb->lock, flags); | ||
374 | out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR, | ||
375 | (tvt + i) | PCIE_REG_IODA_AD_TBL_TVT); | ||
376 | out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, tvt_data1); | ||
377 | out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, tvt_data0); | ||
378 | spin_unlock_irqrestore(&phb->lock, flags); | ||
379 | } | ||
380 | |||
381 | /* Init bits and pieces */ | ||
382 | tbl->table.it_blocksize = 16; | ||
383 | tbl->table.it_offset = addr >> IOMMU_PAGE_SHIFT; | ||
384 | tbl->table.it_size = size >> IOMMU_PAGE_SHIFT; | ||
385 | |||
386 | /* | ||
387 | * It's already blank but we clear it anyway. | ||
388 | * Consider an aditiona interface that makes cleaing optional | ||
389 | */ | ||
390 | iommu_init_table(&tbl->table, nid); | ||
391 | |||
392 | list_add(&tbl->link, &phb->dma_tables); | ||
393 | return tbl; | ||
394 | |||
395 | fail: | ||
396 | pr_debug(" Failed to allocate a 256M TCE table !\n"); | ||
397 | for (i = 0; i < tvts_per_table; i++) | ||
398 | if (tbl->tces[i]) | ||
399 | __free_pages(tbl->tces[i], get_order(0x80000)); | ||
400 | kfree(tbl); | ||
401 | return ERR_PTR(-ENOMEM); | ||
402 | } | ||
403 | |||
404 | static void __devinit wsp_pci_dma_dev_setup(struct pci_dev *pdev) | ||
405 | { | ||
406 | struct dev_archdata *archdata = &pdev->dev.archdata; | ||
407 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | ||
408 | struct wsp_phb *phb = hose->private_data; | ||
409 | struct wsp_dma_table *table = NULL; | ||
410 | unsigned long flags; | ||
411 | int i; | ||
412 | |||
413 | /* Don't assign an iommu table to a bridge */ | ||
414 | if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
415 | return; | ||
416 | |||
417 | pr_debug("%s: Setting up DMA...\n", pci_name(pdev)); | ||
418 | |||
419 | spin_lock_irqsave(&phb->lock, flags); | ||
420 | |||
421 | /* If only one region, check if it already exist */ | ||
422 | if (phb->dma32_num_regions == 1) { | ||
423 | spin_unlock_irqrestore(&phb->lock, flags); | ||
424 | if (list_empty(&phb->dma_tables)) | ||
425 | table = wsp_pci_create_dma32_table(phb, 0, NULL); | ||
426 | else | ||
427 | table = list_first_entry(&phb->dma_tables, | ||
428 | struct wsp_dma_table, | ||
429 | link); | ||
430 | } else { | ||
431 | /* else find a free region */ | ||
432 | for (i = 0; i < phb->dma32_num_regions && !table; i++) { | ||
433 | if (__test_and_set_bit(i, &phb->dma32_map)) | ||
434 | continue; | ||
435 | spin_unlock_irqrestore(&phb->lock, flags); | ||
436 | table = wsp_pci_create_dma32_table(phb, i, pdev); | ||
437 | } | ||
438 | } | ||
439 | |||
440 | /* Check if we got an error */ | ||
441 | if (IS_ERR(table)) { | ||
442 | pr_err("%s: Failed to create DMA table, err %ld !\n", | ||
443 | pci_name(pdev), PTR_ERR(table)); | ||
444 | return; | ||
445 | } | ||
446 | |||
447 | /* Or a valid table */ | ||
448 | if (table) { | ||
449 | pr_info("%s: Setup iommu: 32-bit DMA region 0x%08lx..0x%08lx\n", | ||
450 | pci_name(pdev), | ||
451 | table->table.it_offset << IOMMU_PAGE_SHIFT, | ||
452 | (table->table.it_offset << IOMMU_PAGE_SHIFT) | ||
453 | + phb->dma32_region_size - 1); | ||
454 | archdata->dma_data.iommu_table_base = &table->table; | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | /* Or no room */ | ||
459 | spin_unlock_irqrestore(&phb->lock, flags); | ||
460 | pr_err("%s: Out of DMA space !\n", pci_name(pdev)); | ||
461 | } | ||
462 | |||
463 | static void __init wsp_pcie_configure_hw(struct pci_controller *hose) | ||
464 | { | ||
465 | u64 val; | ||
466 | int i; | ||
467 | |||
468 | #define DUMP_REG(x) \ | ||
469 | pr_debug("%-30s : 0x%016llx\n", #x, in_be64(hose->cfg_data + x)) | ||
470 | |||
471 | #ifdef CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS | ||
472 | /* WSP DD1 has a bogus class code by default in the PCI-E | ||
473 | * root complex's built-in P2P bridge */ | ||
474 | val = in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1); | ||
475 | pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", val); | ||
476 | out_be64(hose->cfg_data + PCIE_REG_SYS_CFG1, | ||
477 | (val & ~PCIE_REG_SYS_CFG1_CLASS_CODE) | (PCI_CLASS_BRIDGE_PCI << 8)); | ||
478 | pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1)); | ||
479 | #endif /* CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS */ | ||
480 | |||
481 | #ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS | ||
482 | /* XXX Disable TCE caching, it doesn't work on DD1 */ | ||
483 | out_be64(hose->cfg_data + 0xe50, | ||
484 | in_be64(hose->cfg_data + 0xe50) | (3ull << 62)); | ||
485 | printk("PCI-E DEBUG CONTROL 5 = 0x%llx\n", in_be64(hose->cfg_data + 0xe50)); | ||
486 | #endif | ||
487 | |||
488 | /* Configure M32A and IO. IO is hard wired to be 1M for now */ | ||
489 | out_be64(hose->cfg_data + PCIE_REG_IO_BASE_ADDR, hose->io_base_phys); | ||
490 | out_be64(hose->cfg_data + PCIE_REG_IO_BASE_MASK, | ||
491 | (~(hose->io_resource.end - hose->io_resource.start)) & | ||
492 | 0x3fffffff000ul); | ||
493 | out_be64(hose->cfg_data + PCIE_REG_IO_START_ADDR, 0 | 1); | ||
494 | |||
495 | out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_ADDR, | ||
496 | hose->mem_resources[0].start); | ||
497 | printk("Want to write to M32A_BASE_MASK : 0x%llx\n", | ||
498 | (~(hose->mem_resources[0].end - | ||
499 | hose->mem_resources[0].start)) & 0x3ffffff0000ul); | ||
500 | out_be64(hose->cfg_data + PCIE_REG_M32A_BASE_MASK, | ||
501 | (~(hose->mem_resources[0].end - | ||
502 | hose->mem_resources[0].start)) & 0x3ffffff0000ul); | ||
503 | out_be64(hose->cfg_data + PCIE_REG_M32A_START_ADDR, | ||
504 | (hose->mem_resources[0].start - hose->pci_mem_offset) | 1); | ||
505 | |||
506 | /* Clear all TVT entries | ||
507 | * | ||
508 | * XX Might get TVT count from device-tree | ||
509 | */ | ||
510 | for (i = 0; i < IODA_TVT_COUNT; i++) { | ||
511 | out_be64(hose->cfg_data + PCIE_REG_IODA_ADDR, | ||
512 | PCIE_REG_IODA_AD_TBL_TVT | i); | ||
513 | out_be64(hose->cfg_data + PCIE_REG_IODA_DATA1, 0); | ||
514 | out_be64(hose->cfg_data + PCIE_REG_IODA_DATA0, 0); | ||
515 | } | ||
516 | |||
517 | /* Kill the TCE cache */ | ||
518 | out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG, | ||
519 | in_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG) | | ||
520 | PCIE_REG_PHBC_64B_TCE_EN); | ||
521 | |||
522 | /* Enable 32 & 64-bit MSIs, IO space and M32A */ | ||
523 | val = PCIE_REG_PHBC_32BIT_MSI_EN | | ||
524 | PCIE_REG_PHBC_IO_EN | | ||
525 | PCIE_REG_PHBC_64BIT_MSI_EN | | ||
526 | PCIE_REG_PHBC_M32A_EN; | ||
527 | if (iommu_is_off) | ||
528 | val |= PCIE_REG_PHBC_DMA_XLATE_BYPASS; | ||
529 | pr_debug("Will write config: 0x%llx\n", val); | ||
530 | out_be64(hose->cfg_data + PCIE_REG_PHB_CONFIG, val); | ||
531 | |||
532 | /* Enable error reporting */ | ||
533 | out_be64(hose->cfg_data + 0xe00, | ||
534 | in_be64(hose->cfg_data + 0xe00) | 0x0008000000000000ull); | ||
535 | |||
536 | /* Mask an error that's generated when doing config space probe | ||
537 | * | ||
538 | * XXX Maybe we should only mask it around config space cycles... that or | ||
539 | * ignore it when we know we had a config space cycle recently ? | ||
540 | */ | ||
541 | out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS_MASK, 0x8000000000000000ull); | ||
542 | out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS_MASK, 0x8000000000000000ull); | ||
543 | |||
544 | /* Enable UTL errors, for now, all of them got to UTL irq 1 | ||
545 | * | ||
546 | * We similarily mask one UTL error caused apparently during normal | ||
547 | * probing. We also mask the link up error | ||
548 | */ | ||
549 | out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_ERR_SEV, 0); | ||
550 | out_be64(hose->cfg_data + PCIE_UTL_RC_ERR_SEVERITY, 0); | ||
551 | out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_ERROR_SEV, 0); | ||
552 | out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_IRQ_EN, 0xffffffff00000000ull); | ||
553 | out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_IRQ_EN, 0xff5fffff00000000ull); | ||
554 | out_be64(hose->cfg_data + PCIE_UTL_EP_ERR_IRQ_EN, 0xffffffff00000000ull); | ||
555 | |||
556 | DUMP_REG(PCIE_REG_IO_BASE_ADDR); | ||
557 | DUMP_REG(PCIE_REG_IO_BASE_MASK); | ||
558 | DUMP_REG(PCIE_REG_IO_START_ADDR); | ||
559 | DUMP_REG(PCIE_REG_M32A_BASE_ADDR); | ||
560 | DUMP_REG(PCIE_REG_M32A_BASE_MASK); | ||
561 | DUMP_REG(PCIE_REG_M32A_START_ADDR); | ||
562 | DUMP_REG(PCIE_REG_M32B_BASE_ADDR); | ||
563 | DUMP_REG(PCIE_REG_M32B_BASE_MASK); | ||
564 | DUMP_REG(PCIE_REG_M32B_START_ADDR); | ||
565 | DUMP_REG(PCIE_REG_M64_BASE_ADDR); | ||
566 | DUMP_REG(PCIE_REG_M64_BASE_MASK); | ||
567 | DUMP_REG(PCIE_REG_M64_START_ADDR); | ||
568 | DUMP_REG(PCIE_REG_PHB_CONFIG); | ||
569 | } | ||
570 | |||
571 | static void wsp_pci_wait_io_idle(struct wsp_phb *phb, unsigned long port) | ||
572 | { | ||
573 | u64 val; | ||
574 | int i; | ||
575 | |||
576 | for (i = 0; i < 10000; i++) { | ||
577 | val = in_be64(phb->hose->cfg_data + 0xe08); | ||
578 | if ((val & 0x1900000000000000ull) == 0x0100000000000000ull) | ||
579 | return; | ||
580 | udelay(1); | ||
581 | } | ||
582 | pr_warning("PCI IO timeout on domain %d port 0x%lx\n", | ||
583 | phb->hose->global_number, port); | ||
584 | } | ||
585 | |||
586 | #define DEF_PCI_AC_RET_pio(name, ret, at, al, aa) \ | ||
587 | static ret wsp_pci_##name at \ | ||
588 | { \ | ||
589 | struct iowa_bus *bus; \ | ||
590 | struct wsp_phb *phb; \ | ||
591 | unsigned long flags; \ | ||
592 | ret rval; \ | ||
593 | bus = iowa_pio_find_bus(aa); \ | ||
594 | WARN_ON(!bus); \ | ||
595 | phb = bus->private; \ | ||
596 | spin_lock_irqsave(&phb->lock, flags); \ | ||
597 | wsp_pci_wait_io_idle(phb, aa); \ | ||
598 | rval = __do_##name al; \ | ||
599 | spin_unlock_irqrestore(&phb->lock, flags); \ | ||
600 | return rval; \ | ||
601 | } | ||
602 | |||
603 | #define DEF_PCI_AC_NORET_pio(name, at, al, aa) \ | ||
604 | static void wsp_pci_##name at \ | ||
605 | { \ | ||
606 | struct iowa_bus *bus; \ | ||
607 | struct wsp_phb *phb; \ | ||
608 | unsigned long flags; \ | ||
609 | bus = iowa_pio_find_bus(aa); \ | ||
610 | WARN_ON(!bus); \ | ||
611 | phb = bus->private; \ | ||
612 | spin_lock_irqsave(&phb->lock, flags); \ | ||
613 | wsp_pci_wait_io_idle(phb, aa); \ | ||
614 | __do_##name al; \ | ||
615 | spin_unlock_irqrestore(&phb->lock, flags); \ | ||
616 | } | ||
617 | |||
618 | #define DEF_PCI_AC_RET_mem(name, ret, at, al, aa) | ||
619 | #define DEF_PCI_AC_NORET_mem(name, at, al, aa) | ||
620 | |||
621 | #define DEF_PCI_AC_RET(name, ret, at, al, space, aa) \ | ||
622 | DEF_PCI_AC_RET_##space(name, ret, at, al, aa) | ||
623 | |||
624 | #define DEF_PCI_AC_NORET(name, at, al, space, aa) \ | ||
625 | DEF_PCI_AC_NORET_##space(name, at, al, aa) \ | ||
626 | |||
627 | |||
628 | #include <asm/io-defs.h> | ||
629 | |||
630 | #undef DEF_PCI_AC_RET | ||
631 | #undef DEF_PCI_AC_NORET | ||
632 | |||
633 | static struct ppc_pci_io wsp_pci_iops = { | ||
634 | .inb = wsp_pci_inb, | ||
635 | .inw = wsp_pci_inw, | ||
636 | .inl = wsp_pci_inl, | ||
637 | .outb = wsp_pci_outb, | ||
638 | .outw = wsp_pci_outw, | ||
639 | .outl = wsp_pci_outl, | ||
640 | .insb = wsp_pci_insb, | ||
641 | .insw = wsp_pci_insw, | ||
642 | .insl = wsp_pci_insl, | ||
643 | .outsb = wsp_pci_outsb, | ||
644 | .outsw = wsp_pci_outsw, | ||
645 | .outsl = wsp_pci_outsl, | ||
646 | }; | ||
647 | |||
648 | static int __init wsp_setup_one_phb(struct device_node *np) | ||
649 | { | ||
650 | struct pci_controller *hose; | ||
651 | struct wsp_phb *phb; | ||
652 | |||
653 | pr_info("PCI: Setting up PCIe host bridge 0x%s\n", np->full_name); | ||
654 | |||
655 | phb = zalloc_maybe_bootmem(sizeof(struct wsp_phb), GFP_KERNEL); | ||
656 | if (!phb) | ||
657 | return -ENOMEM; | ||
658 | hose = pcibios_alloc_controller(np); | ||
659 | if (!hose) { | ||
660 | /* Can't really free the phb */ | ||
661 | return -ENOMEM; | ||
662 | } | ||
663 | hose->private_data = phb; | ||
664 | phb->hose = hose; | ||
665 | |||
666 | INIT_LIST_HEAD(&phb->dma_tables); | ||
667 | spin_lock_init(&phb->lock); | ||
668 | |||
669 | /* XXX Use bus-range property ? */ | ||
670 | hose->first_busno = 0; | ||
671 | hose->last_busno = 0xff; | ||
672 | |||
673 | /* We use cfg_data as the address for the whole bridge MMIO space | ||
674 | */ | ||
675 | hose->cfg_data = of_iomap(hose->dn, 0); | ||
676 | |||
677 | pr_debug("PCIe registers mapped at 0x%p\n", hose->cfg_data); | ||
678 | |||
679 | /* Get the ranges of the device-tree */ | ||
680 | pci_process_bridge_OF_ranges(hose, np, 0); | ||
681 | |||
682 | /* XXX Force re-assigning of everything for now */ | ||
683 | pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC | | ||
684 | PCI_ENABLE_PROC_DOMAINS); | ||
685 | pci_probe_only = 0; | ||
686 | |||
687 | /* Calculate how the TCE space is divided */ | ||
688 | phb->dma32_base = 0; | ||
689 | phb->dma32_num_regions = NUM_DMA32_REGIONS; | ||
690 | if (phb->dma32_num_regions > MAX_TABLE_TVT_COUNT) { | ||
691 | pr_warning("IOMMU: Clamped to %d DMA32 regions\n", | ||
692 | MAX_TABLE_TVT_COUNT); | ||
693 | phb->dma32_num_regions = MAX_TABLE_TVT_COUNT; | ||
694 | } | ||
695 | phb->dma32_region_size = 0x80000000 / phb->dma32_num_regions; | ||
696 | |||
697 | BUG_ON(!is_power_of_2(phb->dma32_region_size)); | ||
698 | |||
699 | /* Setup config ops */ | ||
700 | hose->ops = &wsp_pcie_pci_ops; | ||
701 | |||
702 | /* Configure the HW */ | ||
703 | wsp_pcie_configure_hw(hose); | ||
704 | |||
705 | /* Instanciate IO workarounds */ | ||
706 | iowa_register_bus(hose, &wsp_pci_iops, NULL, phb); | ||
707 | #ifdef CONFIG_PCI_MSI | ||
708 | wsp_setup_phb_msi(hose); | ||
709 | #endif | ||
710 | |||
711 | /* Add to global list */ | ||
712 | list_add(&phb->all, &wsp_phbs); | ||
713 | |||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | void __init wsp_setup_pci(void) | ||
718 | { | ||
719 | struct device_node *np; | ||
720 | int rc; | ||
721 | |||
722 | /* Find host bridges */ | ||
723 | for_each_compatible_node(np, "pciex", PCIE_COMPATIBLE) { | ||
724 | rc = wsp_setup_one_phb(np); | ||
725 | if (rc) | ||
726 | pr_err("Failed to setup PCIe bridge %s, rc=%d\n", | ||
727 | np->full_name, rc); | ||
728 | } | ||
729 | |||
730 | /* Establish device-tree linkage */ | ||
731 | pci_devs_phb_init(); | ||
732 | |||
733 | /* Set DMA ops to use TCEs */ | ||
734 | if (iommu_is_off) { | ||
735 | pr_info("PCI-E: Disabled TCEs, using direct DMA\n"); | ||
736 | set_pci_dma_ops(&dma_direct_ops); | ||
737 | } else { | ||
738 | ppc_md.pci_dma_dev_setup = wsp_pci_dma_dev_setup; | ||
739 | ppc_md.tce_build = tce_build_wsp; | ||
740 | ppc_md.tce_free = tce_free_wsp; | ||
741 | set_pci_dma_ops(&dma_iommu_ops); | ||
742 | } | ||
743 | } | ||
744 | |||
745 | #define err_debug(fmt...) pr_debug(fmt) | ||
746 | //#define err_debug(fmt...) | ||
747 | |||
748 | static int __init wsp_pci_get_err_irq_no_dt(struct device_node *np) | ||
749 | { | ||
750 | const u32 *prop; | ||
751 | int hw_irq; | ||
752 | |||
753 | /* Ok, no interrupts property, let's try to find our child P2P */ | ||
754 | np = of_get_next_child(np, NULL); | ||
755 | if (np == NULL) | ||
756 | return 0; | ||
757 | |||
758 | /* Grab it's interrupt map */ | ||
759 | prop = of_get_property(np, "interrupt-map", NULL); | ||
760 | if (prop == NULL) | ||
761 | return 0; | ||
762 | |||
763 | /* Grab one of the interrupts in there, keep the low 4 bits */ | ||
764 | hw_irq = prop[5] & 0xf; | ||
765 | |||
766 | /* 0..4 for PHB 0 and 5..9 for PHB 1 */ | ||
767 | if (hw_irq < 5) | ||
768 | hw_irq = 4; | ||
769 | else | ||
770 | hw_irq = 9; | ||
771 | hw_irq |= prop[5] & ~0xf; | ||
772 | |||
773 | err_debug("PCI: Using 0x%x as error IRQ for %s\n", | ||
774 | hw_irq, np->parent->full_name); | ||
775 | return irq_create_mapping(NULL, hw_irq); | ||
776 | } | ||
777 | |||
778 | static const struct { | ||
779 | u32 offset; | ||
780 | const char *name; | ||
781 | } wsp_pci_regs[] = { | ||
782 | #define DREG(x) { PCIE_REG_##x, #x } | ||
783 | #define DUTL(x) { PCIE_UTL_##x, "UTL_" #x } | ||
784 | /* Architected registers except CONFIG_ and IODA | ||
785 | * to avoid side effects | ||
786 | */ | ||
787 | DREG(DMA_CHAN_STATUS), | ||
788 | DREG(CPU_LOADSTORE_STATUS), | ||
789 | DREG(LOCK0), | ||
790 | DREG(LOCK1), | ||
791 | DREG(PHB_CONFIG), | ||
792 | DREG(IO_BASE_ADDR), | ||
793 | DREG(IO_BASE_MASK), | ||
794 | DREG(IO_START_ADDR), | ||
795 | DREG(M32A_BASE_ADDR), | ||
796 | DREG(M32A_BASE_MASK), | ||
797 | DREG(M32A_START_ADDR), | ||
798 | DREG(M32B_BASE_ADDR), | ||
799 | DREG(M32B_BASE_MASK), | ||
800 | DREG(M32B_START_ADDR), | ||
801 | DREG(M64_BASE_ADDR), | ||
802 | DREG(M64_BASE_MASK), | ||
803 | DREG(M64_START_ADDR), | ||
804 | DREG(TCE_KILL), | ||
805 | DREG(LOCK2), | ||
806 | DREG(PHB_GEN_CAP), | ||
807 | DREG(PHB_TCE_CAP), | ||
808 | DREG(PHB_IRQ_CAP), | ||
809 | DREG(PHB_EEH_CAP), | ||
810 | DREG(PAPR_ERR_INJ_CONTROL), | ||
811 | DREG(PAPR_ERR_INJ_ADDR), | ||
812 | DREG(PAPR_ERR_INJ_MASK), | ||
813 | |||
814 | /* UTL core regs */ | ||
815 | DUTL(SYS_BUS_CONTROL), | ||
816 | DUTL(STATUS), | ||
817 | DUTL(SYS_BUS_AGENT_STATUS), | ||
818 | DUTL(SYS_BUS_AGENT_ERR_SEV), | ||
819 | DUTL(SYS_BUS_AGENT_IRQ_EN), | ||
820 | DUTL(SYS_BUS_BURST_SZ_CONF), | ||
821 | DUTL(REVISION_ID), | ||
822 | DUTL(OUT_POST_HDR_BUF_ALLOC), | ||
823 | DUTL(OUT_POST_DAT_BUF_ALLOC), | ||
824 | DUTL(IN_POST_HDR_BUF_ALLOC), | ||
825 | DUTL(IN_POST_DAT_BUF_ALLOC), | ||
826 | DUTL(OUT_NP_BUF_ALLOC), | ||
827 | DUTL(IN_NP_BUF_ALLOC), | ||
828 | DUTL(PCIE_TAGS_ALLOC), | ||
829 | DUTL(GBIF_READ_TAGS_ALLOC), | ||
830 | |||
831 | DUTL(PCIE_PORT_CONTROL), | ||
832 | DUTL(PCIE_PORT_STATUS), | ||
833 | DUTL(PCIE_PORT_ERROR_SEV), | ||
834 | DUTL(PCIE_PORT_IRQ_EN), | ||
835 | DUTL(RC_STATUS), | ||
836 | DUTL(RC_ERR_SEVERITY), | ||
837 | DUTL(RC_IRQ_EN), | ||
838 | DUTL(EP_STATUS), | ||
839 | DUTL(EP_ERR_SEVERITY), | ||
840 | DUTL(EP_ERR_IRQ_EN), | ||
841 | DUTL(PCI_PM_CTRL1), | ||
842 | DUTL(PCI_PM_CTRL2), | ||
843 | |||
844 | /* PCIe stack regs */ | ||
845 | DREG(SYSTEM_CONFIG1), | ||
846 | DREG(SYSTEM_CONFIG2), | ||
847 | DREG(EP_SYSTEM_CONFIG), | ||
848 | DREG(EP_FLR), | ||
849 | DREG(EP_BAR_CONFIG), | ||
850 | DREG(LINK_CONFIG), | ||
851 | DREG(PM_CONFIG), | ||
852 | DREG(DLP_CONTROL), | ||
853 | DREG(DLP_STATUS), | ||
854 | DREG(ERR_REPORT_CONTROL), | ||
855 | DREG(SLOT_CONTROL1), | ||
856 | DREG(SLOT_CONTROL2), | ||
857 | DREG(UTL_CONFIG), | ||
858 | DREG(BUFFERS_CONFIG), | ||
859 | DREG(ERROR_INJECT), | ||
860 | DREG(SRIOV_CONFIG), | ||
861 | DREG(PF0_SRIOV_STATUS), | ||
862 | DREG(PF1_SRIOV_STATUS), | ||
863 | DREG(PORT_NUMBER), | ||
864 | DREG(POR_SYSTEM_CONFIG), | ||
865 | |||
866 | /* Internal logic regs */ | ||
867 | DREG(PHB_VERSION), | ||
868 | DREG(RESET), | ||
869 | DREG(PHB_CONTROL), | ||
870 | DREG(PHB_TIMEOUT_CONTROL1), | ||
871 | DREG(PHB_QUIESCE_DMA), | ||
872 | DREG(PHB_DMA_READ_TAG_ACTV), | ||
873 | DREG(PHB_TCE_READ_TAG_ACTV), | ||
874 | |||
875 | /* FIR registers */ | ||
876 | DREG(LEM_FIR_ACCUM), | ||
877 | DREG(LEM_FIR_AND_MASK), | ||
878 | DREG(LEM_FIR_OR_MASK), | ||
879 | DREG(LEM_ACTION0), | ||
880 | DREG(LEM_ACTION1), | ||
881 | DREG(LEM_ERROR_MASK), | ||
882 | DREG(LEM_ERROR_AND_MASK), | ||
883 | DREG(LEM_ERROR_OR_MASK), | ||
884 | |||
885 | /* Error traps registers */ | ||
886 | DREG(PHB_ERR_STATUS), | ||
887 | DREG(PHB_ERR_STATUS), | ||
888 | DREG(PHB_ERR1_STATUS), | ||
889 | DREG(PHB_ERR_INJECT), | ||
890 | DREG(PHB_ERR_LEM_ENABLE), | ||
891 | DREG(PHB_ERR_IRQ_ENABLE), | ||
892 | DREG(PHB_ERR_FREEZE_ENABLE), | ||
893 | DREG(PHB_ERR_SIDE_ENABLE), | ||
894 | DREG(PHB_ERR_LOG_0), | ||
895 | DREG(PHB_ERR_LOG_1), | ||
896 | DREG(PHB_ERR_STATUS_MASK), | ||
897 | DREG(PHB_ERR1_STATUS_MASK), | ||
898 | DREG(MMIO_ERR_STATUS), | ||
899 | DREG(MMIO_ERR1_STATUS), | ||
900 | DREG(MMIO_ERR_INJECT), | ||
901 | DREG(MMIO_ERR_LEM_ENABLE), | ||
902 | DREG(MMIO_ERR_IRQ_ENABLE), | ||
903 | DREG(MMIO_ERR_FREEZE_ENABLE), | ||
904 | DREG(MMIO_ERR_SIDE_ENABLE), | ||
905 | DREG(MMIO_ERR_LOG_0), | ||
906 | DREG(MMIO_ERR_LOG_1), | ||
907 | DREG(MMIO_ERR_STATUS_MASK), | ||
908 | DREG(MMIO_ERR1_STATUS_MASK), | ||
909 | DREG(DMA_ERR_STATUS), | ||
910 | DREG(DMA_ERR1_STATUS), | ||
911 | DREG(DMA_ERR_INJECT), | ||
912 | DREG(DMA_ERR_LEM_ENABLE), | ||
913 | DREG(DMA_ERR_IRQ_ENABLE), | ||
914 | DREG(DMA_ERR_FREEZE_ENABLE), | ||
915 | DREG(DMA_ERR_SIDE_ENABLE), | ||
916 | DREG(DMA_ERR_LOG_0), | ||
917 | DREG(DMA_ERR_LOG_1), | ||
918 | DREG(DMA_ERR_STATUS_MASK), | ||
919 | DREG(DMA_ERR1_STATUS_MASK), | ||
920 | |||
921 | /* Debug and Trace registers */ | ||
922 | DREG(PHB_DEBUG_CONTROL0), | ||
923 | DREG(PHB_DEBUG_STATUS0), | ||
924 | DREG(PHB_DEBUG_CONTROL1), | ||
925 | DREG(PHB_DEBUG_STATUS1), | ||
926 | DREG(PHB_DEBUG_CONTROL2), | ||
927 | DREG(PHB_DEBUG_STATUS2), | ||
928 | DREG(PHB_DEBUG_CONTROL3), | ||
929 | DREG(PHB_DEBUG_STATUS3), | ||
930 | DREG(PHB_DEBUG_CONTROL4), | ||
931 | DREG(PHB_DEBUG_STATUS4), | ||
932 | DREG(PHB_DEBUG_CONTROL5), | ||
933 | DREG(PHB_DEBUG_STATUS5), | ||
934 | |||
935 | /* Don't seem to exist ... | ||
936 | DREG(PHB_DEBUG_CONTROL6), | ||
937 | DREG(PHB_DEBUG_STATUS6), | ||
938 | */ | ||
939 | }; | ||
940 | |||
941 | static int wsp_pci_regs_show(struct seq_file *m, void *private) | ||
942 | { | ||
943 | struct wsp_phb *phb = m->private; | ||
944 | struct pci_controller *hose = phb->hose; | ||
945 | int i; | ||
946 | |||
947 | for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) { | ||
948 | /* Skip write-only regs */ | ||
949 | if (wsp_pci_regs[i].offset == 0xc08 || | ||
950 | wsp_pci_regs[i].offset == 0xc10 || | ||
951 | wsp_pci_regs[i].offset == 0xc38 || | ||
952 | wsp_pci_regs[i].offset == 0xc40) | ||
953 | continue; | ||
954 | seq_printf(m, "0x%03x: 0x%016llx %s\n", | ||
955 | wsp_pci_regs[i].offset, | ||
956 | in_be64(hose->cfg_data + wsp_pci_regs[i].offset), | ||
957 | wsp_pci_regs[i].name); | ||
958 | } | ||
959 | return 0; | ||
960 | } | ||
961 | |||
962 | static int wsp_pci_regs_open(struct inode *inode, struct file *file) | ||
963 | { | ||
964 | return single_open(file, wsp_pci_regs_show, inode->i_private); | ||
965 | } | ||
966 | |||
967 | static const struct file_operations wsp_pci_regs_fops = { | ||
968 | .open = wsp_pci_regs_open, | ||
969 | .read = seq_read, | ||
970 | .llseek = seq_lseek, | ||
971 | .release = single_release, | ||
972 | }; | ||
973 | |||
974 | static int wsp_pci_reg_set(void *data, u64 val) | ||
975 | { | ||
976 | out_be64((void __iomem *)data, val); | ||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | static int wsp_pci_reg_get(void *data, u64 *val) | ||
981 | { | ||
982 | *val = in_be64((void __iomem *)data); | ||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | DEFINE_SIMPLE_ATTRIBUTE(wsp_pci_reg_fops, wsp_pci_reg_get, wsp_pci_reg_set, "0x%llx\n"); | ||
987 | |||
988 | static irqreturn_t wsp_pci_err_irq(int irq, void *dev_id) | ||
989 | { | ||
990 | struct wsp_phb *phb = dev_id; | ||
991 | struct pci_controller *hose = phb->hose; | ||
992 | irqreturn_t handled = IRQ_NONE; | ||
993 | struct wsp_pcie_err_log_data ed; | ||
994 | |||
995 | pr_err("PCI: Error interrupt on %s (PHB %d)\n", | ||
996 | hose->dn->full_name, hose->global_number); | ||
997 | again: | ||
998 | memset(&ed, 0, sizeof(ed)); | ||
999 | |||
1000 | /* Read and clear UTL errors */ | ||
1001 | ed.utl_sys_err = in_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS); | ||
1002 | if (ed.utl_sys_err) | ||
1003 | out_be64(hose->cfg_data + PCIE_UTL_SYS_BUS_AGENT_STATUS, ed.utl_sys_err); | ||
1004 | ed.utl_port_err = in_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS); | ||
1005 | if (ed.utl_port_err) | ||
1006 | out_be64(hose->cfg_data + PCIE_UTL_PCIE_PORT_STATUS, ed.utl_port_err); | ||
1007 | ed.utl_rc_err = in_be64(hose->cfg_data + PCIE_UTL_RC_STATUS); | ||
1008 | if (ed.utl_rc_err) | ||
1009 | out_be64(hose->cfg_data + PCIE_UTL_RC_STATUS, ed.utl_rc_err); | ||
1010 | |||
1011 | /* Read and clear main trap errors */ | ||
1012 | ed.phb_err = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS); | ||
1013 | if (ed.phb_err) { | ||
1014 | ed.phb_err1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS); | ||
1015 | ed.phb_log0 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_0); | ||
1016 | ed.phb_log1 = in_be64(hose->cfg_data + PCIE_REG_PHB_ERR_LOG_1); | ||
1017 | out_be64(hose->cfg_data + PCIE_REG_PHB_ERR1_STATUS, 0); | ||
1018 | out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_STATUS, 0); | ||
1019 | } | ||
1020 | ed.mmio_err = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS); | ||
1021 | if (ed.mmio_err) { | ||
1022 | ed.mmio_err1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS); | ||
1023 | ed.mmio_log0 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_0); | ||
1024 | ed.mmio_log1 = in_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_LOG_1); | ||
1025 | out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR1_STATUS, 0); | ||
1026 | out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_STATUS, 0); | ||
1027 | } | ||
1028 | ed.dma_err = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS); | ||
1029 | if (ed.dma_err) { | ||
1030 | ed.dma_err1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS); | ||
1031 | ed.dma_log0 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_0); | ||
1032 | ed.dma_log1 = in_be64(hose->cfg_data + PCIE_REG_DMA_ERR_LOG_1); | ||
1033 | out_be64(hose->cfg_data + PCIE_REG_DMA_ERR1_STATUS, 0); | ||
1034 | out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_STATUS, 0); | ||
1035 | } | ||
1036 | |||
1037 | /* Now print things out */ | ||
1038 | if (ed.phb_err) { | ||
1039 | pr_err(" PHB Error Status : 0x%016llx\n", ed.phb_err); | ||
1040 | pr_err(" PHB First Error Status: 0x%016llx\n", ed.phb_err1); | ||
1041 | pr_err(" PHB Error Log 0 : 0x%016llx\n", ed.phb_log0); | ||
1042 | pr_err(" PHB Error Log 1 : 0x%016llx\n", ed.phb_log1); | ||
1043 | } | ||
1044 | if (ed.mmio_err) { | ||
1045 | pr_err(" MMIO Error Status : 0x%016llx\n", ed.mmio_err); | ||
1046 | pr_err(" MMIO First Error Status: 0x%016llx\n", ed.mmio_err1); | ||
1047 | pr_err(" MMIO Error Log 0 : 0x%016llx\n", ed.mmio_log0); | ||
1048 | pr_err(" MMIO Error Log 1 : 0x%016llx\n", ed.mmio_log1); | ||
1049 | } | ||
1050 | if (ed.dma_err) { | ||
1051 | pr_err(" DMA Error Status : 0x%016llx\n", ed.dma_err); | ||
1052 | pr_err(" DMA First Error Status: 0x%016llx\n", ed.dma_err1); | ||
1053 | pr_err(" DMA Error Log 0 : 0x%016llx\n", ed.dma_log0); | ||
1054 | pr_err(" DMA Error Log 1 : 0x%016llx\n", ed.dma_log1); | ||
1055 | } | ||
1056 | if (ed.utl_sys_err) | ||
1057 | pr_err(" UTL Sys Error Status : 0x%016llx\n", ed.utl_sys_err); | ||
1058 | if (ed.utl_port_err) | ||
1059 | pr_err(" UTL Port Error Status : 0x%016llx\n", ed.utl_port_err); | ||
1060 | if (ed.utl_rc_err) | ||
1061 | pr_err(" UTL RC Error Status : 0x%016llx\n", ed.utl_rc_err); | ||
1062 | |||
1063 | /* Interrupts are caused by the error traps. If we had any error there | ||
1064 | * we loop again in case the UTL buffered some new stuff between | ||
1065 | * going there and going to the traps | ||
1066 | */ | ||
1067 | if (ed.dma_err || ed.mmio_err || ed.phb_err) { | ||
1068 | handled = IRQ_HANDLED; | ||
1069 | goto again; | ||
1070 | } | ||
1071 | return handled; | ||
1072 | } | ||
1073 | |||
1074 | static void __init wsp_setup_pci_err_reporting(struct wsp_phb *phb) | ||
1075 | { | ||
1076 | struct pci_controller *hose = phb->hose; | ||
1077 | int err_irq, i, rc; | ||
1078 | char fname[16]; | ||
1079 | |||
1080 | /* Create a debugfs file for that PHB */ | ||
1081 | sprintf(fname, "phb%d", phb->hose->global_number); | ||
1082 | phb->ddir = debugfs_create_dir(fname, powerpc_debugfs_root); | ||
1083 | |||
1084 | /* Some useful debug output */ | ||
1085 | if (phb->ddir) { | ||
1086 | struct dentry *d = debugfs_create_dir("regs", phb->ddir); | ||
1087 | char tmp[64]; | ||
1088 | |||
1089 | for (i = 0; i < ARRAY_SIZE(wsp_pci_regs); i++) { | ||
1090 | sprintf(tmp, "%03x_%s", wsp_pci_regs[i].offset, | ||
1091 | wsp_pci_regs[i].name); | ||
1092 | debugfs_create_file(tmp, 0600, d, | ||
1093 | hose->cfg_data + wsp_pci_regs[i].offset, | ||
1094 | &wsp_pci_reg_fops); | ||
1095 | } | ||
1096 | debugfs_create_file("all_regs", 0600, phb->ddir, phb, &wsp_pci_regs_fops); | ||
1097 | } | ||
1098 | |||
1099 | /* Find the IRQ number for that PHB */ | ||
1100 | err_irq = irq_of_parse_and_map(hose->dn, 0); | ||
1101 | if (err_irq == 0) | ||
1102 | /* XXX Error IRQ lacking from device-tree */ | ||
1103 | err_irq = wsp_pci_get_err_irq_no_dt(hose->dn); | ||
1104 | if (err_irq == 0) { | ||
1105 | pr_err("PCI: Failed to fetch error interrupt for %s\n", | ||
1106 | hose->dn->full_name); | ||
1107 | return; | ||
1108 | } | ||
1109 | /* Request it */ | ||
1110 | rc = request_irq(err_irq, wsp_pci_err_irq, 0, "wsp_pci error", phb); | ||
1111 | if (rc) { | ||
1112 | pr_err("PCI: Failed to request interrupt for %s\n", | ||
1113 | hose->dn->full_name); | ||
1114 | } | ||
1115 | /* Enable interrupts for all errors for now */ | ||
1116 | out_be64(hose->cfg_data + PCIE_REG_PHB_ERR_IRQ_ENABLE, 0xffffffffffffffffull); | ||
1117 | out_be64(hose->cfg_data + PCIE_REG_MMIO_ERR_IRQ_ENABLE, 0xffffffffffffffffull); | ||
1118 | out_be64(hose->cfg_data + PCIE_REG_DMA_ERR_IRQ_ENABLE, 0xffffffffffffffffull); | ||
1119 | } | ||
1120 | |||
1121 | /* | ||
1122 | * This is called later to hookup with the error interrupt | ||
1123 | */ | ||
1124 | static int __init wsp_setup_pci_late(void) | ||
1125 | { | ||
1126 | struct wsp_phb *phb; | ||
1127 | |||
1128 | list_for_each_entry(phb, &wsp_phbs, all) | ||
1129 | wsp_setup_pci_err_reporting(phb); | ||
1130 | |||
1131 | return 0; | ||
1132 | } | ||
1133 | arch_initcall(wsp_setup_pci_late); | ||
diff --git a/arch/powerpc/platforms/wsp/wsp_pci.h b/arch/powerpc/platforms/wsp/wsp_pci.h new file mode 100644 index 000000000000..52e9bd95250d --- /dev/null +++ b/arch/powerpc/platforms/wsp/wsp_pci.h | |||
@@ -0,0 +1,268 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Ben Herrenschmidt, IBM Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef __WSP_PCI_H | ||
11 | #define __WSP_PCI_H | ||
12 | |||
13 | /* Architected registers */ | ||
14 | #define PCIE_REG_DMA_CHAN_STATUS 0x110 | ||
15 | #define PCIE_REG_CPU_LOADSTORE_STATUS 0x120 | ||
16 | |||
17 | #define PCIE_REG_CONFIG_DATA 0x130 | ||
18 | #define PCIE_REG_LOCK0 0x138 | ||
19 | #define PCIE_REG_CONFIG_ADDRESS 0x140 | ||
20 | #define PCIE_REG_CA_ENABLE 0x8000000000000000ull | ||
21 | #define PCIE_REG_CA_BUS_MASK 0x0ff0000000000000ull | ||
22 | #define PCIE_REG_CA_BUS_SHIFT (20+32) | ||
23 | #define PCIE_REG_CA_DEV_MASK 0x000f800000000000ull | ||
24 | #define PCIE_REG_CA_DEV_SHIFT (15+32) | ||
25 | #define PCIE_REG_CA_FUNC_MASK 0x0000700000000000ull | ||
26 | #define PCIE_REG_CA_FUNC_SHIFT (12+32) | ||
27 | #define PCIE_REG_CA_REG_MASK 0x00000fff00000000ull | ||
28 | #define PCIE_REG_CA_REG_SHIFT ( 0+32) | ||
29 | #define PCIE_REG_CA_BE_MASK 0x00000000f0000000ull | ||
30 | #define PCIE_REG_CA_BE_SHIFT ( 28) | ||
31 | #define PCIE_REG_LOCK1 0x148 | ||
32 | |||
33 | #define PCIE_REG_PHB_CONFIG 0x160 | ||
34 | #define PCIE_REG_PHBC_64B_TCE_EN 0x2000000000000000ull | ||
35 | #define PCIE_REG_PHBC_MMIO_DMA_FREEZE_EN 0x1000000000000000ull | ||
36 | #define PCIE_REG_PHBC_32BIT_MSI_EN 0x0080000000000000ull | ||
37 | #define PCIE_REG_PHBC_M64_EN 0x0040000000000000ull | ||
38 | #define PCIE_REG_PHBC_IO_EN 0x0008000000000000ull | ||
39 | #define PCIE_REG_PHBC_64BIT_MSI_EN 0x0002000000000000ull | ||
40 | #define PCIE_REG_PHBC_M32A_EN 0x0000800000000000ull | ||
41 | #define PCIE_REG_PHBC_M32B_EN 0x0000400000000000ull | ||
42 | #define PCIE_REG_PHBC_MSI_PE_VALIDATE 0x0000200000000000ull | ||
43 | #define PCIE_REG_PHBC_DMA_XLATE_BYPASS 0x0000100000000000ull | ||
44 | |||
45 | #define PCIE_REG_IO_BASE_ADDR 0x170 | ||
46 | #define PCIE_REG_IO_BASE_MASK 0x178 | ||
47 | #define PCIE_REG_IO_START_ADDR 0x180 | ||
48 | |||
49 | #define PCIE_REG_M32A_BASE_ADDR 0x190 | ||
50 | #define PCIE_REG_M32A_BASE_MASK 0x198 | ||
51 | #define PCIE_REG_M32A_START_ADDR 0x1a0 | ||
52 | |||
53 | #define PCIE_REG_M32B_BASE_ADDR 0x1b0 | ||
54 | #define PCIE_REG_M32B_BASE_MASK 0x1b8 | ||
55 | #define PCIE_REG_M32B_START_ADDR 0x1c0 | ||
56 | |||
57 | #define PCIE_REG_M64_BASE_ADDR 0x1e0 | ||
58 | #define PCIE_REG_M64_BASE_MASK 0x1e8 | ||
59 | #define PCIE_REG_M64_START_ADDR 0x1f0 | ||
60 | |||
61 | #define PCIE_REG_TCE_KILL 0x210 | ||
62 | #define PCIE_REG_TCEKILL_SINGLE 0x8000000000000000ull | ||
63 | #define PCIE_REG_TCEKILL_ADDR_MASK 0x000003fffffffff8ull | ||
64 | #define PCIE_REG_TCEKILL_PS_4K 0 | ||
65 | #define PCIE_REG_TCEKILL_PS_64K 1 | ||
66 | #define PCIE_REG_TCEKILL_PS_16M 2 | ||
67 | #define PCIE_REG_TCEKILL_PS_16G 3 | ||
68 | |||
69 | #define PCIE_REG_IODA_ADDR 0x220 | ||
70 | #define PCIE_REG_IODA_AD_AUTOINC 0x8000000000000000ull | ||
71 | #define PCIE_REG_IODA_AD_TBL_MVT 0x0005000000000000ull | ||
72 | #define PCIE_REG_IODA_AD_TBL_PELT 0x0006000000000000ull | ||
73 | #define PCIE_REG_IODA_AD_TBL_PESTA 0x0007000000000000ull | ||
74 | #define PCIE_REG_IODA_AD_TBL_PESTB 0x0008000000000000ull | ||
75 | #define PCIE_REG_IODA_AD_TBL_TVT 0x0009000000000000ull | ||
76 | #define PCIE_REG_IODA_AD_TBL_TCE 0x000a000000000000ull | ||
77 | #define PCIE_REG_IODA_DATA0 0x228 | ||
78 | #define PCIE_REG_IODA_DATA1 0x230 | ||
79 | |||
80 | #define PCIE_REG_LOCK2 0x240 | ||
81 | |||
82 | #define PCIE_REG_PHB_GEN_CAP 0x250 | ||
83 | #define PCIE_REG_PHB_TCE_CAP 0x258 | ||
84 | #define PCIE_REG_PHB_IRQ_CAP 0x260 | ||
85 | #define PCIE_REG_PHB_EEH_CAP 0x268 | ||
86 | |||
87 | #define PCIE_REG_PAPR_ERR_INJ_CONTROL 0x2b0 | ||
88 | #define PCIE_REG_PAPR_ERR_INJ_ADDR 0x2b8 | ||
89 | #define PCIE_REG_PAPR_ERR_INJ_MASK 0x2c0 | ||
90 | |||
91 | |||
92 | #define PCIE_REG_SYS_CFG1 0x600 | ||
93 | #define PCIE_REG_SYS_CFG1_CLASS_CODE 0x0000000000ffffffull | ||
94 | |||
95 | #define IODA_TVT0_TTA_MASK 0x000fffffffff0000ull | ||
96 | #define IODA_TVT0_TTA_SHIFT 4 | ||
97 | #define IODA_TVT0_BUSNUM_VALID_MASK 0x000000000000e000ull | ||
98 | #define IODA_TVT0_TCE_TABLE_SIZE_MASK 0x0000000000001f00ull | ||
99 | #define IODA_TVT0_TCE_TABLE_SIZE_SHIFT 8 | ||
100 | #define IODA_TVT0_BUSNUM_VALUE_MASK 0x00000000000000ffull | ||
101 | #define IODA_TVT0_BUSNUM_VALID_SHIFT 0 | ||
102 | #define IODA_TVT1_DEVNUM_VALID 0x2000000000000000ull | ||
103 | #define IODA_TVT1_DEVNUM_VALUE_MASK 0x1f00000000000000ull | ||
104 | #define IODA_TVT1_DEVNUM_VALUE_SHIFT 56 | ||
105 | #define IODA_TVT1_FUNCNUM_VALID 0x0008000000000000ull | ||
106 | #define IODA_TVT1_FUNCNUM_VALUE_MASK 0x0007000000000000ull | ||
107 | #define IODA_TVT1_FUNCNUM_VALUE_SHIFT 48 | ||
108 | #define IODA_TVT1_IO_PAGE_SIZE_MASK 0x00001f0000000000ull | ||
109 | #define IODA_TVT1_IO_PAGE_SIZE_SHIFT 40 | ||
110 | #define IODA_TVT1_PE_NUMBER_MASK 0x000000000000003full | ||
111 | #define IODA_TVT1_PE_NUMBER_SHIFT 0 | ||
112 | |||
113 | #define IODA_TVT_COUNT 64 | ||
114 | |||
115 | /* UTL Core registers */ | ||
116 | #define PCIE_UTL_SYS_BUS_CONTROL 0x400 | ||
117 | #define PCIE_UTL_STATUS 0x408 | ||
118 | #define PCIE_UTL_SYS_BUS_AGENT_STATUS 0x410 | ||
119 | #define PCIE_UTL_SYS_BUS_AGENT_ERR_SEV 0x418 | ||
120 | #define PCIE_UTL_SYS_BUS_AGENT_IRQ_EN 0x420 | ||
121 | #define PCIE_UTL_SYS_BUS_BURST_SZ_CONF 0x440 | ||
122 | #define PCIE_UTL_REVISION_ID 0x448 | ||
123 | |||
124 | #define PCIE_UTL_OUT_POST_HDR_BUF_ALLOC 0x4c0 | ||
125 | #define PCIE_UTL_OUT_POST_DAT_BUF_ALLOC 0x4d0 | ||
126 | #define PCIE_UTL_IN_POST_HDR_BUF_ALLOC 0x4e0 | ||
127 | #define PCIE_UTL_IN_POST_DAT_BUF_ALLOC 0x4f0 | ||
128 | #define PCIE_UTL_OUT_NP_BUF_ALLOC 0x500 | ||
129 | #define PCIE_UTL_IN_NP_BUF_ALLOC 0x510 | ||
130 | #define PCIE_UTL_PCIE_TAGS_ALLOC 0x520 | ||
131 | #define PCIE_UTL_GBIF_READ_TAGS_ALLOC 0x530 | ||
132 | |||
133 | #define PCIE_UTL_PCIE_PORT_CONTROL 0x540 | ||
134 | #define PCIE_UTL_PCIE_PORT_STATUS 0x548 | ||
135 | #define PCIE_UTL_PCIE_PORT_ERROR_SEV 0x550 | ||
136 | #define PCIE_UTL_PCIE_PORT_IRQ_EN 0x558 | ||
137 | #define PCIE_UTL_RC_STATUS 0x560 | ||
138 | #define PCIE_UTL_RC_ERR_SEVERITY 0x568 | ||
139 | #define PCIE_UTL_RC_IRQ_EN 0x570 | ||
140 | #define PCIE_UTL_EP_STATUS 0x578 | ||
141 | #define PCIE_UTL_EP_ERR_SEVERITY 0x580 | ||
142 | #define PCIE_UTL_EP_ERR_IRQ_EN 0x588 | ||
143 | |||
144 | #define PCIE_UTL_PCI_PM_CTRL1 0x590 | ||
145 | #define PCIE_UTL_PCI_PM_CTRL2 0x598 | ||
146 | |||
147 | /* PCIe stack registers */ | ||
148 | #define PCIE_REG_SYSTEM_CONFIG1 0x600 | ||
149 | #define PCIE_REG_SYSTEM_CONFIG2 0x608 | ||
150 | #define PCIE_REG_EP_SYSTEM_CONFIG 0x618 | ||
151 | #define PCIE_REG_EP_FLR 0x620 | ||
152 | #define PCIE_REG_EP_BAR_CONFIG 0x628 | ||
153 | #define PCIE_REG_LINK_CONFIG 0x630 | ||
154 | #define PCIE_REG_PM_CONFIG 0x640 | ||
155 | #define PCIE_REG_DLP_CONTROL 0x650 | ||
156 | #define PCIE_REG_DLP_STATUS 0x658 | ||
157 | #define PCIE_REG_ERR_REPORT_CONTROL 0x660 | ||
158 | #define PCIE_REG_SLOT_CONTROL1 0x670 | ||
159 | #define PCIE_REG_SLOT_CONTROL2 0x678 | ||
160 | #define PCIE_REG_UTL_CONFIG 0x680 | ||
161 | #define PCIE_REG_BUFFERS_CONFIG 0x690 | ||
162 | #define PCIE_REG_ERROR_INJECT 0x698 | ||
163 | #define PCIE_REG_SRIOV_CONFIG 0x6a0 | ||
164 | #define PCIE_REG_PF0_SRIOV_STATUS 0x6a8 | ||
165 | #define PCIE_REG_PF1_SRIOV_STATUS 0x6b0 | ||
166 | #define PCIE_REG_PORT_NUMBER 0x700 | ||
167 | #define PCIE_REG_POR_SYSTEM_CONFIG 0x708 | ||
168 | |||
169 | /* PHB internal logic registers */ | ||
170 | #define PCIE_REG_PHB_VERSION 0x800 | ||
171 | #define PCIE_REG_RESET 0x808 | ||
172 | #define PCIE_REG_PHB_CONTROL 0x810 | ||
173 | #define PCIE_REG_PHB_TIMEOUT_CONTROL1 0x878 | ||
174 | #define PCIE_REG_PHB_QUIESCE_DMA 0x888 | ||
175 | #define PCIE_REG_PHB_DMA_READ_TAG_ACTV 0x900 | ||
176 | #define PCIE_REG_PHB_TCE_READ_TAG_ACTV 0x908 | ||
177 | |||
178 | /* FIR registers */ | ||
179 | #define PCIE_REG_LEM_FIR_ACCUM 0xc00 | ||
180 | #define PCIE_REG_LEM_FIR_AND_MASK 0xc08 | ||
181 | #define PCIE_REG_LEM_FIR_OR_MASK 0xc10 | ||
182 | #define PCIE_REG_LEM_ACTION0 0xc18 | ||
183 | #define PCIE_REG_LEM_ACTION1 0xc20 | ||
184 | #define PCIE_REG_LEM_ERROR_MASK 0xc30 | ||
185 | #define PCIE_REG_LEM_ERROR_AND_MASK 0xc38 | ||
186 | #define PCIE_REG_LEM_ERROR_OR_MASK 0xc40 | ||
187 | |||
188 | /* PHB Error registers */ | ||
189 | #define PCIE_REG_PHB_ERR_STATUS 0xc80 | ||
190 | #define PCIE_REG_PHB_ERR1_STATUS 0xc88 | ||
191 | #define PCIE_REG_PHB_ERR_INJECT 0xc90 | ||
192 | #define PCIE_REG_PHB_ERR_LEM_ENABLE 0xc98 | ||
193 | #define PCIE_REG_PHB_ERR_IRQ_ENABLE 0xca0 | ||
194 | #define PCIE_REG_PHB_ERR_FREEZE_ENABLE 0xca8 | ||
195 | #define PCIE_REG_PHB_ERR_SIDE_ENABLE 0xcb8 | ||
196 | #define PCIE_REG_PHB_ERR_LOG_0 0xcc0 | ||
197 | #define PCIE_REG_PHB_ERR_LOG_1 0xcc8 | ||
198 | #define PCIE_REG_PHB_ERR_STATUS_MASK 0xcd0 | ||
199 | #define PCIE_REG_PHB_ERR1_STATUS_MASK 0xcd8 | ||
200 | |||
201 | #define PCIE_REG_MMIO_ERR_STATUS 0xd00 | ||
202 | #define PCIE_REG_MMIO_ERR1_STATUS 0xd08 | ||
203 | #define PCIE_REG_MMIO_ERR_INJECT 0xd10 | ||
204 | #define PCIE_REG_MMIO_ERR_LEM_ENABLE 0xd18 | ||
205 | #define PCIE_REG_MMIO_ERR_IRQ_ENABLE 0xd20 | ||
206 | #define PCIE_REG_MMIO_ERR_FREEZE_ENABLE 0xd28 | ||
207 | #define PCIE_REG_MMIO_ERR_SIDE_ENABLE 0xd38 | ||
208 | #define PCIE_REG_MMIO_ERR_LOG_0 0xd40 | ||
209 | #define PCIE_REG_MMIO_ERR_LOG_1 0xd48 | ||
210 | #define PCIE_REG_MMIO_ERR_STATUS_MASK 0xd50 | ||
211 | #define PCIE_REG_MMIO_ERR1_STATUS_MASK 0xd58 | ||
212 | |||
213 | #define PCIE_REG_DMA_ERR_STATUS 0xd80 | ||
214 | #define PCIE_REG_DMA_ERR1_STATUS 0xd88 | ||
215 | #define PCIE_REG_DMA_ERR_INJECT 0xd90 | ||
216 | #define PCIE_REG_DMA_ERR_LEM_ENABLE 0xd98 | ||
217 | #define PCIE_REG_DMA_ERR_IRQ_ENABLE 0xda0 | ||
218 | #define PCIE_REG_DMA_ERR_FREEZE_ENABLE 0xda8 | ||
219 | #define PCIE_REG_DMA_ERR_SIDE_ENABLE 0xdb8 | ||
220 | #define PCIE_REG_DMA_ERR_LOG_0 0xdc0 | ||
221 | #define PCIE_REG_DMA_ERR_LOG_1 0xdc8 | ||
222 | #define PCIE_REG_DMA_ERR_STATUS_MASK 0xdd0 | ||
223 | #define PCIE_REG_DMA_ERR1_STATUS_MASK 0xdd8 | ||
224 | |||
225 | /* Shortcuts for access to the above using the PHB definitions | ||
226 | * with an offset | ||
227 | */ | ||
228 | #define PCIE_REG_ERR_PHB_OFFSET 0x0 | ||
229 | #define PCIE_REG_ERR_MMIO_OFFSET 0x80 | ||
230 | #define PCIE_REG_ERR_DMA_OFFSET 0x100 | ||
231 | |||
232 | /* Debug and Trace registers */ | ||
233 | #define PCIE_REG_PHB_DEBUG_CONTROL0 0xe00 | ||
234 | #define PCIE_REG_PHB_DEBUG_STATUS0 0xe08 | ||
235 | #define PCIE_REG_PHB_DEBUG_CONTROL1 0xe10 | ||
236 | #define PCIE_REG_PHB_DEBUG_STATUS1 0xe18 | ||
237 | #define PCIE_REG_PHB_DEBUG_CONTROL2 0xe20 | ||
238 | #define PCIE_REG_PHB_DEBUG_STATUS2 0xe28 | ||
239 | #define PCIE_REG_PHB_DEBUG_CONTROL3 0xe30 | ||
240 | #define PCIE_REG_PHB_DEBUG_STATUS3 0xe38 | ||
241 | #define PCIE_REG_PHB_DEBUG_CONTROL4 0xe40 | ||
242 | #define PCIE_REG_PHB_DEBUG_STATUS4 0xe48 | ||
243 | #define PCIE_REG_PHB_DEBUG_CONTROL5 0xe50 | ||
244 | #define PCIE_REG_PHB_DEBUG_STATUS5 0xe58 | ||
245 | #define PCIE_REG_PHB_DEBUG_CONTROL6 0xe60 | ||
246 | #define PCIE_REG_PHB_DEBUG_STATUS6 0xe68 | ||
247 | |||
248 | /* Definition for PCIe errors */ | ||
249 | struct wsp_pcie_err_log_data { | ||
250 | __u64 phb_err; | ||
251 | __u64 phb_err1; | ||
252 | __u64 phb_log0; | ||
253 | __u64 phb_log1; | ||
254 | __u64 mmio_err; | ||
255 | __u64 mmio_err1; | ||
256 | __u64 mmio_log0; | ||
257 | __u64 mmio_log1; | ||
258 | __u64 dma_err; | ||
259 | __u64 dma_err1; | ||
260 | __u64 dma_log0; | ||
261 | __u64 dma_log1; | ||
262 | __u64 utl_sys_err; | ||
263 | __u64 utl_port_err; | ||
264 | __u64 utl_rc_err; | ||
265 | __u64 unused; | ||
266 | }; | ||
267 | |||
268 | #endif /* __WSP_PCI_H */ | ||