blob: b7d79880c9b9b15adf9a30ca8f4a1cdd9922bf53 [file] [log] [blame]
Benjamin Herrenschmidt5738ec62007-12-21 15:39:22 +11001/*
2 * PCI / PCI-X / PCI-Express support for 4xx parts
3 *
4 * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
5 *
6 */
7
8#include <linux/kernel.h>
9#include <linux/pci.h>
10#include <linux/init.h>
11#include <linux/of.h>
12
13#include <asm/io.h>
14#include <asm/pci-bridge.h>
15#include <asm/machdep.h>
16
17#include "ppc4xx_pci.h"
18
19static int dma_offset_set;
20
21/* Move that to a useable header */
22extern unsigned long total_memory;
23
Benjamin Herrenschmidtc839e0e2007-12-21 15:39:23 +110024static void fixup_ppc4xx_pci_bridge(struct pci_dev *dev)
25{
26 struct pci_controller *hose;
27 int i;
28
29 if (dev->devfn != 0 || dev->bus->self != NULL)
30 return;
31
32 hose = pci_bus_to_host(dev->bus);
33 if (hose == NULL)
34 return;
35
36 if (!of_device_is_compatible(hose->dn, "ibm,plb-pciex") &&
37 !of_device_is_compatible(hose->dn, "ibm,plb-pcix") &&
38 !of_device_is_compatible(hose->dn, "ibm,plb-pci"))
39 return;
40
41 /* Hide the PCI host BARs from the kernel as their content doesn't
42 * fit well in the resource management
43 */
44 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
45 dev->resource[i].start = dev->resource[i].end = 0;
46 dev->resource[i].flags = 0;
47 }
48
49 printk(KERN_INFO "PCI: Hiding 4xx host bridge resources %s\n",
50 pci_name(dev));
51}
52DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_ppc4xx_pci_bridge);
53
Benjamin Herrenschmidt5738ec62007-12-21 15:39:22 +110054static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
55 void __iomem *reg,
56 struct resource *res)
57{
58 u64 size;
59 const u32 *ranges;
60 int rlen;
61 int pna = of_n_addr_cells(hose->dn);
62 int np = pna + 5;
63
64 /* Default */
65 res->start = 0;
66 res->end = size = 0x80000000;
67 res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
68
69 /* Get dma-ranges property */
70 ranges = of_get_property(hose->dn, "dma-ranges", &rlen);
71 if (ranges == NULL)
72 goto out;
73
74 /* Walk it */
75 while ((rlen -= np * 4) >= 0) {
76 u32 pci_space = ranges[0];
77 u64 pci_addr = of_read_number(ranges + 1, 2);
78 u64 cpu_addr = of_translate_dma_address(hose->dn, ranges + 3);
79 size = of_read_number(ranges + pna + 3, 2);
80 ranges += np;
81 if (cpu_addr == OF_BAD_ADDR || size == 0)
82 continue;
83
84 /* We only care about memory */
85 if ((pci_space & 0x03000000) != 0x02000000)
86 continue;
87
88 /* We currently only support memory at 0, and pci_addr
89 * within 32 bits space
90 */
91 if (cpu_addr != 0 || pci_addr > 0xffffffff) {
92 printk(KERN_WARNING "%s: Ignored unsupported dma range"
93 " 0x%016llx...0x%016llx -> 0x%016llx\n",
94 hose->dn->full_name,
95 pci_addr, pci_addr + size - 1, cpu_addr);
96 continue;
97 }
98
99 /* Check if not prefetchable */
100 if (!(pci_space & 0x40000000))
101 res->flags &= ~IORESOURCE_PREFETCH;
102
103
104 /* Use that */
105 res->start = pci_addr;
106#ifndef CONFIG_RESOURCES_64BIT
107 /* Beware of 32 bits resources */
108 if ((pci_addr + size) > 0x100000000ull)
109 res->end = 0xffffffff;
110 else
111#endif
112 res->end = res->start + size - 1;
113 break;
114 }
115
116 /* We only support one global DMA offset */
117 if (dma_offset_set && pci_dram_offset != res->start) {
118 printk(KERN_ERR "%s: dma-ranges(s) mismatch\n",
119 hose->dn->full_name);
120 return -ENXIO;
121 }
122
123 /* Check that we can fit all of memory as we don't support
124 * DMA bounce buffers
125 */
126 if (size < total_memory) {
127 printk(KERN_ERR "%s: dma-ranges too small "
128 "(size=%llx total_memory=%lx)\n",
129 hose->dn->full_name, size, total_memory);
130 return -ENXIO;
131 }
132
133 /* Check we are a power of 2 size and that base is a multiple of size*/
134 if (!is_power_of_2(size) ||
135 (res->start & (size - 1)) != 0) {
136 printk(KERN_ERR "%s: dma-ranges unaligned\n",
137 hose->dn->full_name);
138 return -ENXIO;
139 }
140
141 /* Check that we are fully contained within 32 bits space */
142 if (res->end > 0xffffffff) {
143 printk(KERN_ERR "%s: dma-ranges outside of 32 bits space\n",
144 hose->dn->full_name);
145 return -ENXIO;
146 }
147 out:
148 dma_offset_set = 1;
149 pci_dram_offset = res->start;
150
151 printk(KERN_INFO "4xx PCI DMA offset set to 0x%08lx\n",
152 pci_dram_offset);
153 return 0;
154}
155
156/*
157 * 4xx PCI 2.x part
158 */
Benjamin Herrenschmidtc839e0e2007-12-21 15:39:23 +1100159
160static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
161 void __iomem *reg)
162{
163 u32 la, ma, pcila, pciha;
164 int i, j;
165
166 /* Setup outbound memory windows */
167 for (i = j = 0; i < 3; i++) {
168 struct resource *res = &hose->mem_resources[i];
169
170 /* we only care about memory windows */
171 if (!(res->flags & IORESOURCE_MEM))
172 continue;
173 if (j > 2) {
174 printk(KERN_WARNING "%s: Too many ranges\n",
175 hose->dn->full_name);
176 break;
177 }
178
179 /* Calculate register values */
180 la = res->start;
181#ifdef CONFIG_RESOURCES_64BIT
182 pciha = (res->start - hose->pci_mem_offset) >> 32;
183 pcila = (res->start - hose->pci_mem_offset) & 0xffffffffu;
184#else
185 pciha = 0;
186 pcila = res->start - hose->pci_mem_offset;
187#endif
188
189 ma = res->end + 1 - res->start;
190 if (!is_power_of_2(ma) || ma < 0x1000 || ma > 0xffffffffu) {
191 printk(KERN_WARNING "%s: Resource out of range\n",
192 hose->dn->full_name);
193 continue;
194 }
195 ma = (0xffffffffu << ilog2(ma)) | 0x1;
196 if (res->flags & IORESOURCE_PREFETCH)
197 ma |= 0x2;
198
199 /* Program register values */
200 writel(la, reg + PCIL0_PMM0LA + (0x10 * j));
201 writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * j));
202 writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * j));
203 writel(ma, reg + PCIL0_PMM0MA + (0x10 * j));
204 j++;
205 }
206}
207
208static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose,
209 void __iomem *reg,
210 const struct resource *res)
211{
212 resource_size_t size = res->end - res->start + 1;
213 u32 sa;
214
215 /* Calculate window size */
216 sa = (0xffffffffu << ilog2(size)) | 1;
217 sa |= 0x1;
218
219 /* RAM is always at 0 local for now */
220 writel(0, reg + PCIL0_PTM1LA);
221 writel(sa, reg + PCIL0_PTM1MS);
222
223 /* Map on PCI side */
224 early_write_config_dword(hose, hose->first_busno, 0,
225 PCI_BASE_ADDRESS_1, res->start);
226 early_write_config_dword(hose, hose->first_busno, 0,
227 PCI_BASE_ADDRESS_2, 0x00000000);
228 early_write_config_word(hose, hose->first_busno, 0,
229 PCI_COMMAND, 0x0006);
230}
231
Benjamin Herrenschmidt5738ec62007-12-21 15:39:22 +1100232static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
233{
234 /* NYI */
Benjamin Herrenschmidtc839e0e2007-12-21 15:39:23 +1100235 struct resource rsrc_cfg;
236 struct resource rsrc_reg;
237 struct resource dma_window;
238 struct pci_controller *hose = NULL;
239 void __iomem *reg = NULL;
240 const int *bus_range;
241 int primary = 0;
242
243 /* Fetch config space registers address */
244 if (of_address_to_resource(np, 0, &rsrc_cfg)) {
245 printk(KERN_ERR "%s:Can't get PCI config register base !",
246 np->full_name);
247 return;
248 }
249 /* Fetch host bridge internal registers address */
250 if (of_address_to_resource(np, 3, &rsrc_reg)) {
251 printk(KERN_ERR "%s: Can't get PCI internal register base !",
252 np->full_name);
253 return;
254 }
255
256 /* Check if primary bridge */
257 if (of_get_property(np, "primary", NULL))
258 primary = 1;
259
260 /* Get bus range if any */
261 bus_range = of_get_property(np, "bus-range", NULL);
262
263 /* Map registers */
264 reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start);
265 if (reg == NULL) {
266 printk(KERN_ERR "%s: Can't map registers !", np->full_name);
267 goto fail;
268 }
269
270 /* Allocate the host controller data structure */
271 hose = pcibios_alloc_controller(np);
272 if (!hose)
273 goto fail;
274
275 hose->first_busno = bus_range ? bus_range[0] : 0x0;
276 hose->last_busno = bus_range ? bus_range[1] : 0xff;
277
278 /* Setup config space */
279 setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 0x4, 0);
280
281 /* Disable all windows */
282 writel(0, reg + PCIL0_PMM0MA);
283 writel(0, reg + PCIL0_PMM1MA);
284 writel(0, reg + PCIL0_PMM2MA);
285 writel(0, reg + PCIL0_PTM1MS);
286 writel(0, reg + PCIL0_PTM2MS);
287
288 /* Parse outbound mapping resources */
289 pci_process_bridge_OF_ranges(hose, np, primary);
290
291 /* Parse inbound mapping resources */
292 if (ppc4xx_parse_dma_ranges(hose, reg, &dma_window) != 0)
293 goto fail;
294
295 /* Configure outbound ranges POMs */
296 ppc4xx_configure_pci_PMMs(hose, reg);
297
298 /* Configure inbound ranges PIMs */
299 ppc4xx_configure_pci_PTMs(hose, reg, &dma_window);
300
301 /* We don't need the registers anymore */
302 iounmap(reg);
303 return;
304
305 fail:
306 if (hose)
307 pcibios_free_controller(hose);
308 if (reg)
309 iounmap(reg);
Benjamin Herrenschmidt5738ec62007-12-21 15:39:22 +1100310}
311
312/*
313 * 4xx PCI-X part
314 */
315
316static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
317 void __iomem *reg)
318{
319 u32 lah, lal, pciah, pcial, sa;
320 int i, j;
321
322 /* Setup outbound memory windows */
323 for (i = j = 0; i < 3; i++) {
324 struct resource *res = &hose->mem_resources[i];
325
326 /* we only care about memory windows */
327 if (!(res->flags & IORESOURCE_MEM))
328 continue;
329 if (j > 1) {
330 printk(KERN_WARNING "%s: Too many ranges\n",
331 hose->dn->full_name);
332 break;
333 }
334
335 /* Calculate register values */
Benjamin Herrenschmidtc839e0e2007-12-21 15:39:23 +1100336#ifdef CONFIG_RESOURCES_64BIT
Benjamin Herrenschmidt5738ec62007-12-21 15:39:22 +1100337 lah = res->start >> 32;
338 lal = res->start & 0xffffffffu;
339 pciah = (res->start - hose->pci_mem_offset) >> 32;
340 pcial = (res->start - hose->pci_mem_offset) & 0xffffffffu;
341#else
342 lah = pciah = 0;
343 lal = res->start;
344 pcial = res->start - hose->pci_mem_offset;
345#endif
346 sa = res->end + 1 - res->start;
347 if (!is_power_of_2(sa) || sa < 0x100000 ||
348 sa > 0xffffffffu) {
349 printk(KERN_WARNING "%s: Resource out of range\n",
350 hose->dn->full_name);
351 continue;
352 }
353 sa = (0xffffffffu << ilog2(sa)) | 0x1;
354
355 /* Program register values */
356 if (j == 0) {
357 writel(lah, reg + PCIX0_POM0LAH);
358 writel(lal, reg + PCIX0_POM0LAL);
359 writel(pciah, reg + PCIX0_POM0PCIAH);
360 writel(pcial, reg + PCIX0_POM0PCIAL);
361 writel(sa, reg + PCIX0_POM0SA);
362 } else {
363 writel(lah, reg + PCIX0_POM1LAH);
364 writel(lal, reg + PCIX0_POM1LAL);
365 writel(pciah, reg + PCIX0_POM1PCIAH);
366 writel(pcial, reg + PCIX0_POM1PCIAL);
367 writel(sa, reg + PCIX0_POM1SA);
368 }
369 j++;
370 }
371}
372
373static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose,
374 void __iomem *reg,
375 const struct resource *res,
376 int big_pim,
377 int enable_msi_hole)
378{
379 resource_size_t size = res->end - res->start + 1;
380 u32 sa;
381
382 /* RAM is always at 0 */
383 writel(0x00000000, reg + PCIX0_PIM0LAH);
384 writel(0x00000000, reg + PCIX0_PIM0LAL);
385
386 /* Calculate window size */
387 sa = (0xffffffffu << ilog2(size)) | 1;
388 sa |= 0x1;
389 if (res->flags & IORESOURCE_PREFETCH)
390 sa |= 0x2;
391 if (enable_msi_hole)
392 sa |= 0x4;
393 writel(sa, reg + PCIX0_PIM0SA);
394 if (big_pim)
395 writel(0xffffffff, reg + PCIX0_PIM0SAH);
396
397 /* Map on PCI side */
398 writel(0x00000000, reg + PCIX0_BAR0H);
399 writel(res->start, reg + PCIX0_BAR0L);
400 writew(0x0006, reg + PCIX0_COMMAND);
401}
402
403static void __init ppc4xx_probe_pcix_bridge(struct device_node *np)
404{
405 struct resource rsrc_cfg;
406 struct resource rsrc_reg;
407 struct resource dma_window;
408 struct pci_controller *hose = NULL;
409 void __iomem *reg = NULL;
410 const int *bus_range;
411 int big_pim = 0, msi = 0, primary = 0;
412
413 /* Fetch config space registers address */
414 if (of_address_to_resource(np, 0, &rsrc_cfg)) {
415 printk(KERN_ERR "%s:Can't get PCI-X config register base !",
416 np->full_name);
417 return;
418 }
419 /* Fetch host bridge internal registers address */
420 if (of_address_to_resource(np, 3, &rsrc_reg)) {
421 printk(KERN_ERR "%s: Can't get PCI-X internal register base !",
422 np->full_name);
423 return;
424 }
425
426 /* Check if it supports large PIMs (440GX) */
427 if (of_get_property(np, "large-inbound-windows", NULL))
428 big_pim = 1;
429
430 /* Check if we should enable MSIs inbound hole */
431 if (of_get_property(np, "enable-msi-hole", NULL))
432 msi = 1;
433
434 /* Check if primary bridge */
435 if (of_get_property(np, "primary", NULL))
436 primary = 1;
437
438 /* Get bus range if any */
439 bus_range = of_get_property(np, "bus-range", NULL);
440
441 /* Map registers */
442 reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start);
443 if (reg == NULL) {
444 printk(KERN_ERR "%s: Can't map registers !", np->full_name);
445 goto fail;
446 }
447
448 /* Allocate the host controller data structure */
449 hose = pcibios_alloc_controller(np);
450 if (!hose)
451 goto fail;
452
453 hose->first_busno = bus_range ? bus_range[0] : 0x0;
454 hose->last_busno = bus_range ? bus_range[1] : 0xff;
455
456 /* Setup config space */
457 setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 0x4, 0);
458
459 /* Disable all windows */
460 writel(0, reg + PCIX0_POM0SA);
461 writel(0, reg + PCIX0_POM1SA);
462 writel(0, reg + PCIX0_POM2SA);
463 writel(0, reg + PCIX0_PIM0SA);
464 writel(0, reg + PCIX0_PIM1SA);
465 writel(0, reg + PCIX0_PIM2SA);
466 if (big_pim) {
467 writel(0, reg + PCIX0_PIM0SAH);
468 writel(0, reg + PCIX0_PIM2SAH);
469 }
470
471 /* Parse outbound mapping resources */
472 pci_process_bridge_OF_ranges(hose, np, primary);
473
474 /* Parse inbound mapping resources */
475 if (ppc4xx_parse_dma_ranges(hose, reg, &dma_window) != 0)
476 goto fail;
477
478 /* Configure outbound ranges POMs */
479 ppc4xx_configure_pcix_POMs(hose, reg);
480
481 /* Configure inbound ranges PIMs */
482 ppc4xx_configure_pcix_PIMs(hose, reg, &dma_window, big_pim, msi);
483
484 /* We don't need the registers anymore */
485 iounmap(reg);
486 return;
487
488 fail:
489 if (hose)
490 pcibios_free_controller(hose);
491 if (reg)
492 iounmap(reg);
493}
494
495/*
496 * 4xx PCI-Express part
497 */
498static void __init ppc4xx_probe_pciex_bridge(struct device_node *np)
499{
500 /* NYI */
501}
502
503static int __init ppc4xx_pci_find_bridges(void)
504{
505 struct device_node *np;
506
507 for_each_compatible_node(np, NULL, "ibm,plb-pciex")
508 ppc4xx_probe_pciex_bridge(np);
509 for_each_compatible_node(np, NULL, "ibm,plb-pcix")
510 ppc4xx_probe_pcix_bridge(np);
511 for_each_compatible_node(np, NULL, "ibm,plb-pci")
512 ppc4xx_probe_pci_bridge(np);
513
514 return 0;
515}
516arch_initcall(ppc4xx_pci_find_bridges);
517