1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.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/param.h>
37 #include <sys/kernel.h>
38 #include <sys/lock.h>
39 #include <sys/bus.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
42 #include <sys/mutex.h>
43 #include <sys/sysctl.h>
44 #include <sys/systm.h>
45
46 #include <machine/bus.h>
47 #include <machine/resource.h>
48
49 #include <dev/bhnd/bhndreg.h>
50 #include <dev/bhnd/bhndvar.h>
51 #include <dev/bhnd/cores/chipc/chipc.h>
52
53 #include "bhnd_nvram_map.h"
54
55 #include "bhnd_pmureg.h"
56 #include "bhnd_pmuvar.h"
57
58 #include "bhnd_pmu_private.h"
59
60 /*
61 * Broadcom PMU driver.
62 *
63 * On modern BHND chipsets, the PMU, GCI, and SRENG (Save/Restore Engine?)
64 * register blocks are found within a dedicated PMU core (attached via
65 * the AHB 'always on bus').
66 *
67 * On earlier chipsets, these register blocks are found at the same
68 * offsets within the ChipCommon core.
69 */
70
71 static int bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS);
72 static int bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS);
73 static int bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS);
74
75 static uint32_t bhnd_pmu_read_4(bus_size_t reg, void *ctx);
76 static void bhnd_pmu_write_4(bus_size_t reg, uint32_t val, void *ctx);
77 static uint32_t bhnd_pmu_read_chipst(void *ctx);
78
79 static const struct bhnd_pmu_io bhnd_pmu_res_io = {
80 .rd4 = bhnd_pmu_read_4,
81 .wr4 = bhnd_pmu_write_4,
82 .rd_chipst = bhnd_pmu_read_chipst
83 };
84
85 /**
86 * Default bhnd_pmu driver implementation of DEVICE_PROBE().
87 */
88 int
bhnd_pmu_probe(device_t dev)89 bhnd_pmu_probe(device_t dev)
90 {
91 return (BUS_PROBE_DEFAULT);
92 }
93
94 /**
95 * Default bhnd_pmu driver implementation of DEVICE_ATTACH().
96 *
97 * @param dev PMU device.
98 * @param res The PMU device registers. The driver will maintain a borrowed
99 * reference to this resource for the lifetime of the device.
100 */
101 int
bhnd_pmu_attach(device_t dev,struct bhnd_resource * res)102 bhnd_pmu_attach(device_t dev, struct bhnd_resource *res)
103 {
104 struct bhnd_pmu_softc *sc;
105 struct sysctl_ctx_list *ctx;
106 struct sysctl_oid *tree;
107 devclass_t bhnd_class;
108 device_t core, bus;
109 int error;
110
111 sc = device_get_softc(dev);
112 sc->dev = dev;
113 sc->res = res;
114
115 /* Fetch capability flags */
116 sc->caps = bhnd_bus_read_4(sc->res, BHND_PMU_CAP);
117
118 /* Find the bus and bus-attached core */
119 bhnd_class = devclass_find("bhnd");
120 core = sc->dev;
121 while ((bus = device_get_parent(core)) != NULL) {
122 if (device_get_devclass(bus) == bhnd_class)
123 break;
124
125 core = bus;
126 }
127
128 if (core == NULL) {
129 device_printf(sc->dev, "bhnd bus not found\n");
130 return (ENXIO);
131 }
132
133 /* Fetch chip and board info */
134 sc->cid = *bhnd_get_chipid(core);
135 if ((error = bhnd_read_board_info(core, &sc->board))) {
136 device_printf(sc->dev, "error fetching board info: %d\n",
137 error);
138 return (ENXIO);
139 }
140
141 /* Initialize query state */
142 error = bhnd_pmu_query_init(&sc->query, dev, sc->cid, &bhnd_pmu_res_io,
143 sc);
144 if (error)
145 return (error);
146 sc->io = sc->query.io;
147 sc->io_ctx = sc->query.io_ctx;
148
149 BPMU_LOCK_INIT(sc);
150
151 /* Allocate our own core clkctl state directly; we use this to wait on
152 * PMU state transitions, avoiding a cyclic dependency between bhnd(4)'s
153 * clkctl handling and registration of this device as a PMU */
154 sc->clkctl = bhnd_alloc_core_clkctl(core, dev, sc->res, BHND_CLK_CTL_ST,
155 BHND_PMU_MAX_TRANSITION_DLY);
156 if (sc->clkctl == NULL) {
157 device_printf(sc->dev, "failed to allocate clkctl for %s\n",
158 device_get_nameunit(core));
159 error = ENOMEM;
160 goto failed;
161 }
162
163 /* Locate ChipCommon device */
164 sc->chipc_dev = bhnd_retain_provider(dev, BHND_SERVICE_CHIPC);
165 if (sc->chipc_dev == NULL) {
166 device_printf(sc->dev, "chipcommon device not found\n");
167 error = ENXIO;
168 goto failed;
169 }
170
171 /* Initialize PMU */
172 if ((error = bhnd_pmu_init(sc))) {
173 device_printf(sc->dev, "PMU init failed: %d\n", error);
174 goto failed;
175 }
176
177 /* Register ourselves with the bus */
178 if ((error = bhnd_register_provider(dev, BHND_SERVICE_PMU))) {
179 device_printf(sc->dev, "failed to register PMU with bus : %d\n",
180 error);
181 goto failed;
182 }
183
184 /* Set up sysctl nodes */
185 ctx = device_get_sysctl_ctx(dev);
186 tree = device_get_sysctl_tree(dev);
187
188 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
189 "bus_freq", CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0,
190 bhnd_pmu_sysctl_bus_freq, "IU", "Bus clock frequency");
191
192 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
193 "cpu_freq", CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0,
194 bhnd_pmu_sysctl_cpu_freq, "IU", "CPU clock frequency");
195
196 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
197 "mem_freq", CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0,
198 bhnd_pmu_sysctl_mem_freq, "IU", "Memory clock frequency");
199
200 return (0);
201
202 failed:
203 BPMU_LOCK_DESTROY(sc);
204 bhnd_pmu_query_fini(&sc->query);
205
206 if (sc->clkctl != NULL)
207 bhnd_free_core_clkctl(sc->clkctl);
208
209 if (sc->chipc_dev != NULL) {
210 bhnd_release_provider(sc->dev, sc->chipc_dev,
211 BHND_SERVICE_CHIPC);
212 }
213
214 return (error);
215 }
216
217 /**
218 * Default bhnd_pmu driver implementation of DEVICE_DETACH().
219 */
220 int
bhnd_pmu_detach(device_t dev)221 bhnd_pmu_detach(device_t dev)
222 {
223 struct bhnd_pmu_softc *sc;
224 int error;
225
226 sc = device_get_softc(dev);
227
228 if ((error = bhnd_deregister_provider(dev, BHND_SERVICE_ANY)))
229 return (error);
230
231 BPMU_LOCK_DESTROY(sc);
232 bhnd_pmu_query_fini(&sc->query);
233 bhnd_free_core_clkctl(sc->clkctl);
234 bhnd_release_provider(sc->dev, sc->chipc_dev, BHND_SERVICE_CHIPC);
235
236 return (0);
237 }
238
239 /**
240 * Default bhnd_pmu driver implementation of DEVICE_SUSPEND().
241 */
242 int
bhnd_pmu_suspend(device_t dev)243 bhnd_pmu_suspend(device_t dev)
244 {
245 return (0);
246 }
247
248 /**
249 * Default bhnd_pmu driver implementation of DEVICE_RESUME().
250 */
251 int
bhnd_pmu_resume(device_t dev)252 bhnd_pmu_resume(device_t dev)
253 {
254 struct bhnd_pmu_softc *sc;
255 int error;
256
257 sc = device_get_softc(dev);
258
259 /* Re-initialize PMU */
260 if ((error = bhnd_pmu_init(sc))) {
261 device_printf(sc->dev, "PMU init failed: %d\n", error);
262 return (error);
263 }
264
265 return (0);
266 }
267
268 static int
bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS)269 bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS)
270 {
271 struct bhnd_pmu_softc *sc;
272 uint32_t freq;
273
274 sc = arg1;
275
276 BPMU_LOCK(sc);
277 freq = bhnd_pmu_si_clock(&sc->query);
278 BPMU_UNLOCK(sc);
279
280 return (sysctl_handle_32(oidp, NULL, freq, req));
281 }
282
283 static int
bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS)284 bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS)
285 {
286 struct bhnd_pmu_softc *sc;
287 uint32_t freq;
288
289 sc = arg1;
290
291 BPMU_LOCK(sc);
292 freq = bhnd_pmu_cpu_clock(&sc->query);
293 BPMU_UNLOCK(sc);
294
295 return (sysctl_handle_32(oidp, NULL, freq, req));
296 }
297
298 static int
bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS)299 bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS)
300 {
301 struct bhnd_pmu_softc *sc;
302 uint32_t freq;
303
304 sc = arg1;
305
306 BPMU_LOCK(sc);
307 freq = bhnd_pmu_mem_clock(&sc->query);
308 BPMU_UNLOCK(sc);
309
310 return (sysctl_handle_32(oidp, NULL, freq, req));
311 }
312
313 /**
314 * Default bhnd_pmu driver implementation of BHND_PMU_READ_CHIPCTRL().
315 */
316 static uint32_t
bhnd_pmu_read_chipctrl_method(device_t dev,uint32_t reg)317 bhnd_pmu_read_chipctrl_method(device_t dev, uint32_t reg)
318 {
319 struct bhnd_pmu_softc *sc;
320 uint32_t rval;
321
322 sc = device_get_softc(dev);
323
324 BPMU_LOCK(sc);
325 rval = BHND_PMU_CCTRL_READ(sc, reg);
326 BPMU_UNLOCK(sc);
327
328 return (rval);
329 }
330
331 /**
332 * Default bhnd_pmu driver implementation of BHND_PMU_WRITE_CHIPCTRL().
333 */
334 static void
bhnd_pmu_write_chipctrl_method(device_t dev,uint32_t reg,uint32_t value,uint32_t mask)335 bhnd_pmu_write_chipctrl_method(device_t dev, uint32_t reg, uint32_t value,
336 uint32_t mask)
337 {
338 struct bhnd_pmu_softc *sc = device_get_softc(dev);
339
340 BPMU_LOCK(sc);
341 BHND_PMU_CCTRL_WRITE(sc, reg, value, mask);
342 BPMU_UNLOCK(sc);
343 }
344
345 /**
346 * Default bhnd_pmu driver implementation of BHND_PMU_READ_REGCTRL().
347 */
348 static uint32_t
bhnd_pmu_read_regctrl_method(device_t dev,uint32_t reg)349 bhnd_pmu_read_regctrl_method(device_t dev, uint32_t reg)
350 {
351 struct bhnd_pmu_softc *sc;
352 uint32_t rval;
353
354 sc = device_get_softc(dev);
355
356 BPMU_LOCK(sc);
357 rval = BHND_PMU_REGCTRL_READ(sc, reg);
358 BPMU_UNLOCK(sc);
359
360 return (rval);
361 }
362
363 /**
364 * Default bhnd_pmu driver implementation of BHND_PMU_WRITE_REGCTRL().
365 */
366 static void
bhnd_pmu_write_regctrl_method(device_t dev,uint32_t reg,uint32_t value,uint32_t mask)367 bhnd_pmu_write_regctrl_method(device_t dev, uint32_t reg, uint32_t value,
368 uint32_t mask)
369 {
370 struct bhnd_pmu_softc *sc = device_get_softc(dev);
371
372 BPMU_LOCK(sc);
373 BHND_PMU_REGCTRL_WRITE(sc, reg, value, mask);
374 BPMU_UNLOCK(sc);
375 }
376
377 /**
378 * Default bhnd_pmu driver implementation of BHND_PMU_READ_PLLCTRL().
379 */
380 static uint32_t
bhnd_pmu_read_pllctrl_method(device_t dev,uint32_t reg)381 bhnd_pmu_read_pllctrl_method(device_t dev, uint32_t reg)
382 {
383 struct bhnd_pmu_softc *sc;
384 uint32_t rval;
385
386 sc = device_get_softc(dev);
387
388 BPMU_LOCK(sc);
389 rval = BHND_PMU_PLL_READ(sc, reg);
390 BPMU_UNLOCK(sc);
391
392 return (rval);
393 }
394
395 /**
396 * Default bhnd_pmu driver implementation of BHND_PMU_WRITE_PLLCTRL().
397 */
398 static void
bhnd_pmu_write_pllctrl_method(device_t dev,uint32_t reg,uint32_t value,uint32_t mask)399 bhnd_pmu_write_pllctrl_method(device_t dev, uint32_t reg, uint32_t value,
400 uint32_t mask)
401 {
402 struct bhnd_pmu_softc *sc = device_get_softc(dev);
403
404 BPMU_LOCK(sc);
405 BHND_PMU_PLL_WRITE(sc, reg, value, mask);
406 BPMU_UNLOCK(sc);
407 }
408
409 /**
410 * Default bhnd_pmu driver implementation of BHND_PMU_SET_VOLTAGE_RAW().
411 */
412 static int
bhnd_pmu_set_voltage_raw_method(device_t dev,bhnd_pmu_regulator regulator,uint32_t value)413 bhnd_pmu_set_voltage_raw_method(device_t dev, bhnd_pmu_regulator regulator,
414 uint32_t value)
415 {
416 struct bhnd_pmu_softc *sc;
417 int error;
418
419 sc = device_get_softc(dev);
420
421 switch (regulator) {
422 case BHND_REGULATOR_PAREF_LDO:
423 if (value > UINT8_MAX)
424 return (EINVAL);
425
426 BPMU_LOCK(sc);
427 error = bhnd_pmu_set_ldo_voltage(sc, SET_LDO_VOLTAGE_PAREF,
428 value);
429 BPMU_UNLOCK(sc);
430
431 return (error);
432
433 default:
434 return (ENODEV);
435 }
436 }
437
438 /**
439 * Default bhnd_pmu driver implementation of BHND_PMU_ENABLE_REGULATOR().
440 */
441 static int
bhnd_pmu_enable_regulator_method(device_t dev,bhnd_pmu_regulator regulator)442 bhnd_pmu_enable_regulator_method(device_t dev, bhnd_pmu_regulator regulator)
443 {
444 struct bhnd_pmu_softc *sc;
445 int error;
446
447 sc = device_get_softc(dev);
448
449 switch (regulator) {
450 case BHND_REGULATOR_PAREF_LDO:
451 BPMU_LOCK(sc);
452 error = bhnd_pmu_paref_ldo_enable(sc, true);
453 BPMU_UNLOCK(sc);
454
455 return (error);
456
457 default:
458 return (ENODEV);
459 }
460 }
461
462 /**
463 * Default bhnd_pmu driver implementation of BHND_PMU_DISABLE_REGULATOR().
464 */
465 static int
bhnd_pmu_disable_regulator_method(device_t dev,bhnd_pmu_regulator regulator)466 bhnd_pmu_disable_regulator_method(device_t dev, bhnd_pmu_regulator regulator)
467 {
468 struct bhnd_pmu_softc *sc;
469 int error;
470
471 sc = device_get_softc(dev);
472
473 switch (regulator) {
474 case BHND_REGULATOR_PAREF_LDO:
475 BPMU_LOCK(sc);
476 error = bhnd_pmu_paref_ldo_enable(sc, false);
477 BPMU_UNLOCK(sc);
478
479 return (error);
480
481 default:
482 return (ENODEV);
483 }
484 }
485
486 /**
487 * Default bhnd_pmu driver implementation of BHND_PMU_GET_CLOCK_LATENCY().
488 */
489 static int
bhnd_pmu_get_clock_latency_method(device_t dev,bhnd_clock clock,u_int * latency)490 bhnd_pmu_get_clock_latency_method(device_t dev, bhnd_clock clock,
491 u_int *latency)
492 {
493 struct bhnd_pmu_softc *sc;
494 u_int pwrup_delay;
495 int error;
496
497 sc = device_get_softc(dev);
498
499 switch (clock) {
500 case BHND_CLOCK_HT:
501 BPMU_LOCK(sc);
502 error = bhnd_pmu_fast_pwrup_delay(sc, &pwrup_delay);
503 BPMU_UNLOCK(sc);
504
505 if (error)
506 return (error);
507
508 *latency = pwrup_delay;
509 return (0);
510
511 default:
512 return (ENODEV);
513 }
514 }
515
516 /**
517 * Default bhnd_pmu driver implementation of BHND_PMU_GET_CLOCK_FREQ().
518 */
519 static int
bhnd_pmu_get_clock_freq_method(device_t dev,bhnd_clock clock,uint32_t * freq)520 bhnd_pmu_get_clock_freq_method(device_t dev, bhnd_clock clock, uint32_t *freq)
521 {
522 struct bhnd_pmu_softc *sc = device_get_softc(dev);
523
524 BPMU_LOCK(sc);
525 switch (clock) {
526 case BHND_CLOCK_HT:
527 *freq = bhnd_pmu_si_clock(&sc->query);
528 break;
529
530 case BHND_CLOCK_ALP:
531 *freq = bhnd_pmu_alp_clock(&sc->query);
532 break;
533
534 case BHND_CLOCK_ILP:
535 *freq = bhnd_pmu_ilp_clock(&sc->query);
536 break;
537
538 case BHND_CLOCK_DYN:
539 default:
540 BPMU_UNLOCK(sc);
541 return (ENODEV);
542 }
543
544 BPMU_UNLOCK(sc);
545 return (0);
546 }
547
548 /**
549 * Default bhnd_pmu driver implementation of BHND_PMU_REQUEST_SPURAVOID().
550 */
551 static int
bhnd_pmu_request_spuravoid_method(device_t dev,bhnd_pmu_spuravoid spuravoid)552 bhnd_pmu_request_spuravoid_method(device_t dev, bhnd_pmu_spuravoid spuravoid)
553 {
554 struct bhnd_pmu_softc *sc;
555 int error;
556
557 sc = device_get_softc(dev);
558
559 BPMU_LOCK(sc);
560 error = bhnd_pmu_set_spuravoid(sc, spuravoid);
561 BPMU_UNLOCK(sc);
562
563 return (error);
564 }
565
566 /**
567 * Default bhnd_pmu driver implementation of BHND_PMU_GET_TRANSITION_LATENCY().
568 */
569 static u_int
bhnd_pmu_get_max_transition_latency_method(device_t dev)570 bhnd_pmu_get_max_transition_latency_method(device_t dev)
571 {
572 return (BHND_PMU_MAX_TRANSITION_DLY);
573 }
574
575 /* bhnd_pmu_query read_4 callback */
576 static uint32_t
bhnd_pmu_read_4(bus_size_t reg,void * ctx)577 bhnd_pmu_read_4(bus_size_t reg, void *ctx)
578 {
579 struct bhnd_pmu_softc *sc = ctx;
580 return (bhnd_bus_read_4(sc->res, reg));
581 }
582
583 /* bhnd_pmu_query write_4 callback */
584 static void
bhnd_pmu_write_4(bus_size_t reg,uint32_t val,void * ctx)585 bhnd_pmu_write_4(bus_size_t reg, uint32_t val, void *ctx)
586 {
587 struct bhnd_pmu_softc *sc = ctx;
588 return (bhnd_bus_write_4(sc->res, reg, val));
589 }
590
591 /* bhnd_pmu_query read_chipst callback */
592 static uint32_t
bhnd_pmu_read_chipst(void * ctx)593 bhnd_pmu_read_chipst(void *ctx)
594 {
595 struct bhnd_pmu_softc *sc = ctx;
596 return (BHND_CHIPC_READ_CHIPST(sc->chipc_dev));
597 }
598
599 static device_method_t bhnd_pmu_methods[] = {
600 /* Device interface */
601 DEVMETHOD(device_probe, bhnd_pmu_probe),
602 DEVMETHOD(device_detach, bhnd_pmu_detach),
603 DEVMETHOD(device_suspend, bhnd_pmu_suspend),
604 DEVMETHOD(device_resume, bhnd_pmu_resume),
605
606 /* BHND PMU interface */
607 DEVMETHOD(bhnd_pmu_read_chipctrl, bhnd_pmu_read_chipctrl_method),
608 DEVMETHOD(bhnd_pmu_write_chipctrl, bhnd_pmu_write_chipctrl_method),
609 DEVMETHOD(bhnd_pmu_read_regctrl, bhnd_pmu_read_regctrl_method),
610 DEVMETHOD(bhnd_pmu_write_regctrl, bhnd_pmu_write_regctrl_method),
611 DEVMETHOD(bhnd_pmu_read_pllctrl, bhnd_pmu_read_pllctrl_method),
612 DEVMETHOD(bhnd_pmu_write_pllctrl, bhnd_pmu_write_pllctrl_method),
613 DEVMETHOD(bhnd_pmu_set_voltage_raw, bhnd_pmu_set_voltage_raw_method),
614 DEVMETHOD(bhnd_pmu_enable_regulator, bhnd_pmu_enable_regulator_method),
615 DEVMETHOD(bhnd_pmu_disable_regulator, bhnd_pmu_disable_regulator_method),
616
617 DEVMETHOD(bhnd_pmu_get_clock_latency, bhnd_pmu_get_clock_latency_method),
618 DEVMETHOD(bhnd_pmu_get_clock_freq, bhnd_pmu_get_clock_freq_method),
619
620 DEVMETHOD(bhnd_pmu_get_max_transition_latency, bhnd_pmu_get_max_transition_latency_method),
621 DEVMETHOD(bhnd_pmu_request_spuravoid, bhnd_pmu_request_spuravoid_method),
622
623 DEVMETHOD_END
624 };
625
626 DEFINE_CLASS_0(bhnd_pmu, bhnd_pmu_driver, bhnd_pmu_methods, sizeof(struct bhnd_pmu_softc));
627 MODULE_VERSION(bhnd_pmu, 1);
628