]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/fdt/fdt_pci.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / fdt / fdt_pci.c
1 /*-
2  * Copyright (c) 2010 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Semihalf under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/ktr.h>
36 #include <sys/kernel.h>
37 #include <sys/bus.h>
38 #include <sys/rman.h>
39 #include <sys/malloc.h>
40
41 #include <dev/fdt/fdt_common.h>
42 #include <dev/pci/pcireg.h>
43
44 #include <machine/fdt.h>
45
46 #include "ofw_bus_if.h"
47 #include "pcib_if.h"
48
49 #ifdef DEBUG
50 #define debugf(fmt, args...) do { printf("%s(): ", __func__);   \
51     printf(fmt,##args); } while (0)
52 #else
53 #define debugf(fmt, args...)
54 #endif
55
56 #define FDT_RANGES_CELLS        ((3 + 3 + 2) * 2)
57
58 static void
59 fdt_pci_range_dump(struct fdt_pci_range *range)
60 {
61 #ifdef DEBUG
62         printf("\n");
63         printf("  base_pci = 0x%08lx\n", range->base_pci);
64         printf("  base_par = 0x%08lx\n", range->base_parent);
65         printf("  len      = 0x%08lx\n", range->len);
66 #endif
67 }
68
69 int
70 fdt_pci_ranges_decode(phandle_t node, struct fdt_pci_range *io_space,
71     struct fdt_pci_range *mem_space)
72 {
73         pcell_t ranges[FDT_RANGES_CELLS];
74         struct fdt_pci_range *pci_space;
75         pcell_t addr_cells, size_cells, par_addr_cells;
76         pcell_t *rangesptr;
77         pcell_t cell0, cell1, cell2;
78         int tuple_size, tuples, i, rv, offset_cells, len;
79
80         /*
81          * Retrieve 'ranges' property.
82          */
83         if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
84                 return (EINVAL);
85         if (addr_cells != 3 || size_cells != 2)
86                 return (ERANGE);
87
88         par_addr_cells = fdt_parent_addr_cells(node);
89         if (par_addr_cells > 3)
90                 return (ERANGE);
91
92         len = OF_getproplen(node, "ranges");
93         if (len > sizeof(ranges))
94                 return (ENOMEM);
95
96         if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0)
97                 return (EINVAL);
98
99         tuple_size = sizeof(pcell_t) * (addr_cells + par_addr_cells +
100             size_cells);
101         tuples = len / tuple_size;
102
103         /*
104          * Initialize the ranges so that we don't have to worry about
105          * having them all defined in the FDT. In particular, it is
106          * perfectly fine not to want I/O space on PCI busses.
107          */
108         bzero(io_space, sizeof(*io_space));
109         bzero(mem_space, sizeof(*mem_space));
110
111         rangesptr = &ranges[0];
112         offset_cells = 0;
113         for (i = 0; i < tuples; i++) {
114                 cell0 = fdt_data_get((void *)rangesptr, 1);
115                 rangesptr++;
116                 cell1 = fdt_data_get((void *)rangesptr, 1);
117                 rangesptr++;
118                 cell2 = fdt_data_get((void *)rangesptr, 1);
119                 rangesptr++;
120
121                 if (cell0 & 0x02000000) {
122                         pci_space = mem_space;
123                 } else if (cell0 & 0x01000000) {
124                         pci_space = io_space;
125                 } else {
126                         rv = ERANGE;
127                         goto out;
128                 }
129
130                 if (par_addr_cells == 3) {
131                         /*
132                          * This is a PCI subnode 'ranges'. Skip cell0 and
133                          * cell1 of this entry and only use cell2.
134                          */
135                         offset_cells = 2;
136                         rangesptr += offset_cells;
137                 }
138
139                 if (fdt_data_verify((void *)rangesptr, par_addr_cells -
140                     offset_cells)) {
141                         rv = ERANGE;
142                         goto out;
143                 }
144                 pci_space->base_parent = fdt_data_get((void *)rangesptr,
145                     par_addr_cells - offset_cells);
146                 rangesptr += par_addr_cells - offset_cells;
147
148                 if (fdt_data_verify((void *)rangesptr, size_cells)) {
149                         rv = ERANGE;
150                         goto out;
151                 }
152                 pci_space->len = fdt_data_get((void *)rangesptr, size_cells);
153                 rangesptr += size_cells;
154
155                 pci_space->base_pci = cell2;
156         }
157         rv = 0;
158 out:
159         return (rv);
160 }
161
162 int
163 fdt_pci_ranges(phandle_t node, struct fdt_pci_range *io_space,
164     struct fdt_pci_range *mem_space)
165 {
166         int err;
167
168         debugf("Processing PCI node: %x\n", node);
169         if ((err = fdt_pci_ranges_decode(node, io_space, mem_space)) != 0) {
170                 debugf("could not decode parent PCI node 'ranges'\n");
171                 return (err);
172         }
173
174         debugf("Post fixup dump:\n");
175         fdt_pci_range_dump(io_space);
176         fdt_pci_range_dump(mem_space);
177         return (0);
178 }
179
180 static int
181 fdt_addr_cells(phandle_t node, int *addr_cells)
182 {
183         pcell_t cell;
184         int cell_size;
185
186         cell_size = sizeof(cell);
187         if (OF_getprop(node, "#address-cells", &cell, cell_size) < cell_size)
188                 return (EINVAL);
189         *addr_cells = fdt32_to_cpu((int)cell);
190
191         if (*addr_cells > 3)
192                 return (ERANGE);
193         return (0);
194 }
195
196 static int
197 fdt_interrupt_cells(phandle_t node)
198 {
199         pcell_t intr_cells;
200
201         if (OF_getprop(node, "#interrupt-cells", &intr_cells,
202             sizeof(intr_cells)) <= 0) {
203                 debugf("no intr-cells defined, defaulting to 1\n");
204                 intr_cells = 1;
205         }
206         intr_cells = fdt32_to_cpu(intr_cells);
207
208         return ((int)intr_cells);
209 }
210
211 int
212 fdt_pci_intr_info(phandle_t node, struct fdt_pci_intr *intr_info)
213 {
214         void *map, *mask;
215         int acells, icells;
216         int error, len;
217
218         error = fdt_addr_cells(node, &acells);
219         if (error)
220                 return (error);
221
222         icells = fdt_interrupt_cells(node);
223
224         /*
225          * Retrieve the interrupt map and mask properties.
226          */
227         len = OF_getprop_alloc(node, "interrupt-map-mask", 1, &mask);
228         if (len / sizeof(pcell_t) != (acells + icells)) {
229                 debugf("bad mask len = %d\n", len);
230                 goto err;
231         }
232
233         len = OF_getprop_alloc(node, "interrupt-map", 1, &map);
234         if (len <= 0) {
235                 debugf("bad map len = %d\n", len);
236                 goto err;
237         }
238
239         intr_info->map_len = len;
240         intr_info->map = map;
241         intr_info->mask = mask;
242         intr_info->addr_cells = acells;
243         intr_info->intr_cells = icells;
244
245         debugf("acells=%u, icells=%u, map_len=%u\n", acells, icells, len);
246         return (0);
247
248 err:
249         free(mask, M_OFWPROP);
250         return (ENXIO);
251 }
252
253 int
254 fdt_pci_route_intr(int bus, int slot, int func, int pin,
255     struct fdt_pci_intr *intr_info, int *interrupt)
256 {
257         pcell_t child_spec[4], masked[4];
258         ihandle_t iph;
259         pcell_t intr_par;
260         pcell_t *map_ptr;
261         uint32_t addr;
262         int i, j, map_len;
263         int par_intr_cells, par_addr_cells, child_spec_cells, row_cells;
264         int par_idx, spec_idx, err, trig, pol;
265
266         child_spec_cells = intr_info->addr_cells + intr_info->intr_cells;
267         if (child_spec_cells > sizeof(child_spec) / sizeof(pcell_t))
268                 return (ENOMEM);
269
270         addr = (bus << 16) | (slot << 11) | (func << 8);
271         child_spec[0] = addr;
272         child_spec[1] = 0;
273         child_spec[2] = 0;
274         child_spec[3] = pin;
275
276         map_len = intr_info->map_len;
277         map_ptr = intr_info->map;
278
279         par_idx = child_spec_cells;
280         i = 0;
281         while (i < map_len) {
282                 iph = fdt32_to_cpu(map_ptr[par_idx]);
283                 intr_par = OF_instance_to_package(iph);
284
285                 err = fdt_addr_cells(intr_par, &par_addr_cells);
286                 if (err != 0) {
287                         debugf("could not retrieve intr parent #addr-cells\n");
288                         return (err);
289                 }
290                 par_intr_cells = fdt_interrupt_cells(intr_par);
291
292                 row_cells = child_spec_cells + 1 + par_addr_cells +
293                     par_intr_cells;
294
295                 /*
296                  * Apply mask and look up the entry in interrupt map.
297                  */
298                 for (j = 0; j < child_spec_cells; j++) {
299                         masked[j] = child_spec[j] &
300                             fdt32_to_cpu(intr_info->mask[j]);
301
302                         if (masked[j] != fdt32_to_cpu(map_ptr[j]))
303                                 goto next;
304                 }
305
306                 /*
307                  * Decode interrupt of the parent intr controller.
308                  */
309                 spec_idx = child_spec_cells + 1 + par_addr_cells;
310                 err = fdt_intr_decode(intr_par, &map_ptr[spec_idx],
311                     interrupt, &trig, &pol);
312                 if (err != 0) {
313                         debugf("could not decode interrupt\n");
314                         return (err);
315                 }
316                 debugf("decoded intr = %d, trig = %d, pol = %d\n", *interrupt,
317                     trig, pol);
318
319 #if defined(__powerpc__)
320                 powerpc_config_intr(FDT_MAP_IRQ(intr_par, *interrupt), trig,
321                     pol);
322 #endif
323                 return (0);
324
325 next:
326                 map_ptr += row_cells;
327                 i += (row_cells * sizeof(pcell_t));
328         }
329
330         return (ENXIO);
331 }
332
333 #if defined(__arm__)
334 int
335 fdt_pci_devmap(phandle_t node, struct pmap_devmap *devmap, vm_offset_t io_va,
336     vm_offset_t mem_va)
337 {
338         struct fdt_pci_range io_space, mem_space;
339         int error;
340
341         if ((error = fdt_pci_ranges_decode(node, &io_space, &mem_space)) != 0)
342                 return (error);
343
344         devmap->pd_va = (io_va ? io_va : io_space.base_parent);
345         devmap->pd_pa = io_space.base_parent;
346         devmap->pd_size = io_space.len;
347         devmap->pd_prot = VM_PROT_READ | VM_PROT_WRITE;
348         devmap->pd_cache = PTE_NOCACHE;
349         devmap++;
350
351         devmap->pd_va = (mem_va ? mem_va : mem_space.base_parent);
352         devmap->pd_pa = mem_space.base_parent;
353         devmap->pd_size = mem_space.len;
354         devmap->pd_prot = VM_PROT_READ | VM_PROT_WRITE;
355         devmap->pd_cache = PTE_NOCACHE;
356         return (0);
357 }
358 #endif
359
360 #if 0
361 static int
362 fdt_pci_config_bar(device_t dev, int bus, int slot, int func, int bar)
363 {
364 }
365
366 static int
367 fdt_pci_config_normal(device_t dev, int bus, int slot, int func)
368 {
369         int bar;
370         uint8_t command, intline, intpin;
371
372         command = PCIB_READ_CONFIG(dev, bus, slot, func, PCIR_COMMAND, 1);
373         command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
374         PCIB_WRITE_CONFIG(dev, bus, slot, func, PCIR_COMMAND, command, 1);
375
376         /* Program the base address registers. */
377         bar = 0;
378         while (bar <= PCIR_MAX_BAR_0)
379                 bar += fdt_pci_config_bar(dev, bus, slot, func, bar);
380
381         /* Perform interrupt routing. */
382         intpin = PCIB_READ_CONFIG(dev, bus, slot, func, PCIR_INTPIN, 1);
383         intline = fsl_pcib_route_int(dev, bus, slot, func, intpin);
384         PCIB_WRITE_CONFIG(dev, bus, slot, func, PCIR_INTLINE, intline, 1);
385
386         command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
387         PCIB_WRITE_CONFIG(dev, bus, slot, func, PCIR_COMMAND, command, 1);
388 }
389
390 static int
391 fdt_pci_config_bridge(device_t dev, int bus, int secbus, int slot, int func)
392 {
393         int maxbar;
394         uint8_t command;
395
396         command = PCIB_READ_CONFIG(dev, bus, slot, func, PCIR_COMMAND, 1);
397         command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
398         PCIB_WRITE_CONFIG(dev, bus, slot, func, PCIR_COMMAND, command, 1);
399
400         /* Program the base address registers. */
401                         maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6;
402                         bar = 0;
403                         while (bar < maxbar)
404                                 bar += fsl_pcib_init_bar(sc, bus, slot, func,
405                                     bar);
406
407                         /* Perform interrupt routing. */
408                         intpin = fsl_pcib_read_config(sc->sc_dev, bus, slot,
409                             func, PCIR_INTPIN, 1);
410                         intline = fsl_pcib_route_int(sc, bus, slot, func,
411                             intpin);
412                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
413                             PCIR_INTLINE, intline, 1);
414
415                         command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
416                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
417                             PCIR_COMMAND, command, 1);
418
419                         /*
420                          * Handle PCI-PCI bridges
421                          */
422                         class = fsl_pcib_read_config(sc->sc_dev, bus, slot,
423                             func, PCIR_CLASS, 1);
424                         subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot,
425                             func, PCIR_SUBCLASS, 1);
426
427                         /* Allow only proper PCI-PCI briges */
428                         if (class != PCIC_BRIDGE)
429                                 continue;
430                         if (subclass != PCIS_BRIDGE_PCI)
431                                 continue;
432
433                         secbus++;
434
435                         /* Program I/O decoder. */
436                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
437                             PCIR_IOBASEL_1, sc->sc_ioport.rm_start >> 8, 1);
438                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
439                             PCIR_IOLIMITL_1, sc->sc_ioport.rm_end >> 8, 1);
440                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
441                             PCIR_IOBASEH_1, sc->sc_ioport.rm_start >> 16, 2);
442                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
443                             PCIR_IOLIMITH_1, sc->sc_ioport.rm_end >> 16, 2);
444
445                         /* Program (non-prefetchable) memory decoder. */
446                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
447                             PCIR_MEMBASE_1, sc->sc_iomem.rm_start >> 16, 2);
448                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
449                             PCIR_MEMLIMIT_1, sc->sc_iomem.rm_end >> 16, 2);
450
451                         /* Program prefetchable memory decoder. */
452                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
453                             PCIR_PMBASEL_1, 0x0010, 2);
454                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
455                             PCIR_PMLIMITL_1, 0x000f, 2);
456                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
457                             PCIR_PMBASEH_1, 0x00000000, 4);
458                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
459                             PCIR_PMLIMITH_1, 0x00000000, 4);
460
461                         /* Read currect bus register configuration */
462                         old_pribus = fsl_pcib_read_config(sc->sc_dev, bus,
463                             slot, func, PCIR_PRIBUS_1, 1);
464                         old_secbus = fsl_pcib_read_config(sc->sc_dev, bus,
465                             slot, func, PCIR_SECBUS_1, 1);
466                         old_subbus = fsl_pcib_read_config(sc->sc_dev, bus,
467                             slot, func, PCIR_SUBBUS_1, 1);
468
469                         if (bootverbose)
470                                 printf("PCI: reading firmware bus numbers for "
471                                     "secbus = %d (bus/sec/sub) = (%d/%d/%d)\n",
472                                     secbus, old_pribus, old_secbus, old_subbus);
473
474                         new_pribus = bus;
475                         new_secbus = secbus;
476
477                         secbus = fsl_pcib_init(sc, secbus,
478                             (subclass == PCIS_BRIDGE_PCI) ? PCI_SLOTMAX : 0);
479
480                         new_subbus = secbus;
481
482                         if (bootverbose)
483                                 printf("PCI: translate firmware bus numbers "
484                                     "for secbus %d (%d/%d/%d) -> (%d/%d/%d)\n",
485                                     secbus, old_pribus, old_secbus, old_subbus,
486                                     new_pribus, new_secbus, new_subbus);
487
488                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
489                             PCIR_PRIBUS_1, new_pribus, 1);
490                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
491                             PCIR_SECBUS_1, new_secbus, 1);
492                         fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
493                             PCIR_SUBBUS_1, new_subbus, 1);
494
495 }
496
497 static int
498 fdt_pci_config_slot(device_t dev, int bus, int secbus, int slot)
499 {
500         int func, maxfunc;
501         uint16_t vendor;
502         uint8_t hdrtype;
503
504         maxfunc = 0;
505         for (func = 0; func <= maxfunc; func++) {
506                 hdrtype = PCIB_READ_CONFIG(dev, bus, slot, func,
507                     PCIR_HDRTYPE, 1);
508                 if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
509                         continue;
510                 if (func == 0 && (hdrtype & PCIM_MFDEV))
511                         maxfunc = PCI_FUNCMAX;
512
513                 vendor = PCIB_READ_CONFIG(dev, bus, slot, func,
514                     PCIR_VENDOR, 2);
515                 if (vendor == 0xffff)
516                         continue;
517
518                 if ((hdrtype & PCIM_HDRTYPE) == PCIM_HDRTYPE_NORMAL)
519                         fdt_pci_config_normal(dev, bus, slot, func);
520                 else
521                         secbus = fdt_pci_config_bridge(dev, bus, secbus,
522                             slot, func);
523         }
524
525         return (secbus);
526 }
527
528 static int
529 fdt_pci_config_bus(device_t dev, int bus, int maxslot)
530 {
531         int func, maxfunc, secbus, slot;
532
533         secbus = bus;
534         for (slot = 0; slot <= maxslot; slot++)
535                 secbus = fdt_pci_config_slot(dev, bus, secbus, slot);
536
537         return (secbus);
538 }
539
540 int
541 fdt_pci_config_domain(device_t dev)
542 {
543         pcell_t bus_range[2];
544         phandle_t root;
545         int bus, error, maxslot;
546
547         root = ofw_bus_get_node(dev);
548         if (root == 0)
549                 return (EINVAL);
550         if (!fdt_is_type(root, "pci"))
551                 return (EINVAL);
552
553         /*
554          * Determine the bus number of the root in this domain.
555          * Lacking any information, this will be bus 0.
556          * Write the bus number to the bus device, using the IVAR.
557          */
558         if ((OF_getprop(root, "bus-range", bus_range, sizeof(bus_range)) <= 0)
559                 bus = 0;
560         else
561                 bus = fdt32_to_cpu(bus_range[0]);
562
563         error = BUS_WRITE_IVAR(dev, NULL, PCIB_IVAR_BUS, bus);
564         if (error)
565                 return (error);
566
567         /* Get the maximum slot number for bus-enumeration. */
568         maxslot = PCIB_MAXSLOTS(dev);
569
570         bus = fdt_pci_config_bus(dev, bus, maxslot);
571         return (0);
572 }
573 #endif