]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/bhnd.c
MFV: r325668
[FreeBSD/FreeBSD.git] / sys / dev / bhnd / bhnd.c
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);