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