]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/bhnd.c
Add liblutok a lightweight C++ API for lua.
[FreeBSD/FreeBSD.git] / sys / dev / bhnd / bhnd.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
5  * Copyright (c) 2017 The FreeBSD Foundation
6  * All rights reserved.
7  *
8  * Portions of this software were developed by Landon Fuller
9  * under sponsorship from the FreeBSD Foundation.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
19  *    redistribution must be conditioned upon including a substantially
20  *    similar Disclaimer requirement for further binary redistribution.
21  *
22  * NO WARRANTY
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
26  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
27  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
28  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
31  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33  * THE POSSIBILITY OF SUCH DAMAGES.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 /*
40  * Broadcom Home Networking Division (HND) Bus Driver.
41  * 
42  * The Broadcom HND family of devices consists of both SoCs and host-connected
43  * networking chipsets containing a common family of Broadcom IP cores,
44  * including an integrated MIPS and/or ARM cores.
45  * 
46  * HND devices expose a nearly identical interface whether accessible over a 
47  * native SoC interconnect, or when connected via a host interface such as 
48  * PCIe. As a result, the majority of hardware support code should be re-usable 
49  * across host drivers for HND networking chipsets, as well as FreeBSD support 
50  * for Broadcom MIPS/ARM HND SoCs.
51  * 
52  * Earlier HND models used the siba(4) on-chip interconnect, while later models
53  * use bcma(4); the programming model is almost entirely independent
54  * of the actual underlying interconect.
55  */
56
57 #include <sys/param.h>
58 #include <sys/kernel.h>
59 #include <sys/bus.h>
60 #include <sys/module.h>
61 #include <sys/systm.h>
62
63 #include <machine/bus.h>
64 #include <sys/rman.h>
65 #include <machine/resource.h>
66
67 #include <dev/bhnd/cores/pmu/bhnd_pmu.h>
68
69 #include "bhnd_chipc_if.h"
70 #include "bhnd_nvram_if.h"
71
72 #include "bhnd.h"
73 #include "bhndreg.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            *r;
367         struct bhnd_core_clkctl         *clkctl;
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         u_int                            max_latency;
375         int                              error;
376
377         GIANT_REQUIRED; /* for newbus */
378
379         if (device_get_parent(child) != dev)
380                 return (EINVAL);
381
382         sc = device_get_softc(dev);
383         clkctl = bhnd_get_pmu_info(child);
384         pmu_regs = BHND_CLK_CTL_ST;
385
386         /* already allocated? */
387         if (clkctl != NULL) {
388                 panic("duplicate PMU allocation for %s",
389                     device_get_nameunit(child));
390         }
391
392         /* Determine address+size of the core's PMU register block */
393         error = bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &r_addr,
394             &r_size);
395         if (error) {
396                 device_printf(sc->dev, "error fetching register block info for "
397                     "%s: %d\n", device_get_nameunit(child), error);
398                 return (error);
399         }
400
401         if (r_size < (pmu_regs + sizeof(uint32_t))) {
402                 device_printf(sc->dev, "pmu offset %#jx would overrun %s "
403                     "register block\n", (uintmax_t)pmu_regs,
404                     device_get_nameunit(child));
405                 return (ENODEV);
406         }
407
408         /* Locate actual resource containing the core's register block */
409         if ((rl = BUS_GET_RESOURCE_LIST(dev, child)) == NULL) {
410                 device_printf(dev, "NULL resource list returned for %s\n",
411                     device_get_nameunit(child));
412                 return (ENXIO);
413         }
414
415         if ((rle = resource_list_find(rl, SYS_RES_MEMORY, 0)) == NULL) {
416                 device_printf(dev, "cannot locate core register resource "
417                     "for %s\n", device_get_nameunit(child));
418                 return (ENXIO);
419         }
420
421         if (rle->res == NULL) {
422                 device_printf(dev, "core register resource unallocated for "
423                     "%s\n", device_get_nameunit(child));
424                 return (ENXIO);
425         }
426
427         if (r_addr+pmu_regs < rman_get_start(rle->res) ||
428             r_addr+pmu_regs >= rman_get_end(rle->res))
429         {
430                 device_printf(dev, "core register resource does not map PMU "
431                     "registers at %#jx\n for %s\n", r_addr+pmu_regs,
432                     device_get_nameunit(child));
433                 return (ENXIO);
434         }
435
436         /* Adjust PMU register offset relative to the actual start address
437          * of the core's register block allocation.
438          * 
439          * XXX: The saved offset will be invalid if bus_adjust_resource is
440          * used to modify the resource's start address.
441          */
442         if (rman_get_start(rle->res) > r_addr)
443                 pmu_regs -= rman_get_start(rle->res) - r_addr;
444         else
445                 pmu_regs -= r_addr - rman_get_start(rle->res);
446
447         /* Retain a PMU reference for the clkctl instance state */
448         pmu_dev = bhnd_retain_provider(child, BHND_SERVICE_PMU);
449         if (pmu_dev == NULL) {
450                 device_printf(sc->dev, "PMU not found\n");
451                 return (ENXIO);
452         }
453
454         /* Fetch the maximum transition latency from our PMU */
455         max_latency = bhnd_pmu_get_max_transition_latency(pmu_dev);
456
457         /* Allocate a new bhnd_resource wrapping the standard resource we
458          * fetched from the resource list; we'll free this in
459          * bhnd_generic_release_pmu() */
460         r = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT);
461         if (r == NULL) {
462                 bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU);
463                 return (ENOMEM);
464         }
465
466         r->res = rle->res;
467         r->direct = ((rman_get_flags(rle->res) & RF_ACTIVE) != 0);
468
469         /* Allocate the clkctl instance */
470         clkctl = bhnd_alloc_core_clkctl(child, pmu_dev, r, pmu_regs,
471             max_latency);
472         if (clkctl == NULL) {
473                 free(r, M_BHND);
474                 bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU);
475                 return (ENOMEM);
476         }
477
478         bhnd_set_pmu_info(child, clkctl);
479         return (0);
480 }
481
482 /**
483  * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_PMU().
484  */
485 int
486 bhnd_generic_release_pmu(device_t dev, device_t child)
487 {
488         struct bhnd_softc       *sc;
489         struct bhnd_core_clkctl *clkctl;
490         struct bhnd_resource    *r;
491         device_t                 pmu_dev;
492
493         GIANT_REQUIRED; /* for newbus */
494         
495         sc = device_get_softc(dev);
496
497         if (device_get_parent(child) != dev)
498                 return (EINVAL);
499
500         clkctl = bhnd_get_pmu_info(child);
501         if (clkctl == NULL)
502                 panic("pmu over-release for %s", device_get_nameunit(child));
503
504         /* Clear all FORCE, AREQ, and ERSRC flags, unless we're already in
505          * RESET. Suspending a core clears clkctl automatically (and attempting
506          * to access the PMU registers in a suspended core will trigger a
507          * system livelock). */
508         if (!bhnd_is_hw_suspended(clkctl->cc_dev)) {
509                 BHND_CLKCTL_LOCK(clkctl);
510
511                 /* Clear all FORCE, AREQ, and ERSRC flags */
512                 BHND_CLKCTL_SET_4(clkctl, 0x0, BHND_CCS_FORCE_MASK |
513                     BHND_CCS_AREQ_MASK | BHND_CCS_ERSRC_REQ_MASK);
514
515                 BHND_CLKCTL_UNLOCK(clkctl);
516         }
517
518         /* Clear child's PMU info reference */
519         bhnd_set_pmu_info(child, NULL);
520
521         /* Before freeing the clkctl instance, save a pointer to resources we
522          * need to clean up manually */
523         r = clkctl->cc_res;
524         pmu_dev = clkctl->cc_pmu_dev;
525
526         /* Free the clkctl instance */
527         bhnd_free_core_clkctl(clkctl);
528
529         /* Free the child's bhnd resource wrapper */
530         free(r, M_BHND);
531
532         /* Release the child's PMU provider reference */
533         bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU);
534
535         return (0);
536 }
537
538 /**
539  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_CLOCK_LATENCY().
540  */
541 int
542 bhnd_generic_get_clock_latency(device_t dev, device_t child, bhnd_clock clock,
543     u_int *latency)
544 {
545         struct bhnd_core_clkctl *clkctl;
546
547         if (device_get_parent(child) != dev)
548                 return (EINVAL);
549
550         if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
551                 panic("no active PMU allocation");
552
553         return (bhnd_pmu_get_clock_latency(clkctl->cc_pmu_dev, clock, latency));
554 }
555
556 /**
557  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_CLOCK_FREQ().
558  */
559 int
560 bhnd_generic_get_clock_freq(device_t dev, device_t child, bhnd_clock clock,
561     u_int *freq)
562 {
563         struct bhnd_core_clkctl *clkctl;
564
565         if (device_get_parent(child) != dev)
566                 return (EINVAL);
567
568         if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
569                 panic("no active PMU allocation");
570
571         return (bhnd_pmu_get_clock_freq(clkctl->cc_pmu_dev, clock, freq));
572 }
573
574 /**
575  * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_CLOCK().
576  */
577 int
578 bhnd_generic_request_clock(device_t dev, device_t child, bhnd_clock clock)
579 {
580         struct bhnd_softc       *sc;
581         struct bhnd_core_clkctl *clkctl;
582         uint32_t                 avail;
583         uint32_t                 req;
584         int                      error;
585
586         sc = device_get_softc(dev);
587
588         if (device_get_parent(child) != dev)
589                 return (EINVAL);
590
591         if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
592                 panic("no active PMU allocation");
593
594         BHND_ASSERT_CLKCTL_AVAIL(clkctl);
595
596         avail = 0x0;
597         req = 0x0;
598
599         switch (clock) {
600         case BHND_CLOCK_DYN:
601                 break;
602         case BHND_CLOCK_ILP:
603                 req |= BHND_CCS_FORCEILP;
604                 break;
605         case BHND_CLOCK_ALP:
606                 req |= BHND_CCS_FORCEALP;
607                 avail |= BHND_CCS_ALPAVAIL;
608                 break;
609         case BHND_CLOCK_HT:
610                 req |= BHND_CCS_FORCEHT;
611                 avail |= BHND_CCS_HTAVAIL;
612                 break;
613         default:
614                 device_printf(dev, "%s requested unknown clock: %#x\n",
615                     device_get_nameunit(clkctl->cc_dev), clock);
616                 return (ENODEV);
617         }
618
619         BHND_CLKCTL_LOCK(clkctl);
620
621         /* Issue request */
622         BHND_CLKCTL_SET_4(clkctl, req, BHND_CCS_FORCE_MASK);
623
624         /* Wait for clock availability */
625         error = bhnd_core_clkctl_wait(clkctl, avail, avail);
626
627         BHND_CLKCTL_UNLOCK(clkctl);
628
629         return (error);
630 }
631
632 /**
633  * Default bhnd(4) bus driver implementation of BHND_BUS_ENABLE_CLOCKS().
634  */
635 int
636 bhnd_generic_enable_clocks(device_t dev, device_t child, uint32_t clocks)
637 {
638         struct bhnd_softc       *sc;
639         struct bhnd_core_clkctl *clkctl;
640         uint32_t                 avail;
641         uint32_t                 req;
642         int                      error;
643
644         sc = device_get_softc(dev);
645
646         if (device_get_parent(child) != dev)
647                 return (EINVAL);
648
649         if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
650                 panic("no active PMU allocation");
651
652         BHND_ASSERT_CLKCTL_AVAIL(clkctl);
653
654         sc = device_get_softc(dev);
655
656         avail = 0x0;
657         req = 0x0;
658
659         /* Build clock request flags */
660         if (clocks & BHND_CLOCK_DYN)            /* nothing to enable */
661                 clocks &= ~BHND_CLOCK_DYN;
662
663         if (clocks & BHND_CLOCK_ILP)            /* nothing to enable */
664                 clocks &= ~BHND_CLOCK_ILP;
665
666         if (clocks & BHND_CLOCK_ALP) {
667                 req |= BHND_CCS_ALPAREQ;
668                 avail |= BHND_CCS_ALPAVAIL;
669                 clocks &= ~BHND_CLOCK_ALP;
670         }
671
672         if (clocks & BHND_CLOCK_HT) {
673                 req |= BHND_CCS_HTAREQ;
674                 avail |= BHND_CCS_HTAVAIL;
675                 clocks &= ~BHND_CLOCK_HT;
676         }
677
678         /* Check for unknown clock values */
679         if (clocks != 0x0) {
680                 device_printf(dev, "%s requested unknown clocks: %#x\n",
681                     device_get_nameunit(clkctl->cc_dev), clocks);
682                 return (ENODEV);
683         }
684
685         BHND_CLKCTL_LOCK(clkctl);
686
687         /* Issue request */
688         BHND_CLKCTL_SET_4(clkctl, req, BHND_CCS_AREQ_MASK);
689
690         /* Wait for clock availability */
691         error = bhnd_core_clkctl_wait(clkctl, avail, avail);
692
693         BHND_CLKCTL_UNLOCK(clkctl);
694
695         return (error);
696 }
697
698 /**
699  * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_EXT_RSRC().
700  */
701 int
702 bhnd_generic_request_ext_rsrc(device_t dev, device_t child, u_int rsrc)
703 {
704         struct bhnd_softc       *sc;
705         struct bhnd_core_clkctl *clkctl;
706         uint32_t                 req;
707         uint32_t                 avail;
708         int                      error;
709
710         sc = device_get_softc(dev);
711
712         if (device_get_parent(child) != dev)
713                 return (EINVAL);
714
715         if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
716                 panic("no active PMU allocation");
717
718         BHND_ASSERT_CLKCTL_AVAIL(clkctl);
719
720         sc = device_get_softc(dev);
721
722         if (rsrc > BHND_CCS_ERSRC_MAX)
723                 return (EINVAL);
724
725         req = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
726         avail = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_STS);
727
728         BHND_CLKCTL_LOCK(clkctl);
729
730         /* Write request */
731         BHND_CLKCTL_SET_4(clkctl, req, req);
732
733         /* Wait for resource availability */
734         error = bhnd_core_clkctl_wait(clkctl, avail, avail);
735
736         BHND_CLKCTL_UNLOCK(clkctl);
737
738         return (error);
739 }
740
741 /**
742  * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_EXT_RSRC().
743  */
744 int
745 bhnd_generic_release_ext_rsrc(device_t dev, device_t child, u_int rsrc)
746 {
747         struct bhnd_softc       *sc;
748         struct bhnd_core_clkctl *clkctl;
749         uint32_t                 mask;
750
751         sc = device_get_softc(dev);
752
753         if (device_get_parent(child) != dev)
754                 return (EINVAL);
755
756         if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
757                 panic("no active PMU allocation");
758
759
760         BHND_ASSERT_CLKCTL_AVAIL(clkctl);
761
762         sc = device_get_softc(dev);
763
764         if (rsrc > BHND_CCS_ERSRC_MAX)
765                 return (EINVAL);
766
767         mask = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
768
769         /* Clear request */
770         BHND_CLKCTL_LOCK(clkctl);
771         BHND_CLKCTL_SET_4(clkctl, 0x0, mask);
772         BHND_CLKCTL_UNLOCK(clkctl);
773
774         return (0);
775 }
776
777 /**
778  * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
779  * 
780  * This implementation assumes that port and region numbers are 0-indexed and
781  * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and
782  * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall
783  * within the defined range.
784  */
785 static bool
786 bhnd_generic_is_region_valid(device_t dev, device_t child,
787     bhnd_port_type type, u_int port, u_int region)
788 {
789         if (port >= bhnd_get_port_count(child, type))
790                 return (false);
791
792         if (region >= bhnd_get_region_count(child, type, port))
793                 return (false);
794
795         return (true);
796 }
797
798 /**
799  * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
800  * 
801  * This implementation searches @p dev for a registered NVRAM child device.
802  * 
803  * If no NVRAM device is registered with @p dev, the request is delegated to
804  * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
805  */
806 int
807 bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
808     void *buf, size_t *size, bhnd_nvram_type type)
809 {
810         struct bhnd_softc       *sc;
811         device_t                 nvram, parent;
812         int                      error;
813
814         sc = device_get_softc(dev);
815
816         /* If a NVRAM device is available, consult it first */
817         nvram = bhnd_retain_provider(child, BHND_SERVICE_NVRAM);
818         if (nvram != NULL) {
819                 error = BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
820                 bhnd_release_provider(child, nvram, BHND_SERVICE_NVRAM);
821                 return (error);
822         }
823
824         /* Otherwise, try to delegate to parent */
825         if ((parent = device_get_parent(dev)) == NULL)
826                 return (ENODEV);
827
828         return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
829             name, buf, size, type));
830 }
831
832 /**
833  * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD().
834  * 
835  * This implementation requests the device's struct resource_list via
836  * BUS_GET_RESOURCE_LIST.
837  */
838 int
839 bhnd_generic_print_child(device_t dev, device_t child)
840 {
841         struct resource_list    *rl;
842         int                     retval = 0;
843
844         retval += bus_print_child_header(dev, child);
845
846         rl = BUS_GET_RESOURCE_LIST(dev, child);
847         
848         
849         if (rl != NULL) {
850                 retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
851                     "%#jx");
852
853                 retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ,
854                     "%#jd");
855         }
856
857         retval += printf(" at core %u", bhnd_get_core_index(child));
858
859         retval += bus_print_child_domain(dev, child);
860         retval += bus_print_child_footer(dev, child);
861
862         return (retval);
863 }
864
865 /**
866  * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH().
867  * 
868  * This implementation requests the device's struct resource_list via
869  * BUS_GET_RESOURCE_LIST.
870  */
871 void
872 bhnd_generic_probe_nomatch(device_t dev, device_t child)
873 {
874         struct resource_list            *rl;
875         const struct bhnd_nomatch       *nm;
876         bool                             report;
877
878         /* Fetch reporting configuration for this device */
879         report = true;
880         for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) {
881                 if (nm->vendor != bhnd_get_vendor(child))
882                         continue;
883
884                 if (nm->device != bhnd_get_device(child))
885                         continue;
886
887                 report = false;
888                 if (bootverbose && nm->if_verbose)
889                         report = true;
890                 break;
891         }
892         
893         if (!report)
894                 return;
895
896         /* Print the non-matched device info */
897         device_printf(dev, "<%s %s, rev %hhu>", bhnd_get_vendor_name(child),
898                 bhnd_get_device_name(child), bhnd_get_hwrev(child));
899
900         rl = BUS_GET_RESOURCE_LIST(dev, child);
901         if (rl != NULL) {
902                 resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
903                 resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%#jd");
904         }
905
906         printf(" at core %u (no driver attached)\n",
907             bhnd_get_core_index(child));
908 }
909
910 /**
911  * Default implementation of BUS_CHILD_PNPINFO_STR().
912  */
913 static int
914 bhnd_child_pnpinfo_str(device_t dev, device_t child, char *buf,
915     size_t buflen)
916 {
917         if (device_get_parent(child) != dev) {
918                 return (BUS_CHILD_PNPINFO_STR(device_get_parent(dev), child,
919                     buf, buflen));
920         }
921
922         snprintf(buf, buflen, "vendor=0x%hx device=0x%hx rev=0x%hhx",
923             bhnd_get_vendor(child), bhnd_get_device(child),
924             bhnd_get_hwrev(child));
925
926         return (0);
927 }
928
929 /**
930  * Default implementation of BUS_CHILD_LOCATION_STR().
931  */
932 static int
933 bhnd_child_location_str(device_t dev, device_t child, char *buf,
934     size_t buflen)
935 {
936         bhnd_addr_t     addr;
937         bhnd_size_t     size;
938         
939         if (device_get_parent(child) != dev) {
940                 return (BUS_CHILD_LOCATION_STR(device_get_parent(dev), child,
941                     buf, buflen));
942         }
943
944
945         if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size)) {
946                 /* No device default port/region */
947                 if (buflen > 0)
948                         *buf = '\0';
949                 return (0);
950         }
951
952         snprintf(buf, buflen, "port0.0=0x%llx", (unsigned long long) addr);
953         return (0);
954 }
955
956 /**
957  * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED().
958  * 
959  * This implementation manages internal bhnd(4) state, and must be called
960  * by subclassing drivers.
961  */
962 void
963 bhnd_generic_child_deleted(device_t dev, device_t child)
964 {
965         struct bhnd_softc       *sc;
966
967         sc = device_get_softc(dev);
968
969         /* Free device info */
970         if (bhnd_get_pmu_info(child) != NULL) {
971                 /* Releasing PMU requests automatically would be nice,
972                  * but we can't reference per-core PMU register
973                  * resource after driver detach */
974                 panic("%s leaked device pmu state\n",
975                     device_get_nameunit(child));
976         }
977 }
978
979 /**
980  * Helper function for implementing BUS_SUSPEND_CHILD().
981  *
982  * TODO: Power management
983  * 
984  * If @p child is not a direct child of @p dev, suspension is delegated to
985  * the @p dev parent.
986  */
987 int
988 bhnd_generic_suspend_child(device_t dev, device_t child)
989 {
990         if (device_get_parent(child) != dev)
991                 BUS_SUSPEND_CHILD(device_get_parent(dev), child);
992
993         return bus_generic_suspend_child(dev, child);
994 }
995
996 /**
997  * Helper function for implementing BUS_RESUME_CHILD().
998  *
999  * TODO: Power management
1000  * 
1001  * If @p child is not a direct child of @p dev, suspension is delegated to
1002  * the @p dev parent.
1003  */
1004 int
1005 bhnd_generic_resume_child(device_t dev, device_t child)
1006 {
1007         if (device_get_parent(child) != dev)
1008                 BUS_RESUME_CHILD(device_get_parent(dev), child);
1009
1010         return bus_generic_resume_child(dev, child);
1011 }
1012
1013
1014 /**
1015  * Default bhnd(4) bus driver implementation of BUS_SETUP_INTR().
1016  *
1017  * This implementation of BUS_SETUP_INTR() will delegate interrupt setup
1018  * to the parent of @p dev, if any.
1019  */
1020 int
1021 bhnd_generic_setup_intr(device_t dev, device_t child, struct resource *irq,
1022     int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
1023     void **cookiep)
1024 {
1025         return (bus_generic_setup_intr(dev, child, irq, flags, filter, intr,
1026             arg, cookiep));
1027 }
1028
1029 /*
1030  * Delegate all indirect I/O to the parent device. When inherited by
1031  * non-bridged bus implementations, resources will never be marked as
1032  * indirect, and these methods will never be called.
1033  */
1034 #define BHND_IO_READ(_type, _name, _method)                             \
1035 static _type                                                            \
1036 bhnd_read_ ## _name (device_t dev, device_t child,                      \
1037     struct bhnd_resource *r, bus_size_t offset)                         \
1038 {                                                                       \
1039         return (BHND_BUS_READ_ ## _method(                              \
1040                     device_get_parent(dev), child, r, offset));         \
1041 }
1042
1043 #define BHND_IO_WRITE(_type, _name, _method)                            \
1044 static void                                                             \
1045 bhnd_write_ ## _name (device_t dev, device_t child,                     \
1046     struct bhnd_resource *r, bus_size_t offset, _type value)            \
1047 {                                                                       \
1048         return (BHND_BUS_WRITE_ ## _method(                             \
1049                     device_get_parent(dev), child, r, offset,           \
1050                     value));    \
1051 }
1052
1053 #define BHND_IO_MISC(_type, _op, _method)                               \
1054 static void                                                             \
1055 bhnd_ ## _op (device_t dev, device_t child,                             \
1056     struct bhnd_resource *r, bus_size_t offset, _type datap,            \
1057     bus_size_t count)                                                   \
1058 {                                                                       \
1059         BHND_BUS_ ## _method(device_get_parent(dev), child, r,          \
1060             offset, datap, count);                                      \
1061 }       
1062
1063 #define BHND_IO_METHODS(_type, _size)                                   \
1064         BHND_IO_READ(_type, _size, _size)                               \
1065         BHND_IO_WRITE(_type, _size, _size)                              \
1066                                                                         \
1067         BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size)         \
1068         BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size)        \
1069                                                                         \
1070         BHND_IO_MISC(_type*, read_multi_ ## _size,                      \
1071             READ_MULTI_ ## _size)                                       \
1072         BHND_IO_MISC(_type*, write_multi_ ## _size,                     \
1073             WRITE_MULTI_ ## _size)                                      \
1074                                                                         \
1075         BHND_IO_MISC(_type*, read_multi_stream_ ## _size,               \
1076            READ_MULTI_STREAM_ ## _size)                                 \
1077         BHND_IO_MISC(_type*, write_multi_stream_ ## _size,              \
1078            WRITE_MULTI_STREAM_ ## _size)                                \
1079                                                                         \
1080         BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size)   \
1081         BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size) \
1082                                                                         \
1083         BHND_IO_MISC(_type*, read_region_ ## _size,                     \
1084             READ_REGION_ ## _size)                                      \
1085         BHND_IO_MISC(_type*, write_region_ ## _size,                    \
1086             WRITE_REGION_ ## _size)                                     \
1087                                                                         \
1088         BHND_IO_MISC(_type*, read_region_stream_ ## _size,              \
1089             READ_REGION_STREAM_ ## _size)                               \
1090         BHND_IO_MISC(_type*, write_region_stream_ ## _size,             \
1091             WRITE_REGION_STREAM_ ## _size)                              \
1092
1093 BHND_IO_METHODS(uint8_t, 1);
1094 BHND_IO_METHODS(uint16_t, 2);
1095 BHND_IO_METHODS(uint32_t, 4);
1096
1097 static void 
1098 bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r,
1099     bus_size_t offset, bus_size_t length, int flags)
1100 {
1101         BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length,
1102             flags);
1103 }
1104
1105 static device_method_t bhnd_methods[] = {
1106         /* Device interface */ \
1107         DEVMETHOD(device_attach,                bhnd_generic_attach),
1108         DEVMETHOD(device_detach,                bhnd_generic_detach),
1109         DEVMETHOD(device_shutdown,              bhnd_generic_shutdown),
1110         DEVMETHOD(device_suspend,               bhnd_generic_suspend),
1111         DEVMETHOD(device_resume,                bhnd_generic_resume),
1112
1113         /* Bus interface */
1114         DEVMETHOD(bus_child_deleted,            bhnd_generic_child_deleted),
1115         DEVMETHOD(bus_probe_nomatch,            bhnd_generic_probe_nomatch),
1116         DEVMETHOD(bus_print_child,              bhnd_generic_print_child),
1117         DEVMETHOD(bus_child_pnpinfo_str,        bhnd_child_pnpinfo_str),
1118         DEVMETHOD(bus_child_location_str,       bhnd_child_location_str),
1119
1120         DEVMETHOD(bus_suspend_child,            bhnd_generic_suspend_child),
1121         DEVMETHOD(bus_resume_child,             bhnd_generic_resume_child),
1122
1123         DEVMETHOD(bus_set_resource,             bus_generic_rl_set_resource),
1124         DEVMETHOD(bus_get_resource,             bus_generic_rl_get_resource),
1125         DEVMETHOD(bus_delete_resource,          bus_generic_rl_delete_resource),
1126         DEVMETHOD(bus_alloc_resource,           bus_generic_rl_alloc_resource),
1127         DEVMETHOD(bus_adjust_resource,          bus_generic_adjust_resource),
1128         DEVMETHOD(bus_release_resource,         bus_generic_rl_release_resource),
1129         DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
1130         DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
1131
1132         DEVMETHOD(bus_setup_intr,               bhnd_generic_setup_intr),
1133         DEVMETHOD(bus_teardown_intr,            bus_generic_teardown_intr),
1134         DEVMETHOD(bus_config_intr,              bus_generic_config_intr),
1135         DEVMETHOD(bus_bind_intr,                bus_generic_bind_intr),
1136         DEVMETHOD(bus_describe_intr,            bus_generic_describe_intr),
1137
1138         DEVMETHOD(bus_get_dma_tag,              bus_generic_get_dma_tag),
1139
1140         /* BHND interface */
1141         DEVMETHOD(bhnd_bus_get_chipid,          bhnd_bus_generic_get_chipid),
1142         DEVMETHOD(bhnd_bus_is_hw_disabled,      bhnd_bus_generic_is_hw_disabled),
1143
1144         DEVMETHOD(bhnd_bus_get_probe_order,     bhnd_generic_get_probe_order),
1145
1146         DEVMETHOD(bhnd_bus_alloc_pmu,           bhnd_generic_alloc_pmu),
1147         DEVMETHOD(bhnd_bus_release_pmu,         bhnd_generic_release_pmu),
1148         DEVMETHOD(bhnd_bus_request_clock,       bhnd_generic_request_clock),
1149         DEVMETHOD(bhnd_bus_enable_clocks,       bhnd_generic_enable_clocks),
1150         DEVMETHOD(bhnd_bus_request_ext_rsrc,    bhnd_generic_request_ext_rsrc),
1151         DEVMETHOD(bhnd_bus_release_ext_rsrc,    bhnd_generic_release_ext_rsrc),
1152         DEVMETHOD(bhnd_bus_get_clock_latency,   bhnd_generic_get_clock_latency),
1153         DEVMETHOD(bhnd_bus_get_clock_freq,      bhnd_generic_get_clock_freq),
1154
1155         DEVMETHOD(bhnd_bus_is_region_valid,     bhnd_generic_is_region_valid),
1156         DEVMETHOD(bhnd_bus_get_nvram_var,       bhnd_generic_get_nvram_var),
1157
1158         /* BHND interface (bus I/O) */
1159         DEVMETHOD(bhnd_bus_read_1,              bhnd_read_1),
1160         DEVMETHOD(bhnd_bus_read_2,              bhnd_read_2),
1161         DEVMETHOD(bhnd_bus_read_4,              bhnd_read_4),
1162         DEVMETHOD(bhnd_bus_write_1,             bhnd_write_1),
1163         DEVMETHOD(bhnd_bus_write_2,             bhnd_write_2),
1164         DEVMETHOD(bhnd_bus_write_4,             bhnd_write_4),
1165
1166         DEVMETHOD(bhnd_bus_read_stream_1,       bhnd_read_stream_1),
1167         DEVMETHOD(bhnd_bus_read_stream_2,       bhnd_read_stream_2),
1168         DEVMETHOD(bhnd_bus_read_stream_4,       bhnd_read_stream_4),
1169         DEVMETHOD(bhnd_bus_write_stream_1,      bhnd_write_stream_1),
1170         DEVMETHOD(bhnd_bus_write_stream_2,      bhnd_write_stream_2),
1171         DEVMETHOD(bhnd_bus_write_stream_4,      bhnd_write_stream_4),
1172
1173         DEVMETHOD(bhnd_bus_read_multi_1,        bhnd_read_multi_1),
1174         DEVMETHOD(bhnd_bus_read_multi_2,        bhnd_read_multi_2),
1175         DEVMETHOD(bhnd_bus_read_multi_4,        bhnd_read_multi_4),
1176         DEVMETHOD(bhnd_bus_write_multi_1,       bhnd_write_multi_1),
1177         DEVMETHOD(bhnd_bus_write_multi_2,       bhnd_write_multi_2),
1178         DEVMETHOD(bhnd_bus_write_multi_4,       bhnd_write_multi_4),
1179         
1180         DEVMETHOD(bhnd_bus_read_multi_stream_1, bhnd_read_multi_stream_1),
1181         DEVMETHOD(bhnd_bus_read_multi_stream_2, bhnd_read_multi_stream_2),
1182         DEVMETHOD(bhnd_bus_read_multi_stream_4, bhnd_read_multi_stream_4),
1183         DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1),
1184         DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2),
1185         DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4),
1186
1187         DEVMETHOD(bhnd_bus_set_multi_1,         bhnd_set_multi_1),
1188         DEVMETHOD(bhnd_bus_set_multi_2,         bhnd_set_multi_2),
1189         DEVMETHOD(bhnd_bus_set_multi_4,         bhnd_set_multi_4),
1190
1191         DEVMETHOD(bhnd_bus_set_region_1,        bhnd_set_region_1),
1192         DEVMETHOD(bhnd_bus_set_region_2,        bhnd_set_region_2),
1193         DEVMETHOD(bhnd_bus_set_region_4,        bhnd_set_region_4),
1194
1195         DEVMETHOD(bhnd_bus_read_region_1,       bhnd_read_region_1),
1196         DEVMETHOD(bhnd_bus_read_region_2,       bhnd_read_region_2),
1197         DEVMETHOD(bhnd_bus_read_region_4,       bhnd_read_region_4),
1198         DEVMETHOD(bhnd_bus_write_region_1,      bhnd_write_region_1),
1199         DEVMETHOD(bhnd_bus_write_region_2,      bhnd_write_region_2),
1200         DEVMETHOD(bhnd_bus_write_region_4,      bhnd_write_region_4),
1201
1202         DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1),
1203         DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2),
1204         DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4),
1205         DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1),
1206         DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2),
1207         DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4),
1208
1209         DEVMETHOD(bhnd_bus_barrier,                     bhnd_barrier),
1210
1211         DEVMETHOD_END
1212 };
1213
1214 devclass_t bhnd_devclass;       /**< bhnd bus. */
1215 devclass_t bhnd_hostb_devclass; /**< bhnd bus host bridge. */
1216 devclass_t bhnd_nvram_devclass; /**< bhnd NVRAM device */
1217
1218 DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc));
1219 MODULE_VERSION(bhnd, 1);