]> err.no Git - linux-2.6/blob - arch/powerpc/sysdev/ppc4xx_pci.c
b7d79880c9b9b15adf9a30ca8f4a1cdd9922bf53
[linux-2.6] / arch / powerpc / sysdev / ppc4xx_pci.c
1 /*
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
19 static int dma_offset_set;
20
21 /* Move that to a useable header */
22 extern unsigned long total_memory;
23
24 static 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 }
52 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_ppc4xx_pci_bridge);
53
54 static 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  */
159
160 static 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
208 static 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
232 static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
233 {
234         /* NYI */
235         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);
310 }
311
312 /*
313  * 4xx PCI-X part
314  */
315
316 static 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 */
336 #ifdef CONFIG_RESOURCES_64BIT
337                 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
373 static 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
403 static 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  */
498 static void __init ppc4xx_probe_pciex_bridge(struct device_node *np)
499 {
500         /* NYI */
501 }
502
503 static 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 }
516 arch_initcall(ppc4xx_pci_find_bridges);
517