2 * Copyright (C) 2013-2015 Daisuke Aoyama <aoyama@peach.ne.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
32 #include <sys/systm.h>
35 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/mutex.h>
41 #include <sys/sysctl.h>
43 #include <machine/bus.h>
44 #include <machine/cpu.h>
45 #include <machine/intr.h>
47 #include <arm/broadcom/bcm2835/bcm2835_mbox.h>
48 #include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
49 #include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
51 #include "cpufreq_if.h"
55 #define DPRINTF(fmt, ...) do { \
56 printf("%s:%u: ", __func__, __LINE__); \
57 printf(fmt, ##__VA_ARGS__); \
60 #define DPRINTF(fmt, ...)
63 #define HZ2MHZ(freq) ((freq) / (1000 * 1000))
64 #define MHZ2HZ(freq) ((freq) * (1000 * 1000))
67 #define OFFSET2MVOLT(val) (((val) / 1000))
68 #define MVOLT2OFFSET(val) (((val) * 1000))
69 #define DEFAULT_ARM_FREQUENCY 600
70 #define DEFAULT_LOWEST_FREQ 600
72 #define OFFSET2MVOLT(val) (1200 + ((val) * 25))
73 #define MVOLT2OFFSET(val) (((val) - 1200) / 25)
74 #define DEFAULT_ARM_FREQUENCY 700
75 #define DEFAULT_LOWEST_FREQ 300
77 #define DEFAULT_CORE_FREQUENCY 250
78 #define DEFAULT_SDRAM_FREQUENCY 400
79 #define TRANSITION_LATENCY 1000
80 #define MIN_OVER_VOLTAGE -16
81 #define MAX_OVER_VOLTAGE 6
82 #define MSG_ERROR -999999999
84 #define HZSTEP (MHZ2HZ(MHZSTEP))
87 #define VC_LOCK(sc) do { \
88 sema_wait(&vc_sema); \
90 #define VC_UNLOCK(sc) do { \
91 sema_post(&vc_sema); \
94 /* ARM->VC mailbox property semaphore */
95 static struct sema vc_sema;
97 static struct sysctl_ctx_list bcm2835_sysctl_ctx;
99 struct bcm2835_cpufreq_softc {
107 int max_voltage_core;
108 int min_voltage_core;
110 /* the values written in mbox */
118 /* initial hook for waiting mbox intr */
119 struct intr_config_hook init_hook;
122 static int cpufreq_verbose = 0;
123 TUNABLE_INT("hw.bcm2835.cpufreq.verbose", &cpufreq_verbose);
124 static int cpufreq_lowest_freq = DEFAULT_LOWEST_FREQ;
125 TUNABLE_INT("hw.bcm2835.cpufreq.lowest_freq", &cpufreq_lowest_freq);
129 bcm2835_dump(const void *data, int len)
131 const uint8_t *p = (const uint8_t*)data;
134 printf("dump @ %p:\n", data);
135 for (i = 0; i < len; i++) {
136 printf("%2.2x ", p[i]);
147 bcm2835_cpufreq_get_clock_rate(struct bcm2835_cpufreq_softc *sc,
150 struct msg_get_clock_rate msg;
168 /* setup single tag buffer */
169 memset(&msg, 0, sizeof(msg));
170 msg.hdr.buf_size = sizeof(msg);
171 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
172 msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_CLOCK_RATE;
173 msg.tag_hdr.val_buf_size = sizeof(msg.body);
174 msg.tag_hdr.val_len = sizeof(msg.body.req);
175 msg.body.req.clock_id = clock_id;
178 /* call mailbox property */
179 err = bcm2835_mbox_property(&msg, sizeof(msg));
181 device_printf(sc->dev, "can't get clock rate (id=%u)\n",
187 rate = (int)msg.body.resp.rate_hz;
188 DPRINTF("clock = %d(Hz)\n", rate);
193 bcm2835_cpufreq_get_max_clock_rate(struct bcm2835_cpufreq_softc *sc,
196 struct msg_get_max_clock_rate msg;
214 /* setup single tag buffer */
215 memset(&msg, 0, sizeof(msg));
216 msg.hdr.buf_size = sizeof(msg);
217 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
218 msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MAX_CLOCK_RATE;
219 msg.tag_hdr.val_buf_size = sizeof(msg.body);
220 msg.tag_hdr.val_len = sizeof(msg.body.req);
221 msg.body.req.clock_id = clock_id;
224 /* call mailbox property */
225 err = bcm2835_mbox_property(&msg, sizeof(msg));
227 device_printf(sc->dev, "can't get max clock rate (id=%u)\n",
233 rate = (int)msg.body.resp.rate_hz;
234 DPRINTF("clock = %d(Hz)\n", rate);
239 bcm2835_cpufreq_get_min_clock_rate(struct bcm2835_cpufreq_softc *sc,
242 struct msg_get_min_clock_rate msg;
260 /* setup single tag buffer */
261 memset(&msg, 0, sizeof(msg));
262 msg.hdr.buf_size = sizeof(msg);
263 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
264 msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_CLOCK_RATE;
265 msg.tag_hdr.val_buf_size = sizeof(msg.body);
266 msg.tag_hdr.val_len = sizeof(msg.body.req);
267 msg.body.req.clock_id = clock_id;
270 /* call mailbox property */
271 err = bcm2835_mbox_property(&msg, sizeof(msg));
273 device_printf(sc->dev, "can't get min clock rate (id=%u)\n",
279 rate = (int)msg.body.resp.rate_hz;
280 DPRINTF("clock = %d(Hz)\n", rate);
285 bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc,
286 uint32_t clock_id, uint32_t rate_hz)
288 struct msg_set_clock_rate msg;
307 /* setup single tag buffer */
308 memset(&msg, 0, sizeof(msg));
309 msg.hdr.buf_size = sizeof(msg);
310 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
311 msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE;
312 msg.tag_hdr.val_buf_size = sizeof(msg.body);
313 msg.tag_hdr.val_len = sizeof(msg.body.req);
314 msg.body.req.clock_id = clock_id;
315 msg.body.req.rate_hz = rate_hz;
318 /* call mailbox property */
319 err = bcm2835_mbox_property(&msg, sizeof(msg));
321 device_printf(sc->dev, "can't set clock rate (id=%u)\n",
326 /* workaround for core clock */
327 if (clock_id == BCM2835_MBOX_CLOCK_ID_CORE) {
328 /* for safety (may change voltage without changing clock) */
329 DELAY(TRANSITION_LATENCY);
332 * XXX: the core clock is unable to change at once,
333 * to change certainly, write it twice now.
336 /* setup single tag buffer */
337 memset(&msg, 0, sizeof(msg));
338 msg.hdr.buf_size = sizeof(msg);
339 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
340 msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE;
341 msg.tag_hdr.val_buf_size = sizeof(msg.body);
342 msg.tag_hdr.val_len = sizeof(msg.body.req);
343 msg.body.req.clock_id = clock_id;
344 msg.body.req.rate_hz = rate_hz;
347 /* call mailbox property */
348 err = bcm2835_mbox_property(&msg, sizeof(msg));
350 device_printf(sc->dev,
351 "can't set clock rate (id=%u)\n", clock_id);
357 rate = (int)msg.body.resp.rate_hz;
358 DPRINTF("clock = %d(Hz)\n", rate);
363 bcm2835_cpufreq_get_turbo(struct bcm2835_cpufreq_softc *sc)
365 struct msg_get_turbo msg;
383 /* setup single tag buffer */
384 memset(&msg, 0, sizeof(msg));
385 msg.hdr.buf_size = sizeof(msg);
386 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
387 msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_TURBO;
388 msg.tag_hdr.val_buf_size = sizeof(msg.body);
389 msg.tag_hdr.val_len = sizeof(msg.body.req);
393 /* call mailbox property */
394 err = bcm2835_mbox_property(&msg, sizeof(msg));
396 device_printf(sc->dev, "can't get turbo\n");
400 /* result 0=non-turbo, 1=turbo */
401 level = (int)msg.body.resp.level;
402 DPRINTF("level = %d\n", level);
407 bcm2835_cpufreq_set_turbo(struct bcm2835_cpufreq_softc *sc, uint32_t level)
409 struct msg_set_turbo msg;
428 /* replace unknown value to OFF */
429 if (level != BCM2835_MBOX_TURBO_ON && level != BCM2835_MBOX_TURBO_OFF)
430 level = BCM2835_MBOX_TURBO_OFF;
432 /* setup single tag buffer */
433 memset(&msg, 0, sizeof(msg));
434 msg.hdr.buf_size = sizeof(msg);
435 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
436 msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_TURBO;
437 msg.tag_hdr.val_buf_size = sizeof(msg.body);
438 msg.tag_hdr.val_len = sizeof(msg.body.req);
440 msg.body.req.level = level;
443 /* call mailbox property */
444 err = bcm2835_mbox_property(&msg, sizeof(msg));
446 device_printf(sc->dev, "can't set turbo\n");
450 /* result 0=non-turbo, 1=turbo */
451 value = (int)msg.body.resp.level;
452 DPRINTF("level = %d\n", value);
457 bcm2835_cpufreq_get_voltage(struct bcm2835_cpufreq_softc *sc,
460 struct msg_get_voltage msg;
475 * u32: value (offset from 1.2V in units of 0.025V)
478 /* setup single tag buffer */
479 memset(&msg, 0, sizeof(msg));
480 msg.hdr.buf_size = sizeof(msg);
481 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
482 msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_VOLTAGE;
483 msg.tag_hdr.val_buf_size = sizeof(msg.body);
484 msg.tag_hdr.val_len = sizeof(msg.body.req);
485 msg.body.req.voltage_id = voltage_id;
488 /* call mailbox property */
489 err = bcm2835_mbox_property(&msg, sizeof(msg));
491 device_printf(sc->dev, "can't get voltage\n");
495 /* result (offset from 1.2V) */
496 value = (int)msg.body.resp.value;
497 DPRINTF("value = %d\n", value);
502 bcm2835_cpufreq_get_max_voltage(struct bcm2835_cpufreq_softc *sc,
505 struct msg_get_max_voltage msg;
520 * u32: value (offset from 1.2V in units of 0.025V)
523 /* setup single tag buffer */
524 memset(&msg, 0, sizeof(msg));
525 msg.hdr.buf_size = sizeof(msg);
526 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
527 msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MAX_VOLTAGE;
528 msg.tag_hdr.val_buf_size = sizeof(msg.body);
529 msg.tag_hdr.val_len = sizeof(msg.body.req);
530 msg.body.req.voltage_id = voltage_id;
533 /* call mailbox property */
534 err = bcm2835_mbox_property(&msg, sizeof(msg));
536 device_printf(sc->dev, "can't get max voltage\n");
540 /* result (offset from 1.2V) */
541 value = (int)msg.body.resp.value;
542 DPRINTF("value = %d\n", value);
546 bcm2835_cpufreq_get_min_voltage(struct bcm2835_cpufreq_softc *sc,
549 struct msg_get_min_voltage msg;
564 * u32: value (offset from 1.2V in units of 0.025V)
567 /* setup single tag buffer */
568 memset(&msg, 0, sizeof(msg));
569 msg.hdr.buf_size = sizeof(msg);
570 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
571 msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_VOLTAGE;
572 msg.tag_hdr.val_buf_size = sizeof(msg.body);
573 msg.tag_hdr.val_len = sizeof(msg.body.req);
574 msg.body.req.voltage_id = voltage_id;
577 /* call mailbox property */
578 err = bcm2835_mbox_property(&msg, sizeof(msg));
580 device_printf(sc->dev, "can't get min voltage\n");
584 /* result (offset from 1.2V) */
585 value = (int)msg.body.resp.value;
586 DPRINTF("value = %d\n", value);
591 bcm2835_cpufreq_set_voltage(struct bcm2835_cpufreq_softc *sc,
592 uint32_t voltage_id, int32_t value)
594 struct msg_set_voltage msg;
604 * u32: value (offset from 1.2V in units of 0.025V)
609 * u32: value (offset from 1.2V in units of 0.025V)
614 * 0 (1.2 V). Values above 6 are only allowed when force_turbo or
615 * current_limit_override are specified (which set the warranty bit).
617 if (value > MAX_OVER_VOLTAGE || value < MIN_OVER_VOLTAGE) {
618 /* currently not supported */
619 device_printf(sc->dev, "not supported voltage: %d\n", value);
623 /* setup single tag buffer */
624 memset(&msg, 0, sizeof(msg));
625 msg.hdr.buf_size = sizeof(msg);
626 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
627 msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_VOLTAGE;
628 msg.tag_hdr.val_buf_size = sizeof(msg.body);
629 msg.tag_hdr.val_len = sizeof(msg.body.req);
630 msg.body.req.voltage_id = voltage_id;
631 msg.body.req.value = (uint32_t)value;
634 /* call mailbox property */
635 err = bcm2835_mbox_property(&msg, sizeof(msg));
637 device_printf(sc->dev, "can't set voltage\n");
641 /* result (offset from 1.2V) */
642 value = (int)msg.body.resp.value;
643 DPRINTF("value = %d\n", value);
648 bcm2835_cpufreq_get_temperature(struct bcm2835_cpufreq_softc *sc)
650 struct msg_get_temperature msg;
660 * u32: temperature id
664 * u32: temperature id
668 /* setup single tag buffer */
669 memset(&msg, 0, sizeof(msg));
670 msg.hdr.buf_size = sizeof(msg);
671 msg.hdr.code = BCM2835_MBOX_CODE_REQ;
672 msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_TEMPERATURE;
673 msg.tag_hdr.val_buf_size = sizeof(msg.body);
674 msg.tag_hdr.val_len = sizeof(msg.body.req);
675 msg.body.req.temperature_id = 0;
678 /* call mailbox property */
679 err = bcm2835_mbox_property(&msg, sizeof(msg));
681 device_printf(sc->dev, "can't get temperature\n");
685 /* result (temperature of degree C) */
686 value = (int)msg.body.resp.value;
687 DPRINTF("value = %d\n", value);
694 sysctl_bcm2835_cpufreq_arm_freq(SYSCTL_HANDLER_ARGS)
696 struct bcm2835_cpufreq_softc *sc = arg1;
700 /* get realtime value */
702 val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM);
704 if (val == MSG_ERROR)
707 err = sysctl_handle_int(oidp, &val, 0, req);
708 if (err || !req->newptr) /* error || read request */
713 err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
716 if (err == MSG_ERROR) {
717 device_printf(sc->dev, "set clock arm_freq error\n");
720 DELAY(TRANSITION_LATENCY);
726 sysctl_bcm2835_cpufreq_core_freq(SYSCTL_HANDLER_ARGS)
728 struct bcm2835_cpufreq_softc *sc = arg1;
732 /* get realtime value */
734 val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE);
736 if (val == MSG_ERROR)
739 err = sysctl_handle_int(oidp, &val, 0, req);
740 if (err || !req->newptr) /* error || read request */
745 err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
747 if (err == MSG_ERROR) {
749 device_printf(sc->dev, "set clock core_freq error\n");
753 DELAY(TRANSITION_LATENCY);
759 sysctl_bcm2835_cpufreq_sdram_freq(SYSCTL_HANDLER_ARGS)
761 struct bcm2835_cpufreq_softc *sc = arg1;
765 /* get realtime value */
767 val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM);
769 if (val == MSG_ERROR)
772 err = sysctl_handle_int(oidp, &val, 0, req);
773 if (err || !req->newptr) /* error || read request */
778 err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM,
781 if (err == MSG_ERROR) {
782 device_printf(sc->dev, "set clock sdram_freq error\n");
785 DELAY(TRANSITION_LATENCY);
791 sysctl_bcm2835_cpufreq_turbo(SYSCTL_HANDLER_ARGS)
793 struct bcm2835_cpufreq_softc *sc = arg1;
797 /* get realtime value */
799 val = bcm2835_cpufreq_get_turbo(sc);
801 if (val == MSG_ERROR)
804 err = sysctl_handle_int(oidp, &val, 0, req);
805 if (err || !req->newptr) /* error || read request */
810 sc->turbo_mode = BCM2835_MBOX_TURBO_ON;
812 sc->turbo_mode = BCM2835_MBOX_TURBO_OFF;
815 err = bcm2835_cpufreq_set_turbo(sc, sc->turbo_mode);
817 if (err == MSG_ERROR) {
818 device_printf(sc->dev, "set turbo error\n");
821 DELAY(TRANSITION_LATENCY);
827 sysctl_bcm2835_cpufreq_voltage_core(SYSCTL_HANDLER_ARGS)
829 struct bcm2835_cpufreq_softc *sc = arg1;
833 /* get realtime value */
835 val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE);
837 if (val == MSG_ERROR)
840 err = sysctl_handle_int(oidp, &val, 0, req);
841 if (err || !req->newptr) /* error || read request */
845 if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
847 sc->voltage_core = val;
850 err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE,
853 if (err == MSG_ERROR) {
854 device_printf(sc->dev, "set voltage core error\n");
857 DELAY(TRANSITION_LATENCY);
863 sysctl_bcm2835_cpufreq_voltage_sdram_c(SYSCTL_HANDLER_ARGS)
865 struct bcm2835_cpufreq_softc *sc = arg1;
869 /* get realtime value */
871 val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
873 if (val == MSG_ERROR)
876 err = sysctl_handle_int(oidp, &val, 0, req);
877 if (err || !req->newptr) /* error || read request */
881 if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
883 sc->voltage_sdram_c = val;
886 err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C,
887 sc->voltage_sdram_c);
889 if (err == MSG_ERROR) {
890 device_printf(sc->dev, "set voltage sdram_c error\n");
893 DELAY(TRANSITION_LATENCY);
899 sysctl_bcm2835_cpufreq_voltage_sdram_i(SYSCTL_HANDLER_ARGS)
901 struct bcm2835_cpufreq_softc *sc = arg1;
905 /* get realtime value */
907 val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
909 if (val == MSG_ERROR)
912 err = sysctl_handle_int(oidp, &val, 0, req);
913 if (err || !req->newptr) /* error || read request */
917 if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
919 sc->voltage_sdram_i = val;
922 err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I,
923 sc->voltage_sdram_i);
925 if (err == MSG_ERROR) {
926 device_printf(sc->dev, "set voltage sdram_i error\n");
929 DELAY(TRANSITION_LATENCY);
935 sysctl_bcm2835_cpufreq_voltage_sdram_p(SYSCTL_HANDLER_ARGS)
937 struct bcm2835_cpufreq_softc *sc = arg1;
941 /* get realtime value */
943 val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
945 if (val == MSG_ERROR)
948 err = sysctl_handle_int(oidp, &val, 0, req);
949 if (err || !req->newptr) /* error || read request */
953 if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
955 sc->voltage_sdram_p = val;
958 err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P,
959 sc->voltage_sdram_p);
961 if (err == MSG_ERROR) {
962 device_printf(sc->dev, "set voltage sdram_p error\n");
965 DELAY(TRANSITION_LATENCY);
971 sysctl_bcm2835_cpufreq_voltage_sdram(SYSCTL_HANDLER_ARGS)
973 struct bcm2835_cpufreq_softc *sc = arg1;
977 /* multiple write only */
981 err = sysctl_handle_int(oidp, &val, 0, req);
986 if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
988 sc->voltage_sdram = val;
991 err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C,
993 if (err == MSG_ERROR) {
995 device_printf(sc->dev, "set voltage sdram_c error\n");
998 err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I,
1000 if (err == MSG_ERROR) {
1002 device_printf(sc->dev, "set voltage sdram_i error\n");
1005 err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P,
1007 if (err == MSG_ERROR) {
1009 device_printf(sc->dev, "set voltage sdram_p error\n");
1013 DELAY(TRANSITION_LATENCY);
1019 sysctl_bcm2835_cpufreq_temperature(SYSCTL_HANDLER_ARGS)
1021 struct bcm2835_cpufreq_softc *sc = arg1;
1025 /* get realtime value */
1027 val = bcm2835_cpufreq_get_temperature(sc);
1029 if (val == MSG_ERROR)
1032 err = sysctl_handle_int(oidp, &val, 0, req);
1033 if (err || !req->newptr) /* error || read request */
1041 sysctl_bcm2835_devcpu_temperature(SYSCTL_HANDLER_ARGS)
1043 struct bcm2835_cpufreq_softc *sc = arg1;
1047 /* get realtime value */
1049 val = bcm2835_cpufreq_get_temperature(sc);
1051 if (val == MSG_ERROR)
1054 /* 1/1000 celsius (raw) to 1/10 kelvin */
1055 val = val / 100 + TZ_ZEROC;
1057 err = sysctl_handle_int(oidp, &val, 0, req);
1058 if (err || !req->newptr) /* error || read request */
1067 bcm2835_cpufreq_init(void *arg)
1069 struct bcm2835_cpufreq_softc *sc = arg;
1070 struct sysctl_ctx_list *ctx;
1072 int arm_freq, core_freq, sdram_freq;
1073 int arm_max_freq, arm_min_freq, core_max_freq, core_min_freq;
1074 int sdram_max_freq, sdram_min_freq;
1075 int voltage_core, voltage_sdram_c, voltage_sdram_i, voltage_sdram_p;
1076 int max_voltage_core, min_voltage_core;
1077 int max_voltage_sdram_c, min_voltage_sdram_c;
1078 int max_voltage_sdram_i, min_voltage_sdram_i;
1079 int max_voltage_sdram_p, min_voltage_sdram_p;
1080 int turbo, temperature;
1085 arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
1086 BCM2835_MBOX_CLOCK_ID_ARM);
1087 core_freq = bcm2835_cpufreq_get_clock_rate(sc,
1088 BCM2835_MBOX_CLOCK_ID_CORE);
1089 sdram_freq = bcm2835_cpufreq_get_clock_rate(sc,
1090 BCM2835_MBOX_CLOCK_ID_SDRAM);
1093 arm_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
1094 BCM2835_MBOX_CLOCK_ID_ARM);
1095 arm_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
1096 BCM2835_MBOX_CLOCK_ID_ARM);
1097 core_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
1098 BCM2835_MBOX_CLOCK_ID_CORE);
1099 core_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
1100 BCM2835_MBOX_CLOCK_ID_CORE);
1101 sdram_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
1102 BCM2835_MBOX_CLOCK_ID_SDRAM);
1103 sdram_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
1104 BCM2835_MBOX_CLOCK_ID_SDRAM);
1107 turbo = bcm2835_cpufreq_get_turbo(sc);
1109 sc->turbo_mode = BCM2835_MBOX_TURBO_ON;
1111 sc->turbo_mode = BCM2835_MBOX_TURBO_OFF;
1114 voltage_core = bcm2835_cpufreq_get_voltage(sc,
1115 BCM2835_MBOX_VOLTAGE_ID_CORE);
1116 voltage_sdram_c = bcm2835_cpufreq_get_voltage(sc,
1117 BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
1118 voltage_sdram_i = bcm2835_cpufreq_get_voltage(sc,
1119 BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
1120 voltage_sdram_p = bcm2835_cpufreq_get_voltage(sc,
1121 BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
1123 /* current values (offset from 1.2V) */
1124 sc->voltage_core = voltage_core;
1125 sc->voltage_sdram = voltage_sdram_c;
1126 sc->voltage_sdram_c = voltage_sdram_c;
1127 sc->voltage_sdram_i = voltage_sdram_i;
1128 sc->voltage_sdram_p = voltage_sdram_p;
1130 /* max/min voltage */
1131 max_voltage_core = bcm2835_cpufreq_get_max_voltage(sc,
1132 BCM2835_MBOX_VOLTAGE_ID_CORE);
1133 min_voltage_core = bcm2835_cpufreq_get_min_voltage(sc,
1134 BCM2835_MBOX_VOLTAGE_ID_CORE);
1135 max_voltage_sdram_c = bcm2835_cpufreq_get_max_voltage(sc,
1136 BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
1137 max_voltage_sdram_i = bcm2835_cpufreq_get_max_voltage(sc,
1138 BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
1139 max_voltage_sdram_p = bcm2835_cpufreq_get_max_voltage(sc,
1140 BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
1141 min_voltage_sdram_c = bcm2835_cpufreq_get_min_voltage(sc,
1142 BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
1143 min_voltage_sdram_i = bcm2835_cpufreq_get_min_voltage(sc,
1144 BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
1145 min_voltage_sdram_p = bcm2835_cpufreq_get_min_voltage(sc,
1146 BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
1149 temperature = bcm2835_cpufreq_get_temperature(sc);
1152 if (cpufreq_verbose || bootverbose) {
1153 device_printf(sc->dev, "Boot settings:\n");
1154 device_printf(sc->dev,
1155 "current ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n",
1156 HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq),
1157 (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) ? "ON" : "OFF");
1159 device_printf(sc->dev,
1160 "max/min ARM %d/%dMHz, Core %d/%dMHz, SDRAM %d/%dMHz\n",
1161 HZ2MHZ(arm_max_freq), HZ2MHZ(arm_min_freq),
1162 HZ2MHZ(core_max_freq), HZ2MHZ(core_min_freq),
1163 HZ2MHZ(sdram_max_freq), HZ2MHZ(sdram_min_freq));
1165 device_printf(sc->dev,
1166 "current Core %dmV, SDRAM_C %dmV, SDRAM_I %dmV, "
1168 OFFSET2MVOLT(voltage_core), OFFSET2MVOLT(voltage_sdram_c),
1169 OFFSET2MVOLT(voltage_sdram_i),
1170 OFFSET2MVOLT(voltage_sdram_p));
1172 device_printf(sc->dev,
1173 "max/min Core %d/%dmV, SDRAM_C %d/%dmV, SDRAM_I %d/%dmV, "
1174 "SDRAM_P %d/%dmV\n",
1175 OFFSET2MVOLT(max_voltage_core),
1176 OFFSET2MVOLT(min_voltage_core),
1177 OFFSET2MVOLT(max_voltage_sdram_c),
1178 OFFSET2MVOLT(min_voltage_sdram_c),
1179 OFFSET2MVOLT(max_voltage_sdram_i),
1180 OFFSET2MVOLT(min_voltage_sdram_i),
1181 OFFSET2MVOLT(max_voltage_sdram_p),
1182 OFFSET2MVOLT(min_voltage_sdram_p));
1184 device_printf(sc->dev,
1185 "Temperature %d.%dC\n", (temperature / 1000),
1186 (temperature % 1000) / 100);
1187 } else { /* !cpufreq_verbose && !bootverbose */
1188 device_printf(sc->dev,
1189 "ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n",
1190 HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq),
1191 (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) ? "ON" : "OFF");
1194 /* keep in softc (MHz/mV) */
1195 sc->arm_max_freq = HZ2MHZ(arm_max_freq);
1196 sc->arm_min_freq = HZ2MHZ(arm_min_freq);
1197 sc->core_max_freq = HZ2MHZ(core_max_freq);
1198 sc->core_min_freq = HZ2MHZ(core_min_freq);
1199 sc->sdram_max_freq = HZ2MHZ(sdram_max_freq);
1200 sc->sdram_min_freq = HZ2MHZ(sdram_min_freq);
1201 sc->max_voltage_core = OFFSET2MVOLT(max_voltage_core);
1202 sc->min_voltage_core = OFFSET2MVOLT(min_voltage_core);
1204 /* if turbo is on, set to max values */
1205 if (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) {
1206 bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
1208 DELAY(TRANSITION_LATENCY);
1209 bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
1211 DELAY(TRANSITION_LATENCY);
1212 bcm2835_cpufreq_set_clock_rate(sc,
1213 BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_max_freq);
1214 DELAY(TRANSITION_LATENCY);
1216 bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
1218 DELAY(TRANSITION_LATENCY);
1219 bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
1221 DELAY(TRANSITION_LATENCY);
1222 bcm2835_cpufreq_set_clock_rate(sc,
1223 BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_min_freq);
1224 DELAY(TRANSITION_LATENCY);
1229 /* add human readable temperature to dev.cpu node */
1230 cpu = device_get_parent(sc->dev);
1232 ctx = device_get_sysctl_ctx(cpu);
1233 SYSCTL_ADD_PROC(ctx,
1234 SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)), OID_AUTO,
1235 "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
1236 sysctl_bcm2835_devcpu_temperature, "IK",
1237 "Current SoC temperature");
1240 /* release this hook (continue boot) */
1241 config_intrhook_disestablish(&sc->init_hook);
1245 bcm2835_cpufreq_identify(driver_t *driver, device_t parent)
1248 DPRINTF("driver=%p, parent=%p\n", driver, parent);
1249 if (device_find_child(parent, "bcm2835_cpufreq", -1) != NULL)
1251 if (BUS_ADD_CHILD(parent, 0, "bcm2835_cpufreq", -1) == NULL)
1252 device_printf(parent, "add child failed\n");
1256 bcm2835_cpufreq_probe(device_t dev)
1259 if (device_get_unit(dev) != 0)
1261 device_set_desc(dev, "CPU Frequency Control");
1267 bcm2835_cpufreq_attach(device_t dev)
1269 struct bcm2835_cpufreq_softc *sc;
1270 struct sysctl_oid *oid;
1273 sc = device_get_softc(dev);
1276 /* initial values */
1277 sc->arm_max_freq = -1;
1278 sc->arm_min_freq = -1;
1279 sc->core_max_freq = -1;
1280 sc->core_min_freq = -1;
1281 sc->sdram_max_freq = -1;
1282 sc->sdram_min_freq = -1;
1283 sc->max_voltage_core = 0;
1284 sc->min_voltage_core = 0;
1286 /* setup sysctl at first device */
1287 if (device_get_unit(dev) == 0) {
1288 sysctl_ctx_init(&bcm2835_sysctl_ctx);
1289 /* create node for hw.cpufreq */
1290 oid = SYSCTL_ADD_NODE(&bcm2835_sysctl_ctx,
1291 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "cpufreq",
1292 CTLFLAG_RD, NULL, "");
1294 /* Frequency (Hz) */
1295 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1296 OID_AUTO, "arm_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
1297 sysctl_bcm2835_cpufreq_arm_freq, "IU",
1298 "ARM frequency (Hz)");
1299 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1300 OID_AUTO, "core_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
1301 sysctl_bcm2835_cpufreq_core_freq, "IU",
1302 "Core frequency (Hz)");
1303 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1304 OID_AUTO, "sdram_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
1305 sysctl_bcm2835_cpufreq_sdram_freq, "IU",
1306 "SDRAM frequency (Hz)");
1309 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1310 OID_AUTO, "turbo", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
1311 sysctl_bcm2835_cpufreq_turbo, "IU",
1312 "Disables dynamic clocking");
1314 /* Voltage (offset from 1.2V in units of 0.025V) */
1315 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1316 OID_AUTO, "voltage_core", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
1317 sysctl_bcm2835_cpufreq_voltage_core, "I",
1318 "ARM/GPU core voltage"
1319 "(offset from 1.2V in units of 0.025V)");
1320 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1321 OID_AUTO, "voltage_sdram", CTLTYPE_INT | CTLFLAG_WR, sc,
1322 0, sysctl_bcm2835_cpufreq_voltage_sdram, "I",
1323 "SDRAM voltage (offset from 1.2V in units of 0.025V)");
1325 /* Voltage individual SDRAM */
1326 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1327 OID_AUTO, "voltage_sdram_c", CTLTYPE_INT | CTLFLAG_RW, sc,
1328 0, sysctl_bcm2835_cpufreq_voltage_sdram_c, "I",
1329 "SDRAM controller voltage"
1330 "(offset from 1.2V in units of 0.025V)");
1331 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1332 OID_AUTO, "voltage_sdram_i", CTLTYPE_INT | CTLFLAG_RW, sc,
1333 0, sysctl_bcm2835_cpufreq_voltage_sdram_i, "I",
1334 "SDRAM I/O voltage (offset from 1.2V in units of 0.025V)");
1335 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1336 OID_AUTO, "voltage_sdram_p", CTLTYPE_INT | CTLFLAG_RW, sc,
1337 0, sysctl_bcm2835_cpufreq_voltage_sdram_p, "I",
1338 "SDRAM phy voltage (offset from 1.2V in units of 0.025V)");
1341 SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
1342 OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
1343 sysctl_bcm2835_cpufreq_temperature, "I",
1344 "SoC temperature (thousandths of a degree C)");
1348 sema_init(&vc_sema, 1, "vcsema");
1350 /* register callback for using mbox when interrupts are enabled */
1351 sc->init_hook.ich_func = bcm2835_cpufreq_init;
1352 sc->init_hook.ich_arg = sc;
1354 if (config_intrhook_establish(&sc->init_hook) != 0) {
1355 device_printf(dev, "config_intrhook_establish failed\n");
1359 /* this device is controlled by cpufreq(4) */
1360 cpufreq_register(dev);
1366 bcm2835_cpufreq_detach(device_t dev)
1368 struct bcm2835_cpufreq_softc *sc;
1370 sc = device_get_softc(dev);
1372 sema_destroy(&vc_sema);
1374 return (cpufreq_unregister(dev));
1378 bcm2835_cpufreq_set(device_t dev, const struct cf_setting *cf)
1380 struct bcm2835_cpufreq_softc *sc;
1381 uint32_t rate_hz, rem;
1382 int cur_freq, resp_freq, arm_freq, min_freq, core_freq;
1384 if (cf == NULL || cf->freq < 0)
1387 sc = device_get_softc(dev);
1389 /* setting clock (Hz) */
1390 rate_hz = (uint32_t)MHZ2HZ(cf->freq);
1391 rem = rate_hz % HZSTEP;
1396 /* adjust min freq */
1397 min_freq = sc->arm_min_freq;
1398 if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON)
1399 if (min_freq > cpufreq_lowest_freq)
1400 min_freq = cpufreq_lowest_freq;
1402 if (rate_hz < MHZ2HZ(min_freq) || rate_hz > MHZ2HZ(sc->arm_max_freq))
1405 /* set new value and verify it */
1407 cur_freq = bcm2835_cpufreq_get_clock_rate(sc,
1408 BCM2835_MBOX_CLOCK_ID_ARM);
1409 resp_freq = bcm2835_cpufreq_set_clock_rate(sc,
1410 BCM2835_MBOX_CLOCK_ID_ARM, rate_hz);
1411 DELAY(TRANSITION_LATENCY);
1412 arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
1413 BCM2835_MBOX_CLOCK_ID_ARM);
1416 * if non-turbo and lower than or equal min_freq,
1417 * clock down core and sdram to default first.
1419 if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON) {
1420 core_freq = bcm2835_cpufreq_get_clock_rate(sc,
1421 BCM2835_MBOX_CLOCK_ID_CORE);
1422 if (rate_hz > MHZ2HZ(sc->arm_min_freq)) {
1423 bcm2835_cpufreq_set_clock_rate(sc,
1424 BCM2835_MBOX_CLOCK_ID_CORE,
1425 MHZ2HZ(sc->core_max_freq));
1426 DELAY(TRANSITION_LATENCY);
1427 bcm2835_cpufreq_set_clock_rate(sc,
1428 BCM2835_MBOX_CLOCK_ID_SDRAM,
1429 MHZ2HZ(sc->sdram_max_freq));
1430 DELAY(TRANSITION_LATENCY);
1432 if (sc->core_min_freq < DEFAULT_CORE_FREQUENCY &&
1433 core_freq > DEFAULT_CORE_FREQUENCY) {
1434 /* first, down to 250, then down to min */
1435 DELAY(TRANSITION_LATENCY);
1436 bcm2835_cpufreq_set_clock_rate(sc,
1437 BCM2835_MBOX_CLOCK_ID_CORE,
1438 MHZ2HZ(DEFAULT_CORE_FREQUENCY));
1439 DELAY(TRANSITION_LATENCY);
1440 /* reset core voltage */
1441 bcm2835_cpufreq_set_voltage(sc,
1442 BCM2835_MBOX_VOLTAGE_ID_CORE, 0);
1443 DELAY(TRANSITION_LATENCY);
1445 bcm2835_cpufreq_set_clock_rate(sc,
1446 BCM2835_MBOX_CLOCK_ID_CORE,
1447 MHZ2HZ(sc->core_min_freq));
1448 DELAY(TRANSITION_LATENCY);
1449 bcm2835_cpufreq_set_clock_rate(sc,
1450 BCM2835_MBOX_CLOCK_ID_SDRAM,
1451 MHZ2HZ(sc->sdram_min_freq));
1452 DELAY(TRANSITION_LATENCY);
1458 if (resp_freq < 0 || arm_freq < 0 || resp_freq != arm_freq) {
1459 device_printf(dev, "wrong freq\n");
1462 DPRINTF("cpufreq: %d -> %d\n", cur_freq, arm_freq);
1468 bcm2835_cpufreq_get(device_t dev, struct cf_setting *cf)
1470 struct bcm2835_cpufreq_softc *sc;
1476 sc = device_get_softc(dev);
1477 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
1480 /* get cuurent value */
1482 arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
1483 BCM2835_MBOX_CLOCK_ID_ARM);
1486 device_printf(dev, "can't get clock\n");
1490 /* CPU clock in MHz or 100ths of a percent. */
1491 cf->freq = HZ2MHZ(arm_freq);
1492 /* Voltage in mV. */
1493 cf->volts = CPUFREQ_VAL_UNKNOWN;
1494 /* Power consumed in mW. */
1495 cf->power = CPUFREQ_VAL_UNKNOWN;
1496 /* Transition latency in us. */
1497 cf->lat = TRANSITION_LATENCY;
1498 /* Driver providing this setting. */
1505 bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets,
1508 struct bcm2835_cpufreq_softc *sc;
1509 int freq, min_freq, volts, rem;
1512 sc = device_get_softc(dev);
1513 freq = sc->arm_max_freq;
1514 min_freq = sc->arm_min_freq;
1516 /* adjust head freq to STEP */
1517 rem = freq % MHZSTEP;
1519 if (freq < min_freq)
1522 /* if non-turbo, add extra low freq */
1523 if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON)
1524 if (min_freq > cpufreq_lowest_freq)
1525 min_freq = cpufreq_lowest_freq;
1528 /* XXX RPi2 have only 900/600MHz */
1530 volts = sc->min_voltage_core;
1531 sets[idx].freq = freq;
1532 sets[idx].volts = volts;
1533 sets[idx].lat = TRANSITION_LATENCY;
1534 sets[idx].dev = dev;
1536 if (freq != min_freq) {
1537 sets[idx].freq = min_freq;
1538 sets[idx].volts = volts;
1539 sets[idx].lat = TRANSITION_LATENCY;
1540 sets[idx].dev = dev;
1544 /* from freq to min_freq */
1545 for (idx = 0; idx < *count && freq >= min_freq; idx++) {
1546 if (freq > sc->arm_min_freq)
1547 volts = sc->max_voltage_core;
1549 volts = sc->min_voltage_core;
1550 sets[idx].freq = freq;
1551 sets[idx].volts = volts;
1552 sets[idx].lat = TRANSITION_LATENCY;
1553 sets[idx].dev = dev;
1563 bcm2835_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count)
1565 struct bcm2835_cpufreq_softc *sc;
1567 if (sets == NULL || count == NULL)
1570 sc = device_get_softc(dev);
1571 if (sc->arm_min_freq < 0 || sc->arm_max_freq < 0) {
1572 printf("device is not configured\n");
1576 /* fill data with unknown value */
1577 memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * (*count));
1578 /* create new array up to count */
1579 bcm2835_cpufreq_make_freq_list(dev, sets, count);
1585 bcm2835_cpufreq_type(device_t dev, int *type)
1590 *type = CPUFREQ_TYPE_ABSOLUTE;
1595 static device_method_t bcm2835_cpufreq_methods[] = {
1596 /* Device interface */
1597 DEVMETHOD(device_identify, bcm2835_cpufreq_identify),
1598 DEVMETHOD(device_probe, bcm2835_cpufreq_probe),
1599 DEVMETHOD(device_attach, bcm2835_cpufreq_attach),
1600 DEVMETHOD(device_detach, bcm2835_cpufreq_detach),
1602 /* cpufreq interface */
1603 DEVMETHOD(cpufreq_drv_set, bcm2835_cpufreq_set),
1604 DEVMETHOD(cpufreq_drv_get, bcm2835_cpufreq_get),
1605 DEVMETHOD(cpufreq_drv_settings, bcm2835_cpufreq_settings),
1606 DEVMETHOD(cpufreq_drv_type, bcm2835_cpufreq_type),
1611 static devclass_t bcm2835_cpufreq_devclass;
1612 static driver_t bcm2835_cpufreq_driver = {
1614 bcm2835_cpufreq_methods,
1615 sizeof(struct bcm2835_cpufreq_softc),
1618 DRIVER_MODULE(bcm2835_cpufreq, cpu, bcm2835_cpufreq_driver,
1619 bcm2835_cpufreq_devclass, 0, 0);