xref: /freebsd/sys/dev/bhnd/bhnd.c (revision ce437beff1f521b5ac35ea67d0669c46b3bef27f)
1 /*-
2  * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
15  *
16  * NO WARRANTY
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.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*
34  * Broadcom Home Networking Division (HND) Bus Driver.
35  *
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.
39  *
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.
45  *
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.
49  */
50 
51 #include <sys/param.h>
52 #include <sys/kernel.h>
53 #include <sys/bus.h>
54 #include <sys/module.h>
55 #include <sys/systm.h>
56 
57 #include <machine/bus.h>
58 #include <sys/rman.h>
59 #include <machine/resource.h>
60 
61 #include <dev/bhnd/cores/chipc/chipcvar.h>
62 
63 #include "bhnd_chipc_if.h"
64 #include "bhnd_nvram_if.h"
65 
66 #include "bhnd.h"
67 #include "bhndvar.h"
68 
69 MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
70 
71 /* Bus pass at which all bus-required children must be available, and
72  * attachment may be finalized. */
73 #define	BHND_FINISH_ATTACH_PASS	BUS_PASS_DEFAULT
74 
75 /**
76  * bhnd_generic_probe_nomatch() reporting configuration.
77  */
78 static const struct bhnd_nomatch {
79 	uint16_t	vendor;		/**< core designer */
80 	uint16_t	device;		/**< core id */
81 	bool		if_verbose;	/**< print when bootverbose is set. */
82 } bhnd_nomatch_table[] = {
83 	{ BHND_MFGID_ARM,	BHND_COREID_OOB_ROUTER,		true	},
84 	{ BHND_MFGID_ARM,	BHND_COREID_EROM,		true	},
85 	{ BHND_MFGID_ARM,	BHND_COREID_PL301,		true	},
86 	{ BHND_MFGID_ARM,	BHND_COREID_APB_BRIDGE,		true	},
87 	{ BHND_MFGID_ARM,	BHND_COREID_AXI_UNMAPPED,	false	},
88 
89 	{ BHND_MFGID_INVALID,	BHND_COREID_INVALID,		false	}
90 };
91 
92 
93 static int			 bhnd_delete_children(struct bhnd_softc *sc);
94 
95 static int			 bhnd_finish_attach(struct bhnd_softc *sc);
96 
97 static device_t			 bhnd_find_chipc(struct bhnd_softc *sc);
98 static struct chipc_caps	*bhnd_find_chipc_caps(struct bhnd_softc *sc);
99 static device_t			 bhnd_find_platform_dev(struct bhnd_softc *sc,
100 				     const char *classname);
101 static device_t			 bhnd_find_pmu(struct bhnd_softc *sc);
102 static device_t			 bhnd_find_nvram(struct bhnd_softc *sc);
103 
104 static int			 compare_ascending_probe_order(const void *lhs,
105 				     const void *rhs);
106 static int			 compare_descending_probe_order(const void *lhs,
107 				     const void *rhs);
108 
109 /**
110  * Default bhnd(4) bus driver implementation of DEVICE_ATTACH().
111  *
112  * This implementation calls device_probe_and_attach() for each of the device's
113  * children, in bhnd probe order.
114  */
115 int
116 bhnd_generic_attach(device_t dev)
117 {
118 	struct bhnd_softc	*sc;
119 	device_t		*devs;
120 	int			 ndevs;
121 	int			 error;
122 
123 	if (device_is_attached(dev))
124 		return (EBUSY);
125 
126 	sc = device_get_softc(dev);
127 	sc->dev = dev;
128 
129 	if ((error = device_get_children(dev, &devs, &ndevs)))
130 		return (error);
131 
132 	/* Probe and attach all children */
133 	qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
134 	for (int i = 0; i < ndevs; i++) {
135 		device_t child = devs[i];
136 		device_probe_and_attach(child);
137 	}
138 
139 	/* Try to finalize attachment */
140 	if (bus_current_pass >= BHND_FINISH_ATTACH_PASS) {
141 		if ((error = bhnd_finish_attach(sc)))
142 			goto cleanup;
143 	}
144 
145 cleanup:
146 	free(devs, M_TEMP);
147 
148 	if (error)
149 		bhnd_delete_children(sc);
150 
151 	return (error);
152 }
153 
154 /**
155  * Detach and delete all children, in reverse of their attach order.
156  */
157 static int
158 bhnd_delete_children(struct bhnd_softc *sc)
159 {
160 	device_t		*devs;
161 	int			 ndevs;
162 	int			 error;
163 
164 	if ((error = device_get_children(sc->dev, &devs, &ndevs)))
165 		return (error);
166 
167 	/* Detach in the reverse of attach order */
168 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
169 	for (int i = 0; i < ndevs; i++) {
170 		device_t child = devs[i];
171 
172 		/* Terminate on first error */
173 		if ((error = device_delete_child(sc->dev, child)))
174 			goto cleanup;
175 	}
176 
177 cleanup:
178 	free(devs, M_TEMP);
179 	return (error);
180 }
181 
182 /**
183  * Default bhnd(4) bus driver implementation of DEVICE_DETACH().
184  *
185  * This implementation calls device_detach() for each of the device's
186  * children, in reverse bhnd probe order, terminating if any call to
187  * device_detach() fails.
188  */
189 int
190 bhnd_generic_detach(device_t dev)
191 {
192 	struct bhnd_softc	*sc;
193 
194 	if (!device_is_attached(dev))
195 		return (EBUSY);
196 
197 	sc = device_get_softc(dev);
198 	return (bhnd_delete_children(sc));
199 }
200 
201 /**
202  * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN().
203  *
204  * This implementation calls device_shutdown() for each of the device's
205  * children, in reverse bhnd probe order, terminating if any call to
206  * device_shutdown() fails.
207  */
208 int
209 bhnd_generic_shutdown(device_t dev)
210 {
211 	device_t	*devs;
212 	int		 ndevs;
213 	int		 error;
214 
215 	if (!device_is_attached(dev))
216 		return (EBUSY);
217 
218 	if ((error = device_get_children(dev, &devs, &ndevs)))
219 		return (error);
220 
221 	/* Shutdown in the reverse of attach order */
222 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
223 	for (int i = 0; i < ndevs; i++) {
224 		device_t child = devs[i];
225 
226 		/* Terminate on first error */
227 		if ((error = device_shutdown(child)))
228 			goto cleanup;
229 	}
230 
231 cleanup:
232 	free(devs, M_TEMP);
233 	return (error);
234 }
235 
236 /**
237  * Default bhnd(4) bus driver implementation of DEVICE_RESUME().
238  *
239  * This implementation calls BUS_RESUME_CHILD() for each of the device's
240  * children in bhnd probe order, terminating if any call to BUS_RESUME_CHILD()
241  * fails.
242  */
243 int
244 bhnd_generic_resume(device_t dev)
245 {
246 	device_t	*devs;
247 	int		 ndevs;
248 	int		 error;
249 
250 	if (!device_is_attached(dev))
251 		return (EBUSY);
252 
253 	if ((error = device_get_children(dev, &devs, &ndevs)))
254 		return (error);
255 
256 	qsort(devs, ndevs, sizeof(*devs), compare_ascending_probe_order);
257 	for (int i = 0; i < ndevs; i++) {
258 		device_t child = devs[i];
259 
260 		/* Terminate on first error */
261 		if ((error = BUS_RESUME_CHILD(device_get_parent(child), child)))
262 			goto cleanup;
263 	}
264 
265 cleanup:
266 	free(devs, M_TEMP);
267 	return (error);
268 }
269 
270 /**
271  * Default bhnd(4) bus driver implementation of DEVICE_SUSPEND().
272  *
273  * This implementation calls BUS_SUSPEND_CHILD() for each of the device's
274  * children in reverse bhnd probe order. If any call to BUS_SUSPEND_CHILD()
275  * fails, the suspend operation is terminated and any devices that were
276  * suspended are resumed immediately by calling their BUS_RESUME_CHILD()
277  * methods.
278  */
279 int
280 bhnd_generic_suspend(device_t dev)
281 {
282 	device_t	*devs;
283 	int		 ndevs;
284 	int		 error;
285 
286 	if (!device_is_attached(dev))
287 		return (EBUSY);
288 
289 	if ((error = device_get_children(dev, &devs, &ndevs)))
290 		return (error);
291 
292 	/* Suspend in the reverse of attach order */
293 	qsort(devs, ndevs, sizeof(*devs), compare_descending_probe_order);
294 	for (int i = 0; i < ndevs; i++) {
295 		device_t child = devs[i];
296 		error = BUS_SUSPEND_CHILD(device_get_parent(child), child);
297 
298 		/* On error, resume suspended devices and then terminate */
299 		if (error) {
300 			for (int j = 0; j < i; j++) {
301 				BUS_RESUME_CHILD(device_get_parent(devs[j]),
302 				    devs[j]);
303 			}
304 
305 			goto cleanup;
306 		}
307 	}
308 
309 cleanup:
310 	free(devs, M_TEMP);
311 	return (error);
312 }
313 
314 static void
315 bhnd_new_pass(device_t dev)
316 {
317 	struct bhnd_softc	*sc;
318 	int			 error;
319 
320 	sc = device_get_softc(dev);
321 
322 	/* Attach any permissible children */
323 	bus_generic_new_pass(dev);
324 
325 	/* Finalize attachment */
326 	if (!sc->attach_done && bus_current_pass >= BHND_FINISH_ATTACH_PASS) {
327 		if ((error = bhnd_finish_attach(sc))) {
328 			panic("bhnd_finish_attach() failed: %d", error);
329 		}
330 	}
331 }
332 
333 /*
334  * Finish any pending bus attachment operations.
335  *
336  * When attached as a SoC bus (as opposed to a bridged WiFi device), our
337  * platform devices may not be attached until later bus passes, necessitating
338  * delayed initialization on our part.
339  */
340 static int
341 bhnd_finish_attach(struct bhnd_softc *sc)
342 {
343 	struct chipc_caps	*ccaps;
344 
345 	GIANT_REQUIRED;	/* newbus */
346 
347 	KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS,
348 	    ("bhnd_finish_attach() called in pass %d", bus_current_pass));
349 
350 	KASSERT(!sc->attach_done, ("duplicate call to bhnd_finish_attach()"));
351 
352 	/* Locate chipc device */
353 	if ((sc->chipc_dev = bhnd_find_chipc(sc)) == NULL) {
354 		device_printf(sc->dev, "error: ChipCommon device not found\n");
355 		return (ENXIO);
356 	}
357 
358 	ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev);
359 
360 	/* Look for NVRAM device */
361 	if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) {
362 		if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) {
363 			device_printf(sc->dev,
364 			    "warning: NVRAM %s device not found\n",
365 			    bhnd_nvram_src_name(ccaps->nvram_src));
366 		}
367 	}
368 
369 	/* Look for a PMU  */
370 	if (ccaps->pmu) {
371 		if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) {
372 			device_printf(sc->dev,
373 			    "warning: PMU device not found\n");
374 		}
375 	}
376 
377 	/* Mark attach as completed */
378 	sc->attach_done = true;
379 
380 	return (0);
381 }
382 
383 /* Locate the ChipCommon core. */
384 static device_t
385 bhnd_find_chipc(struct bhnd_softc *sc)
386 {
387 	device_t chipc;
388 
389         /* Make sure we're holding Giant for newbus */
390 	GIANT_REQUIRED;
391 
392 	/* chipc_dev is initialized during attachment */
393 	if (sc->attach_done) {
394 		if ((chipc = sc->chipc_dev) == NULL)
395 			return (NULL);
396 
397 		goto found;
398 	}
399 
400 	/* Locate chipc core with a core unit of 0 */
401 	chipc = bhnd_find_child(sc->dev, BHND_DEVCLASS_CC, 0);
402 	if (chipc == NULL)
403 		return (NULL);
404 
405 found:
406 	if (device_get_state(chipc) < DS_ATTACHING) {
407 		device_printf(sc->dev, "chipc found, but did not attach\n");
408 		return (NULL);
409 	}
410 
411 	return (chipc);
412 }
413 
414 /* Locate the ChipCommon core and return the device capabilities  */
415 static struct chipc_caps *
416 bhnd_find_chipc_caps(struct bhnd_softc *sc)
417 {
418 	device_t chipc;
419 
420 	if ((chipc = bhnd_find_chipc(sc)) == NULL) {
421 		device_printf(sc->dev,
422 		    "chipc unavailable; cannot fetch capabilities\n");
423 		return (NULL);
424 	}
425 
426 	return (BHND_CHIPC_GET_CAPS(chipc));
427 }
428 
429 /**
430  * Find an attached platform device on @p dev, searching first for cores
431  * matching @p classname, and if not found, searching the children of the first
432  * bhnd_chipc device on the bus.
433  *
434  * @param sc Driver state.
435  * @param chipc Attached ChipCommon device.
436  * @param classname Device class to search for.
437  *
438  * @retval device_t A matching device.
439  * @retval NULL If no matching device is found.
440  */
441 static device_t
442 bhnd_find_platform_dev(struct bhnd_softc *sc, const char *classname)
443 {
444 	device_t chipc, child;
445 
446         /* Make sure we're holding Giant for newbus */
447 	GIANT_REQUIRED;
448 
449 	/* Look for a directly-attached child */
450 	child = device_find_child(sc->dev, classname, -1);
451 	if (child != NULL)
452 		goto found;
453 
454 	/* Look for the first matching ChipCommon child */
455 	if ((chipc = bhnd_find_chipc(sc)) == NULL) {
456 		device_printf(sc->dev,
457 		    "chipc unavailable; cannot locate %s\n", classname);
458 		return (NULL);
459 	}
460 
461 	child = device_find_child(chipc, classname, -1);
462 	if (child != NULL)
463 		goto found;
464 
465 	/* Look for a parent-attached device (e.g. nexus0 -> bhnd_nvram) */
466 	child = device_find_child(device_get_parent(sc->dev), classname, -1);
467 	if (child == NULL)
468 		return (NULL);
469 
470 found:
471 	if (device_get_state(child) < DS_ATTACHING)
472 		return (NULL);
473 
474 	return (child);
475 }
476 
477 /* Locate the PMU device, if any */
478 static device_t
479 bhnd_find_pmu(struct bhnd_softc *sc)
480 {
481 	struct chipc_caps	*ccaps;
482 
483         /* Make sure we're holding Giant for newbus */
484 	GIANT_REQUIRED;
485 
486 	/* pmu_dev is initialized during attachment */
487 	if (sc->attach_done) {
488 		if (sc->pmu_dev == NULL)
489 			return (NULL);
490 
491 		if (device_get_state(sc->pmu_dev) < DS_ATTACHING)
492 			return (NULL);
493 
494 		return (sc->pmu_dev);
495 	}
496 
497 	if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL)
498 		return (NULL);
499 
500 	if (!ccaps->pmu)
501 		return (NULL);
502 
503 	return (bhnd_find_platform_dev(sc, "bhnd_pmu"));
504 }
505 
506 /* Locate the NVRAM device, if any */
507 static device_t
508 bhnd_find_nvram(struct bhnd_softc *sc)
509 {
510 	struct chipc_caps *ccaps;
511 
512         /* Make sure we're holding Giant for newbus */
513 	GIANT_REQUIRED;
514 
515 
516 	/* nvram_dev is initialized during attachment */
517 	if (sc->attach_done) {
518 		if (sc->nvram_dev == NULL)
519 			return (NULL);
520 
521 		if (device_get_state(sc->nvram_dev) < DS_ATTACHING)
522 			return (NULL);
523 
524 		return (sc->nvram_dev);
525 	}
526 
527 	if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL)
528 		return (NULL);
529 
530 	if (ccaps->nvram_src == BHND_NVRAM_SRC_UNKNOWN)
531 		return (NULL);
532 
533 	return (bhnd_find_platform_dev(sc, "bhnd_nvram"));
534 }
535 
536 /*
537  * Ascending comparison of bhnd device's probe order.
538  */
539 static int
540 compare_ascending_probe_order(const void *lhs, const void *rhs)
541 {
542 	device_t	ldev, rdev;
543 	int		lorder, rorder;
544 
545 	ldev = (*(const device_t *) lhs);
546 	rdev = (*(const device_t *) rhs);
547 
548 	lorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(ldev), ldev);
549 	rorder = BHND_BUS_GET_PROBE_ORDER(device_get_parent(rdev), rdev);
550 
551 	if (lorder < rorder) {
552 		return (-1);
553 	} else if (lorder > rorder) {
554 		return (1);
555 	} else {
556 		return (0);
557 	}
558 }
559 
560 /*
561  * Descending comparison of bhnd device's probe order.
562  */
563 static int
564 compare_descending_probe_order(const void *lhs, const void *rhs)
565 {
566 	return (compare_ascending_probe_order(rhs, lhs));
567 }
568 
569 /**
570  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER().
571  *
572  * This implementation determines probe ordering based on the device's class
573  * and other properties, including whether the device is serving as a host
574  * bridge.
575  */
576 int
577 bhnd_generic_get_probe_order(device_t dev, device_t child)
578 {
579 	switch (bhnd_get_class(child)) {
580 	case BHND_DEVCLASS_CC:
581 		/* Must be early enough to provide NVRAM access to the
582 		 * host bridge */
583 		return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST);
584 
585 	case BHND_DEVCLASS_CC_B:
586 		/* fall through */
587 	case BHND_DEVCLASS_PMU:
588 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY);
589 
590 	case BHND_DEVCLASS_SOC_ROUTER:
591 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE);
592 
593 	case BHND_DEVCLASS_SOC_BRIDGE:
594 		return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST);
595 
596 	case BHND_DEVCLASS_CPU:
597 		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST);
598 
599 	case BHND_DEVCLASS_RAM:
600 		/* fall through */
601 	case BHND_DEVCLASS_MEMC:
602 		return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY);
603 
604 	case BHND_DEVCLASS_NVRAM:
605 		return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY);
606 
607 	case BHND_DEVCLASS_PCI:
608 	case BHND_DEVCLASS_PCIE:
609 	case BHND_DEVCLASS_PCCARD:
610 	case BHND_DEVCLASS_ENET:
611 	case BHND_DEVCLASS_ENET_MAC:
612 	case BHND_DEVCLASS_ENET_PHY:
613 	case BHND_DEVCLASS_WLAN:
614 	case BHND_DEVCLASS_WLAN_MAC:
615 	case BHND_DEVCLASS_WLAN_PHY:
616 	case BHND_DEVCLASS_EROM:
617 	case BHND_DEVCLASS_OTHER:
618 	case BHND_DEVCLASS_INVALID:
619 		if (bhnd_find_hostb_device(dev) == child)
620 			return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY);
621 
622 		return (BHND_PROBE_DEFAULT);
623 	default:
624 		return (BHND_PROBE_DEFAULT);
625 	}
626 }
627 
628 /**
629  * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
630  *
631  * This implementation assumes that port and region numbers are 0-indexed and
632  * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and
633  * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall
634  * within the defined range.
635  */
636 static bool
637 bhnd_generic_is_region_valid(device_t dev, device_t child,
638     bhnd_port_type type, u_int port, u_int region)
639 {
640 	if (port >= bhnd_get_port_count(child, type))
641 		return (false);
642 
643 	if (region >= bhnd_get_region_count(child, type, port))
644 		return (false);
645 
646 	return (true);
647 }
648 
649 /**
650  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
651  *
652  * This implementation searches @p dev for a usable NVRAM child device.
653  *
654  * If no usable child device is found on @p dev, the request is delegated to
655  * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
656  */
657 int
658 bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
659     void *buf, size_t *size, bhnd_nvram_type type)
660 {
661 	struct bhnd_softc	*sc;
662 	device_t		 nvram, parent;
663 
664 	sc = device_get_softc(dev);
665 
666 	/* If a NVRAM device is available, consult it first */
667 	if ((nvram = bhnd_find_nvram(sc)) != NULL)
668 		return BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
669 
670 	/* Otherwise, try to delegate to parent */
671 	if ((parent = device_get_parent(dev)) == NULL)
672 		return (ENODEV);
673 
674 	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
675 	    name, buf, size, type));
676 }
677 
678 /**
679  * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD().
680  *
681  * This implementation requests the device's struct resource_list via
682  * BUS_GET_RESOURCE_LIST.
683  */
684 int
685 bhnd_generic_print_child(device_t dev, device_t child)
686 {
687 	struct resource_list	*rl;
688 	int			retval = 0;
689 
690 	retval += bus_print_child_header(dev, child);
691 
692 	rl = BUS_GET_RESOURCE_LIST(dev, child);
693 	if (rl != NULL) {
694 		retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
695 		    "%#jx");
696 	}
697 
698 	retval += printf(" at core %u", bhnd_get_core_index(child));
699 
700 	retval += bus_print_child_domain(dev, child);
701 	retval += bus_print_child_footer(dev, child);
702 
703 	return (retval);
704 }
705 
706 /**
707  * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH().
708  *
709  * This implementation requests the device's struct resource_list via
710  * BUS_GET_RESOURCE_LIST.
711  */
712 void
713 bhnd_generic_probe_nomatch(device_t dev, device_t child)
714 {
715 	struct resource_list		*rl;
716 	const struct bhnd_nomatch	*nm;
717 	bool				 report;
718 
719 	/* Fetch reporting configuration for this device */
720 	report = true;
721 	for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) {
722 		if (nm->vendor != bhnd_get_vendor(child))
723 			continue;
724 
725 		if (nm->device != bhnd_get_device(child))
726 			continue;
727 
728 		report = false;
729 		if (bootverbose && nm->if_verbose)
730 			report = true;
731 		break;
732 	}
733 
734 	if (!report)
735 		return;
736 
737 	/* Print the non-matched device info */
738 	device_printf(dev, "<%s %s>", bhnd_get_vendor_name(child),
739 		bhnd_get_device_name(child));
740 
741 	rl = BUS_GET_RESOURCE_LIST(dev, child);
742 	if (rl != NULL)
743 		resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
744 
745 	printf(" at core %u (no driver attached)\n",
746 	    bhnd_get_core_index(child));
747 }
748 
749 /**
750  * Default implementation of BUS_CHILD_PNPINFO_STR().
751  */
752 static int
753 bhnd_child_pnpinfo_str(device_t dev, device_t child, char *buf,
754     size_t buflen)
755 {
756 	if (device_get_parent(child) != dev) {
757 		return (BUS_CHILD_PNPINFO_STR(device_get_parent(dev), child,
758 		    buf, buflen));
759 	}
760 
761 	snprintf(buf, buflen, "vendor=0x%hx device=0x%hx rev=0x%hhx",
762 	    bhnd_get_vendor(child), bhnd_get_device(child),
763 	    bhnd_get_hwrev(child));
764 
765 	return (0);
766 }
767 
768 /**
769  * Default implementation of BUS_CHILD_LOCATION_STR().
770  */
771 static int
772 bhnd_child_location_str(device_t dev, device_t child, char *buf,
773     size_t buflen)
774 {
775 	bhnd_addr_t	addr;
776 	bhnd_size_t	size;
777 
778 	if (device_get_parent(child) != dev) {
779 		return (BUS_CHILD_LOCATION_STR(device_get_parent(dev), child,
780 		    buf, buflen));
781 	}
782 
783 
784 	if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) {
785 		/* No device default port/region */
786 		if (buflen > 0)
787 			*buf = '\0';
788 		return (0);
789 	}
790 
791 	snprintf(buf, buflen, "port0.0=0x%llx", (unsigned long long) addr);
792 	return (0);
793 }
794 
795 /**
796  * Default bhnd(4) bus driver implementation of BUS_ADD_CHILD().
797  *
798  * This implementation manages internal bhnd(4) state, and must be called
799  * by subclassing drivers.
800  */
801 device_t
802 bhnd_generic_add_child(device_t dev, u_int order, const char *name, int unit)
803 {
804 	struct bhnd_devinfo	*dinfo;
805 	device_t		 child;
806 
807 	child = device_add_child_ordered(dev, order, name, unit);
808 	if (child == NULL)
809 		return (NULL);
810 
811 	if ((dinfo = BHND_BUS_ALLOC_DEVINFO(dev)) == NULL) {
812 		device_delete_child(dev, child);
813 		return (NULL);
814 	}
815 
816 	device_set_ivars(child, dinfo);
817 
818 	/* Inform concrete bus driver. */
819 	BHND_BUS_CHILD_ADDED(dev, child);
820 
821 	return (child);
822 }
823 
824 /**
825  * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED().
826  *
827  * This implementation manages internal bhnd(4) state, and must be called
828  * by subclassing drivers.
829  */
830 void
831 bhnd_generic_child_deleted(device_t dev, device_t child)
832 {
833 	struct bhnd_softc	*sc;
834 	struct bhnd_devinfo	*dinfo;
835 
836 	sc = device_get_softc(dev);
837 
838 	/* Free device info */
839 	if ((dinfo = device_get_ivars(child)) != NULL)
840 		BHND_BUS_FREE_DEVINFO(dev, dinfo);
841 
842 	/* Clean up platform device references */
843 	if (sc->chipc_dev == child) {
844 		sc->chipc_dev = NULL;
845 	} else if (sc->nvram_dev == child) {
846 		sc->nvram_dev = NULL;
847 	} else if (sc->pmu_dev == child) {
848 		sc->pmu_dev = NULL;
849 	}
850 }
851 
852 /**
853  * Helper function for implementing BUS_SUSPEND_CHILD().
854  *
855  * TODO: Power management
856  *
857  * If @p child is not a direct child of @p dev, suspension is delegated to
858  * the @p dev parent.
859  */
860 int
861 bhnd_generic_suspend_child(device_t dev, device_t child)
862 {
863 	if (device_get_parent(child) != dev)
864 		BUS_SUSPEND_CHILD(device_get_parent(dev), child);
865 
866 	return bus_generic_suspend_child(dev, child);
867 }
868 
869 /**
870  * Helper function for implementing BUS_RESUME_CHILD().
871  *
872  * TODO: Power management
873  *
874  * If @p child is not a direct child of @p dev, suspension is delegated to
875  * the @p dev parent.
876  */
877 int
878 bhnd_generic_resume_child(device_t dev, device_t child)
879 {
880 	if (device_get_parent(child) != dev)
881 		BUS_RESUME_CHILD(device_get_parent(dev), child);
882 
883 	return bus_generic_resume_child(dev, child);
884 }
885 
886 /*
887  * Delegate all indirect I/O to the parent device. When inherited by
888  * non-bridged bus implementations, resources will never be marked as
889  * indirect, and these methods will never be called.
890  */
891 #define	BHND_IO_READ(_type, _name, _method)				\
892 static _type								\
893 bhnd_read_ ## _name (device_t dev, device_t child,			\
894     struct bhnd_resource *r, bus_size_t offset)				\
895 {									\
896 	return (BHND_BUS_READ_ ## _method(				\
897 		    device_get_parent(dev), child, r, offset));		\
898 }
899 
900 #define	BHND_IO_WRITE(_type, _name, _method)				\
901 static void								\
902 bhnd_write_ ## _name (device_t dev, device_t child,			\
903     struct bhnd_resource *r, bus_size_t offset, _type value)		\
904 {									\
905 	return (BHND_BUS_WRITE_ ## _method(				\
906 		    device_get_parent(dev), child, r, offset,		\
907 		    value));	\
908 }
909 
910 #define	BHND_IO_MISC(_type, _op, _method)				\
911 static void								\
912 bhnd_ ## _op (device_t dev, device_t child,				\
913     struct bhnd_resource *r, bus_size_t offset, _type datap,		\
914     bus_size_t count)							\
915 {									\
916 	BHND_BUS_ ## _method(device_get_parent(dev), child, r,		\
917 	    offset, datap, count);					\
918 }
919 
920 #define	BHND_IO_METHODS(_type, _size)					\
921 	BHND_IO_READ(_type, _size, _size)				\
922 	BHND_IO_WRITE(_type, _size, _size)				\
923 									\
924 	BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size)		\
925 	BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size)	\
926 									\
927 	BHND_IO_MISC(_type*, read_multi_ ## _size,			\
928 	    READ_MULTI_ ## _size)					\
929 	BHND_IO_MISC(_type*, write_multi_ ## _size,			\
930 	    WRITE_MULTI_ ## _size)					\
931 									\
932 	BHND_IO_MISC(_type*, read_multi_stream_ ## _size,		\
933 	   READ_MULTI_STREAM_ ## _size)					\
934 	BHND_IO_MISC(_type*, write_multi_stream_ ## _size,		\
935 	   WRITE_MULTI_STREAM_ ## _size)				\
936 									\
937 	BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size)	\
938 	BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size)	\
939 									\
940 	BHND_IO_MISC(_type*, read_region_ ## _size,			\
941 	    READ_REGION_ ## _size)					\
942 	BHND_IO_MISC(_type*, write_region_ ## _size,			\
943 	    WRITE_REGION_ ## _size)					\
944 									\
945 	BHND_IO_MISC(_type*, read_region_stream_ ## _size,		\
946 	    READ_REGION_STREAM_ ## _size)				\
947 	BHND_IO_MISC(_type*, write_region_stream_ ## _size,		\
948 	    WRITE_REGION_STREAM_ ## _size)				\
949 
950 BHND_IO_METHODS(uint8_t, 1);
951 BHND_IO_METHODS(uint16_t, 2);
952 BHND_IO_METHODS(uint32_t, 4);
953 
954 static void
955 bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r,
956     bus_size_t offset, bus_size_t length, int flags)
957 {
958 	BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length,
959 	    flags);
960 }
961 
962 static device_method_t bhnd_methods[] = {
963 	/* Device interface */ \
964 	DEVMETHOD(device_attach,		bhnd_generic_attach),
965 	DEVMETHOD(device_detach,		bhnd_generic_detach),
966 	DEVMETHOD(device_shutdown,		bhnd_generic_shutdown),
967 	DEVMETHOD(device_suspend,		bhnd_generic_suspend),
968 	DEVMETHOD(device_resume,		bhnd_generic_resume),
969 
970 	/* Bus interface */
971 	DEVMETHOD(bus_new_pass,			bhnd_new_pass),
972 	DEVMETHOD(bus_add_child,		bhnd_generic_add_child),
973 	DEVMETHOD(bus_child_deleted,		bhnd_generic_child_deleted),
974 	DEVMETHOD(bus_probe_nomatch,		bhnd_generic_probe_nomatch),
975 	DEVMETHOD(bus_print_child,		bhnd_generic_print_child),
976 	DEVMETHOD(bus_child_pnpinfo_str,	bhnd_child_pnpinfo_str),
977 	DEVMETHOD(bus_child_location_str,	bhnd_child_location_str),
978 
979 	DEVMETHOD(bus_suspend_child,		bhnd_generic_suspend_child),
980 	DEVMETHOD(bus_resume_child,		bhnd_generic_resume_child),
981 
982 	DEVMETHOD(bus_set_resource,		bus_generic_rl_set_resource),
983 	DEVMETHOD(bus_get_resource,		bus_generic_rl_get_resource),
984 	DEVMETHOD(bus_delete_resource,		bus_generic_rl_delete_resource),
985 	DEVMETHOD(bus_alloc_resource,		bus_generic_rl_alloc_resource),
986 	DEVMETHOD(bus_adjust_resource,		bus_generic_adjust_resource),
987 	DEVMETHOD(bus_release_resource,		bus_generic_rl_release_resource),
988 	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
989 	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
990 
991 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
992 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
993 	DEVMETHOD(bus_config_intr,		bus_generic_config_intr),
994 	DEVMETHOD(bus_bind_intr,		bus_generic_bind_intr),
995 	DEVMETHOD(bus_describe_intr,		bus_generic_describe_intr),
996 
997 	DEVMETHOD(bus_get_dma_tag,		bus_generic_get_dma_tag),
998 
999 	/* BHND interface */
1000 	DEVMETHOD(bhnd_bus_get_chipid,		bhnd_bus_generic_get_chipid),
1001 	DEVMETHOD(bhnd_bus_get_probe_order,	bhnd_generic_get_probe_order),
1002 	DEVMETHOD(bhnd_bus_is_region_valid,	bhnd_generic_is_region_valid),
1003 	DEVMETHOD(bhnd_bus_is_hw_disabled,	bhnd_bus_generic_is_hw_disabled),
1004 	DEVMETHOD(bhnd_bus_get_nvram_var,	bhnd_generic_get_nvram_var),
1005 
1006 	/* BHND interface (bus I/O) */
1007 	DEVMETHOD(bhnd_bus_read_1,		bhnd_read_1),
1008 	DEVMETHOD(bhnd_bus_read_2,		bhnd_read_2),
1009 	DEVMETHOD(bhnd_bus_read_4,		bhnd_read_4),
1010 	DEVMETHOD(bhnd_bus_write_1,		bhnd_write_1),
1011 	DEVMETHOD(bhnd_bus_write_2,		bhnd_write_2),
1012 	DEVMETHOD(bhnd_bus_write_4,		bhnd_write_4),
1013 
1014 	DEVMETHOD(bhnd_bus_read_stream_1,	bhnd_read_stream_1),
1015 	DEVMETHOD(bhnd_bus_read_stream_2,	bhnd_read_stream_2),
1016 	DEVMETHOD(bhnd_bus_read_stream_4,	bhnd_read_stream_4),
1017 	DEVMETHOD(bhnd_bus_write_stream_1,	bhnd_write_stream_1),
1018 	DEVMETHOD(bhnd_bus_write_stream_2,	bhnd_write_stream_2),
1019 	DEVMETHOD(bhnd_bus_write_stream_4,	bhnd_write_stream_4),
1020 
1021 	DEVMETHOD(bhnd_bus_read_multi_1,	bhnd_read_multi_1),
1022 	DEVMETHOD(bhnd_bus_read_multi_2,	bhnd_read_multi_2),
1023 	DEVMETHOD(bhnd_bus_read_multi_4,	bhnd_read_multi_4),
1024 	DEVMETHOD(bhnd_bus_write_multi_1,	bhnd_write_multi_1),
1025 	DEVMETHOD(bhnd_bus_write_multi_2,	bhnd_write_multi_2),
1026 	DEVMETHOD(bhnd_bus_write_multi_4,	bhnd_write_multi_4),
1027 
1028 	DEVMETHOD(bhnd_bus_read_multi_stream_1,	bhnd_read_multi_stream_1),
1029 	DEVMETHOD(bhnd_bus_read_multi_stream_2,	bhnd_read_multi_stream_2),
1030 	DEVMETHOD(bhnd_bus_read_multi_stream_4,	bhnd_read_multi_stream_4),
1031 	DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1),
1032 	DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2),
1033 	DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4),
1034 
1035 	DEVMETHOD(bhnd_bus_set_multi_1,		bhnd_set_multi_1),
1036 	DEVMETHOD(bhnd_bus_set_multi_2,		bhnd_set_multi_2),
1037 	DEVMETHOD(bhnd_bus_set_multi_4,		bhnd_set_multi_4),
1038 
1039 	DEVMETHOD(bhnd_bus_set_region_1,	bhnd_set_region_1),
1040 	DEVMETHOD(bhnd_bus_set_region_2,	bhnd_set_region_2),
1041 	DEVMETHOD(bhnd_bus_set_region_4,	bhnd_set_region_4),
1042 
1043 	DEVMETHOD(bhnd_bus_read_region_1,	bhnd_read_region_1),
1044 	DEVMETHOD(bhnd_bus_read_region_2,	bhnd_read_region_2),
1045 	DEVMETHOD(bhnd_bus_read_region_4,	bhnd_read_region_4),
1046 	DEVMETHOD(bhnd_bus_write_region_1,	bhnd_write_region_1),
1047 	DEVMETHOD(bhnd_bus_write_region_2,	bhnd_write_region_2),
1048 	DEVMETHOD(bhnd_bus_write_region_4,	bhnd_write_region_4),
1049 
1050 	DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1),
1051 	DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2),
1052 	DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4),
1053 	DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1),
1054 	DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2),
1055 	DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4),
1056 
1057 	DEVMETHOD(bhnd_bus_barrier,			bhnd_barrier),
1058 
1059 	DEVMETHOD_END
1060 };
1061 
1062 devclass_t bhnd_devclass;	/**< bhnd bus. */
1063 devclass_t bhnd_hostb_devclass;	/**< bhnd bus host bridge. */
1064 devclass_t bhnd_nvram_devclass;	/**< bhnd NVRAM device */
1065 
1066 DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc));
1067 MODULE_VERSION(bhnd, 1);
1068