]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/arm/mv/mv_pci.c
MFC r362623:
[FreeBSD/stable/8.git] / sys / arm / mv / mv_pci.c
1 /*-
2  * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
3  * All rights reserved.
4  *
5  * Developed by Semihalf.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of MARVELL nor the names of contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 /*
33  * Marvell integrated PCI/PCI-Express controller driver.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/module.h>
45 #include <sys/mutex.h>
46 #include <sys/queue.h>
47 #include <sys/bus.h>
48 #include <sys/rman.h>
49 #include <sys/endian.h>
50
51 #include <vm/vm.h>
52 #include <vm/pmap.h>
53
54 #include <dev/pci/pcivar.h>
55 #include <dev/pci/pcireg.h>
56 #include <dev/pci/pcib_private.h>
57
58 #include "pcib_if.h"
59
60 #include <machine/resource.h>
61 #include <machine/bus.h>
62
63 #include <arm/mv/mvreg.h>
64 #include <arm/mv/mvvar.h>
65
66 #define PCI_CFG_ENA             (1 << 31)
67 #define PCI_CFG_BUS(bus)        (((bus) & 0xff) << 16)
68 #define PCI_CFG_DEV(dev)        (((dev) & 0x1f) << 11)
69 #define PCI_CFG_FUN(fun)        (((fun) & 0x7) << 8)
70 #define PCI_CFG_PCIE_REG(reg)   ((reg) & 0xfc)
71
72 #define PCI_REG_CFG_ADDR        0x0C78
73 #define PCI_REG_CFG_DATA        0x0C7C
74 #define PCI_REG_P2P_CONF        0x1D14
75
76 #define PCIE_REG_CFG_ADDR       0x18F8
77 #define PCIE_REG_CFG_DATA       0x18FC
78 #define PCIE_REG_CONTROL        0x1A00
79 #define   PCIE_CTRL_LINK1X      0x00000001
80 #define PCIE_REG_STATUS         0x1A04
81 #define PCIE_REG_IRQ_MASK       0x1910
82
83 #define STATUS_LINK_DOWN        1
84 #define STATUS_BUS_OFFS         8
85 #define STATUS_BUS_MASK         (0xFF << STATUS_BUS_OFFS)
86 #define STATUS_DEV_OFFS         16
87 #define STATUS_DEV_MASK         (0x1F << STATUS_DEV_OFFS)
88
89 #define P2P_CONF_BUS_OFFS       16
90 #define P2P_CONF_BUS_MASK       (0xFF << P2P_CONF_BUS_OFFS)
91 #define P2P_CONF_DEV_OFFS       24
92 #define P2P_CONF_DEV_MASK       (0x1F << P2P_CONF_DEV_OFFS)
93
94 #define PCI_VENDORID_MRVL       0x11AB
95
96 struct pcib_mbus_softc {
97         device_t        sc_dev;
98
99         struct rman     sc_iomem_rman;
100         bus_addr_t      sc_iomem_base;
101         bus_addr_t      sc_iomem_size;
102         bus_addr_t      sc_iomem_alloc;         /* Next allocation. */
103
104         struct rman     sc_ioport_rman;
105         bus_addr_t      sc_ioport_base;
106         bus_addr_t      sc_ioport_size;
107         bus_addr_t      sc_ioport_alloc;        /* Next allocation. */
108
109         struct resource *sc_res;
110         bus_space_handle_t sc_bsh;
111         bus_space_tag_t sc_bst;
112         int             sc_rid;
113
114         int             sc_busnr;               /* Host bridge bus number */
115         int             sc_devnr;               /* Host bridge device number */
116
117         const struct obio_pci *sc_info;
118 };
119
120 static void pcib_mbus_identify(driver_t *driver, device_t parent);
121 static int pcib_mbus_probe(device_t);
122 static int pcib_mbus_attach(device_t);
123
124 static struct resource *pcib_mbus_alloc_resource(device_t, device_t, int, int *,
125     u_long, u_long, u_long, u_int);
126 static int pcib_mbus_release_resource(device_t, device_t, int, int,
127     struct resource *);
128 static int pcib_mbus_read_ivar(device_t, device_t, int, uintptr_t *);
129 static int pcib_mbus_write_ivar(device_t, device_t, int, uintptr_t);
130
131 static int pcib_mbus_maxslots(device_t);
132 static uint32_t pcib_mbus_read_config(device_t, u_int, u_int, u_int, u_int,
133     int);
134 static void pcib_mbus_write_config(device_t, u_int, u_int, u_int, u_int,
135     uint32_t, int);
136 static int pcib_mbus_init(struct pcib_mbus_softc *sc, int bus, int maxslot);
137 static int pcib_mbus_init_bar(struct pcib_mbus_softc *sc, int bus, int slot,
138     int func, int barno);
139 static void pcib_mbus_init_bridge(struct pcib_mbus_softc *sc, int bus, int slot,
140     int func);
141 static int pcib_mbus_init_resources(struct pcib_mbus_softc *sc, int bus,
142     int slot, int func, int hdrtype);
143
144 /*
145  * Bus interface definitions.
146  */
147 static device_method_t pcib_mbus_methods[] = {
148         /* Device interface */
149         DEVMETHOD(device_identify,              pcib_mbus_identify),
150         DEVMETHOD(device_probe,                 pcib_mbus_probe),
151         DEVMETHOD(device_attach,                pcib_mbus_attach),
152
153         /* Bus interface */
154         DEVMETHOD(bus_read_ivar,                pcib_mbus_read_ivar),
155         DEVMETHOD(bus_write_ivar,               pcib_mbus_write_ivar),
156         DEVMETHOD(bus_alloc_resource,           pcib_mbus_alloc_resource),
157         DEVMETHOD(bus_release_resource,         pcib_mbus_release_resource),
158         DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
159         DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
160         DEVMETHOD(bus_setup_intr,               bus_generic_setup_intr),
161         DEVMETHOD(bus_teardown_intr,            bus_generic_teardown_intr),
162
163         /* pcib interface */
164         DEVMETHOD(pcib_maxslots,                pcib_mbus_maxslots),
165         DEVMETHOD(pcib_read_config,             pcib_mbus_read_config),
166         DEVMETHOD(pcib_write_config,            pcib_mbus_write_config),
167         DEVMETHOD(pcib_route_interrupt,         pcib_route_interrupt),
168
169         DEVMETHOD_END
170 };
171
172 static driver_t pcib_mbus_driver = {
173         "pcib",
174         pcib_mbus_methods,
175         sizeof(struct pcib_mbus_softc),
176 };
177
178 devclass_t pcib_devclass;
179
180 DRIVER_MODULE(pcib, mbus, pcib_mbus_driver, pcib_devclass, 0, 0);
181
182 static struct mtx pcicfg_mtx;
183
184 static inline void
185 pcib_write_irq_mask(struct pcib_mbus_softc *sc, uint32_t mask)
186 {
187
188         if (!sc->sc_info->op_type != MV_TYPE_PCI)
189                 return;
190
191         bus_space_write_4(sc->sc_bst, sc->sc_bsh,
192             PCIE_REG_IRQ_MASK, mask);
193 }
194
195 static void
196 pcib_mbus_hw_cfginit(void)
197 {
198         static int opened = 0;
199
200         if (opened)
201                 return;
202
203         mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN);
204         opened = 1;
205 }
206
207 static uint32_t
208 pcib_mbus_hw_cfgread(struct pcib_mbus_softc *sc, u_int bus, u_int slot,
209     u_int func, u_int reg, int bytes)
210 {
211         uint32_t addr, data, ca, cd;
212
213         ca = (sc->sc_info->op_type != MV_TYPE_PCI) ?
214             PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
215         cd = (sc->sc_info->op_type != MV_TYPE_PCI) ?
216             PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
217         addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
218             PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
219
220         mtx_lock_spin(&pcicfg_mtx);
221         bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
222
223         data = ~0;
224         switch (bytes) {
225         case 1:
226                 data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
227                     cd + (reg & 3));
228                 break;
229         case 2:
230                 data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh,
231                     cd + (reg & 2)));
232                 break;
233         case 4:
234                 data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
235                     cd));
236                 break;
237         }
238         mtx_unlock_spin(&pcicfg_mtx);
239         return (data);
240 }
241
242 static void
243 pcib_mbus_hw_cfgwrite(struct pcib_mbus_softc *sc, u_int bus, u_int slot,
244     u_int func, u_int reg, uint32_t data, int bytes)
245 {
246         uint32_t addr, ca, cd;
247
248         ca = (sc->sc_info->op_type != MV_TYPE_PCI) ?
249             PCIE_REG_CFG_ADDR : PCI_REG_CFG_ADDR;
250         cd = (sc->sc_info->op_type != MV_TYPE_PCI) ?
251             PCIE_REG_CFG_DATA : PCI_REG_CFG_DATA;
252         addr = PCI_CFG_ENA | PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) |
253             PCI_CFG_FUN(func) | PCI_CFG_PCIE_REG(reg);
254
255         mtx_lock_spin(&pcicfg_mtx);
256         bus_space_write_4(sc->sc_bst, sc->sc_bsh, ca, addr);
257
258         switch (bytes) {
259         case 1:
260                 bus_space_write_1(sc->sc_bst, sc->sc_bsh,
261                     cd + (reg & 3), data);
262                 break;
263         case 2:
264                 bus_space_write_2(sc->sc_bst, sc->sc_bsh,
265                     cd + (reg & 2), htole16(data));
266                 break;
267         case 4:
268                 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
269                     cd, htole32(data));
270                 break;
271         }
272         mtx_unlock_spin(&pcicfg_mtx);
273 }
274
275 static int
276 pcib_mbus_maxslots(device_t dev)
277 {
278         struct pcib_mbus_softc *sc = device_get_softc(dev);
279
280         return ((sc->sc_info->op_type != MV_TYPE_PCI) ? 1 : PCI_SLOTMAX);
281 }
282
283 static uint32_t
284 pcib_mbus_read_config(device_t dev, u_int bus, u_int slot, u_int func,
285     u_int reg, int bytes)
286 {
287         struct pcib_mbus_softc *sc = device_get_softc(dev);
288
289         /* Skip self */
290         if (bus == sc->sc_busnr && slot == sc->sc_devnr)
291                 return (~0U);
292
293         return (pcib_mbus_hw_cfgread(sc, bus, slot, func, reg, bytes));
294 }
295
296 static void
297 pcib_mbus_write_config(device_t dev, u_int bus, u_int slot, u_int func,
298     u_int reg, uint32_t val, int bytes)
299 {
300         struct pcib_mbus_softc *sc = device_get_softc(dev);
301
302         /* Skip self */
303         if (bus == sc->sc_busnr && slot == sc->sc_devnr)
304                 return;
305
306         pcib_mbus_hw_cfgwrite(sc, bus, slot, func, reg, val, bytes);
307 }
308
309 static void
310 pcib_mbus_add_child(driver_t *driver, device_t parent, struct pcib_mbus_softc *sc)
311 {
312         device_t child;
313         int error;
314
315         /* Configure CPU decoding windows */
316         error = decode_win_cpu_set(sc->sc_info->op_io_win_target,
317             sc->sc_info->op_io_win_attr, sc->sc_info->op_io_base,
318             sc->sc_info->op_io_size, -1);
319         if (error < 0) {
320                 device_printf(parent, "Could not set up CPU decode "
321                     "window for PCI IO\n");
322                 return;
323         }
324         error = decode_win_cpu_set(sc->sc_info->op_mem_win_target,
325             sc->sc_info->op_mem_win_attr, sc->sc_info->op_mem_base,
326             sc->sc_info->op_mem_size, -1);
327         if (error < 0) {
328                 device_printf(parent, "Could not set up CPU decode "
329                     "windows for PCI MEM\n");
330                 return;
331         }
332
333         /* Create driver instance */
334         child = BUS_ADD_CHILD(parent, 0, driver->name, -1);
335         bus_set_resource(child, SYS_RES_MEMORY, 0,
336             sc->sc_info->op_base, sc->sc_info->op_size);
337         device_set_softc(child, sc);
338 }
339
340 static void
341 pcib_mbus_identify(driver_t *driver, device_t parent)
342 {
343         const struct obio_pci *info = mv_pci_info;
344         struct pcib_mbus_softc *sc;
345         uint32_t control;
346
347         while (info->op_base) {
348                 sc = malloc(driver->size, M_DEVBUF, M_NOWAIT | M_ZERO);
349                 if (sc == NULL) {
350                         device_printf(parent, "Could not allocate pcib "
351                             "memory\n");
352                         break;
353                 }
354                 sc->sc_info = info++;
355
356                 /*
357                  * PCI bridge objects are instantiated immediately. PCI-Express
358                  * bridges require more complicated handling depending on
359                  * platform configuration.
360                  */
361                 if (sc->sc_info->op_type == MV_TYPE_PCI) {
362                         pcib_mbus_add_child(driver, parent, sc);
363                         continue;
364                 }
365
366                 /*
367                  * Read link configuration
368                  */
369                 sc->sc_rid = 0;
370                 sc->sc_res = BUS_ALLOC_RESOURCE(parent, parent, SYS_RES_MEMORY,
371                     &sc->sc_rid, sc->sc_info->op_base, sc->sc_info->op_base +
372                     sc->sc_info->op_size - 1, sc->sc_info->op_size,
373                     RF_ACTIVE);
374                 if (sc->sc_res == NULL) {
375                         device_printf(parent, "Could not map pcib memory\n");
376                         break;
377                 }
378
379                 sc->sc_bst = rman_get_bustag(sc->sc_res);
380                 sc->sc_bsh = rman_get_bushandle(sc->sc_res);
381
382                 control = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
383                     PCIE_REG_CONTROL);
384
385                 BUS_RELEASE_RESOURCE(parent, parent, SYS_RES_MEMORY, sc->sc_rid,
386                     sc->sc_res);
387
388                 /*
389                  * If this PCI-E port (controller) is configured (by the
390                  * underlying firmware) with lane width other than 1x, there
391                  * are auxiliary resources defined for aggregating more width
392                  * on our lane. Skip all such entries as they are not
393                  * standalone ports and must not have a device object
394                  * instantiated.
395                  */
396                 if ((control & PCIE_CTRL_LINK1X) == 0)
397                         while (info->op_base &&
398                             info->op_type == MV_TYPE_PCIE_AGGR_LANE)
399                                 info++;
400
401                 pcib_mbus_add_child(driver, parent, sc);
402         }
403 }
404
405 static int
406 pcib_mbus_probe(device_t self)
407 {
408         char buf[128];
409         struct pcib_mbus_softc *sc;
410         const char *id, *type;
411         uint32_t val;
412         int rv = ENOENT, bus, dev;
413
414         sc = device_get_softc(self);
415
416         sc->sc_rid = 0;
417         sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid,
418             RF_ACTIVE);
419         if (sc->sc_res == NULL) {
420                 device_printf(self, "Could not map memory\n");
421                 return (ENXIO);
422         }
423
424         sc->sc_bst = rman_get_bustag(sc->sc_res);
425         sc->sc_bsh = rman_get_bushandle(sc->sc_res);
426
427         pcib_mbus_hw_cfginit();
428
429         /* Retrieve configuration of the bridge */
430         if (sc->sc_info->op_type == MV_TYPE_PCI) {
431                 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
432                     PCI_REG_P2P_CONF);
433                 bus = sc->sc_busnr = (val & P2P_CONF_BUS_MASK) >>
434                     P2P_CONF_BUS_OFFS;
435                 dev = sc->sc_devnr = (val & P2P_CONF_DEV_MASK) >>
436                     P2P_CONF_DEV_OFFS;
437         } else {
438                 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, PCIE_REG_STATUS);
439                 if (val & STATUS_LINK_DOWN)
440                         goto out;
441                 bus = sc->sc_busnr = (val & STATUS_BUS_MASK) >> STATUS_BUS_OFFS;
442                 dev = sc->sc_devnr = (val & STATUS_DEV_MASK) >> STATUS_DEV_OFFS;
443         }
444
445         val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, PCIR_VENDOR, 2);
446         if (val != PCI_VENDORID_MRVL)
447                 goto out;
448
449         val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, PCIR_DEVICE, 2);
450         switch (val) {
451         case 0x5281:
452                 id = "88F5281";
453                 break;
454         case 0x5182:
455                 id = "88F5182";
456                 break;
457         case 0x6281:
458                 id = "88F6281";
459                 break;
460         case 0x6381:
461                 id = "MV78100 Z0";
462                 break;
463         case 0x7810:
464                 id = "MV78100";
465                 break;
466         case 0x7820:
467                 /*
468                  * According to documentation ID 0x7820 is assigned to MV78200.
469                  * However some MV78100 chips also use it.
470                  */
471                 id = "MV78100/MV78200";
472                 break;
473         default:
474                 device_printf(self, "unknown Marvell PCI bridge: %x\n", val);
475                 goto out;
476         }
477
478         type = "PCI";
479         val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, PCIR_CAP_PTR, 1);
480         while (val != 0) {
481                 val = pcib_mbus_hw_cfgread(sc, bus, dev, 0, val, 2);
482                 switch (val & 0xff) {
483                 case PCIY_PCIX:
484                         type = "PCI-X";
485                         break;
486                 case PCIY_EXPRESS:
487                         type = "PCI-Express";
488                         break;
489                 }
490                 val = (val >> 8) & 0xff;
491         }
492
493         snprintf(buf, sizeof(buf), "Marvell %s %s host controller", id,
494             type);
495         device_set_desc_copy(self, buf);
496         rv = BUS_PROBE_DEFAULT;
497 out:
498         bus_release_resource(self, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
499         return (rv);
500 }
501
502 static int
503 pcib_mbus_attach(device_t self)
504 {
505         struct pcib_mbus_softc *sc;
506         uint32_t val;
507         int err;
508
509         sc = device_get_softc(self);
510         sc->sc_dev = self;
511
512         sc->sc_rid = 0;
513         sc->sc_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &sc->sc_rid,
514             RF_ACTIVE);
515         if (sc->sc_res == NULL) {
516                 device_printf(self, "Could not map memory\n");
517                 return (ENXIO);
518         }
519         sc->sc_bst = rman_get_bustag(sc->sc_res);
520         sc->sc_bsh = rman_get_bushandle(sc->sc_res);
521
522         /* Enable PCI bridge */
523         val = pcib_mbus_hw_cfgread(sc, sc->sc_busnr, sc->sc_devnr, 0,
524             PCIR_COMMAND, 2);
525         val |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
526             PCIM_CMD_PORTEN;
527         pcib_mbus_hw_cfgwrite(sc, sc->sc_busnr, sc->sc_devnr, 0,
528             PCIR_COMMAND, val, 2);
529
530         sc->sc_iomem_base = sc->sc_info->op_mem_base;
531         sc->sc_iomem_size = sc->sc_info->op_mem_size;
532         sc->sc_iomem_alloc = sc->sc_info->op_mem_base;
533
534         sc->sc_ioport_base = sc->sc_info->op_io_base;
535         sc->sc_ioport_size = sc->sc_info->op_io_size;
536         sc->sc_ioport_alloc = sc->sc_info->op_io_base;
537
538         sc->sc_iomem_rman.rm_type = RMAN_ARRAY;
539         err = rman_init(&sc->sc_iomem_rman);
540         if (err)
541                 return (err);
542
543         sc->sc_ioport_rman.rm_type = RMAN_ARRAY;
544         err = rman_init(&sc->sc_ioport_rman);
545         if (err) {
546                 rman_fini(&sc->sc_iomem_rman);
547                 return (err);
548         }
549
550         err = rman_manage_region(&sc->sc_iomem_rman, sc->sc_iomem_base,
551             sc->sc_iomem_base + sc->sc_iomem_size - 1);
552         if (err)
553                 goto error;
554
555         err = rman_manage_region(&sc->sc_ioport_rman, sc->sc_ioport_base,
556             sc->sc_ioport_base + sc->sc_ioport_size - 1);
557         if (err)
558                 goto error;
559
560         err = pcib_mbus_init(sc, sc->sc_busnr, pcib_mbus_maxslots(sc->sc_dev));
561         if (err)
562                 goto error;
563
564         device_add_child(self, "pci", -1);
565         return (bus_generic_attach(self));
566
567 error:
568         rman_fini(&sc->sc_iomem_rman);
569         rman_fini(&sc->sc_ioport_rman);
570         return (err);
571 }
572
573 static int
574 pcib_mbus_init_bar(struct pcib_mbus_softc *sc, int bus, int slot, int func,
575     int barno)
576 {
577         bus_addr_t *allocp, limit;
578         uint32_t addr, bar, mask, size;
579         int reg, width;
580
581         reg = PCIR_BAR(barno);
582         bar = pcib_mbus_read_config(sc->sc_dev, bus, slot, func, reg, 4);
583         if (bar == 0)
584                 return (1);
585
586         /* Calculate BAR size: 64 or 32 bit (in 32-bit units) */
587         width = ((bar & 7) == 4) ? 2 : 1;
588
589         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4);
590         size = pcib_mbus_read_config(sc->sc_dev, bus, slot, func, reg, 4);
591
592         /* Get BAR type and size */
593         if (bar & 1) {
594                 /* I/O port */
595                 allocp = &sc->sc_ioport_alloc;
596                 limit = sc->sc_ioport_base + sc->sc_ioport_size;
597                 size &= ~0x3;
598                 if ((size & 0xffff0000) == 0)
599                         size |= 0xffff0000;
600         } else {
601                 /* Memory */
602                 allocp = &sc->sc_iomem_alloc;
603                 limit = sc->sc_iomem_base + sc->sc_iomem_size;
604                 size &= ~0xF;
605         }
606         mask = ~size;
607         size = mask + 1;
608
609         /* Sanity check (must be a power of 2) */
610         if (size & mask)
611                 return (width);
612
613         addr = (*allocp + mask) & ~mask;
614         if ((*allocp = addr + size) > limit)
615                 return (-1);
616
617         if (bootverbose)
618                 printf("PCI %u:%u:%u: reg %x: size=%08x: addr=%08x\n",
619                     bus, slot, func, reg, size, addr);
620
621         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
622         if (width == 2)
623                 pcib_mbus_write_config(sc->sc_dev, bus, slot, func, reg + 4,
624                     0, 4);
625
626         return (width);
627 }
628
629 static void
630 pcib_mbus_init_bridge(struct pcib_mbus_softc *sc, int bus, int slot, int func)
631 {
632         bus_addr_t io_base, mem_base;
633         uint32_t io_limit, mem_limit;
634         int secbus;
635
636         io_base = sc->sc_info->op_io_base;
637         io_limit = io_base + sc->sc_info->op_io_size - 1;
638         mem_base = sc->sc_info->op_mem_base;
639         mem_limit = mem_base + sc->sc_info->op_mem_size - 1;
640
641         /* Configure I/O decode registers */
642         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEL_1,
643             io_base >> 8, 1);
644         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEH_1,
645             io_base >> 16, 2);
646         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITL_1,
647             io_limit >> 8, 1);
648         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITH_1,
649             io_limit >> 16, 2);
650
651         /* Configure memory decode registers */
652         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMBASE_1,
653             mem_base >> 16, 2);
654         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMLIMIT_1,
655             mem_limit >> 16, 2);
656
657         /* Disable memory prefetch decode */
658         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEL_1,
659             0x10, 2);
660         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEH_1,
661             0x0, 4);
662         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITL_1,
663             0xF, 2);
664         pcib_mbus_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITH_1,
665             0x0, 4);
666
667         secbus = pcib_mbus_read_config(sc->sc_dev, bus, slot, func,
668             PCIR_SECBUS_1, 1);
669
670         /* Configure buses behind the bridge */
671         pcib_mbus_init(sc, secbus, PCI_SLOTMAX);
672 }
673
674 static int
675 pcib_mbus_init_resources(struct pcib_mbus_softc *sc, int bus, int slot,
676     int func, int hdrtype)
677 {
678         const struct obio_pci_irq_map *map = sc->sc_info->op_pci_irq_map;
679         int maxbar = (hdrtype & PCIM_HDRTYPE) ? 0 : 6;
680         int bar = 0, irq = -1;
681         int pin, i;
682
683         /* Program the base address registers */
684         while (bar < maxbar) {
685                 i = pcib_mbus_init_bar(sc, bus, slot, func, bar);
686                 bar += i;
687                 if (i < 0) {
688                         device_printf(sc->sc_dev,
689                             "PCI IO/Memory space exhausted\n");
690                         return (ENOMEM);
691                 }
692         }
693
694         /* Perform interrupt routing */
695         pin = pcib_mbus_read_config(sc->sc_dev, bus, slot, func,
696             PCIR_INTPIN, 1);
697
698         if (map != NULL)
699                 while (map->opim_irq >= 0) {
700                         if ((map->opim_slot == slot || map->opim_slot < 0) &&
701                             (map->opim_pin == pin || map->opim_pin < 0))
702                                 irq = map->opim_irq;
703
704                         map++;
705                 }
706         else
707                 irq = sc->sc_info->op_irq;
708
709         if (irq >= 0)
710                 pcib_mbus_write_config(sc->sc_dev, bus, slot, func,
711                     PCIR_INTLINE, irq, 1);
712         else {
713                 device_printf(sc->sc_dev, "Missing IRQ routing information "
714                     "for PCI device %u:%u:%u\n", bus, slot, func);
715                 return (ENXIO);
716         }
717
718         return (0);
719 }
720
721 static int
722 pcib_mbus_init(struct pcib_mbus_softc *sc, int bus, int maxslot)
723 {
724         int slot, func, maxfunc, error;
725         uint8_t hdrtype, command, class, subclass;
726
727         for (slot = 0; slot <= maxslot; slot++) {
728                 maxfunc = 0;
729                 for (func = 0; func <= maxfunc; func++) {
730                         hdrtype = pcib_mbus_read_config(sc->sc_dev, bus, slot,
731                             func, PCIR_HDRTYPE, 1);
732
733                         if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
734                                 continue;
735
736                         if (func == 0 && (hdrtype & PCIM_MFDEV))
737                                 maxfunc = PCI_FUNCMAX;
738
739                         command = pcib_mbus_read_config(sc->sc_dev, bus, slot,
740                             func, PCIR_COMMAND, 1);
741                         command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN);
742                         pcib_mbus_write_config(sc->sc_dev, bus, slot, func,
743                             PCIR_COMMAND, command, 1);
744
745                         error = pcib_mbus_init_resources(sc, bus, slot, func,
746                             hdrtype);
747
748                         if (error)
749                                 return (error);
750
751                         command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN |
752                             PCIM_CMD_PORTEN;
753                         pcib_mbus_write_config(sc->sc_dev, bus, slot, func,
754                             PCIR_COMMAND, command, 1);
755
756                         /* Handle PCI-PCI bridges */
757                         class = pcib_mbus_read_config(sc->sc_dev, bus, slot,
758                             func, PCIR_CLASS, 1);
759                         subclass = pcib_mbus_read_config(sc->sc_dev, bus, slot,
760                             func, PCIR_SUBCLASS, 1);
761
762                         if (class != PCIC_BRIDGE ||
763                             subclass != PCIS_BRIDGE_PCI)
764                                 continue;
765
766                         pcib_mbus_init_bridge(sc, bus, slot, func);
767                 }
768         }
769
770         /* Enable all ABCD interrupts */
771         pcib_write_irq_mask(sc, (0xF << 24));
772
773         return (0);
774 }
775
776 static struct resource *
777 pcib_mbus_alloc_resource(device_t dev, device_t child, int type, int *rid,
778     u_long start, u_long end, u_long count, u_int flags)
779 {
780         struct pcib_mbus_softc *sc = device_get_softc(dev);
781         struct rman *rm = NULL;
782         struct resource *res;
783
784         switch (type) {
785         case SYS_RES_IOPORT:
786                 rm = &sc->sc_ioport_rman;
787                 break;
788         case SYS_RES_MEMORY:
789                 rm = &sc->sc_iomem_rman;
790                 break;
791         default:
792                 return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
793                     type, rid, start, end, count, flags));
794         };
795
796         res = rman_reserve_resource(rm, start, end, count, flags, child);
797         if (res == NULL)
798                 return (NULL);
799
800         rman_set_rid(res, *rid);
801         rman_set_bustag(res, obio_tag);
802         rman_set_bushandle(res, start);
803
804         if (flags & RF_ACTIVE)
805                 if (bus_activate_resource(child, type, *rid, res)) {
806                         rman_release_resource(res);
807                         return (NULL);
808                 }
809
810         return (res);
811 }
812
813 static int
814 pcib_mbus_release_resource(device_t dev, device_t child, int type, int rid,
815     struct resource *res)
816 {
817
818         if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY)
819                 return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
820                     type, rid, res));
821
822         return (rman_release_resource(res));
823 }
824
825 static int
826 pcib_mbus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
827 {
828         struct pcib_mbus_softc *sc = device_get_softc(dev);
829
830         switch (which) {
831         case PCIB_IVAR_BUS:
832                 *result = sc->sc_busnr;
833                 return (0);
834         case PCIB_IVAR_DOMAIN:
835                 *result = device_get_unit(dev);
836                 return (0);
837         }
838
839         return (ENOENT);
840 }
841
842 static int
843 pcib_mbus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
844 {
845         struct pcib_mbus_softc *sc = device_get_softc(dev);
846
847         switch (which) {
848         case PCIB_IVAR_BUS:
849                 sc->sc_busnr = value;
850                 return (0);
851         }
852
853         return (ENOENT);
854 }