xref: /freebsd/sys/dev/bhnd/cores/pmu/bhnd_pmu.c (revision f126890a)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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