]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/bhndb/bhndb_pci.c
MFV r357783:
[FreeBSD/FreeBSD.git] / sys / dev / bhnd / bhndb / bhndb_pci.c
1 /*-
2  * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
3  * Copyright (c) 2017 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * Portions of this software were developed by Landon Fuller
7  * under sponsorship from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer,
14  *    without modification.
15  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
16  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
17  *    redistribution must be conditioned upon including a substantially
18  *    similar Disclaimer requirement for further binary redistribution.
19  *
20  * NO WARRANTY
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
24  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
25  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
26  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31  * THE POSSIBILITY OF SUCH DAMAGES.
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 /*
38  * PCI-specific implementation for the BHNDB bridge driver.
39  * 
40  * Provides support for bridging from a PCI parent bus to a BHND-compatible
41  * bus (e.g. bcma or siba) via a Broadcom PCI core configured in end-point
42  * mode.
43  * 
44  * This driver handles all initial generic host-level PCI interactions with a
45  * PCI/PCIe bridge core operating in endpoint mode. Once the bridged bhnd(4)
46  * bus has been enumerated, this driver works in tandem with a core-specific
47  * bhnd_pci_hostb driver to manage the PCI core.
48  */
49
50 #include <sys/param.h>
51 #include <sys/kernel.h>
52 #include <sys/bus.h>
53 #include <sys/limits.h>
54 #include <sys/malloc.h>
55 #include <sys/module.h>
56 #include <sys/systm.h>
57
58 #include <dev/pci/pcireg.h>
59 #include <dev/pci/pcivar.h>
60
61 #include <dev/bhnd/bhnd.h>
62 #include <dev/bhnd/bhndreg.h>
63
64 #include <dev/bhnd/bhnd_erom.h>
65 #include <dev/bhnd/bhnd_eromvar.h>
66
67 #include <dev/bhnd/siba/sibareg.h>
68
69 #include <dev/bhnd/cores/pci/bhnd_pcireg.h>
70
71 #include "bhnd_pwrctl_hostb_if.h"
72
73 #include "bhndb_pcireg.h"
74 #include "bhndb_pcivar.h"
75 #include "bhndb_private.h"
76
77 struct bhndb_pci_eio;
78 struct bhndb_pci_probe;
79
80 static int              bhndb_pci_alloc_msi(struct bhndb_pci_softc *sc,
81                             int *msi_count);
82
83 static int              bhndb_pci_add_children(struct bhndb_pci_softc *sc);
84
85 static bhnd_devclass_t  bhndb_expected_pci_devclass(device_t dev);
86 static bool             bhndb_is_pcie_attached(device_t dev);
87
88 static int              bhndb_enable_pci_clocks(device_t dev);
89 static int              bhndb_disable_pci_clocks(device_t dev);
90
91 static int              bhndb_pci_compat_setregwin(device_t dev,
92                             device_t pci_dev, const struct bhndb_regwin *,
93                             bhnd_addr_t);
94 static int              bhndb_pci_fast_setregwin(device_t dev, device_t pci_dev,
95                             const struct bhndb_regwin *, bhnd_addr_t);
96
97 static void             bhndb_pci_write_core(struct bhndb_pci_softc *sc,
98                             bus_size_t offset, uint32_t value, u_int width);
99 static uint32_t         bhndb_pci_read_core(struct bhndb_pci_softc *sc,
100                             bus_size_t offset, u_int width);
101
102 static int              bhndb_pci_srsh_pi_war(struct bhndb_pci_softc *sc,
103                             struct bhndb_pci_probe *probe);
104
105 static bus_addr_t       bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc);
106 static bus_size_t       bhndb_pci_sprom_size(struct bhndb_pci_softc *sc);
107
108 static int              bhndb_pci_probe_alloc(struct bhndb_pci_probe **probe,
109                             device_t dev, bhnd_devclass_t pci_devclass);
110 static void             bhndb_pci_probe_free(struct bhndb_pci_probe *probe);
111
112 static int              bhndb_pci_probe_copy_core_table(
113                             struct bhndb_pci_probe *probe,
114                             struct bhnd_core_info **cores, u_int *ncores);
115 static void             bhndb_pci_probe_free_core_table(
116                             struct bhnd_core_info *cores);
117
118 static void             bhndb_pci_probe_write(struct bhndb_pci_probe *sc,
119                             bhnd_addr_t addr, bhnd_size_t offset,
120                             uint32_t value, u_int width);
121 static uint32_t         bhndb_pci_probe_read(struct bhndb_pci_probe *sc,
122                             bhnd_addr_t addr, bhnd_size_t offset, u_int width);
123
124 static void             bhndb_pci_eio_init(struct bhndb_pci_eio *eio,
125                             struct bhndb_pci_probe *probe);
126 static int              bhndb_pci_eio_map(struct bhnd_erom_io *eio,
127                             bhnd_addr_t addr, bhnd_size_t size);
128 static int              bhndb_pci_eio_tell(struct bhnd_erom_io *eio,
129                             bhnd_addr_t *addr, bhnd_size_t *size);
130 static uint32_t         bhndb_pci_eio_read(struct bhnd_erom_io *eio,
131                             bhnd_size_t offset, u_int width);
132
133 #define BHNDB_PCI_MSI_COUNT     1
134
135 static struct bhndb_pci_quirk   bhndb_pci_quirks[];
136 static struct bhndb_pci_quirk   bhndb_pcie_quirks[];
137 static struct bhndb_pci_quirk   bhndb_pcie2_quirks[];
138
139 static struct bhndb_pci_core bhndb_pci_cores[] = {
140         BHNDB_PCI_CORE(PCI,     bhndb_pci_quirks),
141         BHNDB_PCI_CORE(PCIE,    bhndb_pcie_quirks),
142         BHNDB_PCI_CORE(PCIE2,   bhndb_pcie2_quirks),
143         BHNDB_PCI_CORE_END
144 };
145
146 /* bhndb_pci erom I/O instance state */
147 struct bhndb_pci_eio {
148         struct bhnd_erom_io              eio;
149         bool                             mapped;        /**< true if a valid mapping exists */
150         bhnd_addr_t                      addr;          /**< mapped address */
151         bhnd_size_t                      size;          /**< mapped size */
152         struct bhndb_pci_probe          *probe;         /**< borrowed probe reference */
153 };
154
155 /**
156  * Provides early bus access to the bridged device's cores and core enumeration
157  * table.
158  *
159  * May be safely used during probe or early device attach, prior to calling
160  * bhndb_attach().
161  */
162 struct bhndb_pci_probe {
163         device_t                         dev;           /**< bridge device */
164         device_t                         pci_dev;       /**< parent PCI device */
165         struct bhnd_chipid               cid;           /**< chip identification */
166         struct bhnd_core_info            hostb_core;    /**< PCI bridge core info */
167
168         struct bhndb_pci_eio             erom_io;       /**< erom I/O instance */
169         bhnd_erom_class_t               *erom_class;    /**< probed erom class */
170         bhnd_erom_t                     *erom;          /**< erom parser */
171         struct bhnd_core_info           *cores;         /**< erom-owned core table */
172         u_int                            ncores;        /**< number of cores */
173
174         const struct bhndb_regwin       *m_win;         /**< mapped register window, or NULL if no mapping */
175         struct resource                 *m_res;         /**< resource containing the register window, or NULL if no window mapped */
176         bhnd_addr_t                      m_target;      /**< base address mapped by m_win */
177         bhnd_addr_t                      m_addr;        /**< mapped address */
178         bhnd_size_t                      m_size;        /**< mapped size */
179         bool                             m_valid;       /**< true if a valid mapping exists, false otherwise */
180
181         struct bhndb_host_resources     *hr;            /**< backing host resources */
182 };
183
184
185 static struct bhndb_pci_quirk bhndb_pci_quirks[] = {
186         /* Backplane interrupt flags must be routed via siba-specific
187          * SIBA_CFG0_INTVEC configuration register; the BHNDB_PCI_INT_MASK
188          * PCI configuration register is unsupported. */
189         {{ BHND_MATCH_CHIP_TYPE         (SIBA) },
190          { BHND_MATCH_CORE_REV          (HWREV_LTE(5)) },
191                 BHNDB_PCI_QUIRK_SIBA_INTVEC },
192
193         /* All PCI core revisions require the SRSH work-around */
194         BHNDB_PCI_QUIRK(HWREV_ANY,      BHNDB_PCI_QUIRK_SRSH_WAR),
195         BHNDB_PCI_QUIRK_END
196 };
197
198 static struct bhndb_pci_quirk bhndb_pcie_quirks[] = {
199         /* All PCIe-G1 core revisions require the SRSH work-around */
200         BHNDB_PCI_QUIRK(HWREV_ANY,      BHNDB_PCI_QUIRK_SRSH_WAR),
201         BHNDB_PCI_QUIRK_END
202 };
203
204 static struct bhndb_pci_quirk bhndb_pcie2_quirks[] = {
205         BHNDB_PCI_QUIRK_END
206 };
207
208 /**
209  * Return the device table entry for @p ci, or NULL if none.
210  */
211 static struct bhndb_pci_core *
212 bhndb_pci_find_core(struct bhnd_core_info *ci)
213 {
214         for (size_t i = 0; !BHNDB_PCI_IS_CORE_END(&bhndb_pci_cores[i]); i++) {
215                 struct bhndb_pci_core *entry = &bhndb_pci_cores[i];
216
217                 if (bhnd_core_matches(ci, &entry->match))
218                         return (entry);
219         }
220
221         return (NULL);
222 }
223
224 /**
225  * Return all quirk flags for the given @p cid and @p ci.
226  */
227 static uint32_t
228 bhndb_pci_get_core_quirks(struct bhnd_chipid *cid, struct bhnd_core_info *ci)
229 {
230         struct bhndb_pci_core   *entry;
231         struct bhndb_pci_quirk  *qtable;
232         uint32_t                 quirks;
233
234         quirks = 0;
235
236         /* No core entry? */
237         if ((entry = bhndb_pci_find_core(ci)) == NULL)
238                 return (quirks);
239
240         /* No quirks? */
241         if ((qtable = entry->quirks) == NULL)
242                 return (quirks);
243
244         for (size_t i = 0; !BHNDB_PCI_IS_QUIRK_END(&qtable[i]); i++) {
245                 struct bhndb_pci_quirk *q = &qtable[i];
246
247                 if (!bhnd_chip_matches(cid, &q->chip_desc))
248                         continue;
249
250                 if (!bhnd_core_matches(ci, &q->core_desc))
251                         continue;
252
253                 quirks |= q->quirks;
254         }
255
256         return (quirks);
257 }
258
259 /** 
260  * Default bhndb_pci implementation of device_probe().
261  * 
262  * Verifies that the parent is a PCI/PCIe device.
263  */
264 static int
265 bhndb_pci_probe(device_t dev)
266 {
267         struct bhndb_pci_probe  *probe;
268         struct bhndb_pci_core   *entry;
269         bhnd_devclass_t          hostb_devclass;
270         device_t                 parent, parent_bus;
271         devclass_t               pci, bus_devclass;
272         int                      error;
273
274         probe = NULL;
275
276         /* Our parent must be a PCI/PCIe device. */
277         pci = devclass_find("pci");
278         parent = device_get_parent(dev);
279         parent_bus = device_get_parent(parent);
280         if (parent_bus == NULL)
281                 return (ENXIO);
282
283         /* The bus device class may inherit from 'pci' */
284         for (bus_devclass = device_get_devclass(parent_bus);
285             bus_devclass != NULL;
286             bus_devclass = devclass_get_parent(bus_devclass))
287         {
288                 if (bus_devclass == pci)
289                         break;
290         }
291
292         if (bus_devclass != pci)
293                 return (ENXIO);
294
295         /* Enable clocks */
296         if ((error = bhndb_enable_pci_clocks(dev)))
297                 return (error);
298
299         /* Identify the chip and enumerate the bridged cores */
300         hostb_devclass = bhndb_expected_pci_devclass(dev);
301         if ((error = bhndb_pci_probe_alloc(&probe, dev, hostb_devclass)))
302                 goto cleanup;
303
304         /* Look for a matching core table entry */
305         if ((entry = bhndb_pci_find_core(&probe->hostb_core)) == NULL) {
306                 error = ENXIO;
307                 goto cleanup;
308         }
309
310         device_set_desc(dev, "PCI-BHND bridge");
311
312         /* fall-through */
313         error = BUS_PROBE_DEFAULT;
314
315 cleanup:
316         if (probe != NULL)
317                 bhndb_pci_probe_free(probe);
318
319         bhndb_disable_pci_clocks(dev);
320
321         return (error);
322 }
323
324 /**
325  * Attempt to allocate MSI interrupts, returning the count in @p msi_count
326  * on success.
327  */
328 static int
329 bhndb_pci_alloc_msi(struct bhndb_pci_softc *sc, int *msi_count)
330 {
331         int error, count;
332
333         /* Is MSI available? */
334         if (pci_msi_count(sc->parent) < BHNDB_PCI_MSI_COUNT)
335                 return (ENXIO);
336
337         /* Allocate expected message count */
338         count = BHNDB_PCI_MSI_COUNT;
339         if ((error = pci_alloc_msi(sc->parent, &count))) {
340                 device_printf(sc->dev, "failed to allocate MSI interrupts: "
341                     "%d\n", error);
342
343                 return (error);
344         }
345
346         if (count < BHNDB_PCI_MSI_COUNT) {
347                 pci_release_msi(sc->parent);
348                 return (ENXIO);
349         }
350
351         *msi_count = count;
352         return (0);
353 }
354
355 static int
356 bhndb_pci_attach(device_t dev)
357 {
358         struct bhndb_pci_softc  *sc;
359         struct bhnd_chipid       cid;
360         struct bhnd_core_info   *cores, hostb_core;
361         bhnd_erom_class_t       *erom_class;
362         struct bhndb_pci_probe  *probe;
363         u_int                    ncores;
364         int                      irq_rid;
365         int                      error;
366
367         sc = device_get_softc(dev);
368         sc->dev = dev;
369         sc->parent = device_get_parent(dev);
370         sc->pci_devclass = bhndb_expected_pci_devclass(dev);
371         sc->pci_quirks = 0;
372         sc->set_regwin = NULL;
373
374         BHNDB_PCI_LOCK_INIT(sc);
375
376         probe = NULL;
377         cores = NULL;
378
379         /* Enable PCI bus mastering */
380         pci_enable_busmaster(sc->parent);
381
382         /* Enable clocks (if required by this hardware) */
383         if ((error = bhndb_enable_pci_clocks(sc->dev)))
384                 goto cleanup;
385
386         /* Identify the chip and enumerate the bridged cores */
387         error = bhndb_pci_probe_alloc(&probe, dev, sc->pci_devclass);
388         if (error)
389                 goto cleanup;
390
391         sc->pci_quirks = bhndb_pci_get_core_quirks(&probe->cid,
392             &probe->hostb_core);
393
394         /* Select the appropriate register window handler */
395         if (probe->cid.chip_type == BHND_CHIPTYPE_SIBA) {
396                 sc->set_regwin = bhndb_pci_compat_setregwin;
397         } else {
398                 sc->set_regwin = bhndb_pci_fast_setregwin;
399         }
400
401         /*
402          * Fix up our PCI base address in the SPROM shadow, if necessary.
403          * 
404          * This must be done prior to accessing any static register windows
405          * that map the PCI core.
406          */
407         if ((error = bhndb_pci_srsh_pi_war(sc, probe)))
408                 goto cleanup;
409
410         /* Set up PCI interrupt handling */
411         if (bhndb_pci_alloc_msi(sc, &sc->msi_count) == 0) {
412                 /* MSI uses resource IDs starting at 1 */
413                 irq_rid = 1;
414
415                 device_printf(dev, "Using MSI interrupts on %s\n",
416                     device_get_nameunit(sc->parent));
417         } else {
418                 sc->msi_count = 0;
419                 irq_rid = 0;
420
421                 device_printf(dev, "Using INTx interrupts on %s\n",
422                     device_get_nameunit(sc->parent));
423         }
424
425         sc->isrc = bhndb_alloc_intr_isrc(sc->parent, irq_rid, 0, RM_MAX_END, 1,
426             RF_SHAREABLE | RF_ACTIVE);
427         if (sc->isrc == NULL) {
428                 device_printf(sc->dev, "failed to allocate interrupt "
429                     "resource\n");
430                 error = ENXIO;
431                 goto cleanup;
432         }
433
434         /*
435          * Copy out the probe results and then free our probe state, releasing
436          * its exclusive ownership of host bridge resources.
437          * 
438          * This must be done prior to full configuration of the bridge via
439          * bhndb_attach().
440          */
441         cid = probe->cid;
442         erom_class = probe->erom_class;
443         hostb_core = probe->hostb_core;
444
445         error = bhndb_pci_probe_copy_core_table(probe, &cores, &ncores);
446         if (error) {
447                 cores = NULL;
448                 goto cleanup;
449         }
450
451         bhndb_pci_probe_free(probe);
452         probe = NULL;
453
454         /* Perform bridge attach */
455         error = bhndb_attach(dev, &cid, cores, ncores, &hostb_core, erom_class);
456         if (error)
457                 goto cleanup;
458
459         /* Add any additional child devices */
460         if ((error = bhndb_pci_add_children(sc)))
461                 goto cleanup;
462
463         /* Probe and attach our children */
464         if ((error = bus_generic_attach(dev)))
465                 goto cleanup;
466
467         bhndb_pci_probe_free_core_table(cores);
468
469         return (0);
470
471 cleanup:
472         device_delete_children(dev);
473
474         if (sc->isrc != NULL)
475                 bhndb_free_intr_isrc(sc->isrc);
476
477         if (sc->msi_count > 0)
478                 pci_release_msi(sc->parent);
479
480         if (cores != NULL)
481                 bhndb_pci_probe_free_core_table(cores);
482
483         if (probe != NULL)
484                 bhndb_pci_probe_free(probe);
485
486         bhndb_disable_pci_clocks(sc->dev);
487
488         pci_disable_busmaster(sc->parent);
489
490         BHNDB_PCI_LOCK_DESTROY(sc);
491
492         return (error);
493 }
494
495 static int
496 bhndb_pci_detach(device_t dev)
497 {
498         struct bhndb_pci_softc  *sc;
499         int                      error;
500
501         sc = device_get_softc(dev);
502
503         /* Attempt to detach our children */
504         if ((error = bus_generic_detach(dev)))
505                 return (error);
506
507         /* Perform generic bridge detach */
508         if ((error = bhndb_generic_detach(dev)))
509                 return (error);
510
511         /* Disable clocks (if required by this hardware) */
512         if ((error = bhndb_disable_pci_clocks(sc->dev)))
513                 return (error);
514
515         /* Free our interrupt resources */
516         bhndb_free_intr_isrc(sc->isrc);
517
518         /* Release MSI interrupts */
519         if (sc->msi_count > 0)
520                 pci_release_msi(sc->parent);
521
522         /* Disable PCI bus mastering */
523         pci_disable_busmaster(sc->parent);
524
525         BHNDB_PCI_LOCK_DESTROY(sc);
526
527         return (0);
528 }
529
530 static int
531 bhndb_pci_add_children(struct bhndb_pci_softc *sc)
532 {
533         bus_size_t               nv_sz;
534         int                      error;
535
536         /**
537          * If SPROM is mapped directly into BAR0, add child NVRAM
538          * device.
539          */
540         nv_sz = bhndb_pci_sprom_size(sc);
541         if (nv_sz > 0) {
542                 struct bhndb_devinfo    *dinfo;
543                 device_t                 child;
544
545                 if (bootverbose) {
546                         device_printf(sc->dev, "found SPROM (%ju bytes)\n",
547                             (uintmax_t)nv_sz);
548                 }
549
550                 /* Add sprom device, ordered early enough to be available
551                  * before the bridged bhnd(4) bus is attached. */
552                 child = BUS_ADD_CHILD(sc->dev,
553                     BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY, "bhnd_nvram", -1);
554                 if (child == NULL) {
555                         device_printf(sc->dev, "failed to add sprom device\n");
556                         return (ENXIO);
557                 }
558
559                 /* Initialize device address space and resource covering the
560                  * BAR0 SPROM shadow. */
561                 dinfo = device_get_ivars(child);
562                 dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE;
563
564                 error = bus_set_resource(child, SYS_RES_MEMORY, 0,
565                     bhndb_pci_sprom_addr(sc), nv_sz);
566                 if (error) {
567                         device_printf(sc->dev,
568                             "failed to register sprom resources\n");
569                         return (error);
570                 }
571         }
572
573         return (0);
574 }
575
576 static const struct bhndb_regwin *
577 bhndb_pci_sprom_regwin(struct bhndb_pci_softc *sc)
578 {
579         struct bhndb_resources          *bres;
580         const struct bhndb_hwcfg        *cfg;
581         const struct bhndb_regwin       *sprom_win;
582
583         bres = sc->bhndb.bus_res;
584         cfg = bres->cfg;
585
586         sprom_win = bhndb_regwin_find_type(cfg->register_windows,
587             BHNDB_REGWIN_T_SPROM, BHNDB_PCI_V0_BAR0_SPROM_SIZE);
588
589         return (sprom_win);
590 }
591
592 static bus_addr_t
593 bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc)
594 {
595         const struct bhndb_regwin       *sprom_win;
596         struct resource                 *r;
597
598         /* Fetch the SPROM register window */
599         sprom_win = bhndb_pci_sprom_regwin(sc);
600         KASSERT(sprom_win != NULL, ("requested sprom address on PCI_V2+"));
601
602         /* Fetch the associated resource */
603         r = bhndb_host_resource_for_regwin(sc->bhndb.bus_res->res, sprom_win);
604         KASSERT(r != NULL, ("missing resource for sprom window\n"));
605
606         return (rman_get_start(r) + sprom_win->win_offset);
607 }
608
609 static bus_size_t
610 bhndb_pci_sprom_size(struct bhndb_pci_softc *sc)
611 {
612         const struct bhndb_regwin       *sprom_win;
613         uint32_t                         sctl;
614         bus_size_t                       sprom_sz;
615
616         sprom_win = bhndb_pci_sprom_regwin(sc);
617
618         /* PCI_V2 and later devices map SPROM/OTP via ChipCommon */
619         if (sprom_win == NULL)
620                 return (0);
621
622         /* Determine SPROM size */
623         sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4);
624         if (sctl & BHNDB_PCI_SPROM_BLANK)
625                 return (0);
626
627         switch (sctl & BHNDB_PCI_SPROM_SZ_MASK) {
628         case BHNDB_PCI_SPROM_SZ_1KB:
629                 sprom_sz = (1 * 1024);
630                 break;
631
632         case BHNDB_PCI_SPROM_SZ_4KB:
633                 sprom_sz = (4 * 1024);
634                 break;
635
636         case BHNDB_PCI_SPROM_SZ_16KB:
637                 sprom_sz = (16 * 1024);
638                 break;
639
640         case BHNDB_PCI_SPROM_SZ_RESERVED:
641         default:
642                 device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl);
643                 return (0);
644         }
645
646         /* If the device has a larger SPROM than can be addressed via our SPROM
647          * register window, the SPROM image data will still be located within
648          * the window's addressable range */
649         sprom_sz = MIN(sprom_sz, sprom_win->win_size);
650
651         return (sprom_sz);
652 }
653
654 /**
655  * Return the host resource providing a static mapping of the PCI core's
656  * registers.
657  * 
658  * @param       sc              bhndb PCI driver state.
659  * @param       offset          The required readable offset within the PCI core
660  *                              register block.
661  * @param       size            The required readable size at @p offset.
662  * @param[out]  res             On success, the host resource containing our PCI
663  *                              core's register window.
664  * @param[out]  res_offset      On success, the @p offset relative to @p res.
665  *
666  * @retval 0            success
667  * @retval ENXIO        if a valid static register window mapping the PCI core
668  *                      registers is not available.
669  */
670 static int
671 bhndb_pci_get_core_regs(struct bhndb_pci_softc *sc, bus_size_t offset,
672     bus_size_t size, struct resource **res, bus_size_t *res_offset)
673 {
674         const struct bhndb_regwin       *win;
675         struct resource                 *r;
676
677         /* Locate the static register window mapping the requested offset */
678         win = bhndb_regwin_find_core(sc->bhndb.bus_res->cfg->register_windows,
679             sc->pci_devclass, 0, BHND_PORT_DEVICE, 0, 0, offset, size);
680         if (win == NULL) {
681                 device_printf(sc->dev, "missing PCI core register window\n");
682                 return (ENXIO);
683         }
684
685         /* Fetch the resource containing the register window */
686         r = bhndb_host_resource_for_regwin(sc->bhndb.bus_res->res, win);
687         if (r == NULL) {
688                 device_printf(sc->dev, "missing PCI core register resource\n");
689                 return (ENXIO);
690         }
691
692         KASSERT(offset >= win->d.core.offset, ("offset %#jx outside of "
693             "register window", (uintmax_t)offset));
694
695         *res = r;
696         *res_offset = win->win_offset + (offset - win->d.core.offset);
697
698         return (0);
699 }
700
701 /**
702  * Write a 1, 2, or 4 byte data item to the PCI core's registers at @p offset.
703  * 
704  * @param sc            bhndb PCI driver state.
705  * @param offset        register write offset.
706  * @param value         value to be written.
707  * @param width         item width (1, 2, or 4 bytes).
708  */
709 static void
710 bhndb_pci_write_core(struct bhndb_pci_softc *sc, bus_size_t offset,
711     uint32_t value, u_int width)
712 {
713         struct resource *r;
714         bus_size_t       r_offset;
715         int              error;
716
717         error = bhndb_pci_get_core_regs(sc, offset, width, &r, &r_offset);
718         if (error) {
719                 panic("no PCI register window mapping %#jx+%#x: %d",
720                     (uintmax_t)offset, width, error);
721         }
722
723         switch (width) {
724         case 1:
725                 bus_write_1(r, r_offset, value);
726                 break;
727         case 2:
728                 bus_write_2(r, r_offset, value);
729                 break;
730         case 4:
731                 bus_write_4(r, r_offset, value);
732                 break;
733         default:
734                 panic("invalid width: %u", width);
735         }
736 }
737
738 /**
739  * Read a 1, 2, or 4 byte data item from the PCI core's registers
740  * at @p offset.
741  * 
742  * @param sc            bhndb PCI driver state.
743  * @param offset        register read offset.
744  * @param width         item width (1, 2, or 4 bytes).
745  */
746 static uint32_t
747 bhndb_pci_read_core(struct bhndb_pci_softc *sc, bus_size_t offset, u_int width)
748 {
749         struct resource *r;
750         bus_size_t       r_offset;
751         int              error;
752
753         error = bhndb_pci_get_core_regs(sc, offset, width, &r, &r_offset);
754         if (error) {
755                 panic("no PCI register window mapping %#jx+%#x: %d",
756                     (uintmax_t)offset, width, error);
757         }
758
759         switch (width) {
760         case 1:
761                 return (bus_read_1(r, r_offset));
762         case 2:
763                 return (bus_read_2(r, r_offset));
764         case 4:
765                 return (bus_read_4(r, r_offset));
766         default:
767                 panic("invalid width: %u", width);
768         }
769 }
770
771 /**
772  * Fix-up power on defaults for SPROM-less devices.
773  *
774  * On SPROM-less devices, the PCI(e) cores will be initialized with their their
775  * Power-on-Reset defaults; this can leave the BHND_PCI_SRSH_PI value pointing
776  * to the wrong backplane address. This value is used by the PCI core when
777  * performing address translation between static register windows in BAR0 that
778  * map the PCI core's register block, and backplane address space.
779  *
780  * When translating accesses via these BAR0 regions, the PCI bridge determines
781  * the base address of the PCI core by concatenating:
782  *
783  *      [bits]  [source]
784  *      31:16   bits [31:16] of the enumeration space address (e.g. 0x18000000)
785  *      15:12   value of BHND_PCI_SRSH_PI from the PCI core's SPROM shadow
786  *      11:0    bits [11:0] of the PCI bus address
787  *
788  * For example, on a PCI_V0 device, the following PCI core register offsets are
789  * mapped into BAR0:
790  *
791  *      [BAR0 offset]           [description]           [PCI core offset]
792  *      0x1000-0x17FF           sprom shadow            0x800-0xFFF
793  *      0x1800-0x1DFF           device registers        0x000-0x5FF
794  *      0x1E00+0x1FFF           siba config registers   0xE00-0xFFF
795  *
796  * This function checks -- and if necessary, corrects -- the BHND_PCI_SRSH_PI
797  * value in the SPROM shadow. 
798  *
799  * This workaround must applied prior to accessing any static register windows
800  * that map the PCI core.
801  * 
802  * Applies to all PCI and PCIe-G1 core revisions.
803  */
804 static int
805 bhndb_pci_srsh_pi_war(struct bhndb_pci_softc *sc,
806     struct bhndb_pci_probe *probe)
807 {
808         struct bhnd_core_match  md;
809         bhnd_addr_t             pci_addr;
810         bhnd_size_t             pci_size;
811         bus_size_t              srsh_offset;
812         uint16_t                srsh_val, pci_val;
813         uint16_t                val;
814         int                     error;
815
816         if ((sc->pci_quirks & BHNDB_PCI_QUIRK_SRSH_WAR) == 0)
817                 return (0);
818
819         /* Use an equality match descriptor to look up our PCI core's base
820          * address in the EROM */
821         md = bhnd_core_get_match_desc(&probe->hostb_core);
822         error = bhnd_erom_lookup_core_addr(probe->erom, &md, BHND_PORT_DEVICE,
823             0, 0, NULL, &pci_addr, &pci_size);
824         if (error) {
825                 device_printf(sc->dev, "no base address found for the PCI host "
826                     "bridge core: %d\n", error);
827                 return (error);
828         }
829
830         /* Fetch the SPROM SRSH_PI value */
831         srsh_offset = BHND_PCI_SPROM_SHADOW + BHND_PCI_SRSH_PI_OFFSET;
832         val = bhndb_pci_probe_read(probe, pci_addr, srsh_offset, sizeof(val));
833         srsh_val = (val & BHND_PCI_SRSH_PI_MASK) >> BHND_PCI_SRSH_PI_SHIFT;
834
835         /* If it doesn't match PCI core's base address, update the SPROM
836          * shadow */
837         pci_val = (pci_addr & BHND_PCI_SRSH_PI_ADDR_MASK) >>
838             BHND_PCI_SRSH_PI_ADDR_SHIFT;
839         if (srsh_val != pci_val) {
840                 val &= ~BHND_PCI_SRSH_PI_MASK;
841                 val |= (pci_val << BHND_PCI_SRSH_PI_SHIFT);
842                 bhndb_pci_probe_write(probe, pci_addr, srsh_offset, val,
843                     sizeof(val));
844         }
845
846         return (0);
847 }
848
849 static int
850 bhndb_pci_resume(device_t dev)
851 {
852         struct bhndb_pci_softc  *sc;
853         int                      error;
854
855         sc = device_get_softc(dev);
856         
857         /* Enable clocks (if supported by this hardware) */
858         if ((error = bhndb_enable_pci_clocks(sc->dev)))
859                 return (error);
860
861         /* Perform resume */
862         return (bhndb_generic_resume(dev));
863 }
864
865 static int
866 bhndb_pci_suspend(device_t dev)
867 {
868         struct bhndb_pci_softc  *sc;
869         int                      error;
870
871         sc = device_get_softc(dev);
872         
873         /* Disable clocks (if supported by this hardware) */
874         if ((error = bhndb_disable_pci_clocks(sc->dev)))
875                 return (error);
876
877         /* Perform suspend */
878         return (bhndb_generic_suspend(dev));
879 }
880
881 static int
882 bhndb_pci_set_window_addr(device_t dev, const struct bhndb_regwin *rw,
883     bhnd_addr_t addr)
884 {
885         struct bhndb_pci_softc *sc = device_get_softc(dev);
886         return (sc->set_regwin(sc->dev, sc->parent, rw, addr));
887 }
888
889 /**
890  * A siba(4) and bcma(4)-compatible bhndb_set_window_addr implementation.
891  * 
892  * On siba(4) devices, it's possible that writing a PCI window register may
893  * not succeed; it's necessary to immediately read the configuration register
894  * and retry if not set to the desired value.
895  * 
896  * This is not necessary on bcma(4) devices, but other than the overhead of
897  * validating the register, there's no harm in performing the verification.
898  */
899 static int
900 bhndb_pci_compat_setregwin(device_t dev, device_t pci_dev,
901     const struct bhndb_regwin *rw, bhnd_addr_t addr)
902 {
903         int             error;
904         int             reg;
905
906         if (rw->win_type != BHNDB_REGWIN_T_DYN)
907                 return (ENODEV);
908
909         reg = rw->d.dyn.cfg_offset;
910         for (u_int i = 0; i < BHNDB_PCI_BARCTRL_WRITE_RETRY; i++) {
911                 if ((error = bhndb_pci_fast_setregwin(dev, pci_dev, rw, addr)))
912                         return (error);
913
914                 if (pci_read_config(pci_dev, reg, 4) == addr)
915                         return (0);
916
917                 DELAY(10);
918         }
919
920         /* Unable to set window */
921         return (ENODEV);
922 }
923
924 /**
925  * A bcma(4)-only bhndb_set_window_addr implementation.
926  */
927 static int
928 bhndb_pci_fast_setregwin(device_t dev, device_t pci_dev,
929     const struct bhndb_regwin *rw, bhnd_addr_t addr)
930 {
931         /* The PCI bridge core only supports 32-bit addressing, regardless
932          * of the bus' support for 64-bit addressing */
933         if (addr > UINT32_MAX)
934                 return (ERANGE);
935
936         switch (rw->win_type) {
937         case BHNDB_REGWIN_T_DYN:
938                 /* Addresses must be page aligned */
939                 if (addr % rw->win_size != 0)
940                         return (EINVAL);
941
942                 pci_write_config(pci_dev, rw->d.dyn.cfg_offset, addr, 4);
943                 break;
944         default:
945                 return (ENODEV);
946         }
947
948         return (0);
949 }
950
951 static int
952 bhndb_pci_populate_board_info(device_t dev, device_t child,
953     struct bhnd_board_info *info)
954 {
955         struct bhndb_pci_softc  *sc;
956
957         sc = device_get_softc(dev);
958
959         /* 
960          * On a subset of Apple BCM4360 modules, always prefer the
961          * PCI subdevice to the SPROM-supplied boardtype.
962          * 
963          * TODO:
964          * 
965          * Broadcom's own drivers implement this override, and then later use
966          * the remapped BCM4360 board type to determine the required
967          * board-specific workarounds.
968          * 
969          * Without access to this hardware, it's unclear why this mapping
970          * is done, and we must do the same. If we can survey the hardware
971          * in question, it may be possible to replace this behavior with
972          * explicit references to the SPROM-supplied boardtype(s) in our
973          * quirk definitions.
974          */
975         if (pci_get_subvendor(sc->parent) == PCI_VENDOR_APPLE) {
976                 switch (info->board_type) {
977                 case BHND_BOARD_BCM94360X29C:
978                 case BHND_BOARD_BCM94360X29CP2:
979                 case BHND_BOARD_BCM94360X51:
980                 case BHND_BOARD_BCM94360X51P2:
981                         info->board_type = 0;   /* allow override below */
982                         break;
983                 default:
984                         break;
985                 }
986         }
987
988         /* If NVRAM did not supply vendor/type/devid info, provide the PCI
989          * subvendor/subdevice/device values. */
990         if (info->board_vendor == 0)
991                 info->board_vendor = pci_get_subvendor(sc->parent);
992
993         if (info->board_type == 0)
994                 info->board_type = pci_get_subdevice(sc->parent);
995
996         if (info->board_devid == 0)
997                 info->board_devid = pci_get_device(sc->parent);
998
999         return (0);
1000 }
1001
1002 /**
1003  * Examine the bridge device @p dev and return the expected host bridge
1004  * device class.
1005  *
1006  * @param dev The bhndb bridge device
1007  */
1008 static bhnd_devclass_t
1009 bhndb_expected_pci_devclass(device_t dev)
1010 {
1011         if (bhndb_is_pcie_attached(dev))
1012                 return (BHND_DEVCLASS_PCIE);
1013         else
1014                 return (BHND_DEVCLASS_PCI);
1015 }
1016
1017 /**
1018  * Return true if the bridge device @p dev is attached via PCIe,
1019  * false otherwise.
1020  *
1021  * @param dev The bhndb bridge device
1022  */
1023 static bool
1024 bhndb_is_pcie_attached(device_t dev)
1025 {
1026         int reg;
1027
1028         if (pci_find_cap(device_get_parent(dev), PCIY_EXPRESS, &reg) == 0)
1029                 return (true);
1030
1031         return (false);
1032 }
1033
1034 /**
1035  * Enable externally managed clocks, if required.
1036  * 
1037  * Some PCI chipsets (BCM4306, possibly others) chips do not support
1038  * the idle low-power clock. Clocking must be bootstrapped at
1039  * attach/resume by directly adjusting GPIO registers exposed in the
1040  * PCI config space, and correspondingly, explicitly shutdown at
1041  * detach/suspend.
1042  *
1043  * @note This function may be safely called prior to device attach, (e.g.
1044  * from DEVICE_PROBE).
1045  *
1046  * @param dev The bhndb bridge device
1047  */
1048 static int
1049 bhndb_enable_pci_clocks(device_t dev)
1050 {
1051         device_t                pci_dev;
1052         uint32_t                gpio_in, gpio_out, gpio_en;
1053         uint32_t                gpio_flags;
1054         uint16_t                pci_status;
1055
1056         pci_dev = device_get_parent(dev);
1057
1058         /* Only supported and required on PCI devices */
1059         if (bhndb_is_pcie_attached(dev))
1060                 return (0);
1061
1062         /* Read state of XTAL pin */
1063         gpio_in = pci_read_config(pci_dev, BHNDB_PCI_GPIO_IN, 4);
1064         if (gpio_in & BHNDB_PCI_GPIO_XTAL_ON)
1065                 return (0); /* already enabled */
1066
1067         /* Fetch current config */
1068         gpio_out = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUT, 4);
1069         gpio_en = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, 4);
1070
1071         /* Set PLL_OFF/XTAL_ON pins to HIGH and enable both pins */
1072         gpio_flags = (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
1073         gpio_out |= gpio_flags;
1074         gpio_en |= gpio_flags;
1075
1076         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
1077         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
1078         DELAY(1000);
1079
1080         /* Reset PLL_OFF */
1081         gpio_out &= ~BHNDB_PCI_GPIO_PLL_OFF;
1082         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
1083         DELAY(5000);
1084
1085         /* Clear any PCI 'sent target-abort' flag. */
1086         pci_status = pci_read_config(pci_dev, PCIR_STATUS, 2);
1087         pci_status &= ~PCIM_STATUS_STABORT;
1088         pci_write_config(pci_dev, PCIR_STATUS, pci_status, 2);
1089
1090         return (0);
1091 }
1092
1093 /**
1094  * Disable externally managed clocks, if required.
1095  *
1096  * This function may be safely called prior to device attach, (e.g.
1097  * from DEVICE_PROBE).
1098  *
1099  * @param dev The bhndb bridge device
1100  */
1101 static int
1102 bhndb_disable_pci_clocks(device_t dev)
1103 {
1104         device_t        pci_dev;
1105         uint32_t        gpio_out, gpio_en;
1106
1107         pci_dev = device_get_parent(dev);
1108
1109         /* Only supported and required on PCI devices */
1110         if (bhndb_is_pcie_attached(dev))
1111                 return (0);
1112
1113         /* Fetch current config */
1114         gpio_out = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUT, 4);
1115         gpio_en = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, 4);
1116
1117         /* Set PLL_OFF to HIGH, XTAL_ON to LOW. */
1118         gpio_out &= ~BHNDB_PCI_GPIO_XTAL_ON;
1119         gpio_out |= BHNDB_PCI_GPIO_PLL_OFF;
1120         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
1121
1122         /* Enable both output pins */
1123         gpio_en |= (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
1124         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
1125
1126         return (0);
1127 }
1128
1129 static bhnd_clksrc
1130 bhndb_pci_pwrctl_get_clksrc(device_t dev, device_t child,
1131         bhnd_clock clock)
1132 {
1133         struct bhndb_pci_softc  *sc;
1134         uint32_t                 gpio_out;
1135
1136         sc = device_get_softc(dev);
1137
1138         /* Only supported on PCI devices */
1139         if (bhndb_is_pcie_attached(sc->dev))
1140                 return (BHND_CLKSRC_UNKNOWN);
1141
1142         /* Only ILP is supported */
1143         if (clock != BHND_CLOCK_ILP)
1144                 return (BHND_CLKSRC_UNKNOWN);
1145
1146         gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
1147         if (gpio_out & BHNDB_PCI_GPIO_SCS)
1148                 return (BHND_CLKSRC_PCI);
1149         else
1150                 return (BHND_CLKSRC_XTAL);
1151 }
1152
1153 static int
1154 bhndb_pci_pwrctl_gate_clock(device_t dev, device_t child,
1155         bhnd_clock clock)
1156 {
1157         struct bhndb_pci_softc *sc = device_get_softc(dev);
1158
1159         /* Only supported on PCI devices */
1160         if (bhndb_is_pcie_attached(sc->dev))
1161                 return (ENODEV);
1162
1163         /* Only HT is supported */
1164         if (clock != BHND_CLOCK_HT)
1165                 return (ENXIO);
1166
1167         return (bhndb_disable_pci_clocks(sc->dev));
1168 }
1169
1170 static int
1171 bhndb_pci_pwrctl_ungate_clock(device_t dev, device_t child,
1172         bhnd_clock clock)
1173 {
1174         struct bhndb_pci_softc *sc = device_get_softc(dev);
1175
1176         /* Only supported on PCI devices */
1177         if (bhndb_is_pcie_attached(sc->dev))
1178                 return (ENODEV);
1179
1180         /* Only HT is supported */
1181         if (clock != BHND_CLOCK_HT)
1182                 return (ENXIO);
1183
1184         return (bhndb_enable_pci_clocks(sc->dev));
1185 }
1186
1187 /**
1188  * BHNDB_MAP_INTR_ISRC()
1189  */
1190 static int
1191 bhndb_pci_map_intr_isrc(device_t dev, struct resource *irq,
1192     struct bhndb_intr_isrc **isrc)
1193 {
1194         struct bhndb_pci_softc *sc = device_get_softc(dev);
1195
1196         /* There's only one bridged interrupt to choose from */
1197         *isrc = sc->isrc;
1198         return (0);
1199 }
1200
1201 /* siba-specific implementation of BHNDB_ROUTE_INTERRUPTS() */
1202 static int
1203 bhndb_pci_route_siba_interrupts(struct bhndb_pci_softc *sc, device_t child)
1204 {
1205         uint32_t        sbintvec;
1206         u_int           ivec;
1207         int             error;
1208
1209         KASSERT(sc->pci_quirks & BHNDB_PCI_QUIRK_SIBA_INTVEC,
1210             ("route_siba_interrupts not supported by this hardware"));
1211
1212         /* Fetch the sbflag# for the child */
1213         if ((error = bhnd_get_intr_ivec(child, 0, &ivec)))
1214                 return (error);
1215
1216         if (ivec > (sizeof(sbintvec)*8) - 1 /* aka '31' */) {
1217                 /* This should never be an issue in practice */
1218                 device_printf(sc->dev, "cannot route interrupts to high "
1219                     "sbflag# %u\n", ivec);
1220                 return (ENXIO);
1221         }
1222
1223         BHNDB_PCI_LOCK(sc);
1224
1225         sbintvec = bhndb_pci_read_core(sc, SB0_REG_ABS(SIBA_CFG0_INTVEC), 4);
1226         sbintvec |= (1 << ivec);
1227         bhndb_pci_write_core(sc, SB0_REG_ABS(SIBA_CFG0_INTVEC), sbintvec, 4);
1228
1229         BHNDB_PCI_UNLOCK(sc);
1230
1231         return (0);
1232 }
1233
1234 /* BHNDB_ROUTE_INTERRUPTS() */
1235 static int
1236 bhndb_pci_route_interrupts(device_t dev, device_t child)
1237 {
1238         struct bhndb_pci_softc  *sc;
1239         struct bhnd_core_info    core;
1240         uint32_t                 core_bit;
1241         uint32_t                 intmask;
1242
1243         sc = device_get_softc(dev);
1244
1245         if (sc->pci_quirks & BHNDB_PCI_QUIRK_SIBA_INTVEC)
1246                 return (bhndb_pci_route_siba_interrupts(sc, child));
1247
1248         core = bhnd_get_core_info(child);
1249         if (core.core_idx > BHNDB_PCI_SBIM_COREIDX_MAX) {
1250                 /* This should never be an issue in practice */
1251                 device_printf(dev, "cannot route interrupts to high core "
1252                     "index %u\n", core.core_idx);
1253                 return (ENXIO);
1254         }
1255
1256         BHNDB_PCI_LOCK(sc);
1257
1258         core_bit = (1<<core.core_idx) << BHNDB_PCI_SBIM_SHIFT;
1259         intmask = pci_read_config(sc->parent, BHNDB_PCI_INT_MASK, 4);
1260         intmask |= core_bit;
1261         pci_write_config(sc->parent, BHNDB_PCI_INT_MASK, intmask, 4);
1262
1263         BHNDB_PCI_UNLOCK(sc);
1264
1265         return (0);
1266 }
1267
1268 /**
1269  * Using the generic PCI bridge hardware configuration, allocate, initialize
1270  * and return a new bhndb_pci probe state instance.
1271  * 
1272  * On success, the caller assumes ownership of the returned probe instance, and
1273  * is responsible for releasing this reference using bhndb_pci_probe_free().
1274  * 
1275  * @param[out]  probe           On success, the newly allocated probe instance.
1276  * @param       dev             The bhndb_pci bridge device.
1277  * @param       hostb_devclass  The expected device class of the bridge core.
1278  *
1279  * @retval 0            success
1280  * @retval non-zero     if allocating the probe state fails, a regular
1281  *                      unix error code will be returned.
1282  * 
1283  * @note This function requires exclusive ownership over allocating and 
1284  * configuring host bridge resources, and should only be called prior to
1285  * completion of device attach and full configuration of the bridge.
1286  */
1287 static int
1288 bhndb_pci_probe_alloc(struct bhndb_pci_probe **probe, device_t dev,
1289     bhnd_devclass_t hostb_devclass)
1290 {
1291         struct bhndb_pci_probe          *p;
1292         struct bhnd_erom_io             *eio;
1293         const struct bhndb_hwcfg        *hwcfg;
1294         const struct bhnd_chipid        *hint;
1295         device_t                         parent_dev;
1296         int                              error;
1297
1298         parent_dev = device_get_parent(dev);
1299         eio = NULL;
1300
1301         p = malloc(sizeof(*p), M_BHND, M_ZERO|M_WAITOK);
1302         p->dev = dev;
1303         p->pci_dev = parent_dev;
1304
1305         /* Our register window mapping state must be initialized at this point,
1306          * as bhndb_pci_eio will begin making calls into
1307          * bhndb_pci_probe_(read|write|get_mapping) */
1308         p->m_win = NULL;
1309         p->m_res = NULL;
1310         p->m_valid = false;
1311
1312         bhndb_pci_eio_init(&p->erom_io, p);
1313         eio = &p->erom_io.eio;
1314
1315         /* Fetch our chipid hint (if any) and generic hardware configuration */
1316         hwcfg = BHNDB_BUS_GET_GENERIC_HWCFG(parent_dev, dev);
1317         hint = BHNDB_BUS_GET_CHIPID(parent_dev, dev);
1318
1319         /* Allocate our host resources */
1320         error = bhndb_alloc_host_resources(&p->hr, dev, parent_dev, hwcfg);
1321         if (error) {
1322                 p->hr = NULL;
1323                 goto failed;
1324         }
1325
1326         /* Map the first bus core from our bridged bhnd(4) bus */
1327         error = bhnd_erom_io_map(eio, BHND_DEFAULT_CHIPC_ADDR,
1328             BHND_DEFAULT_CORE_SIZE);
1329         if (error)
1330                 goto failed;
1331
1332         /* Probe for a usable EROM class, and read the chip identifier */
1333         p->erom_class = bhnd_erom_probe_driver_classes(
1334             device_get_devclass(dev), eio, hint, &p->cid);
1335         if (p->erom_class == NULL) {
1336                 device_printf(dev, "device enumeration unsupported; no "
1337                     "compatible driver found\n");
1338
1339                 error = ENXIO;
1340                 goto failed;
1341         }
1342
1343         /* Allocate EROM parser */
1344         p->erom = bhnd_erom_alloc(p->erom_class, &p->cid, eio);
1345         if (p->erom == NULL) {
1346                 device_printf(dev, "failed to allocate device enumeration "
1347                     "table parser\n");
1348                 error = ENXIO;
1349                 goto failed;
1350         }
1351
1352         /* The EROM I/O instance is now owned by our EROM parser */
1353         eio = NULL;
1354
1355         /* Read the full core table */
1356         error = bhnd_erom_get_core_table(p->erom, &p->cores, &p->ncores);
1357         if (error) {
1358                 device_printf(p->dev, "error fetching core table: %d\n",
1359                     error);
1360
1361                 p->cores = NULL;
1362                 goto failed;
1363         }
1364
1365         /* Identify the host bridge core */
1366         error = bhndb_find_hostb_core(p->cores, p->ncores, hostb_devclass,
1367             &p->hostb_core);
1368         if (error) {
1369                 device_printf(dev, "failed to identify the host bridge "
1370                     "core: %d\n", error);
1371
1372                 goto failed;
1373         }
1374
1375         *probe = p;
1376         return (0);
1377
1378 failed:
1379         if (eio != NULL) {
1380                 KASSERT(p->erom == NULL, ("I/O instance will be freed by "
1381                     "its owning parser"));
1382
1383                 bhnd_erom_io_fini(eio);
1384         }
1385
1386         if (p->erom != NULL) {
1387                 if (p->cores != NULL)
1388                         bhnd_erom_free_core_table(p->erom, p->cores);
1389
1390                 bhnd_erom_free(p->erom);
1391         } else {
1392                 KASSERT(p->cores == NULL, ("cannot free erom-owned core table "
1393                     "without erom reference"));
1394         }
1395
1396         if (p->hr != NULL)
1397                 bhndb_release_host_resources(p->hr);
1398
1399         free(p, M_BHND);
1400
1401         return (error);
1402 }
1403
1404 /**
1405  * Free the given @p probe instance and any associated host bridge resources.
1406  */
1407 static void
1408 bhndb_pci_probe_free(struct bhndb_pci_probe *probe)
1409 {
1410         bhnd_erom_free_core_table(probe->erom, probe->cores);
1411         bhnd_erom_free(probe->erom);
1412         bhndb_release_host_resources(probe->hr);
1413         free(probe, M_BHND);
1414 }
1415
1416 /**
1417  * Return a copy of probed core table from @p probe.
1418  * 
1419  * @param       probe           The probe instance.
1420  * @param[out]  cores           On success, a copy of the probed core table. The
1421  *                              caller is responsible for freeing this table
1422  *                              bhndb_pci_probe_free_core_table().
1423  * @param[out]  ncores          On success, the number of cores found in
1424  *                              @p cores.
1425  * 
1426  * @retval 0            success
1427  * @retval non-zero     if enumerating the bridged bhnd(4) bus fails, a regular
1428  *                      unix error code will be returned.
1429  */
1430 static int
1431 bhndb_pci_probe_copy_core_table(struct bhndb_pci_probe *probe,
1432     struct bhnd_core_info **cores, u_int *ncores)
1433 {
1434         size_t len = sizeof(**cores) * probe->ncores;
1435
1436         *cores = malloc(len, M_BHND, M_WAITOK);
1437         memcpy(*cores, probe->cores, len);
1438
1439         *ncores = probe->ncores;
1440
1441         return (0);
1442 }
1443
1444 /**
1445  * Free a core table previously returned by bhndb_pci_probe_copy_core_table().
1446  * 
1447  * @param cores The core table to be freed.
1448  */
1449 static void
1450 bhndb_pci_probe_free_core_table(struct bhnd_core_info *cores)
1451 {
1452         free(cores, M_BHND);
1453 }
1454
1455 /**
1456  * Return true if @p addr and @p size are mapped by the dynamic register window
1457  * backing @p probe. 
1458  */
1459 static bool
1460 bhndb_pci_probe_has_mapping(struct bhndb_pci_probe *probe, bhnd_addr_t addr,
1461     bhnd_size_t size)
1462 {
1463         if (!probe->m_valid)
1464                 return (false);
1465
1466         KASSERT(probe->m_win != NULL, ("missing register window"));
1467         KASSERT(probe->m_res != NULL, ("missing regwin resource"));
1468         KASSERT(probe->m_win->win_type == BHNDB_REGWIN_T_DYN,
1469             ("unexpected window type %d", probe->m_win->win_type));
1470
1471         if (addr < probe->m_target)
1472                 return (false);
1473
1474         if (addr >= probe->m_target + probe->m_win->win_size)
1475                 return (false);
1476
1477         if ((probe->m_target + probe->m_win->win_size) - addr < size)
1478                 return (false);
1479
1480         return (true);
1481 }
1482
1483 /**
1484  * Attempt to adjust the dynamic register window backing @p probe to permit
1485  * accessing @p size bytes at @p addr.
1486  * 
1487  * @param       probe           The bhndb_pci probe state to be modified.
1488  * @param       addr            The address at which @p size bytes will mapped.
1489  * @param       size            The number of bytes to be mapped.
1490  * @param[out]  res             On success, will be set to the host resource
1491  *                              mapping @p size bytes at @p addr.
1492  * @param[out]  res_offset      On success, will be set to the offset of @addr
1493  *                              within @p res.
1494  * 
1495  * @retval 0            success
1496  * @retval non-zero     if an error occurs adjusting the backing dynamic
1497  *                      register window.
1498  */
1499 static int
1500 bhndb_pci_probe_map(struct bhndb_pci_probe *probe, bhnd_addr_t addr,
1501     bhnd_size_t offset, bhnd_size_t size, struct resource **res,
1502     bus_size_t *res_offset)
1503 {
1504         const struct bhndb_regwin       *regwin, *regwin_table;
1505         struct resource                 *regwin_res;
1506         bhnd_addr_t                      target;
1507         int                              error;
1508
1509         /* Determine the absolute address */
1510         if (BHND_SIZE_MAX - offset < addr) {
1511                 device_printf(probe->dev, "invalid offset %#jx+%#jx\n", addr,
1512                     offset);
1513                 return (ENXIO);
1514         }
1515
1516         addr += offset;
1517
1518         /* Can we use the existing mapping? */
1519         if (bhndb_pci_probe_has_mapping(probe, addr, size)) {
1520                 *res = probe->m_res;
1521                 *res_offset = (addr - probe->m_target) +
1522                     probe->m_win->win_offset;
1523
1524                 return (0);
1525         }
1526
1527         /* Locate a useable dynamic register window */
1528         regwin_table = probe->hr->cfg->register_windows;
1529         regwin = bhndb_regwin_find_type(regwin_table,
1530             BHNDB_REGWIN_T_DYN, size);
1531         if (regwin == NULL) {
1532                 device_printf(probe->dev, "unable to map %#jx+%#jx; no "
1533                     "usable dynamic register window found\n", addr,
1534                     size);
1535                 return (ENXIO);
1536         }
1537
1538         /* Locate the host resource mapping our register window */
1539         regwin_res = bhndb_host_resource_for_regwin(probe->hr, regwin);
1540         if (regwin_res == NULL) {
1541                 device_printf(probe->dev, "unable to map %#jx+%#jx; no "
1542                     "usable register resource found\n", addr, size);
1543                 return (ENXIO);
1544         }
1545
1546         /* Page-align the target address */
1547         target = addr - (addr % regwin->win_size);
1548
1549         /* Configure the register window */
1550         error = bhndb_pci_compat_setregwin(probe->dev, probe->pci_dev,
1551             regwin, target);
1552         if (error) {
1553                 device_printf(probe->dev, "failed to configure dynamic "
1554                     "register window: %d\n", error);
1555                 return (error);
1556         }
1557
1558         /* Update our mapping state */
1559         probe->m_win = regwin;
1560         probe->m_res = regwin_res;
1561         probe->m_addr = addr;
1562         probe->m_size = size;
1563         probe->m_target = target;
1564         probe->m_valid = true;
1565
1566         *res = regwin_res;
1567         *res_offset = (addr - target) + regwin->win_offset;
1568
1569         return (0);
1570 }
1571
1572 /**
1573  * Write a data item to the bridged address space at the given @p offset from
1574  * @p addr.
1575  *
1576  * A dynamic register window will be used to map @p addr.
1577  * 
1578  * @param probe         The bhndb_pci probe state to be used to perform the
1579  *                      write.
1580  * @param addr          The base address.
1581  * @param offset        The offset from @p addr at which @p value will be
1582  *                      written.
1583  * @param value         The data item to be written.
1584  * @param width         The data item width (1, 2, or 4 bytes).
1585  */
1586 static void
1587 bhndb_pci_probe_write(struct bhndb_pci_probe *probe, bhnd_addr_t addr,
1588     bhnd_size_t offset, uint32_t value, u_int width)
1589 {
1590         struct resource *r;
1591         bus_size_t       res_offset;
1592         int              error;
1593
1594         /* Map the target address */
1595         error = bhndb_pci_probe_map(probe, addr, offset, width, &r,
1596             &res_offset);
1597         if (error) {
1598                 device_printf(probe->dev, "error mapping %#jx+%#jx for "
1599                     "writing: %d\n", addr, offset, error);
1600                 return;
1601         }
1602
1603         /* Perform write */
1604         switch (width) {
1605         case 1:
1606                 return (bus_write_1(r, res_offset, value));
1607         case 2:
1608                 return (bus_write_2(r, res_offset, value));
1609         case 4:
1610                 return (bus_write_4(r, res_offset, value));
1611         default:
1612                 panic("unsupported width: %u", width);
1613         }
1614 }
1615
1616 /**
1617  * Read a data item from the bridged address space at the given @p offset
1618  * from @p addr.
1619  * 
1620  * A dynamic register window will be used to map @p addr.
1621  * 
1622  * @param probe         The bhndb_pci probe state to be used to perform the
1623  *                      read.
1624  * @param addr          The base address.
1625  * @param offset        The offset from @p addr at which to read a data item of
1626  *                      @p width bytes.
1627  * @param width         Item width (1, 2, or 4 bytes).
1628  */
1629 static uint32_t
1630 bhndb_pci_probe_read(struct bhndb_pci_probe *probe, bhnd_addr_t addr,
1631     bhnd_size_t offset, u_int width)
1632 {
1633         struct resource *r;
1634         bus_size_t       res_offset;
1635         int              error;
1636
1637         /* Map the target address */
1638         error = bhndb_pci_probe_map(probe, addr, offset, width, &r,
1639             &res_offset);
1640         if (error) {
1641                 device_printf(probe->dev, "error mapping %#jx+%#jx for "
1642                     "reading: %d\n", addr, offset, error);
1643                 return (UINT32_MAX);
1644         }
1645
1646         /* Perform read */
1647         switch (width) {
1648         case 1:
1649                 return (bus_read_1(r, res_offset));
1650         case 2:
1651                 return (bus_read_2(r, res_offset));
1652         case 4:
1653                 return (bus_read_4(r, res_offset));
1654         default:
1655                 panic("unsupported width: %u", width);
1656         }
1657 }
1658
1659 /**
1660  * Initialize a new bhndb PCI bridge EROM I/O instance. All I/O will be
1661  * performed using @p probe.
1662  * 
1663  * @param pio           The instance to be initialized.
1664  * @param probe         The bhndb_pci probe state to be used to perform all
1665  *                      I/O.
1666  */
1667 static void
1668 bhndb_pci_eio_init(struct bhndb_pci_eio *pio, struct bhndb_pci_probe *probe)
1669 {
1670         memset(pio, 0, sizeof(*pio));
1671
1672         pio->eio.map = bhndb_pci_eio_map;
1673         pio->eio.tell = bhndb_pci_eio_tell;
1674         pio->eio.read = bhndb_pci_eio_read;
1675         pio->eio.fini = NULL;
1676
1677         pio->mapped = false;
1678         pio->addr = 0;
1679         pio->size = 0;
1680         pio->probe = probe;
1681 }
1682
1683 /* bhnd_erom_io_map() implementation */
1684 static int
1685 bhndb_pci_eio_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
1686     bhnd_size_t size)
1687 {
1688         struct bhndb_pci_eio *pio = (struct bhndb_pci_eio *)eio;
1689
1690         if (BHND_ADDR_MAX - addr < size)
1691                 return (EINVAL); /* addr+size would overflow */
1692
1693         pio->addr = addr;
1694         pio->size = size;
1695         pio->mapped = true;
1696
1697         return (0);
1698 }
1699
1700 /* bhnd_erom_io_tell() implementation */
1701 static int
1702 bhndb_pci_eio_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr,
1703     bhnd_size_t *size)
1704 {
1705         struct bhndb_pci_eio *pio = (struct bhndb_pci_eio *)eio;
1706
1707         if (!pio->mapped)
1708                 return (ENXIO);
1709
1710         *addr = pio->addr;
1711         *size = pio->size;
1712
1713         return (0);
1714 }
1715
1716 /* bhnd_erom_io_read() implementation */
1717 static uint32_t
1718 bhndb_pci_eio_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width)
1719 {
1720         struct bhndb_pci_eio *pio = (struct bhndb_pci_eio *)eio;
1721
1722         /* Must have a valid mapping */
1723         if (!pio->mapped) 
1724                 panic("no active mapping");
1725
1726         /* The requested subrange must fall within the existing mapped range */
1727         if (offset > pio->size ||
1728             width > pio->size ||
1729             pio->size - offset < width)
1730         {
1731                 panic("invalid offset %#jx", offset);
1732         }
1733
1734         return (bhndb_pci_probe_read(pio->probe, pio->addr, offset, width));
1735 }
1736
1737 static device_method_t bhndb_pci_methods[] = {
1738         /* Device interface */
1739         DEVMETHOD(device_probe,                         bhndb_pci_probe),
1740         DEVMETHOD(device_attach,                        bhndb_pci_attach),
1741         DEVMETHOD(device_resume,                        bhndb_pci_resume),
1742         DEVMETHOD(device_suspend,                       bhndb_pci_suspend),
1743         DEVMETHOD(device_detach,                        bhndb_pci_detach),
1744
1745         /* BHNDB interface */
1746         DEVMETHOD(bhndb_set_window_addr,                bhndb_pci_set_window_addr),
1747         DEVMETHOD(bhndb_populate_board_info,            bhndb_pci_populate_board_info),
1748         DEVMETHOD(bhndb_map_intr_isrc,                  bhndb_pci_map_intr_isrc),
1749         DEVMETHOD(bhndb_route_interrupts,               bhndb_pci_route_interrupts),
1750
1751         /* BHND PWRCTL hostb interface */
1752         DEVMETHOD(bhnd_pwrctl_hostb_get_clksrc,         bhndb_pci_pwrctl_get_clksrc),
1753         DEVMETHOD(bhnd_pwrctl_hostb_gate_clock,         bhndb_pci_pwrctl_gate_clock),
1754         DEVMETHOD(bhnd_pwrctl_hostb_ungate_clock,       bhndb_pci_pwrctl_ungate_clock),
1755
1756         DEVMETHOD_END
1757 };
1758
1759 DEFINE_CLASS_1(bhndb, bhndb_pci_driver, bhndb_pci_methods,
1760     sizeof(struct bhndb_pci_softc), bhndb_driver);
1761
1762 MODULE_VERSION(bhndb_pci, 1);
1763 MODULE_DEPEND(bhndb_pci, bhnd_pci_hostb, 1, 1, 1);
1764 MODULE_DEPEND(bhndb_pci, pci, 1, 1, 1);
1765 MODULE_DEPEND(bhndb_pci, bhndb, 1, 1, 1);
1766 MODULE_DEPEND(bhndb_pci, bhnd, 1, 1, 1);