1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
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 /*
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/sbuf.h>
60 #include <sys/systm.h>
61
62 #include <machine/bus.h>
63 #include <sys/rman.h>
64 #include <machine/resource.h>
65
66 #include <dev/bhnd/cores/pmu/bhnd_pmu.h>
67
68 #include "bhnd_chipc_if.h"
69 #include "bhnd_nvram_if.h"
70
71 #include "bhnd.h"
72 #include "bhndreg.h"
73 #include "bhndvar.h"
74
75 #include "bhnd_private.h"
76
77 MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
78
79 /**
80 * bhnd_generic_probe_nomatch() reporting configuration.
81 */
82 static const struct bhnd_nomatch {
83 uint16_t vendor; /**< core designer */
84 uint16_t device; /**< core id */
85 bool if_verbose; /**< print when bootverbose is set. */
86 } bhnd_nomatch_table[] = {
87 { BHND_MFGID_ARM, BHND_COREID_OOB_ROUTER, true },
88 { BHND_MFGID_ARM, BHND_COREID_EROM, true },
89 { BHND_MFGID_ARM, BHND_COREID_PL301, true },
90 { BHND_MFGID_ARM, BHND_COREID_APB_BRIDGE, true },
91 { BHND_MFGID_ARM, BHND_COREID_AXI_UNMAPPED, false },
92 { BHND_MFGID_INVALID, BHND_COREID_INVALID, false }
93 };
94
95 static int bhnd_delete_children(struct bhnd_softc *sc);
96
97 /**
98 * Default bhnd(4) bus driver implementation of DEVICE_ATTACH().
99 *
100 * This implementation calls device_probe_and_attach() for each of the device's
101 * children, in bhnd probe order.
102 */
103 int
bhnd_generic_attach(device_t dev)104 bhnd_generic_attach(device_t dev)
105 {
106 struct bhnd_softc *sc;
107 int error;
108
109 if (device_is_attached(dev))
110 return (EBUSY);
111
112 sc = device_get_softc(dev);
113 sc->dev = dev;
114
115 /* Probe and attach all children */
116 if ((error = bhnd_bus_probe_children(dev))) {
117 bhnd_delete_children(sc);
118 return (error);
119 }
120
121 return (0);
122 }
123
124 /**
125 * Detach and delete all children, in reverse of their attach order.
126 */
127 static int
bhnd_delete_children(struct bhnd_softc * sc)128 bhnd_delete_children(struct bhnd_softc *sc)
129 {
130 device_t *devs;
131 int ndevs;
132 int error;
133
134 /* Fetch children in detach order */
135 error = bhnd_bus_get_children(sc->dev, &devs, &ndevs,
136 BHND_DEVICE_ORDER_DETACH);
137 if (error)
138 return (error);
139
140 /* Perform detach */
141 for (int i = 0; i < ndevs; i++) {
142 device_t child = devs[i];
143
144 /* Terminate on first error */
145 if ((error = device_delete_child(sc->dev, child)))
146 goto cleanup;
147 }
148
149 cleanup:
150 bhnd_bus_free_children(devs);
151 return (error);
152 }
153
154 /**
155 * Default bhnd(4) bus driver implementation of DEVICE_DETACH().
156 *
157 * This implementation calls device_detach() for each of the device's
158 * children, in reverse bhnd probe order, terminating if any call to
159 * device_detach() fails.
160 */
161 int
bhnd_generic_detach(device_t dev)162 bhnd_generic_detach(device_t dev)
163 {
164 struct bhnd_softc *sc;
165 int error;
166
167 if (!device_is_attached(dev))
168 return (EBUSY);
169
170 sc = device_get_softc(dev);
171
172 if ((error = bhnd_delete_children(sc)))
173 return (error);
174
175 return (0);
176 }
177
178 /**
179 * Default bhnd(4) bus driver implementation of DEVICE_SHUTDOWN().
180 *
181 * This implementation calls device_shutdown() for each of the device's
182 * children, in reverse bhnd probe order, terminating if any call to
183 * device_shutdown() fails.
184 */
185 int
bhnd_generic_shutdown(device_t dev)186 bhnd_generic_shutdown(device_t dev)
187 {
188 device_t *devs;
189 int ndevs;
190 int error;
191
192 if (!device_is_attached(dev))
193 return (EBUSY);
194
195 /* Fetch children in detach order */
196 error = bhnd_bus_get_children(dev, &devs, &ndevs,
197 BHND_DEVICE_ORDER_DETACH);
198 if (error)
199 return (error);
200
201 /* Perform shutdown */
202 for (int i = 0; i < ndevs; i++) {
203 device_t child = devs[i];
204
205 /* Terminate on first error */
206 if ((error = device_shutdown(child)))
207 goto cleanup;
208 }
209
210 cleanup:
211 bhnd_bus_free_children(devs);
212 return (error);
213 }
214
215 /**
216 * Default bhnd(4) bus driver implementation of DEVICE_RESUME().
217 *
218 * This implementation calls BUS_RESUME_CHILD() for each of the device's
219 * children in bhnd probe order, terminating if any call to BUS_RESUME_CHILD()
220 * fails.
221 */
222 int
bhnd_generic_resume(device_t dev)223 bhnd_generic_resume(device_t dev)
224 {
225 device_t *devs;
226 int ndevs;
227 int error;
228
229 if (!device_is_attached(dev))
230 return (EBUSY);
231
232 /* Fetch children in attach order */
233 error = bhnd_bus_get_children(dev, &devs, &ndevs,
234 BHND_DEVICE_ORDER_ATTACH);
235 if (error)
236 return (error);
237
238 /* Perform resume */
239 for (int i = 0; i < ndevs; i++) {
240 device_t child = devs[i];
241
242 /* Terminate on first error */
243 if ((error = BUS_RESUME_CHILD(device_get_parent(child), child)))
244 goto cleanup;
245 }
246
247 cleanup:
248 bhnd_bus_free_children(devs);
249 return (error);
250 }
251
252 /**
253 * Default bhnd(4) bus driver implementation of DEVICE_SUSPEND().
254 *
255 * This implementation calls BUS_SUSPEND_CHILD() for each of the device's
256 * children in reverse bhnd probe order. If any call to BUS_SUSPEND_CHILD()
257 * fails, the suspend operation is terminated and any devices that were
258 * suspended are resumed immediately by calling their BUS_RESUME_CHILD()
259 * methods.
260 */
261 int
bhnd_generic_suspend(device_t dev)262 bhnd_generic_suspend(device_t dev)
263 {
264 device_t *devs;
265 int ndevs;
266 int error;
267
268 if (!device_is_attached(dev))
269 return (EBUSY);
270
271 /* Fetch children in detach order */
272 error = bhnd_bus_get_children(dev, &devs, &ndevs,
273 BHND_DEVICE_ORDER_DETACH);
274 if (error)
275 return (error);
276
277 /* Perform suspend */
278 for (int i = 0; i < ndevs; i++) {
279 device_t child = devs[i];
280 error = BUS_SUSPEND_CHILD(device_get_parent(child), child);
281
282 /* On error, resume suspended devices and then terminate */
283 if (error) {
284 for (int j = 0; j < i; j++) {
285 BUS_RESUME_CHILD(device_get_parent(devs[j]),
286 devs[j]);
287 }
288
289 goto cleanup;
290 }
291 }
292
293 cleanup:
294 bhnd_bus_free_children(devs);
295 return (error);
296 }
297
298 /**
299 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_PROBE_ORDER().
300 *
301 * This implementation determines probe ordering based on the device's class
302 * and other properties, including whether the device is serving as a host
303 * bridge.
304 */
305 int
bhnd_generic_get_probe_order(device_t dev,device_t child)306 bhnd_generic_get_probe_order(device_t dev, device_t child)
307 {
308 switch (bhnd_get_class(child)) {
309 case BHND_DEVCLASS_CC:
310 /* Must be early enough to provide NVRAM access to the
311 * host bridge */
312 return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_FIRST);
313
314 case BHND_DEVCLASS_CC_B:
315 /* fall through */
316 case BHND_DEVCLASS_PMU:
317 return (BHND_PROBE_BUS + BHND_PROBE_ORDER_EARLY);
318
319 case BHND_DEVCLASS_SOC_ROUTER:
320 return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LATE);
321
322 case BHND_DEVCLASS_SOC_BRIDGE:
323 return (BHND_PROBE_BUS + BHND_PROBE_ORDER_LAST);
324
325 case BHND_DEVCLASS_CPU:
326 return (BHND_PROBE_CPU + BHND_PROBE_ORDER_FIRST);
327
328 case BHND_DEVCLASS_RAM:
329 /* fall through */
330 case BHND_DEVCLASS_MEMC:
331 return (BHND_PROBE_CPU + BHND_PROBE_ORDER_EARLY);
332
333 case BHND_DEVCLASS_NVRAM:
334 return (BHND_PROBE_RESOURCE + BHND_PROBE_ORDER_EARLY);
335
336 case BHND_DEVCLASS_PCI:
337 case BHND_DEVCLASS_PCIE:
338 case BHND_DEVCLASS_PCCARD:
339 case BHND_DEVCLASS_ENET:
340 case BHND_DEVCLASS_ENET_MAC:
341 case BHND_DEVCLASS_ENET_PHY:
342 case BHND_DEVCLASS_WLAN:
343 case BHND_DEVCLASS_WLAN_MAC:
344 case BHND_DEVCLASS_WLAN_PHY:
345 case BHND_DEVCLASS_EROM:
346 case BHND_DEVCLASS_OTHER:
347 case BHND_DEVCLASS_INVALID:
348 if (bhnd_bus_find_hostb_device(dev) == child)
349 return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY);
350
351 return (BHND_PROBE_DEFAULT);
352 default:
353 return (BHND_PROBE_DEFAULT);
354 }
355 }
356
357 /**
358 * Default bhnd(4) bus driver implementation of BHND_BUS_ALLOC_PMU().
359 */
360 int
bhnd_generic_alloc_pmu(device_t dev,device_t child)361 bhnd_generic_alloc_pmu(device_t dev, device_t child)
362 {
363 struct bhnd_softc *sc;
364 struct bhnd_resource *r;
365 struct bhnd_core_clkctl *clkctl;
366 struct resource_list *rl;
367 struct resource_list_entry *rle;
368 device_t pmu_dev;
369 bhnd_addr_t r_addr;
370 bhnd_size_t r_size;
371 bus_size_t pmu_regs;
372 u_int max_latency;
373 int error;
374
375 bus_topo_assert();
376
377 if (device_get_parent(child) != dev)
378 return (EINVAL);
379
380 sc = device_get_softc(dev);
381 clkctl = bhnd_get_pmu_info(child);
382 pmu_regs = BHND_CLK_CTL_ST;
383
384 /* already allocated? */
385 if (clkctl != NULL) {
386 panic("duplicate PMU allocation for %s",
387 device_get_nameunit(child));
388 }
389
390 /* Determine address+size of the core's PMU register block */
391 error = bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &r_addr,
392 &r_size);
393 if (error) {
394 device_printf(sc->dev, "error fetching register block info for "
395 "%s: %d\n", device_get_nameunit(child), error);
396 return (error);
397 }
398
399 if (r_size < (pmu_regs + sizeof(uint32_t))) {
400 device_printf(sc->dev, "pmu offset %#jx would overrun %s "
401 "register block\n", (uintmax_t)pmu_regs,
402 device_get_nameunit(child));
403 return (ENODEV);
404 }
405
406 /* Locate actual resource containing the core's register block */
407 if ((rl = BUS_GET_RESOURCE_LIST(dev, child)) == NULL) {
408 device_printf(dev, "NULL resource list returned for %s\n",
409 device_get_nameunit(child));
410 return (ENXIO);
411 }
412
413 if ((rle = resource_list_find(rl, SYS_RES_MEMORY, 0)) == NULL) {
414 device_printf(dev, "cannot locate core register resource "
415 "for %s\n", device_get_nameunit(child));
416 return (ENXIO);
417 }
418
419 if (rle->res == NULL) {
420 device_printf(dev, "core register resource unallocated for "
421 "%s\n", device_get_nameunit(child));
422 return (ENXIO);
423 }
424
425 if (r_addr+pmu_regs < rman_get_start(rle->res) ||
426 r_addr+pmu_regs >= rman_get_end(rle->res))
427 {
428 device_printf(dev, "core register resource does not map PMU "
429 "registers at %#jx\n for %s\n", r_addr+pmu_regs,
430 device_get_nameunit(child));
431 return (ENXIO);
432 }
433
434 /* Adjust PMU register offset relative to the actual start address
435 * of the core's register block allocation.
436 *
437 * XXX: The saved offset will be invalid if bus_adjust_resource is
438 * used to modify the resource's start address.
439 */
440 if (rman_get_start(rle->res) > r_addr)
441 pmu_regs -= rman_get_start(rle->res) - r_addr;
442 else
443 pmu_regs -= r_addr - rman_get_start(rle->res);
444
445 /* Retain a PMU reference for the clkctl instance state */
446 pmu_dev = bhnd_retain_provider(child, BHND_SERVICE_PMU);
447 if (pmu_dev == NULL) {
448 device_printf(sc->dev, "PMU not found\n");
449 return (ENXIO);
450 }
451
452 /* Fetch the maximum transition latency from our PMU */
453 max_latency = bhnd_pmu_get_max_transition_latency(pmu_dev);
454
455 /* Allocate a new bhnd_resource wrapping the standard resource we
456 * fetched from the resource list; we'll free this in
457 * bhnd_generic_release_pmu() */
458 r = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT);
459 if (r == NULL) {
460 bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU);
461 return (ENOMEM);
462 }
463
464 r->res = rle->res;
465 r->direct = ((rman_get_flags(rle->res) & RF_ACTIVE) != 0);
466
467 /* Allocate the clkctl instance */
468 clkctl = bhnd_alloc_core_clkctl(child, pmu_dev, r, pmu_regs,
469 max_latency);
470 if (clkctl == NULL) {
471 free(r, M_BHND);
472 bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU);
473 return (ENOMEM);
474 }
475
476 bhnd_set_pmu_info(child, clkctl);
477 return (0);
478 }
479
480 /**
481 * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_PMU().
482 */
483 int
bhnd_generic_release_pmu(device_t dev,device_t child)484 bhnd_generic_release_pmu(device_t dev, device_t child)
485 {
486 struct bhnd_core_clkctl *clkctl;
487 struct bhnd_resource *r;
488 device_t pmu_dev;
489
490 bus_topo_assert();
491
492 if (device_get_parent(child) != dev)
493 return (EINVAL);
494
495 clkctl = bhnd_get_pmu_info(child);
496 if (clkctl == NULL)
497 panic("pmu over-release for %s", device_get_nameunit(child));
498
499 /* Clear all FORCE, AREQ, and ERSRC flags, unless we're already in
500 * RESET. Suspending a core clears clkctl automatically (and attempting
501 * to access the PMU registers in a suspended core will trigger a
502 * system livelock). */
503 if (!bhnd_is_hw_suspended(clkctl->cc_dev)) {
504 BHND_CLKCTL_LOCK(clkctl);
505
506 /* Clear all FORCE, AREQ, and ERSRC flags */
507 BHND_CLKCTL_SET_4(clkctl, 0x0, BHND_CCS_FORCE_MASK |
508 BHND_CCS_AREQ_MASK | BHND_CCS_ERSRC_REQ_MASK);
509
510 BHND_CLKCTL_UNLOCK(clkctl);
511 }
512
513 /* Clear child's PMU info reference */
514 bhnd_set_pmu_info(child, NULL);
515
516 /* Before freeing the clkctl instance, save a pointer to resources we
517 * need to clean up manually */
518 r = clkctl->cc_res;
519 pmu_dev = clkctl->cc_pmu_dev;
520
521 /* Free the clkctl instance */
522 bhnd_free_core_clkctl(clkctl);
523
524 /* Free the child's bhnd resource wrapper */
525 free(r, M_BHND);
526
527 /* Release the child's PMU provider reference */
528 bhnd_release_provider(child, pmu_dev, BHND_SERVICE_PMU);
529
530 return (0);
531 }
532
533 /**
534 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_CLOCK_LATENCY().
535 */
536 int
bhnd_generic_get_clock_latency(device_t dev,device_t child,bhnd_clock clock,u_int * latency)537 bhnd_generic_get_clock_latency(device_t dev, device_t child, bhnd_clock clock,
538 u_int *latency)
539 {
540 struct bhnd_core_clkctl *clkctl;
541
542 if (device_get_parent(child) != dev)
543 return (EINVAL);
544
545 if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
546 panic("no active PMU allocation");
547
548 return (bhnd_pmu_get_clock_latency(clkctl->cc_pmu_dev, clock, latency));
549 }
550
551 /**
552 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_CLOCK_FREQ().
553 */
554 int
bhnd_generic_get_clock_freq(device_t dev,device_t child,bhnd_clock clock,u_int * freq)555 bhnd_generic_get_clock_freq(device_t dev, device_t child, bhnd_clock clock,
556 u_int *freq)
557 {
558 struct bhnd_core_clkctl *clkctl;
559
560 if (device_get_parent(child) != dev)
561 return (EINVAL);
562
563 if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
564 panic("no active PMU allocation");
565
566 return (bhnd_pmu_get_clock_freq(clkctl->cc_pmu_dev, clock, freq));
567 }
568
569 /**
570 * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_CLOCK().
571 */
572 int
bhnd_generic_request_clock(device_t dev,device_t child,bhnd_clock clock)573 bhnd_generic_request_clock(device_t dev, device_t child, bhnd_clock clock)
574 {
575 struct bhnd_core_clkctl *clkctl;
576 uint32_t avail;
577 uint32_t req;
578 int error;
579
580 if (device_get_parent(child) != dev)
581 return (EINVAL);
582
583 if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
584 panic("no active PMU allocation");
585
586 BHND_ASSERT_CLKCTL_AVAIL(clkctl);
587
588 avail = 0x0;
589 req = 0x0;
590
591 switch (clock) {
592 case BHND_CLOCK_DYN:
593 break;
594 case BHND_CLOCK_ILP:
595 req |= BHND_CCS_FORCEILP;
596 break;
597 case BHND_CLOCK_ALP:
598 req |= BHND_CCS_FORCEALP;
599 avail |= BHND_CCS_ALPAVAIL;
600 break;
601 case BHND_CLOCK_HT:
602 req |= BHND_CCS_FORCEHT;
603 avail |= BHND_CCS_HTAVAIL;
604 break;
605 default:
606 device_printf(dev, "%s requested unknown clock: %#x\n",
607 device_get_nameunit(clkctl->cc_dev), clock);
608 return (ENODEV);
609 }
610
611 BHND_CLKCTL_LOCK(clkctl);
612
613 /* Issue request */
614 BHND_CLKCTL_SET_4(clkctl, req, BHND_CCS_FORCE_MASK);
615
616 /* Wait for clock availability */
617 error = bhnd_core_clkctl_wait(clkctl, avail, avail);
618
619 BHND_CLKCTL_UNLOCK(clkctl);
620
621 return (error);
622 }
623
624 /**
625 * Default bhnd(4) bus driver implementation of BHND_BUS_ENABLE_CLOCKS().
626 */
627 int
bhnd_generic_enable_clocks(device_t dev,device_t child,uint32_t clocks)628 bhnd_generic_enable_clocks(device_t dev, device_t child, uint32_t clocks)
629 {
630 struct bhnd_core_clkctl *clkctl;
631 uint32_t avail;
632 uint32_t req;
633 int error;
634
635 if (device_get_parent(child) != dev)
636 return (EINVAL);
637
638 if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
639 panic("no active PMU allocation");
640
641 BHND_ASSERT_CLKCTL_AVAIL(clkctl);
642
643 avail = 0x0;
644 req = 0x0;
645
646 /* Build clock request flags */
647 if (clocks & BHND_CLOCK_DYN) /* nothing to enable */
648 clocks &= ~BHND_CLOCK_DYN;
649
650 if (clocks & BHND_CLOCK_ILP) /* nothing to enable */
651 clocks &= ~BHND_CLOCK_ILP;
652
653 if (clocks & BHND_CLOCK_ALP) {
654 req |= BHND_CCS_ALPAREQ;
655 avail |= BHND_CCS_ALPAVAIL;
656 clocks &= ~BHND_CLOCK_ALP;
657 }
658
659 if (clocks & BHND_CLOCK_HT) {
660 req |= BHND_CCS_HTAREQ;
661 avail |= BHND_CCS_HTAVAIL;
662 clocks &= ~BHND_CLOCK_HT;
663 }
664
665 /* Check for unknown clock values */
666 if (clocks != 0x0) {
667 device_printf(dev, "%s requested unknown clocks: %#x\n",
668 device_get_nameunit(clkctl->cc_dev), clocks);
669 return (ENODEV);
670 }
671
672 BHND_CLKCTL_LOCK(clkctl);
673
674 /* Issue request */
675 BHND_CLKCTL_SET_4(clkctl, req, BHND_CCS_AREQ_MASK);
676
677 /* Wait for clock availability */
678 error = bhnd_core_clkctl_wait(clkctl, avail, avail);
679
680 BHND_CLKCTL_UNLOCK(clkctl);
681
682 return (error);
683 }
684
685 /**
686 * Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_EXT_RSRC().
687 */
688 int
bhnd_generic_request_ext_rsrc(device_t dev,device_t child,u_int rsrc)689 bhnd_generic_request_ext_rsrc(device_t dev, device_t child, u_int rsrc)
690 {
691 struct bhnd_core_clkctl *clkctl;
692 uint32_t req;
693 uint32_t avail;
694 int error;
695
696 if (device_get_parent(child) != dev)
697 return (EINVAL);
698
699 if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
700 panic("no active PMU allocation");
701
702 BHND_ASSERT_CLKCTL_AVAIL(clkctl);
703
704 if (rsrc > BHND_CCS_ERSRC_MAX)
705 return (EINVAL);
706
707 req = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
708 avail = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_STS);
709
710 BHND_CLKCTL_LOCK(clkctl);
711
712 /* Write request */
713 BHND_CLKCTL_SET_4(clkctl, req, req);
714
715 /* Wait for resource availability */
716 error = bhnd_core_clkctl_wait(clkctl, avail, avail);
717
718 BHND_CLKCTL_UNLOCK(clkctl);
719
720 return (error);
721 }
722
723 /**
724 * Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_EXT_RSRC().
725 */
726 int
bhnd_generic_release_ext_rsrc(device_t dev,device_t child,u_int rsrc)727 bhnd_generic_release_ext_rsrc(device_t dev, device_t child, u_int rsrc)
728 {
729 struct bhnd_core_clkctl *clkctl;
730 uint32_t mask;
731
732 if (device_get_parent(child) != dev)
733 return (EINVAL);
734
735 if ((clkctl = bhnd_get_pmu_info(child)) == NULL)
736 panic("no active PMU allocation");
737
738 BHND_ASSERT_CLKCTL_AVAIL(clkctl);
739
740 if (rsrc > BHND_CCS_ERSRC_MAX)
741 return (EINVAL);
742
743 mask = BHND_CCS_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
744
745 /* Clear request */
746 BHND_CLKCTL_LOCK(clkctl);
747 BHND_CLKCTL_SET_4(clkctl, 0x0, mask);
748 BHND_CLKCTL_UNLOCK(clkctl);
749
750 return (0);
751 }
752
753 /**
754 * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
755 *
756 * This implementation assumes that port and region numbers are 0-indexed and
757 * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and
758 * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall
759 * within the defined range.
760 */
761 static bool
bhnd_generic_is_region_valid(device_t dev,device_t child,bhnd_port_type type,u_int port,u_int region)762 bhnd_generic_is_region_valid(device_t dev, device_t child,
763 bhnd_port_type type, u_int port, u_int region)
764 {
765 if (port >= bhnd_get_port_count(child, type))
766 return (false);
767
768 if (region >= bhnd_get_region_count(child, type, port))
769 return (false);
770
771 return (true);
772 }
773
774 /**
775 * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
776 *
777 * This implementation searches @p dev for a registered NVRAM child device.
778 *
779 * If no NVRAM device is registered with @p dev, the request is delegated to
780 * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
781 */
782 int
bhnd_generic_get_nvram_var(device_t dev,device_t child,const char * name,void * buf,size_t * size,bhnd_nvram_type type)783 bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
784 void *buf, size_t *size, bhnd_nvram_type type)
785 {
786 device_t nvram, parent;
787 int error;
788
789 /* If a NVRAM device is available, consult it first */
790 nvram = bhnd_retain_provider(child, BHND_SERVICE_NVRAM);
791 if (nvram != NULL) {
792 error = BHND_NVRAM_GETVAR(nvram, name, buf, size, type);
793 bhnd_release_provider(child, nvram, BHND_SERVICE_NVRAM);
794 return (error);
795 }
796
797 /* Otherwise, try to delegate to parent */
798 if ((parent = device_get_parent(dev)) == NULL)
799 return (ENODEV);
800
801 return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
802 name, buf, size, type));
803 }
804
805 /**
806 * Default bhnd(4) bus driver implementation of BUS_PRINT_CHILD().
807 *
808 * This implementation requests the device's struct resource_list via
809 * BUS_GET_RESOURCE_LIST.
810 */
811 int
bhnd_generic_print_child(device_t dev,device_t child)812 bhnd_generic_print_child(device_t dev, device_t child)
813 {
814 struct resource_list *rl;
815 int retval = 0;
816
817 retval += bus_print_child_header(dev, child);
818
819 rl = BUS_GET_RESOURCE_LIST(dev, child);
820
821 if (rl != NULL) {
822 retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
823 "%#jx");
824
825 retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ,
826 "%#jd");
827 }
828
829 retval += printf(" at core %u", bhnd_get_core_index(child));
830
831 retval += bus_print_child_domain(dev, child);
832 retval += bus_print_child_footer(dev, child);
833
834 return (retval);
835 }
836
837 /**
838 * Default bhnd(4) bus driver implementation of BUS_PROBE_NOMATCH().
839 *
840 * This implementation requests the device's struct resource_list via
841 * BUS_GET_RESOURCE_LIST.
842 */
843 void
bhnd_generic_probe_nomatch(device_t dev,device_t child)844 bhnd_generic_probe_nomatch(device_t dev, device_t child)
845 {
846 struct resource_list *rl;
847 const struct bhnd_nomatch *nm;
848 bool report;
849
850 /* Fetch reporting configuration for this device */
851 report = true;
852 for (nm = bhnd_nomatch_table; nm->device != BHND_COREID_INVALID; nm++) {
853 if (nm->vendor != bhnd_get_vendor(child))
854 continue;
855
856 if (nm->device != bhnd_get_device(child))
857 continue;
858
859 report = false;
860 if (bootverbose && nm->if_verbose)
861 report = true;
862 break;
863 }
864
865 if (!report)
866 return;
867
868 /* Print the non-matched device info */
869 device_printf(dev, "<%s %s, rev %hhu>", bhnd_get_vendor_name(child),
870 bhnd_get_device_name(child), bhnd_get_hwrev(child));
871
872 rl = BUS_GET_RESOURCE_LIST(dev, child);
873 if (rl != NULL) {
874 resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
875 resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%#jd");
876 }
877
878 printf(" at core %u (no driver attached)\n",
879 bhnd_get_core_index(child));
880 }
881
882 static int
bhnd_child_pnpinfo(device_t dev,device_t child,struct sbuf * sb)883 bhnd_child_pnpinfo(device_t dev, device_t child, struct sbuf *sb)
884 {
885 if (device_get_parent(child) != dev)
886 return (BUS_CHILD_PNPINFO(device_get_parent(dev), child, sb));
887
888 sbuf_printf(sb, "vendor=0x%hx device=0x%hx rev=0x%hhx",
889 bhnd_get_vendor(child), bhnd_get_device(child),
890 bhnd_get_hwrev(child));
891
892 return (0);
893 }
894
895 static int
bhnd_child_location(device_t dev,device_t child,struct sbuf * sb)896 bhnd_child_location(device_t dev, device_t child, struct sbuf *sb)
897 {
898 bhnd_addr_t addr;
899 bhnd_size_t size;
900
901 if (device_get_parent(child) != dev)
902 return (BUS_CHILD_LOCATION(device_get_parent(dev), child, sb));
903
904 if (bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &addr, &size))
905 return (0);
906
907 sbuf_printf(sb, "port0.0=0x%llx", (unsigned long long) addr);
908 return (0);
909 }
910
911 /**
912 * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED().
913 *
914 * This implementation manages internal bhnd(4) state, and must be called
915 * by subclassing drivers.
916 */
917 void
bhnd_generic_child_deleted(device_t dev,device_t child)918 bhnd_generic_child_deleted(device_t dev, device_t child)
919 {
920
921 /* Free device info */
922 if (bhnd_get_pmu_info(child) != NULL) {
923 /* Releasing PMU requests automatically would be nice,
924 * but we can't reference per-core PMU register
925 * resource after driver detach */
926 panic("%s leaked device pmu state\n",
927 device_get_nameunit(child));
928 }
929 }
930
931 /**
932 * Helper function for implementing BUS_SUSPEND_CHILD().
933 *
934 * TODO: Power management
935 *
936 * If @p child is not a direct child of @p dev, suspension is delegated to
937 * the @p dev parent.
938 */
939 int
bhnd_generic_suspend_child(device_t dev,device_t child)940 bhnd_generic_suspend_child(device_t dev, device_t child)
941 {
942 if (device_get_parent(child) != dev)
943 BUS_SUSPEND_CHILD(device_get_parent(dev), child);
944
945 return bus_generic_suspend_child(dev, child);
946 }
947
948 /**
949 * Helper function for implementing BUS_RESUME_CHILD().
950 *
951 * TODO: Power management
952 *
953 * If @p child is not a direct child of @p dev, suspension is delegated to
954 * the @p dev parent.
955 */
956 int
bhnd_generic_resume_child(device_t dev,device_t child)957 bhnd_generic_resume_child(device_t dev, device_t child)
958 {
959 if (device_get_parent(child) != dev)
960 BUS_RESUME_CHILD(device_get_parent(dev), child);
961
962 return bus_generic_resume_child(dev, child);
963 }
964
965 /**
966 * Default bhnd(4) bus driver implementation of BUS_SETUP_INTR().
967 *
968 * This implementation of BUS_SETUP_INTR() will delegate interrupt setup
969 * to the parent of @p dev, if any.
970 */
971 int
bhnd_generic_setup_intr(device_t dev,device_t child,struct resource * irq,int flags,driver_filter_t * filter,driver_intr_t * intr,void * arg,void ** cookiep)972 bhnd_generic_setup_intr(device_t dev, device_t child, struct resource *irq,
973 int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
974 void **cookiep)
975 {
976 return (bus_generic_setup_intr(dev, child, irq, flags, filter, intr,
977 arg, cookiep));
978 }
979
980 /*
981 * Delegate all indirect I/O to the parent device. When inherited by
982 * non-bridged bus implementations, resources will never be marked as
983 * indirect, and these methods will never be called.
984 */
985 #define BHND_IO_READ(_type, _name, _method) \
986 static _type \
987 bhnd_read_ ## _name (device_t dev, device_t child, \
988 struct bhnd_resource *r, bus_size_t offset) \
989 { \
990 return (BHND_BUS_READ_ ## _method( \
991 device_get_parent(dev), child, r, offset)); \
992 }
993
994 #define BHND_IO_WRITE(_type, _name, _method) \
995 static void \
996 bhnd_write_ ## _name (device_t dev, device_t child, \
997 struct bhnd_resource *r, bus_size_t offset, _type value) \
998 { \
999 return (BHND_BUS_WRITE_ ## _method( \
1000 device_get_parent(dev), child, r, offset, \
1001 value)); \
1002 }
1003
1004 #define BHND_IO_MISC(_type, _op, _method) \
1005 static void \
1006 bhnd_ ## _op (device_t dev, device_t child, \
1007 struct bhnd_resource *r, bus_size_t offset, _type datap, \
1008 bus_size_t count) \
1009 { \
1010 BHND_BUS_ ## _method(device_get_parent(dev), child, r, \
1011 offset, datap, count); \
1012 }
1013
1014 #define BHND_IO_METHODS(_type, _size) \
1015 BHND_IO_READ(_type, _size, _size) \
1016 BHND_IO_WRITE(_type, _size, _size) \
1017 \
1018 BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size) \
1019 BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size) \
1020 \
1021 BHND_IO_MISC(_type*, read_multi_ ## _size, \
1022 READ_MULTI_ ## _size) \
1023 BHND_IO_MISC(_type*, write_multi_ ## _size, \
1024 WRITE_MULTI_ ## _size) \
1025 \
1026 BHND_IO_MISC(_type*, read_multi_stream_ ## _size, \
1027 READ_MULTI_STREAM_ ## _size) \
1028 BHND_IO_MISC(_type*, write_multi_stream_ ## _size, \
1029 WRITE_MULTI_STREAM_ ## _size) \
1030 \
1031 BHND_IO_MISC(_type, set_multi_ ## _size, SET_MULTI_ ## _size) \
1032 BHND_IO_MISC(_type, set_region_ ## _size, SET_REGION_ ## _size) \
1033 \
1034 BHND_IO_MISC(_type*, read_region_ ## _size, \
1035 READ_REGION_ ## _size) \
1036 BHND_IO_MISC(_type*, write_region_ ## _size, \
1037 WRITE_REGION_ ## _size) \
1038 \
1039 BHND_IO_MISC(_type*, read_region_stream_ ## _size, \
1040 READ_REGION_STREAM_ ## _size) \
1041 BHND_IO_MISC(_type*, write_region_stream_ ## _size, \
1042 WRITE_REGION_STREAM_ ## _size) \
1043
1044 BHND_IO_METHODS(uint8_t, 1);
1045 BHND_IO_METHODS(uint16_t, 2);
1046 BHND_IO_METHODS(uint32_t, 4);
1047
1048 static void
bhnd_barrier(device_t dev,device_t child,struct bhnd_resource * r,bus_size_t offset,bus_size_t length,int flags)1049 bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r,
1050 bus_size_t offset, bus_size_t length, int flags)
1051 {
1052 BHND_BUS_BARRIER(device_get_parent(dev), child, r, offset, length,
1053 flags);
1054 }
1055
1056 static device_method_t bhnd_methods[] = {
1057 /* Device interface */ \
1058 DEVMETHOD(device_attach, bhnd_generic_attach),
1059 DEVMETHOD(device_detach, bhnd_generic_detach),
1060 DEVMETHOD(device_shutdown, bhnd_generic_shutdown),
1061 DEVMETHOD(device_suspend, bhnd_generic_suspend),
1062 DEVMETHOD(device_resume, bhnd_generic_resume),
1063
1064 /* Bus interface */
1065 DEVMETHOD(bus_child_deleted, bhnd_generic_child_deleted),
1066 DEVMETHOD(bus_probe_nomatch, bhnd_generic_probe_nomatch),
1067 DEVMETHOD(bus_print_child, bhnd_generic_print_child),
1068 DEVMETHOD(bus_child_pnpinfo, bhnd_child_pnpinfo),
1069 DEVMETHOD(bus_child_location, bhnd_child_location),
1070
1071 DEVMETHOD(bus_suspend_child, bhnd_generic_suspend_child),
1072 DEVMETHOD(bus_resume_child, bhnd_generic_resume_child),
1073
1074 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
1075 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
1076 DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource),
1077 DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
1078 DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
1079 DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
1080 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
1081 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
1082
1083 DEVMETHOD(bus_setup_intr, bhnd_generic_setup_intr),
1084 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
1085 DEVMETHOD(bus_config_intr, bus_generic_config_intr),
1086 DEVMETHOD(bus_bind_intr, bus_generic_bind_intr),
1087 DEVMETHOD(bus_describe_intr, bus_generic_describe_intr),
1088
1089 DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag),
1090
1091 /* BHND interface */
1092 DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid),
1093 DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled),
1094
1095 DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order),
1096
1097 DEVMETHOD(bhnd_bus_alloc_pmu, bhnd_generic_alloc_pmu),
1098 DEVMETHOD(bhnd_bus_release_pmu, bhnd_generic_release_pmu),
1099 DEVMETHOD(bhnd_bus_request_clock, bhnd_generic_request_clock),
1100 DEVMETHOD(bhnd_bus_enable_clocks, bhnd_generic_enable_clocks),
1101 DEVMETHOD(bhnd_bus_request_ext_rsrc, bhnd_generic_request_ext_rsrc),
1102 DEVMETHOD(bhnd_bus_release_ext_rsrc, bhnd_generic_release_ext_rsrc),
1103 DEVMETHOD(bhnd_bus_get_clock_latency, bhnd_generic_get_clock_latency),
1104 DEVMETHOD(bhnd_bus_get_clock_freq, bhnd_generic_get_clock_freq),
1105
1106 DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid),
1107 DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var),
1108
1109 /* BHND interface (bus I/O) */
1110 DEVMETHOD(bhnd_bus_read_1, bhnd_read_1),
1111 DEVMETHOD(bhnd_bus_read_2, bhnd_read_2),
1112 DEVMETHOD(bhnd_bus_read_4, bhnd_read_4),
1113 DEVMETHOD(bhnd_bus_write_1, bhnd_write_1),
1114 DEVMETHOD(bhnd_bus_write_2, bhnd_write_2),
1115 DEVMETHOD(bhnd_bus_write_4, bhnd_write_4),
1116
1117 DEVMETHOD(bhnd_bus_read_stream_1, bhnd_read_stream_1),
1118 DEVMETHOD(bhnd_bus_read_stream_2, bhnd_read_stream_2),
1119 DEVMETHOD(bhnd_bus_read_stream_4, bhnd_read_stream_4),
1120 DEVMETHOD(bhnd_bus_write_stream_1, bhnd_write_stream_1),
1121 DEVMETHOD(bhnd_bus_write_stream_2, bhnd_write_stream_2),
1122 DEVMETHOD(bhnd_bus_write_stream_4, bhnd_write_stream_4),
1123
1124 DEVMETHOD(bhnd_bus_read_multi_1, bhnd_read_multi_1),
1125 DEVMETHOD(bhnd_bus_read_multi_2, bhnd_read_multi_2),
1126 DEVMETHOD(bhnd_bus_read_multi_4, bhnd_read_multi_4),
1127 DEVMETHOD(bhnd_bus_write_multi_1, bhnd_write_multi_1),
1128 DEVMETHOD(bhnd_bus_write_multi_2, bhnd_write_multi_2),
1129 DEVMETHOD(bhnd_bus_write_multi_4, bhnd_write_multi_4),
1130
1131 DEVMETHOD(bhnd_bus_read_multi_stream_1, bhnd_read_multi_stream_1),
1132 DEVMETHOD(bhnd_bus_read_multi_stream_2, bhnd_read_multi_stream_2),
1133 DEVMETHOD(bhnd_bus_read_multi_stream_4, bhnd_read_multi_stream_4),
1134 DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1),
1135 DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2),
1136 DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4),
1137
1138 DEVMETHOD(bhnd_bus_set_multi_1, bhnd_set_multi_1),
1139 DEVMETHOD(bhnd_bus_set_multi_2, bhnd_set_multi_2),
1140 DEVMETHOD(bhnd_bus_set_multi_4, bhnd_set_multi_4),
1141
1142 DEVMETHOD(bhnd_bus_set_region_1, bhnd_set_region_1),
1143 DEVMETHOD(bhnd_bus_set_region_2, bhnd_set_region_2),
1144 DEVMETHOD(bhnd_bus_set_region_4, bhnd_set_region_4),
1145
1146 DEVMETHOD(bhnd_bus_read_region_1, bhnd_read_region_1),
1147 DEVMETHOD(bhnd_bus_read_region_2, bhnd_read_region_2),
1148 DEVMETHOD(bhnd_bus_read_region_4, bhnd_read_region_4),
1149 DEVMETHOD(bhnd_bus_write_region_1, bhnd_write_region_1),
1150 DEVMETHOD(bhnd_bus_write_region_2, bhnd_write_region_2),
1151 DEVMETHOD(bhnd_bus_write_region_4, bhnd_write_region_4),
1152
1153 DEVMETHOD(bhnd_bus_read_region_stream_1,bhnd_read_region_stream_1),
1154 DEVMETHOD(bhnd_bus_read_region_stream_2,bhnd_read_region_stream_2),
1155 DEVMETHOD(bhnd_bus_read_region_stream_4,bhnd_read_region_stream_4),
1156 DEVMETHOD(bhnd_bus_write_region_stream_1, bhnd_write_region_stream_1),
1157 DEVMETHOD(bhnd_bus_write_region_stream_2, bhnd_write_region_stream_2),
1158 DEVMETHOD(bhnd_bus_write_region_stream_4, bhnd_write_region_stream_4),
1159
1160 DEVMETHOD(bhnd_bus_barrier, bhnd_barrier),
1161
1162 DEVMETHOD_END
1163 };
1164
1165 DEFINE_CLASS_0(bhnd, bhnd_driver, bhnd_methods, sizeof(struct bhnd_softc));
1166 MODULE_VERSION(bhnd, 1);
1167