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