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