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