]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
Import PCG-C into sys/contrib
[FreeBSD/FreeBSD.git] / sys / arm / broadcom / bcm2835 / bcm2835_cpufreq.c
1 /*-
2  * Copyright (C) 2013-2015 Daisuke Aoyama <aoyama@peach.ne.jp>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/cpu.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/mutex.h>
40 #include <sys/sema.h>
41 #include <sys/sysctl.h>
42
43 #include <machine/bus.h>
44 #include <machine/cpu.h>
45 #include <machine/intr.h>
46
47 #include <dev/ofw/ofw_bus.h>
48 #include <dev/ofw/ofw_bus_subr.h>
49
50 #include <arm/broadcom/bcm2835/bcm2835_firmware.h>
51 #include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
52
53 #include "cpufreq_if.h"
54
55 #ifdef DEBUG
56 #define DPRINTF(fmt, ...) do {                  \
57         printf("%s:%u: ", __func__, __LINE__);  \
58         printf(fmt, ##__VA_ARGS__);             \
59 } while (0)
60 #else
61 #define DPRINTF(fmt, ...)
62 #endif
63
64 #define HZ2MHZ(freq) ((freq) / (1000 * 1000))
65 #define MHZ2HZ(freq) ((freq) * (1000 * 1000))
66
67 #ifdef SOC_BCM2835
68 #define OFFSET2MVOLT(val) (1200 + ((val) * 25))
69 #define MVOLT2OFFSET(val) (((val) - 1200) / 25)
70 #define DEFAULT_ARM_FREQUENCY    700
71 #define DEFAULT_LOWEST_FREQ      300
72 #else
73 #define OFFSET2MVOLT(val) (((val) / 1000))
74 #define MVOLT2OFFSET(val) (((val) * 1000))
75 #define DEFAULT_ARM_FREQUENCY    600
76 #define DEFAULT_LOWEST_FREQ      600
77 #endif
78 #define DEFAULT_CORE_FREQUENCY   250
79 #define DEFAULT_SDRAM_FREQUENCY  400
80 #define TRANSITION_LATENCY      1000
81 #define MIN_OVER_VOLTAGE         -16
82 #define MAX_OVER_VOLTAGE           6
83 #define MSG_ERROR         -999999999
84 #define MHZSTEP                  100
85 #define HZSTEP     (MHZ2HZ(MHZSTEP))
86 #define TZ_ZEROC                2731
87
88 #define VC_LOCK(sc) do {                        \
89                 sema_wait(&vc_sema);            \
90         } while (0)
91 #define VC_UNLOCK(sc) do {                      \
92                 sema_post(&vc_sema);            \
93         } while (0)
94
95 /* ARM->VC mailbox property semaphore */
96 static struct sema vc_sema;
97
98 static struct sysctl_ctx_list bcm2835_sysctl_ctx;
99
100 struct bcm2835_cpufreq_softc {
101         device_t        dev;
102         device_t        firmware;
103         int             arm_max_freq;
104         int             arm_min_freq;
105         int             core_max_freq;
106         int             core_min_freq;
107         int             sdram_max_freq;
108         int             sdram_min_freq;
109         int             max_voltage_core;
110         int             min_voltage_core;
111
112         /* the values written in mbox */
113         int             voltage_core;
114         int             voltage_sdram;
115         int             voltage_sdram_c;
116         int             voltage_sdram_i;
117         int             voltage_sdram_p;
118         int             turbo_mode;
119
120         /* initial hook for waiting mbox intr */
121         struct intr_config_hook init_hook;
122 };
123
124 static struct ofw_compat_data compat_data[] = {
125         { "broadcom,bcm2835-vc",        1 },
126         { "broadcom,bcm2708-vc",        1 },
127         { "brcm,bcm2709",       1 },
128         { "brcm,bcm2835",       1 },
129         { "brcm,bcm2836",       1 },
130         { "brcm,bcm2837",       1 },
131         { "brcm,bcm2711",       1 },
132         { NULL, 0 }
133 };
134
135 static int cpufreq_verbose = 0;
136 TUNABLE_INT("hw.bcm2835.cpufreq.verbose", &cpufreq_verbose);
137 static int cpufreq_lowest_freq = DEFAULT_LOWEST_FREQ;
138 TUNABLE_INT("hw.bcm2835.cpufreq.lowest_freq", &cpufreq_lowest_freq);
139
140 #ifdef PROP_DEBUG
141 static void
142 bcm2835_dump(const void *data, int len)
143 {
144         const uint8_t *p = (const uint8_t*)data;
145         int i;
146
147         printf("dump @ %p:\n", data);
148         for (i = 0; i < len; i++) {
149                 printf("%2.2x ", p[i]);
150                 if ((i % 4) == 3)
151                         printf(" ");
152                 if ((i % 16) == 15)
153                         printf("\n");
154         }
155         printf("\n");
156 }
157 #endif
158
159 static int
160 bcm2835_cpufreq_get_clock_rate(struct bcm2835_cpufreq_softc *sc,
161     uint32_t clock_id)
162 {
163         union msg_get_clock_rate_body msg;
164         int rate;
165         int err;
166
167         /*
168          * Get clock rate
169          *   Tag: 0x00030002
170          *   Request:
171          *     Length: 4
172          *     Value:
173          *       u32: clock id
174          *   Response:
175          *     Length: 8
176          *     Value:
177          *       u32: clock id
178          *       u32: rate (in Hz)
179          */
180
181         /* setup single tag buffer */
182         memset(&msg, 0, sizeof(msg));
183         msg.req.clock_id = clock_id;
184
185         /* call mailbox property */
186         err = bcm2835_firmware_property(sc->firmware,
187             BCM2835_FIRMWARE_TAG_GET_CLOCK_RATE, &msg, sizeof(msg));
188         if (err) {
189                 device_printf(sc->dev, "can't get clock rate (id=%u)\n",
190                     clock_id);
191                 return (MSG_ERROR);
192         }
193
194         /* result (Hz) */
195         rate = (int)msg.resp.rate_hz;
196         DPRINTF("clock = %d(Hz)\n", rate);
197         return (rate);
198 }
199
200 static int
201 bcm2835_cpufreq_get_max_clock_rate(struct bcm2835_cpufreq_softc *sc,
202     uint32_t clock_id)
203 {
204         union msg_get_clock_rate_body msg;
205         int rate;
206         int err;
207
208         /*
209          * Get max clock rate
210          *   Tag: 0x00030004
211          *   Request:
212          *     Length: 4
213          *     Value:
214          *       u32: clock id
215          *   Response:
216          *     Length: 8
217          *     Value:
218          *       u32: clock id
219          *       u32: rate (in Hz)
220          */
221
222         /* setup single tag buffer */
223         memset(&msg, 0, sizeof(msg));
224         msg.req.clock_id = clock_id;
225
226         /* call mailbox property */
227         err = bcm2835_firmware_property(sc->firmware,
228             BCM2835_FIRMWARE_TAG_GET_MAX_CLOCK_RATE, &msg, sizeof(msg));
229         if (err) {
230                 device_printf(sc->dev, "can't get max clock rate (id=%u)\n",
231                     clock_id);
232                 return (MSG_ERROR);
233         }
234
235         /* result (Hz) */
236         rate = (int)msg.resp.rate_hz;
237         DPRINTF("clock = %d(Hz)\n", rate);
238         return (rate);
239 }
240
241 static int
242 bcm2835_cpufreq_get_min_clock_rate(struct bcm2835_cpufreq_softc *sc,
243     uint32_t clock_id)
244 {
245         union msg_get_clock_rate_body msg;
246         int rate;
247         int err;
248
249         /*
250          * Get min clock rate
251          *   Tag: 0x00030007
252          *   Request:
253          *     Length: 4
254          *     Value:
255          *       u32: clock id
256          *   Response:
257          *     Length: 8
258          *     Value:
259          *       u32: clock id
260          *       u32: rate (in Hz)
261          */
262
263         /* setup single tag buffer */
264         memset(&msg, 0, sizeof(msg));
265         msg.req.clock_id = clock_id;
266
267         /* call mailbox property */
268         err = bcm2835_firmware_property(sc->firmware,
269             BCM2835_FIRMWARE_TAG_GET_MIN_CLOCK_RATE, &msg, sizeof(msg));
270         if (err) {
271                 device_printf(sc->dev, "can't get min clock rate (id=%u)\n",
272                     clock_id);
273                 return (MSG_ERROR);
274         }
275
276         /* result (Hz) */
277         rate = (int)msg.resp.rate_hz;
278         DPRINTF("clock = %d(Hz)\n", rate);
279         return (rate);
280 }
281
282 static int
283 bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc,
284     uint32_t clock_id, uint32_t rate_hz)
285 {
286         union msg_set_clock_rate_body msg;
287         int rate;
288         int err;
289
290         /*
291          * Set clock rate
292          *   Tag: 0x00038002
293          *   Request:
294          *     Length: 8
295          *     Value:
296          *       u32: clock id
297          *       u32: rate (in Hz)
298          *   Response:
299          *     Length: 8
300          *     Value:
301          *       u32: clock id
302          *       u32: rate (in Hz)
303          */
304
305         /* setup single tag buffer */
306         memset(&msg, 0, sizeof(msg));
307         msg.req.clock_id = clock_id;
308         msg.req.rate_hz = rate_hz;
309
310         /* call mailbox property */
311         err = bcm2835_firmware_property(sc->firmware,
312             BCM2835_FIRMWARE_TAG_SET_CLOCK_RATE, &msg, sizeof(msg));
313         if (err) {
314                 device_printf(sc->dev, "can't set clock rate (id=%u)\n",
315                     clock_id);
316                 return (MSG_ERROR);
317         }
318
319         /* workaround for core clock */
320         if (clock_id == BCM2835_FIRMWARE_CLOCK_ID_CORE) {
321                 /* for safety (may change voltage without changing clock) */
322                 DELAY(TRANSITION_LATENCY);
323
324                 /*
325                  * XXX: the core clock is unable to change at once,
326                  * to change certainly, write it twice now.
327                  */
328
329                 /* setup single tag buffer */
330                 memset(&msg, 0, sizeof(msg));
331                 msg.req.clock_id = clock_id;
332                 msg.req.rate_hz = rate_hz;
333
334                 /* call mailbox property */
335                 err = bcm2835_firmware_property(sc->firmware,
336                     BCM2835_FIRMWARE_TAG_SET_CLOCK_RATE, &msg, sizeof(msg));
337                 if (err) {
338                         device_printf(sc->dev,
339                             "can't set clock rate (id=%u)\n", clock_id);
340                         return (MSG_ERROR);
341                 }
342         }
343
344         /* result (Hz) */
345         rate = (int)msg.resp.rate_hz;
346         DPRINTF("clock = %d(Hz)\n", rate);
347         return (rate);
348 }
349
350 static int
351 bcm2835_cpufreq_get_turbo(struct bcm2835_cpufreq_softc *sc)
352 {
353         union msg_get_turbo_body msg;
354         int level;
355         int err;
356
357         /*
358          * Get turbo
359          *   Tag: 0x00030009
360          *   Request:
361          *     Length: 4
362          *     Value:
363          *       u32: id
364          *   Response:
365          *     Length: 8
366          *     Value:
367          *       u32: id
368          *       u32: level
369          */
370
371         /* setup single tag buffer */
372         memset(&msg, 0, sizeof(msg));
373         msg.req.id = 0;
374
375         /* call mailbox property */
376         err = bcm2835_firmware_property(sc->firmware,
377             BCM2835_FIRMWARE_TAG_GET_TURBO, &msg, sizeof(msg));
378         if (err) {
379                 device_printf(sc->dev, "can't get turbo\n");
380                 return (MSG_ERROR);
381         }
382
383         /* result 0=non-turbo, 1=turbo */
384         level = (int)msg.resp.level;
385         DPRINTF("level = %d\n", level);
386         return (level);
387 }
388
389 static int
390 bcm2835_cpufreq_set_turbo(struct bcm2835_cpufreq_softc *sc, uint32_t level)
391 {
392         union msg_set_turbo_body msg;
393         int value;
394         int err;
395
396         /*
397          * Set turbo
398          *   Tag: 0x00038009
399          *   Request:
400          *     Length: 8
401          *     Value:
402          *       u32: id
403          *       u32: level
404          *   Response:
405          *     Length: 8
406          *     Value:
407          *       u32: id
408          *       u32: level
409          */
410
411         /* replace unknown value to OFF */
412         if (level != BCM2835_FIRMWARE_TURBO_ON &&
413             level != BCM2835_FIRMWARE_TURBO_OFF)
414                 level = BCM2835_FIRMWARE_TURBO_OFF;
415
416         /* setup single tag buffer */
417         memset(&msg, 0, sizeof(msg));
418         msg.req.id = 0;
419         msg.req.level = level;
420
421         /* call mailbox property */
422         err = bcm2835_firmware_property(sc->firmware,
423             BCM2835_FIRMWARE_TAG_SET_TURBO, &msg, sizeof(msg));
424         if (err) {
425                 device_printf(sc->dev, "can't set turbo\n");
426                 return (MSG_ERROR);
427         }
428
429         /* result 0=non-turbo, 1=turbo */
430         value = (int)msg.resp.level;
431         DPRINTF("level = %d\n", value);
432         return (value);
433 }
434
435 static int
436 bcm2835_cpufreq_get_voltage(struct bcm2835_cpufreq_softc *sc,
437     uint32_t voltage_id)
438 {
439         union msg_get_voltage_body msg;
440         int value;
441         int err;
442
443         /*
444          * Get voltage
445          *   Tag: 0x00030003
446          *   Request:
447          *     Length: 4
448          *     Value:
449          *       u32: voltage id
450          *   Response:
451          *     Length: 8
452          *     Value:
453          *       u32: voltage id
454          *       u32: value (offset from 1.2V in units of 0.025V)
455          */
456
457         /* setup single tag buffer */
458         memset(&msg, 0, sizeof(msg));
459         msg.req.voltage_id = voltage_id;
460
461         /* call mailbox property */
462         err = bcm2835_firmware_property(sc->firmware,
463             BCM2835_FIRMWARE_TAG_GET_VOLTAGE, &msg, sizeof(msg));
464         if (err) {
465                 device_printf(sc->dev, "can't get voltage\n");
466                 return (MSG_ERROR);
467         }
468
469         /* result (offset from 1.2V) */
470         value = (int)msg.resp.value;
471         DPRINTF("value = %d\n", value);
472         return (value);
473 }
474
475 static int
476 bcm2835_cpufreq_get_max_voltage(struct bcm2835_cpufreq_softc *sc,
477     uint32_t voltage_id)
478 {
479         union msg_get_voltage_body msg;
480         int value;
481         int err;
482
483         /*
484          * Get voltage
485          *   Tag: 0x00030005
486          *   Request:
487          *     Length: 4
488          *     Value:
489          *       u32: voltage id
490          *   Response:
491          *     Length: 8
492          *     Value:
493          *       u32: voltage id
494          *       u32: value (offset from 1.2V in units of 0.025V)
495          */
496
497         /* setup single tag buffer */
498         memset(&msg, 0, sizeof(msg));
499         msg.req.voltage_id = voltage_id;
500
501         /* call mailbox property */
502         err = bcm2835_firmware_property(sc->firmware,
503             BCM2835_FIRMWARE_TAG_GET_MAX_VOLTAGE, &msg, sizeof(msg));
504         if (err) {
505                 device_printf(sc->dev, "can't get max voltage\n");
506                 return (MSG_ERROR);
507         }
508
509         /* result (offset from 1.2V) */
510         value = (int)msg.resp.value;
511         DPRINTF("value = %d\n", value);
512         return (value);
513 }
514 static int
515 bcm2835_cpufreq_get_min_voltage(struct bcm2835_cpufreq_softc *sc,
516     uint32_t voltage_id)
517 {
518         union msg_get_voltage_body msg;
519         int value;
520         int err;
521
522         /*
523          * Get voltage
524          *   Tag: 0x00030008
525          *   Request:
526          *     Length: 4
527          *     Value:
528          *       u32: voltage id
529          *   Response:
530          *     Length: 8
531          *     Value:
532          *       u32: voltage id
533          *       u32: value (offset from 1.2V in units of 0.025V)
534          */
535
536         /* setup single tag buffer */
537         memset(&msg, 0, sizeof(msg));
538         msg.req.voltage_id = voltage_id;
539
540         /* call mailbox property */
541         err = bcm2835_firmware_property(sc->firmware,
542             BCM2835_FIRMWARE_TAG_GET_MIN_VOLTAGE, &msg, sizeof(msg));
543         if (err) {
544                 device_printf(sc->dev, "can't get min voltage\n");
545                 return (MSG_ERROR);
546         }
547
548         /* result (offset from 1.2V) */
549         value = (int)msg.resp.value;
550         DPRINTF("value = %d\n", value);
551         return (value);
552 }
553
554 static int
555 bcm2835_cpufreq_set_voltage(struct bcm2835_cpufreq_softc *sc,
556     uint32_t voltage_id, int32_t value)
557 {
558         union msg_set_voltage_body msg;
559         int err;
560
561         /*
562          * Set voltage
563          *   Tag: 0x00038003
564          *   Request:
565          *     Length: 4
566          *     Value:
567          *       u32: voltage id
568          *       u32: value (offset from 1.2V in units of 0.025V)
569          *   Response:
570          *     Length: 8
571          *     Value:
572          *       u32: voltage id
573          *       u32: value (offset from 1.2V in units of 0.025V)
574          */
575
576         /*
577          * over_voltage:
578          * 0 (1.2 V). Values above 6 are only allowed when force_turbo or
579          * current_limit_override are specified (which set the warranty bit).
580          */
581         if (value > MAX_OVER_VOLTAGE || value < MIN_OVER_VOLTAGE) {
582                 /* currently not supported */
583                 device_printf(sc->dev, "not supported voltage: %d\n", value);
584                 return (MSG_ERROR);
585         }
586
587         /* setup single tag buffer */
588         memset(&msg, 0, sizeof(msg));
589         msg.req.voltage_id = voltage_id;
590         msg.req.value = (uint32_t)value;
591
592         /* call mailbox property */
593         err = bcm2835_firmware_property(sc->firmware,
594             BCM2835_FIRMWARE_TAG_SET_VOLTAGE, &msg, sizeof(msg));
595         if (err) {
596                 device_printf(sc->dev, "can't set voltage\n");
597                 return (MSG_ERROR);
598         }
599
600         /* result (offset from 1.2V) */
601         value = (int)msg.resp.value;
602         DPRINTF("value = %d\n", value);
603         return (value);
604 }
605
606 static int
607 bcm2835_cpufreq_get_temperature(struct bcm2835_cpufreq_softc *sc)
608 {
609         union msg_get_temperature_body msg;
610         int value;
611         int err;
612
613         /*
614          * Get temperature
615          *   Tag: 0x00030006
616          *   Request:
617          *     Length: 4
618          *     Value:
619          *       u32: temperature id
620          *   Response:
621          *     Length: 8
622          *     Value:
623          *       u32: temperature id
624          *       u32: value
625          */
626
627         /* setup single tag buffer */
628         memset(&msg, 0, sizeof(msg));
629         msg.req.temperature_id = 0;
630
631         /* call mailbox property */
632         err = bcm2835_firmware_property(sc->firmware,
633             BCM2835_FIRMWARE_TAG_GET_TEMPERATURE, &msg, sizeof(msg));
634         if (err) {
635                 device_printf(sc->dev, "can't get temperature\n");
636                 return (MSG_ERROR);
637         }
638
639         /* result (temperature of degree C) */
640         value = (int)msg.resp.value;
641         DPRINTF("value = %d\n", value);
642         return (value);
643 }
644
645
646
647 static int
648 sysctl_bcm2835_cpufreq_arm_freq(SYSCTL_HANDLER_ARGS)
649 {
650         struct bcm2835_cpufreq_softc *sc = arg1;
651         int val;
652         int err;
653
654         /* get realtime value */
655         VC_LOCK(sc);
656         val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_FIRMWARE_CLOCK_ID_ARM);
657         VC_UNLOCK(sc);
658         if (val == MSG_ERROR)
659                 return (EIO);
660
661         err = sysctl_handle_int(oidp, &val, 0, req);
662         if (err || !req->newptr) /* error || read request */
663                 return (err);
664
665         /* write request */
666         VC_LOCK(sc);
667         err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_FIRMWARE_CLOCK_ID_ARM,
668             val);
669         VC_UNLOCK(sc);
670         if (err == MSG_ERROR) {
671                 device_printf(sc->dev, "set clock arm_freq error\n");
672                 return (EIO);
673         }
674         DELAY(TRANSITION_LATENCY);
675
676         return (0);
677 }
678
679 static int
680 sysctl_bcm2835_cpufreq_core_freq(SYSCTL_HANDLER_ARGS)
681 {
682         struct bcm2835_cpufreq_softc *sc = arg1;
683         int val;
684         int err;
685
686         /* get realtime value */
687         VC_LOCK(sc);
688         val = bcm2835_cpufreq_get_clock_rate(sc,
689             BCM2835_FIRMWARE_CLOCK_ID_CORE);
690         VC_UNLOCK(sc);
691         if (val == MSG_ERROR)
692                 return (EIO);
693
694         err = sysctl_handle_int(oidp, &val, 0, req);
695         if (err || !req->newptr) /* error || read request */
696                 return (err);
697
698         /* write request */
699         VC_LOCK(sc);
700         err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_FIRMWARE_CLOCK_ID_CORE,
701             val);
702         if (err == MSG_ERROR) {
703                 VC_UNLOCK(sc);
704                 device_printf(sc->dev, "set clock core_freq error\n");
705                 return (EIO);
706         }
707         VC_UNLOCK(sc);
708         DELAY(TRANSITION_LATENCY);
709
710         return (0);
711 }
712
713 static int
714 sysctl_bcm2835_cpufreq_sdram_freq(SYSCTL_HANDLER_ARGS)
715 {
716         struct bcm2835_cpufreq_softc *sc = arg1;
717         int val;
718         int err;
719
720         /* get realtime value */
721         VC_LOCK(sc);
722         val = bcm2835_cpufreq_get_clock_rate(sc,
723             BCM2835_FIRMWARE_CLOCK_ID_SDRAM);
724         VC_UNLOCK(sc);
725         if (val == MSG_ERROR)
726                 return (EIO);
727
728         err = sysctl_handle_int(oidp, &val, 0, req);
729         if (err || !req->newptr) /* error || read request */
730                 return (err);
731
732         /* write request */
733         VC_LOCK(sc);
734         err = bcm2835_cpufreq_set_clock_rate(sc,
735             BCM2835_FIRMWARE_CLOCK_ID_SDRAM, val);
736         VC_UNLOCK(sc);
737         if (err == MSG_ERROR) {
738                 device_printf(sc->dev, "set clock sdram_freq error\n");
739                 return (EIO);
740         }
741         DELAY(TRANSITION_LATENCY);
742
743         return (0);
744 }
745
746 static int
747 sysctl_bcm2835_cpufreq_turbo(SYSCTL_HANDLER_ARGS)
748 {
749         struct bcm2835_cpufreq_softc *sc = arg1;
750         int val;
751         int err;
752
753         /* get realtime value */
754         VC_LOCK(sc);
755         val = bcm2835_cpufreq_get_turbo(sc);
756         VC_UNLOCK(sc);
757         if (val == MSG_ERROR)
758                 return (EIO);
759
760         err = sysctl_handle_int(oidp, &val, 0, req);
761         if (err || !req->newptr) /* error || read request */
762                 return (err);
763
764         /* write request */
765         if (val > 0)
766                 sc->turbo_mode = BCM2835_FIRMWARE_TURBO_ON;
767         else
768                 sc->turbo_mode = BCM2835_FIRMWARE_TURBO_OFF;
769
770         VC_LOCK(sc);
771         err = bcm2835_cpufreq_set_turbo(sc, sc->turbo_mode);
772         VC_UNLOCK(sc);
773         if (err == MSG_ERROR) {
774                 device_printf(sc->dev, "set turbo error\n");
775                 return (EIO);
776         }
777         DELAY(TRANSITION_LATENCY);
778
779         return (0);
780 }
781
782 static int
783 sysctl_bcm2835_cpufreq_voltage_core(SYSCTL_HANDLER_ARGS)
784 {
785         struct bcm2835_cpufreq_softc *sc = arg1;
786         int val;
787         int err;
788
789         /* get realtime value */
790         VC_LOCK(sc);
791         val = bcm2835_cpufreq_get_voltage(sc, BCM2835_FIRMWARE_VOLTAGE_ID_CORE);
792         VC_UNLOCK(sc);
793         if (val == MSG_ERROR)
794                 return (EIO);
795
796         err = sysctl_handle_int(oidp, &val, 0, req);
797         if (err || !req->newptr) /* error || read request */
798                 return (err);
799
800         /* write request */
801         if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
802                 return (EINVAL);
803         sc->voltage_core = val;
804
805         VC_LOCK(sc);
806         err = bcm2835_cpufreq_set_voltage(sc, BCM2835_FIRMWARE_VOLTAGE_ID_CORE,
807             sc->voltage_core);
808         VC_UNLOCK(sc);
809         if (err == MSG_ERROR) {
810                 device_printf(sc->dev, "set voltage core error\n");
811                 return (EIO);
812         }
813         DELAY(TRANSITION_LATENCY);
814
815         return (0);
816 }
817
818 static int
819 sysctl_bcm2835_cpufreq_voltage_sdram_c(SYSCTL_HANDLER_ARGS)
820 {
821         struct bcm2835_cpufreq_softc *sc = arg1;
822         int val;
823         int err;
824
825         /* get realtime value */
826         VC_LOCK(sc);
827         val = bcm2835_cpufreq_get_voltage(sc,
828             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C);
829         VC_UNLOCK(sc);
830         if (val == MSG_ERROR)
831                 return (EIO);
832
833         err = sysctl_handle_int(oidp, &val, 0, req);
834         if (err || !req->newptr) /* error || read request */
835                 return (err);
836
837         /* write request */
838         if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
839                 return (EINVAL);
840         sc->voltage_sdram_c = val;
841
842         VC_LOCK(sc);
843         err = bcm2835_cpufreq_set_voltage(sc,
844             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C,
845            sc->voltage_sdram_c);
846         VC_UNLOCK(sc);
847         if (err == MSG_ERROR) {
848                 device_printf(sc->dev, "set voltage sdram_c error\n");
849                 return (EIO);
850         }
851         DELAY(TRANSITION_LATENCY);
852
853         return (0);
854 }
855
856 static int
857 sysctl_bcm2835_cpufreq_voltage_sdram_i(SYSCTL_HANDLER_ARGS)
858 {
859         struct bcm2835_cpufreq_softc *sc = arg1;
860         int val;
861         int err;
862
863         /* get realtime value */
864         VC_LOCK(sc);
865         val = bcm2835_cpufreq_get_voltage(sc,
866             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I);
867         VC_UNLOCK(sc);
868         if (val == MSG_ERROR)
869                 return (EIO);
870
871         err = sysctl_handle_int(oidp, &val, 0, req);
872         if (err || !req->newptr) /* error || read request */
873                 return (err);
874
875         /* write request */
876         if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
877                 return (EINVAL);
878         sc->voltage_sdram_i = val;
879
880         VC_LOCK(sc);
881         err = bcm2835_cpufreq_set_voltage(sc,
882             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I, sc->voltage_sdram_i);
883         VC_UNLOCK(sc);
884         if (err == MSG_ERROR) {
885                 device_printf(sc->dev, "set voltage sdram_i error\n");
886                 return (EIO);
887         }
888         DELAY(TRANSITION_LATENCY);
889
890         return (0);
891 }
892
893 static int
894 sysctl_bcm2835_cpufreq_voltage_sdram_p(SYSCTL_HANDLER_ARGS)
895 {
896         struct bcm2835_cpufreq_softc *sc = arg1;
897         int val;
898         int err;
899
900         /* get realtime value */
901         VC_LOCK(sc);
902         val = bcm2835_cpufreq_get_voltage(sc,
903             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P);
904         VC_UNLOCK(sc);
905         if (val == MSG_ERROR)
906                 return (EIO);
907
908         err = sysctl_handle_int(oidp, &val, 0, req);
909         if (err || !req->newptr) /* error || read request */
910                 return (err);
911
912         /* write request */
913         if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
914                 return (EINVAL);
915         sc->voltage_sdram_p = val;
916
917         VC_LOCK(sc);
918         err = bcm2835_cpufreq_set_voltage(sc,
919             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P, sc->voltage_sdram_p);
920         VC_UNLOCK(sc);
921         if (err == MSG_ERROR) {
922                 device_printf(sc->dev, "set voltage sdram_p error\n");
923                 return (EIO);
924         }
925         DELAY(TRANSITION_LATENCY);
926
927         return (0);
928 }
929
930 static int
931 sysctl_bcm2835_cpufreq_voltage_sdram(SYSCTL_HANDLER_ARGS)
932 {
933         struct bcm2835_cpufreq_softc *sc = arg1;
934         int val;
935         int err;
936
937         /* multiple write only */
938         if (!req->newptr)
939                 return (EINVAL);
940         val = 0;
941         err = sysctl_handle_int(oidp, &val, 0, req);
942         if (err)
943                 return (err);
944
945         /* write request */
946         if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
947                 return (EINVAL);
948         sc->voltage_sdram = val;
949
950         VC_LOCK(sc);
951         err = bcm2835_cpufreq_set_voltage(sc,
952             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C, val);
953         if (err == MSG_ERROR) {
954                 VC_UNLOCK(sc);
955                 device_printf(sc->dev, "set voltage sdram_c error\n");
956                 return (EIO);
957         }
958         err = bcm2835_cpufreq_set_voltage(sc,
959             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I, val);
960         if (err == MSG_ERROR) {
961                 VC_UNLOCK(sc);
962                 device_printf(sc->dev, "set voltage sdram_i error\n");
963                 return (EIO);
964         }
965         err = bcm2835_cpufreq_set_voltage(sc,
966             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P, val);
967         if (err == MSG_ERROR) {
968                 VC_UNLOCK(sc);
969                 device_printf(sc->dev, "set voltage sdram_p error\n");
970                 return (EIO);
971         }
972         VC_UNLOCK(sc);
973         DELAY(TRANSITION_LATENCY);
974
975         return (0);
976 }
977
978 static int
979 sysctl_bcm2835_cpufreq_temperature(SYSCTL_HANDLER_ARGS)
980 {
981         struct bcm2835_cpufreq_softc *sc = arg1;
982         int val;
983         int err;
984
985         /* get realtime value */
986         VC_LOCK(sc);
987         val = bcm2835_cpufreq_get_temperature(sc);
988         VC_UNLOCK(sc);
989         if (val == MSG_ERROR)
990                 return (EIO);
991
992         err = sysctl_handle_int(oidp, &val, 0, req);
993         if (err || !req->newptr) /* error || read request */
994                 return (err);
995
996         /* write request */
997         return (EINVAL);
998 }
999
1000 static int
1001 sysctl_bcm2835_devcpu_temperature(SYSCTL_HANDLER_ARGS)
1002 {
1003         struct bcm2835_cpufreq_softc *sc = arg1;
1004         int val;
1005         int err;
1006
1007         /* get realtime value */
1008         VC_LOCK(sc);
1009         val = bcm2835_cpufreq_get_temperature(sc);
1010         VC_UNLOCK(sc);
1011         if (val == MSG_ERROR)
1012                 return (EIO);
1013
1014         /* 1/1000 celsius (raw) to 1/10 kelvin */
1015         val = val / 100 + TZ_ZEROC;
1016
1017         err = sysctl_handle_int(oidp, &val, 0, req);
1018         if (err || !req->newptr) /* error || read request */
1019                 return (err);
1020
1021         /* write request */
1022         return (EINVAL);
1023 }
1024
1025
1026 static void
1027 bcm2835_cpufreq_init(void *arg)
1028 {
1029         struct bcm2835_cpufreq_softc *sc = arg;
1030         struct sysctl_ctx_list *ctx;
1031         device_t cpu;
1032         int arm_freq, core_freq, sdram_freq;
1033         int arm_max_freq, arm_min_freq, core_max_freq, core_min_freq;
1034         int sdram_max_freq, sdram_min_freq;
1035         int voltage_core, voltage_sdram_c, voltage_sdram_i, voltage_sdram_p;
1036         int max_voltage_core, min_voltage_core;
1037         int max_voltage_sdram_c, min_voltage_sdram_c;
1038         int max_voltage_sdram_i, min_voltage_sdram_i;
1039         int max_voltage_sdram_p, min_voltage_sdram_p;
1040         int turbo, temperature;
1041
1042         VC_LOCK(sc);
1043
1044         /* current clock */
1045         arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
1046             BCM2835_FIRMWARE_CLOCK_ID_ARM);
1047         core_freq = bcm2835_cpufreq_get_clock_rate(sc,
1048             BCM2835_FIRMWARE_CLOCK_ID_CORE);
1049         sdram_freq = bcm2835_cpufreq_get_clock_rate(sc,
1050             BCM2835_FIRMWARE_CLOCK_ID_SDRAM);
1051
1052         /* max/min clock */
1053         arm_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
1054             BCM2835_FIRMWARE_CLOCK_ID_ARM);
1055         arm_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
1056             BCM2835_FIRMWARE_CLOCK_ID_ARM);
1057         core_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
1058             BCM2835_FIRMWARE_CLOCK_ID_CORE);
1059         core_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
1060             BCM2835_FIRMWARE_CLOCK_ID_CORE);
1061         sdram_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
1062             BCM2835_FIRMWARE_CLOCK_ID_SDRAM);
1063         sdram_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
1064             BCM2835_FIRMWARE_CLOCK_ID_SDRAM);
1065
1066         /* turbo mode */
1067         turbo = bcm2835_cpufreq_get_turbo(sc);
1068         if (turbo > 0)
1069                 sc->turbo_mode = BCM2835_FIRMWARE_TURBO_ON;
1070         else
1071                 sc->turbo_mode = BCM2835_FIRMWARE_TURBO_OFF;
1072
1073         /* voltage */
1074         voltage_core = bcm2835_cpufreq_get_voltage(sc,
1075             BCM2835_FIRMWARE_VOLTAGE_ID_CORE);
1076         voltage_sdram_c = bcm2835_cpufreq_get_voltage(sc,
1077             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C);
1078         voltage_sdram_i = bcm2835_cpufreq_get_voltage(sc,
1079             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I);
1080         voltage_sdram_p = bcm2835_cpufreq_get_voltage(sc,
1081             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P);
1082
1083         /* current values (offset from 1.2V) */
1084         sc->voltage_core = voltage_core;
1085         sc->voltage_sdram = voltage_sdram_c;
1086         sc->voltage_sdram_c = voltage_sdram_c;
1087         sc->voltage_sdram_i = voltage_sdram_i;
1088         sc->voltage_sdram_p = voltage_sdram_p;
1089
1090         /* max/min voltage */
1091         max_voltage_core = bcm2835_cpufreq_get_max_voltage(sc,
1092             BCM2835_FIRMWARE_VOLTAGE_ID_CORE);
1093         min_voltage_core = bcm2835_cpufreq_get_min_voltage(sc,
1094             BCM2835_FIRMWARE_VOLTAGE_ID_CORE);
1095         max_voltage_sdram_c = bcm2835_cpufreq_get_max_voltage(sc,
1096             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C);
1097         max_voltage_sdram_i = bcm2835_cpufreq_get_max_voltage(sc,
1098             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I);
1099         max_voltage_sdram_p = bcm2835_cpufreq_get_max_voltage(sc,
1100             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P);
1101         min_voltage_sdram_c = bcm2835_cpufreq_get_min_voltage(sc,
1102             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C);
1103         min_voltage_sdram_i = bcm2835_cpufreq_get_min_voltage(sc,
1104             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I);
1105         min_voltage_sdram_p = bcm2835_cpufreq_get_min_voltage(sc,
1106             BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P);
1107
1108         /* temperature */
1109         temperature = bcm2835_cpufreq_get_temperature(sc);
1110
1111         /* show result */
1112         if (cpufreq_verbose || bootverbose) {
1113                 device_printf(sc->dev, "Boot settings:\n");
1114                 device_printf(sc->dev,
1115                     "current ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n",
1116                     HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq),
1117                     (sc->turbo_mode == BCM2835_FIRMWARE_TURBO_ON) ? "ON":"OFF");
1118
1119                 device_printf(sc->dev,
1120                     "max/min ARM %d/%dMHz, Core %d/%dMHz, SDRAM %d/%dMHz\n",
1121                     HZ2MHZ(arm_max_freq), HZ2MHZ(arm_min_freq),
1122                     HZ2MHZ(core_max_freq), HZ2MHZ(core_min_freq),
1123                     HZ2MHZ(sdram_max_freq), HZ2MHZ(sdram_min_freq));
1124
1125                 device_printf(sc->dev,
1126                     "current Core %dmV, SDRAM_C %dmV, SDRAM_I %dmV, "
1127                     "SDRAM_P %dmV\n",
1128                     OFFSET2MVOLT(voltage_core), OFFSET2MVOLT(voltage_sdram_c),
1129                     OFFSET2MVOLT(voltage_sdram_i), 
1130                     OFFSET2MVOLT(voltage_sdram_p));
1131
1132                 device_printf(sc->dev,
1133                     "max/min Core %d/%dmV, SDRAM_C %d/%dmV, SDRAM_I %d/%dmV, "
1134                     "SDRAM_P %d/%dmV\n",
1135                     OFFSET2MVOLT(max_voltage_core),
1136                     OFFSET2MVOLT(min_voltage_core),
1137                     OFFSET2MVOLT(max_voltage_sdram_c),
1138                     OFFSET2MVOLT(min_voltage_sdram_c),
1139                     OFFSET2MVOLT(max_voltage_sdram_i),
1140                     OFFSET2MVOLT(min_voltage_sdram_i),
1141                     OFFSET2MVOLT(max_voltage_sdram_p),
1142                     OFFSET2MVOLT(min_voltage_sdram_p));
1143
1144                 device_printf(sc->dev,
1145                     "Temperature %d.%dC\n", (temperature / 1000),
1146                     (temperature % 1000) / 100);
1147         } else { /* !cpufreq_verbose && !bootverbose */
1148                 device_printf(sc->dev,
1149                     "ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n",
1150                     HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq),
1151                     (sc->turbo_mode == BCM2835_FIRMWARE_TURBO_ON) ? "ON":"OFF");
1152         }
1153
1154         /* keep in softc (MHz/mV) */
1155         sc->arm_max_freq = HZ2MHZ(arm_max_freq);
1156         sc->arm_min_freq = HZ2MHZ(arm_min_freq);
1157         sc->core_max_freq = HZ2MHZ(core_max_freq);
1158         sc->core_min_freq = HZ2MHZ(core_min_freq);
1159         sc->sdram_max_freq = HZ2MHZ(sdram_max_freq);
1160         sc->sdram_min_freq = HZ2MHZ(sdram_min_freq);
1161         sc->max_voltage_core = OFFSET2MVOLT(max_voltage_core);
1162         sc->min_voltage_core = OFFSET2MVOLT(min_voltage_core);
1163
1164         /* if turbo is on, set to max values */
1165         if (sc->turbo_mode == BCM2835_FIRMWARE_TURBO_ON) {
1166                 bcm2835_cpufreq_set_clock_rate(sc,
1167                     BCM2835_FIRMWARE_CLOCK_ID_ARM, arm_max_freq);
1168                 DELAY(TRANSITION_LATENCY);
1169                 bcm2835_cpufreq_set_clock_rate(sc,
1170                     BCM2835_FIRMWARE_CLOCK_ID_CORE, core_max_freq);
1171                 DELAY(TRANSITION_LATENCY);
1172                 bcm2835_cpufreq_set_clock_rate(sc,
1173                     BCM2835_FIRMWARE_CLOCK_ID_SDRAM, sdram_max_freq);
1174                 DELAY(TRANSITION_LATENCY);
1175         } else {
1176                 bcm2835_cpufreq_set_clock_rate(sc,
1177                     BCM2835_FIRMWARE_CLOCK_ID_ARM, arm_min_freq);
1178                 DELAY(TRANSITION_LATENCY);
1179                 bcm2835_cpufreq_set_clock_rate(sc,
1180                     BCM2835_FIRMWARE_CLOCK_ID_CORE, core_min_freq);
1181                 DELAY(TRANSITION_LATENCY);
1182                 bcm2835_cpufreq_set_clock_rate(sc,
1183                     BCM2835_FIRMWARE_CLOCK_ID_SDRAM, sdram_min_freq);
1184                 DELAY(TRANSITION_LATENCY);
1185         }
1186
1187         VC_UNLOCK(sc);
1188
1189         /* add human readable temperature to dev.cpu node */
1190         cpu = device_get_parent(sc->dev);
1191         if (cpu != NULL) {
1192                 ctx = device_get_sysctl_ctx(cpu);
1193                 SYSCTL_ADD_PROC(ctx,
1194                     SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)), OID_AUTO,
1195                     "temperature",
1196                     CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0,
1197                     sysctl_bcm2835_devcpu_temperature, "IK",
1198                     "Current SoC temperature");
1199         }
1200
1201         /* release this hook (continue boot) */
1202         config_intrhook_disestablish(&sc->init_hook);
1203 }
1204
1205 static void
1206 bcm2835_cpufreq_identify(driver_t *driver, device_t parent)
1207 {
1208         const struct ofw_compat_data *compat;
1209         phandle_t root;
1210
1211         root = OF_finddevice("/");
1212         for (compat = compat_data; compat->ocd_str != NULL; compat++)
1213                 if (ofw_bus_node_is_compatible(root, compat->ocd_str))
1214                         break;
1215
1216         if (compat->ocd_data == 0)
1217                 return;
1218
1219         DPRINTF("driver=%p, parent=%p\n", driver, parent);
1220         if (device_find_child(parent, "bcm2835_cpufreq", -1) != NULL)
1221                 return;
1222         if (BUS_ADD_CHILD(parent, 0, "bcm2835_cpufreq", -1) == NULL)
1223                 device_printf(parent, "add child failed\n");
1224 }
1225
1226 static int
1227 bcm2835_cpufreq_probe(device_t dev)
1228 {
1229
1230         if (device_get_unit(dev) != 0)
1231                 return (ENXIO);
1232         device_set_desc(dev, "CPU Frequency Control");
1233
1234         return (0);
1235 }
1236
1237 static int
1238 bcm2835_cpufreq_attach(device_t dev)
1239 {
1240         struct bcm2835_cpufreq_softc *sc;
1241         struct sysctl_oid *oid;
1242
1243         /* set self dev */
1244         sc = device_get_softc(dev);
1245         sc->dev = dev;
1246         sc->firmware = devclass_get_device(
1247             devclass_find("bcm2835_firmware"), 0);
1248         if (sc->firmware == NULL) {
1249                 device_printf(dev, "Unable to find firmware device\n");
1250                 return (ENXIO);
1251         }
1252
1253         /* initial values */
1254         sc->arm_max_freq = -1;
1255         sc->arm_min_freq = -1;
1256         sc->core_max_freq = -1;
1257         sc->core_min_freq = -1;
1258         sc->sdram_max_freq = -1;
1259         sc->sdram_min_freq = -1;
1260         sc->max_voltage_core = 0;
1261         sc->min_voltage_core = 0;
1262
1263         /* setup sysctl at first device */
1264         if (device_get_unit(dev) == 0) {
1265                 sysctl_ctx_init(&bcm2835_sysctl_ctx);
1266                 /* create node for hw.cpufreq */
1267                 oid = SYSCTL_ADD_NODE(&bcm2835_sysctl_ctx,
1268                     SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "cpufreq",
1269                     CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
1270
1271                 /* Frequency (Hz) */
1272                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1273                     OID_AUTO, "arm_freq",
1274                     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
1275                     sysctl_bcm2835_cpufreq_arm_freq, "IU",
1276                     "ARM frequency (Hz)");
1277                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1278                     OID_AUTO, "core_freq",
1279                     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
1280                     sysctl_bcm2835_cpufreq_core_freq, "IU",
1281                     "Core frequency (Hz)");
1282                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1283                     OID_AUTO, "sdram_freq",
1284                     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
1285                     sysctl_bcm2835_cpufreq_sdram_freq, "IU",
1286                     "SDRAM frequency (Hz)");
1287
1288                 /* Turbo state */
1289                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1290                     OID_AUTO, "turbo",
1291                     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
1292                     sysctl_bcm2835_cpufreq_turbo, "IU",
1293                     "Disables dynamic clocking");
1294
1295                 /* Voltage (offset from 1.2V in units of 0.025V) */
1296                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1297                     OID_AUTO, "voltage_core",
1298                     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
1299                     sysctl_bcm2835_cpufreq_voltage_core, "I",
1300                     "ARM/GPU core voltage"
1301                     "(offset from 1.2V in units of 0.025V)");
1302                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1303                     OID_AUTO, "voltage_sdram",
1304                     CTLTYPE_INT | CTLFLAG_WR | CTLFLAG_NEEDGIANT, sc,
1305                     0, sysctl_bcm2835_cpufreq_voltage_sdram, "I",
1306                     "SDRAM voltage (offset from 1.2V in units of 0.025V)");
1307
1308                 /* Voltage individual SDRAM */
1309                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1310                     OID_AUTO, "voltage_sdram_c",
1311                     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc,
1312                     0, sysctl_bcm2835_cpufreq_voltage_sdram_c, "I",
1313                     "SDRAM controller voltage"
1314                     "(offset from 1.2V in units of 0.025V)");
1315                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1316                     OID_AUTO, "voltage_sdram_i",
1317                     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc,
1318                     0, sysctl_bcm2835_cpufreq_voltage_sdram_i, "I",
1319                     "SDRAM I/O voltage (offset from 1.2V in units of 0.025V)");
1320                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1321                     OID_AUTO, "voltage_sdram_p",
1322                     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc,
1323                     0, sysctl_bcm2835_cpufreq_voltage_sdram_p, "I",
1324                     "SDRAM phy voltage (offset from 1.2V in units of 0.025V)");
1325
1326                 /* Temperature */
1327                 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1328                     OID_AUTO, "temperature",
1329                     CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, 0,
1330                     sysctl_bcm2835_cpufreq_temperature, "I",
1331                     "SoC temperature (thousandths of a degree C)");
1332         }
1333
1334         /* ARM->VC lock */
1335         sema_init(&vc_sema, 1, "vcsema");
1336
1337         /* register callback for using mbox when interrupts are enabled */
1338         sc->init_hook.ich_func = bcm2835_cpufreq_init;
1339         sc->init_hook.ich_arg = sc;
1340
1341         if (config_intrhook_establish(&sc->init_hook) != 0) {
1342                 device_printf(dev, "config_intrhook_establish failed\n");
1343                 return (ENOMEM);
1344         }
1345
1346         /* this device is controlled by cpufreq(4) */
1347         cpufreq_register(dev);
1348
1349         return (0);
1350 }
1351
1352 static int
1353 bcm2835_cpufreq_detach(device_t dev)
1354 {
1355
1356         sema_destroy(&vc_sema);
1357
1358         return (cpufreq_unregister(dev));
1359 }
1360
1361 static int
1362 bcm2835_cpufreq_set(device_t dev, const struct cf_setting *cf)
1363 {
1364         struct bcm2835_cpufreq_softc *sc;
1365         uint32_t rate_hz, rem;
1366         int resp_freq, arm_freq, min_freq, core_freq;
1367 #ifdef DEBUG
1368         int cur_freq;
1369 #endif
1370
1371         if (cf == NULL || cf->freq < 0)
1372                 return (EINVAL);
1373
1374         sc = device_get_softc(dev);
1375
1376         /* setting clock (Hz) */
1377         rate_hz = (uint32_t)MHZ2HZ(cf->freq);
1378         rem = rate_hz % HZSTEP;
1379         rate_hz -= rem;
1380         if (rate_hz == 0)
1381                 return (EINVAL);
1382
1383         /* adjust min freq */
1384         min_freq = sc->arm_min_freq;
1385         if (sc->turbo_mode != BCM2835_FIRMWARE_TURBO_ON)
1386                 if (min_freq > cpufreq_lowest_freq)
1387                         min_freq = cpufreq_lowest_freq;
1388
1389         if (rate_hz < MHZ2HZ(min_freq) || rate_hz > MHZ2HZ(sc->arm_max_freq))
1390                 return (EINVAL);
1391
1392         /* set new value and verify it */
1393         VC_LOCK(sc);
1394 #ifdef DEBUG
1395         cur_freq = bcm2835_cpufreq_get_clock_rate(sc,
1396             BCM2835_FIRMWARE_CLOCK_ID_ARM);
1397 #endif
1398         resp_freq = bcm2835_cpufreq_set_clock_rate(sc,
1399             BCM2835_FIRMWARE_CLOCK_ID_ARM, rate_hz);
1400         DELAY(TRANSITION_LATENCY);
1401         arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
1402             BCM2835_FIRMWARE_CLOCK_ID_ARM);
1403
1404         /*
1405          * if non-turbo and lower than or equal min_freq,
1406          * clock down core and sdram to default first.
1407          */
1408         if (sc->turbo_mode != BCM2835_FIRMWARE_TURBO_ON) {
1409                 core_freq = bcm2835_cpufreq_get_clock_rate(sc,
1410                     BCM2835_FIRMWARE_CLOCK_ID_CORE);
1411                 if (rate_hz > MHZ2HZ(sc->arm_min_freq)) {
1412                         bcm2835_cpufreq_set_clock_rate(sc,
1413                             BCM2835_FIRMWARE_CLOCK_ID_CORE,
1414                             MHZ2HZ(sc->core_max_freq));
1415                         DELAY(TRANSITION_LATENCY);
1416                         bcm2835_cpufreq_set_clock_rate(sc,
1417                             BCM2835_FIRMWARE_CLOCK_ID_SDRAM,
1418                             MHZ2HZ(sc->sdram_max_freq));
1419                         DELAY(TRANSITION_LATENCY);
1420                 } else {
1421                         if (sc->core_min_freq < DEFAULT_CORE_FREQUENCY &&
1422                             core_freq > DEFAULT_CORE_FREQUENCY) {
1423                                 /* first, down to 250, then down to min */
1424                                 DELAY(TRANSITION_LATENCY);
1425                                 bcm2835_cpufreq_set_clock_rate(sc,
1426                                     BCM2835_FIRMWARE_CLOCK_ID_CORE,
1427                                     MHZ2HZ(DEFAULT_CORE_FREQUENCY));
1428                                 DELAY(TRANSITION_LATENCY);
1429                                 /* reset core voltage */
1430                                 bcm2835_cpufreq_set_voltage(sc,
1431                                     BCM2835_FIRMWARE_VOLTAGE_ID_CORE, 0);
1432                                 DELAY(TRANSITION_LATENCY);
1433                         }
1434                         bcm2835_cpufreq_set_clock_rate(sc,
1435                             BCM2835_FIRMWARE_CLOCK_ID_CORE,
1436                             MHZ2HZ(sc->core_min_freq));
1437                         DELAY(TRANSITION_LATENCY);
1438                         bcm2835_cpufreq_set_clock_rate(sc,
1439                             BCM2835_FIRMWARE_CLOCK_ID_SDRAM,
1440                             MHZ2HZ(sc->sdram_min_freq));
1441                         DELAY(TRANSITION_LATENCY);
1442                 }
1443         }
1444
1445         VC_UNLOCK(sc);
1446
1447         if (resp_freq < 0 || arm_freq < 0 || resp_freq != arm_freq) {
1448                 device_printf(dev, "wrong freq\n");
1449                 return (EIO);
1450         }
1451         DPRINTF("cpufreq: %d -> %d\n", cur_freq, arm_freq);
1452
1453         return (0);
1454 }
1455
1456 static int
1457 bcm2835_cpufreq_get(device_t dev, struct cf_setting *cf)
1458 {
1459         struct bcm2835_cpufreq_softc *sc;
1460         int arm_freq;
1461
1462         if (cf == NULL)
1463                 return (EINVAL);
1464
1465         sc = device_get_softc(dev);
1466         memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
1467         cf->dev = NULL;
1468
1469         /* get cuurent value */
1470         VC_LOCK(sc);
1471         arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
1472             BCM2835_FIRMWARE_CLOCK_ID_ARM);
1473         VC_UNLOCK(sc);
1474         if (arm_freq < 0) {
1475                 device_printf(dev, "can't get clock\n");
1476                 return (EINVAL);
1477         }
1478
1479         /* CPU clock in MHz or 100ths of a percent. */
1480         cf->freq = HZ2MHZ(arm_freq);
1481         /* Voltage in mV. */
1482         cf->volts = CPUFREQ_VAL_UNKNOWN;
1483         /* Power consumed in mW. */
1484         cf->power = CPUFREQ_VAL_UNKNOWN;
1485         /* Transition latency in us. */
1486         cf->lat = TRANSITION_LATENCY;
1487         /* Driver providing this setting. */
1488         cf->dev = dev;
1489
1490         return (0);
1491 }
1492
1493 static int
1494 bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets,
1495     int *count)
1496 {
1497         struct bcm2835_cpufreq_softc *sc;
1498         int freq, min_freq, volts, rem;
1499         int idx;
1500
1501         sc = device_get_softc(dev);
1502         freq = sc->arm_max_freq;
1503         min_freq = sc->arm_min_freq;
1504
1505         /* adjust head freq to STEP */
1506         rem = freq % MHZSTEP;
1507         freq -= rem;
1508         if (freq < min_freq)
1509                 freq = min_freq;
1510
1511         /* if non-turbo, add extra low freq */
1512         if (sc->turbo_mode != BCM2835_FIRMWARE_TURBO_ON)
1513                 if (min_freq > cpufreq_lowest_freq)
1514                         min_freq = cpufreq_lowest_freq;
1515
1516 #ifdef SOC_BCM2835
1517         /* from freq to min_freq */
1518         for (idx = 0; idx < *count && freq >= min_freq; idx++) {
1519                 if (freq > sc->arm_min_freq)
1520                         volts = sc->max_voltage_core;
1521                 else
1522                         volts = sc->min_voltage_core;
1523                 sets[idx].freq = freq;
1524                 sets[idx].volts = volts;
1525                 sets[idx].lat = TRANSITION_LATENCY;
1526                 sets[idx].dev = dev;
1527                 freq -= MHZSTEP;
1528         }
1529 #else
1530         /* XXX RPi2 have only 900/600MHz */
1531         idx = 0;
1532         volts = sc->min_voltage_core;
1533         sets[idx].freq = freq;
1534         sets[idx].volts = volts;
1535         sets[idx].lat = TRANSITION_LATENCY;
1536         sets[idx].dev = dev;
1537         idx++;
1538         if (freq != min_freq) {
1539                 sets[idx].freq = min_freq;
1540                 sets[idx].volts = volts;
1541                 sets[idx].lat = TRANSITION_LATENCY;
1542                 sets[idx].dev = dev;
1543                 idx++;
1544         }
1545 #endif
1546         *count = idx;
1547
1548         return (0);
1549 }
1550
1551 static int
1552 bcm2835_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count)
1553 {
1554         struct bcm2835_cpufreq_softc *sc;
1555
1556         if (sets == NULL || count == NULL)
1557                 return (EINVAL);
1558
1559         sc = device_get_softc(dev);
1560         if (sc->arm_min_freq < 0 || sc->arm_max_freq < 0) {
1561                 printf("device is not configured\n");
1562                 return (EINVAL);
1563         }
1564
1565         /* fill data with unknown value */
1566         memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * (*count));
1567         /* create new array up to count */
1568         bcm2835_cpufreq_make_freq_list(dev, sets, count);
1569
1570         return (0);
1571 }
1572
1573 static int
1574 bcm2835_cpufreq_type(device_t dev, int *type)
1575 {
1576
1577         if (type == NULL)
1578                 return (EINVAL);
1579         *type = CPUFREQ_TYPE_ABSOLUTE;
1580
1581         return (0);
1582 }
1583
1584 static device_method_t bcm2835_cpufreq_methods[] = {
1585         /* Device interface */
1586         DEVMETHOD(device_identify,      bcm2835_cpufreq_identify),
1587         DEVMETHOD(device_probe,         bcm2835_cpufreq_probe),
1588         DEVMETHOD(device_attach,        bcm2835_cpufreq_attach),
1589         DEVMETHOD(device_detach,        bcm2835_cpufreq_detach),
1590
1591         /* cpufreq interface */
1592         DEVMETHOD(cpufreq_drv_set,      bcm2835_cpufreq_set),
1593         DEVMETHOD(cpufreq_drv_get,      bcm2835_cpufreq_get),
1594         DEVMETHOD(cpufreq_drv_settings, bcm2835_cpufreq_settings),
1595         DEVMETHOD(cpufreq_drv_type,     bcm2835_cpufreq_type),
1596
1597         DEVMETHOD_END
1598 };
1599
1600 static devclass_t bcm2835_cpufreq_devclass;
1601 static driver_t bcm2835_cpufreq_driver = {
1602         "bcm2835_cpufreq",
1603         bcm2835_cpufreq_methods,
1604         sizeof(struct bcm2835_cpufreq_softc),
1605 };
1606
1607 DRIVER_MODULE(bcm2835_cpufreq, cpu, bcm2835_cpufreq_driver,
1608     bcm2835_cpufreq_devclass, 0, 0);
1609 MODULE_DEPEND(bcm2835_cpufreq, bcm2835_firmware, 1, 1, 1);