2 * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
34 * Broadcom Home Networking Division (HND) Bus Driver.
36 * The Broadcom HND family of devices consists of both SoCs and host-connected
37 * networking chipsets containing a common family of Broadcom IP cores,
38 * including an integrated MIPS and/or ARM cores.
40 * HND devices expose a nearly identical interface whether accessible over a
41 * native SoC interconnect, or when connected via a host interface such as
42 * PCIe. As a result, the majority of hardware support code should be re-usable
43 * across host drivers for HND networking chipsets, as well as FreeBSD support
44 * for Broadcom MIPS/ARM HND SoCs.
46 * Earlier HND models used the siba(4) on-chip interconnect, while later models
47 * use bcma(4); the programming model is almost entirely independent
48 * of the actual underlying interconect.
51 #include <sys/param.h>
52 #include <sys/kernel.h>
54 #include <sys/module.h>
55 #include <sys/systm.h>
57 #include <machine/bus.h>
59 #include <machine/resource.h>
61 #include <dev/bhnd/cores/chipc/chipcvar.h>
63 #include <dev/bhnd/cores/pmu/bhnd_pmu.h>
64 #include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
66 #include "bhnd_chipc_if.h"
67 #include "bhnd_nvram_if.h"
72 MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
74 /* Bus pass at which all bus-required children must be available, and
75 * attachment may be finalized. */
76 #define BHND_FINISH_ATTACH_PASS BUS_PASS_DEFAULT
79 * bhnd_generic_probe_nomatch() reporting configuration.
81 static const struct bhnd_nomatch {
82 uint16_t vendor; /**< core designer */
83 uint16_t device; /**< core id */
84 bool if_verbose; /**< print when bootverbose is set. */
85 } bhnd_nomatch_table[] = {
86 { BHND_MFGID_ARM, BHND_COREID_OOB_ROUTER, true },
87 { BHND_MFGID_ARM, BHND_COREID_EROM, true },
88 { BHND_MFGID_ARM, BHND_COREID_PL301, true },
89 { BHND_MFGID_ARM, BHND_COREID_APB_BRIDGE, true },
90 { BHND_MFGID_ARM, BHND_COREID_AXI_UNMAPPED, false },
92 { BHND_MFGID_INVALID, BHND_COREID_INVALID, false }
96 static int bhnd_delete_children(struct bhnd_softc *sc);
98 static int bhnd_finish_attach(struct bhnd_softc *sc);
100 static device_t bhnd_find_chipc(struct bhnd_softc *sc);
101 static struct chipc_caps *bhnd_find_chipc_caps(struct bhnd_softc *sc);
102 static device_t bhnd_find_platform_dev(struct bhnd_softc *sc,
103 const char *classname);
104 static device_t bhnd_find_pmu(struct bhnd_softc *sc);
105 static device_t bhnd_find_nvram(struct bhnd_softc *sc);
107 static int compare_ascending_probe_order(const void *lhs,
109 static int compare_descending_probe_order(const void *lhs,
113 * Default bhnd(4) bus driver implementation of DEVICE_ATTACH().
115 * This implementation calls device_probe_and_attach() for each of the device's
116 * children, in bhnd probe order.
119 bhnd_generic_attach(device_t dev)
121 struct bhnd_softc *sc;
126 if (device_is_attached(dev))
129 sc = device_get_softc(dev);
132 if ((error = device_get_children(dev, &devs, &ndevs)))
135 /* Probe and attach all children */
136 qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
137 for (int i = 0; i < ndevs; i++) {
138 device_t child = devs[i];
139 device_probe_and_attach(child);
142 /* Try to finalize attachment */
143 if (bus_current_pass >= BHND_FINISH_ATTACH_PASS) {
144 if ((error = bhnd_finish_attach(sc)))
152 bhnd_delete_children(sc);
158 * Detach and delete all children, in reverse of their attach order.
161 bhnd_delete_children(struct bhnd_softc *sc)
167 if ((error = device_get_children(sc->dev, &devs, &ndevs)))
170 /* Detach in the reverse of attach order */
171 qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
172 for (int i = 0; i < ndevs; i++) {
173 device_t child = devs[i];
175 /* Terminate on first error */
176 if ((error = device_delete_child(sc->dev, child)))
186 * Default bhnd(4) bus driver implementation of DEVICE_DETACH().
188 * This implementation calls device_detach() for each of the device's
189 * children, in reverse bhnd probe order, terminating if any call to
190 * device_detach() fails.
193 bhnd_generic_detach(device_t dev)
195 struct bhnd_softc *sc;
197 if (!device_is_attached(dev))
200 sc = device_get_softc(dev);
201 return (bhnd_delete_children(sc));
205 * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN().
207 * This implementation calls device_shutdown() for each of the device's
208 * children, in reverse bhnd probe order, terminating if any call to
209 * device_shutdown() fails.
212 bhnd_generic_shutdown(device_t dev)
218 if (!device_is_attached(dev))
221 if ((error = device_get_children(dev, &devs, &ndevs)))
224 /* Shutdown in the reverse of attach order */
225 qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
226 for (int i = 0; i < ndevs; i++) {
227 device_t child = devs[i];
229 /* Terminate on first error */
230 if ((error = device_shutdown(child)))
240 * Default bhnd(4) bus driver implementation of DEVICE_RESUME().
242 * This implementation calls BUS_RESUME_CHILD() for each of the device's
243 * children in bhnd probe order, terminating if any call to BUS_RESUME_CHILD()
247 bhnd_generic_resume(device_t dev)
253 if (!device_is_attached(dev))
256 if ((error = device_get_children(dev, &devs, &ndevs)))
259 qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
260 for (int i = 0; i < ndevs; i++) {
261 device_t child = devs[i];
263 /* Terminate on first error */
264 if ((error = BUS_RESUME_CHILD(device_get_parent(child), child)))
274 * Default bhnd(4) bus driver implementation of DEVICE_SUSPEND().
276 * This implementation calls BUS_SUSPEND_CHILD() for each of the device's
277 * children in reverse bhnd probe order. If any call to BUS_SUSPEND_CHILD()
278 * fails, the suspend operation is terminated and any devices that were
279 * suspended are resumed immediately by calling their BUS_RESUME_CHILD()
283 bhnd_generic_suspend(device_t dev)
289 if (!device_is_attached(dev))
292 if ((error = device_get_children(dev, &devs, &ndevs)))
295 /* Suspend in the reverse of attach order */
296 qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
297 for (int i = 0; i < ndevs; i++) {
298 device_t child = devs[i];
299 error = BUS_SUSPEND_CHILD(device_get_parent(child), child);
301 /* On error, resume suspended devices and then terminate */
303 for (int j = 0; j < i; j++) {
304 BUS_RESUME_CHILD(device_get_parent(devs[j]),
318 bhnd_new_pass(device_t dev)
320 struct bhnd_softc *sc;
323 sc = device_get_softc(dev);
325 /* Attach any permissible children */
326 bus_generic_new_pass(dev);
328 /* Finalize attachment */
329 if (!sc->attach_done && bus_current_pass >= BHND_FINISH_ATTACH_PASS) {
330 if ((error = bhnd_finish_attach(sc))) {
331 panic("bhnd_finish_attach() failed: %d", error);
337 * Finish any pending bus attachment operations.
339 * When attached as a SoC bus (as opposed to a bridged WiFi device), our
340 * platform devices may not be attached until later bus passes, necessitating
341 * delayed initialization on our part.
344 bhnd_finish_attach(struct bhnd_softc *sc)
346 struct chipc_caps *ccaps;
348 GIANT_REQUIRED; /* for newbus */
350 KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS,
351 ("bhnd_finish_attach() called in pass %d", bus_current_pass));
353 KASSERT(!sc->attach_done, ("duplicate call to bhnd_finish_attach()"));
355 /* Locate chipc device */
356 if ((sc->chipc_dev = bhnd_find_chipc(sc)) == NULL) {
357 device_printf(sc->dev, "error: ChipCommon device not found\n");
361 ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev);
363 /* Look for NVRAM device */
364 if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) {
365 if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) {
366 device_printf(sc->dev,
367 "warning: NVRAM %s device not found\n",
368 bhnd_nvram_src_name(ccaps->nvram_src));
373 if (ccaps->pmu || ccaps->pwr_ctrl) {
374 if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) {
375 device_printf(sc->dev,
376 "attach failed: supported PMU not found\n");
381 /* Mark attach as completed */
382 sc->attach_done = true;
387 /* Locate the ChipCommon core. */
389 bhnd_find_chipc(struct bhnd_softc *sc)
393 /* Make sure we're holding Giant for newbus */
396 /* chipc_dev is initialized during attachment */
397 if (sc->attach_done) {
398 if ((chipc = sc->chipc_dev) == NULL)
404 /* Locate chipc core with a core unit of 0 */
405 chipc = bhnd_find_child(sc->dev, BHND_DEVCLASS_CC, 0);
410 if (device_get_state(chipc) < DS_ATTACHING) {
411 device_printf(sc->dev, "chipc found, but did not attach\n");
418 /* Locate the ChipCommon core and return the device capabilities */
419 static struct chipc_caps *
420 bhnd_find_chipc_caps(struct bhnd_softc *sc)
424 if ((chipc = bhnd_find_chipc(sc)) == NULL) {
425 device_printf(sc->dev,
426 "chipc unavailable; cannot fetch capabilities\n");
430 return (BHND_CHIPC_GET_CAPS(chipc));
434 * Find an attached platform device on @p dev, searching first for cores
435 * matching @p classname, and if not found, searching the children of the first
436 * bhnd_chipc device on the bus.
438 * @param sc Driver state.
439 * @param chipc Attached ChipCommon device.
440 * @param classname Device class to search for.
442 * @retval device_t A matching device.
443 * @retval NULL If no matching device is found.
446 bhnd_find_platform_dev(struct bhnd_softc *sc, const char *classname)
448 device_t chipc, child;
450 /* Make sure we're holding Giant for newbus */
453 /* Look for a directly-attached child */
454 child = device_find_child(sc->dev, classname, -1);
458 /* Look for the first matching ChipCommon child */
459 if ((chipc = bhnd_find_chipc(sc)) == NULL) {
460 device_printf(sc->dev,
461 "chipc unavailable; cannot locate %s\n", classname);
465 child = device_find_child(chipc, classname, -1);
469 /* Look for a parent-attached device (e.g. nexus0 -> bhnd_nvram) */
470 child = device_find_child(device_get_parent(sc->dev), classname, -1);
475 if (device_get_state(child) < DS_ATTACHING)
481 /* Locate the PMU device, if any */
483 bhnd_find_pmu(struct bhnd_softc *sc)
485 /* Make sure we're holding Giant for newbus */
488 /* pmu_dev is initialized during attachment */
489 if (sc->attach_done) {
490 if (sc->pmu_dev == NULL)
493 if (device_get_state(sc->pmu_dev) < DS_ATTACHING)
496 return (sc->pmu_dev);
500 return (bhnd_find_platform_dev(sc, "bhnd_pmu"));
503 /* Locate the NVRAM device, if any */
505 bhnd_find_nvram(struct bhnd_softc *sc)
507 struct chipc_caps *ccaps;
509 /* Make sure we're holding Giant for newbus */
513 /* nvram_dev is initialized during attachment */
514 if (sc->attach_done) {
515 if (sc->nvram_dev == NULL)
518 if (device_get_state(sc->nvram_dev) < DS_ATTACHING)
521 return (sc->nvram_dev);
524 if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL)
527 if (ccaps->nvram_src == BHND_NVRAM_SRC_UNKNOWN)
530 return (bhnd_find_platform_dev(sc, "bhnd_nvram"));
534 * Ascending comparison of bhnd device's probe order.
537 compare_ascending_probe_order(const void *lhs, const void *rhs)
542 ldev = (*(const device_t *) lhs);
543 rdev = (*(const device_t *) rhs);
545 lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev);
546 rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev);
548 if (lorder < rorder) {
550 } else if (lorder > rorder) {
558 * Descending comparison of bhnd device's probe order.
561 compare_descending_probe_order(const void *lhs, const void *rhs)
563 return (compare_ascending_probe_order(rhs, lhs));
567 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER().
569 * This implementation determines probe ordering based on the device's class
570 * and other properties, including whether the device is serving as a host
574 bhnd_generic_get_probe_order(device_t dev, device_t child)
576 switch (bhnd_get_class(child)) {
577 case BHND_DEVCLASS_CC:
578 /* Must be early enough to provide NVRAM access to the
580 return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST);
582 case BHND_DEVCLASS_CC_B:
584 case BHND_DEVCLASS_PMU:
585 return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY);
587 case BHND_DEVCLASS_SOC_ROUTER:
588 return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE);
590 case BHND_DEVCLASS_SOC_BRIDGE:
591 return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST);
593 case BHND_DEVCLASS_CPU:
594 return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST);
596 case BHND_DEVCLASS_RAM:
598 case BHND_DEVCLASS_MEMC:
599 return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY);
601 case BHND_DEVCLASS_NVRAM:
602 return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY);
604 case BHND_DEVCLASS_PCI:
605 case BHND_DEVCLASS_PCIE:
606 case BHND_DEVCLASS_PCCARD:
607 case BHND_DEVCLASS_ENET:
608 case BHND_DEVCLASS_ENET_MAC:
609 case BHND_DEVCLASS_ENET_PHY:
610 case BHND_DEVCLASS_WLAN:
611 case BHND_DEVCLASS_WLAN_MAC:
612 case BHND_DEVCLASS_WLAN_PHY:
613 case BHND_DEVCLASS_EROM:
614 case BHND_DEVCLASS_OTHER:
615 case BHND_DEVCLASS_INVALID:
616 if (bhnd_find_hostb_device(dev) == child)
617 return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY);
619 return (BHND_PROBE_DEFAULT);
621 return (BHND_PROBE_DEFAULT);
626 * Default bhnd(4) bus driver implementation of BHND_BUS_ALLOC_PMU().
629 bhnd_generic_alloc_pmu(device_t dev, device_t child)
631 struct bhnd_softc *sc;
632 struct bhnd_resource *br;
633 struct chipc_caps *ccaps;
634 struct bhnd_devinfo *dinfo;
635 struct bhnd_core_pmu_info *pm;
636 struct resource_list *rl;
637 struct resource_list_entry *rle;
644 GIANT_REQUIRED; /* for newbus */
646 sc = device_get_softc(dev);
647 dinfo = device_get_ivars(child);
648 pmu_regs = BHND_CLK_CTL_ST;
650 if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL) {
651 device_printf(sc->dev, "alloc_pmu failed: chipc "
652 "capabilities unavailable\n");
656 if ((pmu_dev = bhnd_find_pmu(sc)) == NULL) {
657 device_printf(sc->dev,
658 "pmu unavailable; cannot allocate request state\n");
662 /* already allocated? */
663 if (dinfo->pmu_info != NULL) {
664 panic("duplicate PMU allocation for %s",
665 device_get_nameunit(child));
668 /* Determine address+size of the core's PMU register block */
669 error = bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &r_addr,
672 device_printf(sc->dev, "error fetching register block info for "
673 "%s: %d\n", device_get_nameunit(child), error);
677 if (r_size < (pmu_regs + sizeof(uint32_t))) {
678 device_printf(sc->dev, "pmu offset %#jx would overrun %s "
679 "register block\n", (uintmax_t)pmu_regs,
680 device_get_nameunit(child));
684 /* Locate actual resource containing the core's register block */
685 if ((rl = BUS_GET_RESOURCE_LIST(dev, child)) == NULL) {
686 device_printf(dev, "NULL resource list returned for %s\n",
687 device_get_nameunit(child));
691 if ((rle = resource_list_find(rl, SYS_RES_MEMORY, 0)) == NULL) {
692 device_printf(dev, "cannot locate core register resource "
693 "for %s\n", device_get_nameunit(child));
697 if (rle->res == NULL) {
698 device_printf(dev, "core register resource unallocated for "
699 "%s\n", device_get_nameunit(child));
703 if (r_addr+pmu_regs < rman_get_start(rle->res) ||
704 r_addr+pmu_regs >= rman_get_end(rle->res))
706 device_printf(dev, "core register resource does not map PMU "
707 "registers at %#jx\n for %s\n", r_addr+pmu_regs,
708 device_get_nameunit(child));
712 /* Adjust PMU register offset relative to the actual start address
713 * of the core's register block allocation.
715 * XXX: The saved offset will be invalid if bus_adjust_resource is
716 * used to modify the resource's start address.
718 if (rman_get_start(rle->res) > r_addr)
719 pmu_regs -= rman_get_start(rle->res) - r_addr;
721 pmu_regs -= r_addr - rman_get_start(rle->res);
723 /* Allocate and initialize PMU info */
724 br = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT);
729 br->direct = ((rman_get_flags(rle->res) & RF_ACTIVE) != 0);
731 pm = malloc(sizeof(*dinfo->pmu_info), M_BHND, M_NOWAIT);
737 pm->pm_pmu = pmu_dev;
739 pm->pm_regs = pmu_regs;
741 dinfo->pmu_info = pm;
746 * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_PMU().
749 bhnd_generic_release_pmu(device_t dev, device_t child)
751 struct bhnd_softc *sc;
752 struct bhnd_devinfo *dinfo;
756 GIANT_REQUIRED; /* for newbus */
758 sc = device_get_softc(dev);
759 dinfo = device_get_ivars(child);
761 if ((pmu = bhnd_find_pmu(sc)) == NULL) {
762 device_printf(sc->dev,
763 "pmu unavailable; cannot release request state\n");
767 /* dispatch release request */
768 if (dinfo->pmu_info == NULL)
769 panic("pmu over-release for %s", device_get_nameunit(child));
771 if ((error = BHND_PMU_CORE_RELEASE(pmu, dinfo->pmu_info)))
775 free(dinfo->pmu_info->pm_res, M_BHND);
776 free(dinfo->pmu_info, M_BHND);
777 dinfo->pmu_info = NULL;
783 * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_CLOCK().
786 bhnd_generic_request_clock(device_t dev, device_t child, bhnd_clock clock)
788 struct bhnd_softc *sc;
789 struct bhnd_devinfo *dinfo;
790 struct bhnd_core_pmu_info *pm;
792 sc = device_get_softc(dev);
793 dinfo = device_get_ivars(child);
795 if ((pm = dinfo->pmu_info) == NULL)
796 panic("no active PMU request state");
798 /* dispatch request to PMU */
799 return (BHND_PMU_CORE_REQ_CLOCK(pm->pm_pmu, pm, clock));
803 * Default bhnd(4) bus driver implementation of BHND_BUS_ENABLE_CLOCKS().
806 bhnd_generic_enable_clocks(device_t dev, device_t child, uint32_t clocks)
808 struct bhnd_softc *sc;
809 struct bhnd_devinfo *dinfo;
810 struct bhnd_core_pmu_info *pm;
812 sc = device_get_softc(dev);
813 dinfo = device_get_ivars(child);
815 if ((pm = dinfo->pmu_info) == NULL)
816 panic("no active PMU request state");
818 /* dispatch request to PMU */
819 return (BHND_PMU_CORE_EN_CLOCKS(pm->pm_pmu, pm, clocks));
823 * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_EXT_RSRC().
826 bhnd_generic_request_ext_rsrc(device_t dev, device_t child, u_int rsrc)
828 struct bhnd_softc *sc;
829 struct bhnd_devinfo *dinfo;
830 struct bhnd_core_pmu_info *pm;
832 sc = device_get_softc(dev);
833 dinfo = device_get_ivars(child);
835 if ((pm = dinfo->pmu_info) == NULL)
836 panic("no active PMU request state");
838 /* dispatch request to PMU */
839 return (BHND_PMU_CORE_REQ_EXT_RSRC(pm->pm_pmu, pm, rsrc));
843 * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_EXT_RSRC().
846 bhnd_generic_release_ext_rsrc(device_t dev, device_t child, u_int rsrc)
848 struct bhnd_softc *sc;
849 struct bhnd_devinfo *dinfo;
850 struct bhnd_core_pmu_info *pm;
852 sc = device_get_softc(dev);
853 dinfo = device_get_ivars(child);
855 if ((pm = dinfo->pmu_info) == NULL)
856 panic("no active PMU request state");
858 /* dispatch request to PMU */
859 return (BHND_PMU_CORE_RELEASE_EXT_RSRC(pm->pm_pmu, pm, rsrc));
864 * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
866 * This implementation assumes that port and region numbers are 0-indexed and
867 * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and
868 * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall
869 * within the defined range.
872 bhnd_generic_is_region_valid(device_t dev, device_t child,
873 bhnd_port_type type, u_int port, u_int region)
875 if (port >= bhnd_get_port_count(child, type))
878 if (region >= bhnd_get_region_count(child, type, port))
885 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
887 * This implementation searches @p dev for a usable NVRAM child device.
889 * If no usable child device is found on @p dev, the request is delegated to
890 * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
893 bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
894 void *buf, size_t *size, bhnd_nvram_type type)
896 struct bhnd_softc *sc;
897 device_t nvram, parent;
899 sc = device_get_softc(dev);
901 /* If a NVRAM device is available, consult it first */
902 if ((nvram = bhnd_find_nvram(sc)) != NULL)
903 return BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
905 /* Otherwise, try to delegate to parent */
906 if ((parent = device_get_parent(dev)) == NULL)
909 return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
910 name, buf, size, type));
914 * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD().
916 * This implementation requests the device's struct resource_list via
917 * BUS_GET_RESOURCE_LIST.
920 bhnd_generic_print_child(device_t dev, device_t child)
922 struct resource_list *rl;
925 retval += bus_print_child_header(dev, child);
927 rl = BUS_GET_RESOURCE_LIST(dev, child);
929 retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
933 retval += printf(" at core %u", bhnd_get_core_index(child));
935 retval += bus_print_child_domain(dev, child);
936 retval += bus_print_child_footer(dev, child);
942 * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH().
944 * This implementation requests the device's struct resource_list via
945 * BUS_GET_RESOURCE_LIST.
948 bhnd_generic_probe_nomatch(device_t dev, device_t child)
950 struct resource_list *rl;
951 const struct bhnd_nomatch *nm;
954 /* Fetch reporting configuration for this device */
956 for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) {
957 if (nm->vendor != bhnd_get_vendor(child))
960 if (nm->device != bhnd_get_device(child))
964 if (bootverbose && nm->if_verbose)
972 /* Print the non-matched device info */
973 device_printf(dev, "<%s %s>", bhnd_get_vendor_name(child),
974 bhnd_get_device_name(child));
976 rl = BUS_GET_RESOURCE_LIST(dev, child);
978 resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
980 printf(" at core %u (no driver attached)\n",
981 bhnd_get_core_index(child));
985 * Default implementation of BUS_CHILD_PNPINFO_STR().
988 bhnd_child_pnpinfo_str(device_t dev, device_t child, char *buf,
991 if (device_get_parent(child) != dev) {
992 return (BUS_CHILD_PNPINFO_STR(device_get_parent(dev), child,
996 snprintf(buf, buflen, "vendor=0x%hx device=0x%hx rev=0x%hhx",
997 bhnd_get_vendor(child), bhnd_get_device(child),
998 bhnd_get_hwrev(child));
1004 * Default implementation of BUS_CHILD_LOCATION_STR().
1007 bhnd_child_location_str(device_t dev, device_t child, char *buf,
1013 if (device_get_parent(child) != dev) {
1014 return (BUS_CHILD_LOCATION_STR(device_get_parent(dev), child,
1019 if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) {
1020 /* No device default port/region */
1026 snprintf(buf, buflen, "port0.0=0x%llx", (unsigned long long) addr);
1031 * Default bhnd(4) bus driver implementation of BUS_ADD_CHILD().
1033 * This implementation manages internal bhnd(4) state, and must be called
1034 * by subclassing drivers.
1037 bhnd_generic_add_child(device_t dev, u_int order, const char *name, int unit)
1039 struct bhnd_devinfo *dinfo;
1042 child = device_add_child_ordered(dev, order, name, unit);
1046 if ((dinfo = BHND_BUS_ALLOC_DEVINFO(dev)) == NULL) {
1047 device_delete_child(dev, child);
1051 device_set_ivars(child, dinfo);
1057 * Default bhnd(4) bus driver implementation of BHND_BUS_CHILD_ADDED().
1059 * This implementation manages internal bhnd(4) state, and must be called
1060 * by subclassing drivers.
1063 bhnd_generic_child_added(device_t dev, device_t child)
1068 * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED().
1070 * This implementation manages internal bhnd(4) state, and must be called
1071 * by subclassing drivers.
1074 bhnd_generic_child_deleted(device_t dev, device_t child)
1076 struct bhnd_softc *sc;
1077 struct bhnd_devinfo *dinfo;
1079 sc = device_get_softc(dev);
1081 /* Free device info */
1082 if ((dinfo = device_get_ivars(child)) != NULL) {
1083 if (dinfo->pmu_info != NULL) {
1084 /* Releasing PMU requests automatically would be nice,
1085 * but we can't reference per-core PMU register
1086 * resource after driver detach */
1087 panic("%s leaked device pmu state\n",
1088 device_get_nameunit(child));
1091 BHND_BUS_FREE_DEVINFO(dev, dinfo);
1094 /* Clean up platform device references */
1095 if (sc->chipc_dev == child) {
1096 sc->chipc_dev = NULL;
1097 } else if (sc->nvram_dev == child) {
1098 sc->nvram_dev = NULL;
1099 } else if (sc->pmu_dev == child) {
1105 * Helper function for implementing BUS_SUSPEND_CHILD().
1107 * TODO: Power management
1109 * If @p child is not a direct child of @p dev, suspension is delegated to
1110 * the @p dev parent.
1113 bhnd_generic_suspend_child(device_t dev, device_t child)
1115 if (device_get_parent(child) != dev)
1116 BUS_SUSPEND_CHILD(device_get_parent(dev), child);
1118 return bus_generic_suspend_child(dev, child);
1122 * Helper function for implementing BUS_RESUME_CHILD().
1124 * TODO: Power management
1126 * If @p child is not a direct child of @p dev, suspension is delegated to
1127 * the @p dev parent.
1130 bhnd_generic_resume_child(device_t dev, device_t child)
1132 if (device_get_parent(child) != dev)
1133 BUS_RESUME_CHILD(device_get_parent(dev), child);
1135 return bus_generic_resume_child(dev, child);
1139 * Delegate all indirect I/O to the parent device. When inherited by
1140 * non-bridged bus implementations, resources will never be marked as
1141 * indirect, and these methods will never be called.
1143 #define BHND_IO_READ(_type, _name, _method) \
1145 bhnd_read_ ## _name (device_t dev, device_t child, \
1146 struct bhnd_resource *r, bus_size_t offset) \
1148 return (BHND_BUS_READ_ ## _method( \
1149 device_get_parent(dev), child, r, offset)); \
1152 #define BHND_IO_WRITE(_type, _name, _method) \
1154 bhnd_write_ ## _name (device_t dev, device_t child, \
1155 struct bhnd_resource *r, bus_size_t offset, _type value) \
1157 return (BHND_BUS_WRITE_ ## _method( \
1158 device_get_parent(dev), child, r, offset, \
1162 #define BHND_IO_MISC(_type, _op, _method) \
1164 bhnd_ ## _op (device_t dev, device_t child, \
1165 struct bhnd_resource *r, bus_size_t offset, _type datap, \
1168 BHND_BUS_ ## _method(device_get_parent(dev), child, r, \
1169 offset, datap, count); \
1172 #define BHND_IO_METHODS(_type, _size) \
1173 BHND_IO_READ(_type, _size, _size) \
1174 BHND_IO_WRITE(_type, _size, _size) \
1176 BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size) \
1177 BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size) \
1179 BHND_IO_MISC(_type*, read_multi_ ## _size, \
1180 READ_MULTI_ ## _size) \
1181 BHND_IO_MISC(_type*, write_multi_ ## _size, \
1182 WRITE_MULTI_ ## _size) \
1184 BHND_IO_MISC(_type*, read_multi_stream_ ## _size, \
1185 READ_MULTI_STREAM_ ## _size) \
1186 BHND_IO_MISC(_type*, write_multi_stream_ ## _size, \
1187 WRITE_MULTI_STREAM_ ## _size) \
1189 BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size) \
1190 BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size) \
1192 BHND_IO_MISC(_type*, read_region_ ## _size, \
1193 READ_REGION_ ## _size) \
1194 BHND_IO_MISC(_type*, write_region_ ## _size, \
1195 WRITE_REGION_ ## _size) \
1197 BHND_IO_MISC(_type*, read_region_stream_ ## _size, \
1198 READ_REGION_STREAM_ ## _size) \
1199 BHND_IO_MISC(_type*, write_region_stream_ ## _size, \
1200 WRITE_REGION_STREAM_ ## _size) \
1202 BHND_IO_METHODS(uint8_t, 1);
1203 BHND_IO_METHODS(uint16_t, 2);
1204 BHND_IO_METHODS(uint32_t, 4);
1207 bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r,
1208 bus_size_t offset, bus_size_t length, int flags)
1210 BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length,
1214 static device_method_t bhnd_methods[] = {
1215 /* Device interface */ \
1216 DEVMETHOD(device_attach, bhnd_generic_attach),
1217 DEVMETHOD(device_detach, bhnd_generic_detach),
1218 DEVMETHOD(device_shutdown, bhnd_generic_shutdown),
1219 DEVMETHOD(device_suspend, bhnd_generic_suspend),
1220 DEVMETHOD(device_resume, bhnd_generic_resume),
1223 DEVMETHOD(bus_new_pass, bhnd_new_pass),
1224 DEVMETHOD(bus_add_child, bhnd_generic_add_child),
1225 DEVMETHOD(bus_child_deleted, bhnd_generic_child_deleted),
1226 DEVMETHOD(bus_probe_nomatch, bhnd_generic_probe_nomatch),
1227 DEVMETHOD(bus_print_child, bhnd_generic_print_child),
1228 DEVMETHOD(bus_child_pnpinfo_str, bhnd_child_pnpinfo_str),
1229 DEVMETHOD(bus_child_location_str, bhnd_child_location_str),
1231 DEVMETHOD(bus_suspend_child, bhnd_generic_suspend_child),
1232 DEVMETHOD(bus_resume_child, bhnd_generic_resume_child),
1234 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
1235 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
1236 DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource),
1237 DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
1238 DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
1239 DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
1240 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
1241 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
1243 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
1244 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
1245 DEVMETHOD(bus_config_intr, bus_generic_config_intr),
1246 DEVMETHOD(bus_bind_intr, bus_generic_bind_intr),
1247 DEVMETHOD(bus_describe_intr, bus_generic_describe_intr),
1249 DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag),
1251 /* BHND interface */
1252 DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid),
1253 DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled),
1254 DEVMETHOD(bhnd_bus_read_board_info, bhnd_bus_generic_read_board_info),
1256 DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order),
1258 DEVMETHOD(bhnd_bus_alloc_pmu, bhnd_generic_alloc_pmu),
1259 DEVMETHOD(bhnd_bus_release_pmu, bhnd_generic_release_pmu),
1260 DEVMETHOD(bhnd_bus_request_clock, bhnd_generic_request_clock),
1261 DEVMETHOD(bhnd_bus_enable_clocks, bhnd_generic_enable_clocks),
1262 DEVMETHOD(bhnd_bus_request_ext_rsrc, bhnd_generic_request_ext_rsrc),
1263 DEVMETHOD(bhnd_bus_release_ext_rsrc, bhnd_generic_release_ext_rsrc),
1265 DEVMETHOD(bhnd_bus_child_added, bhnd_generic_child_added),
1266 DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid),
1267 DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var),
1269 /* BHND interface (bus I/O) */
1270 DEVMETHOD(bhnd_bus_read_1, bhnd_read_1),
1271 DEVMETHOD(bhnd_bus_read_2, bhnd_read_2),
1272 DEVMETHOD(bhnd_bus_read_4, bhnd_read_4),
1273 DEVMETHOD(bhnd_bus_write_1, bhnd_write_1),
1274 DEVMETHOD(bhnd_bus_write_2, bhnd_write_2),
1275 DEVMETHOD(bhnd_bus_write_4, bhnd_write_4),
1277 DEVMETHOD(bhnd_bus_read_stream_1, bhnd_read_stream_1),
1278 DEVMETHOD(bhnd_bus_read_stream_2, bhnd_read_stream_2),
1279 DEVMETHOD(bhnd_bus_read_stream_4, bhnd_read_stream_4),
1280 DEVMETHOD(bhnd_bus_write_stream_1, bhnd_write_stream_1),
1281 DEVMETHOD(bhnd_bus_write_stream_2, bhnd_write_stream_2),
1282 DEVMETHOD(bhnd_bus_write_stream_4, bhnd_write_stream_4),
1284 DEVMETHOD(bhnd_bus_read_multi_1, bhnd_read_multi_1),
1285 DEVMETHOD(bhnd_bus_read_multi_2, bhnd_read_multi_2),
1286 DEVMETHOD(bhnd_bus_read_multi_4, bhnd_read_multi_4),
1287 DEVMETHOD(bhnd_bus_write_multi_1, bhnd_write_multi_1),
1288 DEVMETHOD(bhnd_bus_write_multi_2, bhnd_write_multi_2),
1289 DEVMETHOD(bhnd_bus_write_multi_4, bhnd_write_multi_4),
1291 DEVMETHOD(bhnd_bus_read_multi_stream_1, bhnd_read_multi_stream_1),
1292 DEVMETHOD(bhnd_bus_read_multi_stream_2, bhnd_read_multi_stream_2),
1293 DEVMETHOD(bhnd_bus_read_multi_stream_4, bhnd_read_multi_stream_4),
1294 DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1),
1295 DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2),
1296 DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4),
1298 DEVMETHOD(bhnd_bus_set_multi_1, bhnd_set_multi_1),
1299 DEVMETHOD(bhnd_bus_set_multi_2, bhnd_set_multi_2),
1300 DEVMETHOD(bhnd_bus_set_multi_4, bhnd_set_multi_4),
1302 DEVMETHOD(bhnd_bus_set_region_1, bhnd_set_region_1),
1303 DEVMETHOD(bhnd_bus_set_region_2, bhnd_set_region_2),
1304 DEVMETHOD(bhnd_bus_set_region_4, bhnd_set_region_4),
1306 DEVMETHOD(bhnd_bus_read_region_1, bhnd_read_region_1),
1307 DEVMETHOD(bhnd_bus_read_region_2, bhnd_read_region_2),
1308 DEVMETHOD(bhnd_bus_read_region_4, bhnd_read_region_4),
1309 DEVMETHOD(bhnd_bus_write_region_1, bhnd_write_region_1),
1310 DEVMETHOD(bhnd_bus_write_region_2, bhnd_write_region_2),
1311 DEVMETHOD(bhnd_bus_write_region_4, bhnd_write_region_4),
1313 DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1),
1314 DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2),
1315 DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4),
1316 DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1),
1317 DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2),
1318 DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4),
1320 DEVMETHOD(bhnd_bus_barrier, bhnd_barrier),
1325 devclass_t bhnd_devclass; /**< bhnd bus. */
1326 devclass_t bhnd_hostb_devclass; /**< bhnd bus host bridge. */
1327 devclass_t bhnd_nvram_devclass; /**< bhnd NVRAM device */
1329 DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc));
1330 MODULE_VERSION(bhnd, 1);