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