]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/cores/pmu/bhnd_pmu.c
Upgrade to OpenSSH 7.7p1.
[FreeBSD/FreeBSD.git] / sys / dev / bhnd / cores / pmu / bhnd_pmu.c
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 devclass_t bhnd_pmu_devclass;   /**< bhnd(4) PMU device class */
75
76 static int      bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS);
77 static int      bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS);
78 static int      bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS);
79
80 static uint32_t bhnd_pmu_read_4(bus_size_t reg, void *ctx);
81 static void     bhnd_pmu_write_4(bus_size_t reg, uint32_t val, void *ctx);
82 static uint32_t bhnd_pmu_read_chipst(void *ctx);
83
84 static 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  */
93 int
94 bhnd_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  */
106 int
107 bhnd_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
207 failed:
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  */
225 int
226 bhnd_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  */
247 int
248 bhnd_pmu_suspend(device_t dev)
249 {
250         return (0);
251 }
252
253 /**
254  * Default bhnd_pmu driver implementation of DEVICE_RESUME().
255  */
256 int
257 bhnd_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
273 static int
274 bhnd_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
288 static int
289 bhnd_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
303 static int
304 bhnd_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  */
321 static uint32_t
322 bhnd_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  */
339 static void
340 bhnd_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  */
353 static uint32_t
354 bhnd_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  */
371 static void
372 bhnd_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  */
385 static uint32_t
386 bhnd_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  */
403 static void
404 bhnd_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  */
417 static int
418 bhnd_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  */
446 static int
447 bhnd_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  */
470 static int
471 bhnd_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  */
495 static int
496 bhnd_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  */
525 static int
526 bhnd_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  */
557 static int
558 bhnd_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  */
575 static u_int
576 bhnd_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 */
582 static uint32_t
583 bhnd_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 */
590 static void
591 bhnd_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 */
598 static uint32_t
599 bhnd_pmu_read_chipst(void *ctx)
600 {
601         struct bhnd_pmu_softc *sc = ctx;
602         return (BHND_CHIPC_READ_CHIPST(sc->chipc_dev));
603 }
604
605 static 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
632 DEFINE_CLASS_0(bhnd_pmu, bhnd_pmu_driver, bhnd_pmu_methods, sizeof(struct bhnd_pmu_softc));
633 MODULE_VERSION(bhnd_pmu, 1);