xref: /freebsd/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c (revision b1f92fa22938fe29ab7e53692ffe0ed7a0ecc4d0)
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 <arm/broadcom/bcm2835/bcm2835_mbox.h>
48 #include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
49 #include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
50 
51 #include "cpufreq_if.h"
52 #include "mbox_if.h"
53 
54 #ifdef DEBUG
55 #define DPRINTF(fmt, ...) do {			\
56 	printf("%s:%u: ", __func__, __LINE__);	\
57 	printf(fmt, ##__VA_ARGS__);		\
58 } while (0)
59 #else
60 #define DPRINTF(fmt, ...)
61 #endif
62 
63 #define	HZ2MHZ(freq) ((freq) / (1000 * 1000))
64 #define	MHZ2HZ(freq) ((freq) * (1000 * 1000))
65 
66 #ifdef SOC_BCM2836
67 #define	OFFSET2MVOLT(val) (((val) / 1000))
68 #define	MVOLT2OFFSET(val) (((val) * 1000))
69 #define	DEFAULT_ARM_FREQUENCY	 600
70 #define	DEFAULT_LOWEST_FREQ	 600
71 #else
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
76 #endif
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
83 #define	MHZSTEP			 100
84 #define	HZSTEP	   (MHZ2HZ(MHZSTEP))
85 #define	TZ_ZEROC		2732
86 
87 #define VC_LOCK(sc) do {			\
88 		sema_wait(&vc_sema);		\
89 	} while (0)
90 #define VC_UNLOCK(sc) do {			\
91 		sema_post(&vc_sema);		\
92 	} while (0)
93 
94 /* ARM->VC mailbox property semaphore */
95 static struct sema vc_sema;
96 
97 static struct sysctl_ctx_list bcm2835_sysctl_ctx;
98 
99 struct bcm2835_cpufreq_softc {
100 	device_t	dev;
101 	int		arm_max_freq;
102 	int		arm_min_freq;
103 	int		core_max_freq;
104 	int		core_min_freq;
105 	int		sdram_max_freq;
106 	int		sdram_min_freq;
107 	int		max_voltage_core;
108 	int		min_voltage_core;
109 
110 	/* the values written in mbox */
111 	int		voltage_core;
112 	int		voltage_sdram;
113 	int		voltage_sdram_c;
114 	int		voltage_sdram_i;
115 	int		voltage_sdram_p;
116 	int		turbo_mode;
117 
118 	/* initial hook for waiting mbox intr */
119 	struct intr_config_hook	init_hook;
120 };
121 
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);
126 
127 #ifdef PROP_DEBUG
128 static void
129 bcm2835_dump(const void *data, int len)
130 {
131 	const uint8_t *p = (const uint8_t*)data;
132 	int i;
133 
134 	printf("dump @ %p:\n", data);
135 	for (i = 0; i < len; i++) {
136 		printf("%2.2x ", p[i]);
137 		if ((i % 4) == 3)
138 			printf(" ");
139 		if ((i % 16) == 15)
140 			printf("\n");
141 	}
142 	printf("\n");
143 }
144 #endif
145 
146 static int
147 bcm2835_cpufreq_get_clock_rate(struct bcm2835_cpufreq_softc *sc,
148     uint32_t clock_id)
149 {
150 	struct msg_get_clock_rate msg;
151 	int rate;
152 	int err;
153 
154 	/*
155 	 * Get clock rate
156 	 *   Tag: 0x00030002
157 	 *   Request:
158 	 *     Length: 4
159 	 *     Value:
160 	 *       u32: clock id
161 	 *   Response:
162 	 *     Length: 8
163 	 *     Value:
164 	 *       u32: clock id
165 	 *       u32: rate (in Hz)
166 	 */
167 
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;
176 	msg.end_tag = 0;
177 
178 	/* call mailbox property */
179 	err = bcm2835_mbox_property(&msg, sizeof(msg));
180 	if (err) {
181 		device_printf(sc->dev, "can't get clock rate (id=%u)\n",
182 		    clock_id);
183 		return (MSG_ERROR);
184 	}
185 
186 	/* result (Hz) */
187 	rate = (int)msg.body.resp.rate_hz;
188 	DPRINTF("clock = %d(Hz)\n", rate);
189 	return (rate);
190 }
191 
192 static int
193 bcm2835_cpufreq_get_max_clock_rate(struct bcm2835_cpufreq_softc *sc,
194     uint32_t clock_id)
195 {
196 	struct msg_get_max_clock_rate msg;
197 	int rate;
198 	int err;
199 
200 	/*
201 	 * Get max clock rate
202 	 *   Tag: 0x00030004
203 	 *   Request:
204 	 *     Length: 4
205 	 *     Value:
206 	 *       u32: clock id
207 	 *   Response:
208 	 *     Length: 8
209 	 *     Value:
210 	 *       u32: clock id
211 	 *       u32: rate (in Hz)
212 	 */
213 
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;
222 	msg.end_tag = 0;
223 
224 	/* call mailbox property */
225 	err = bcm2835_mbox_property(&msg, sizeof(msg));
226 	if (err) {
227 		device_printf(sc->dev, "can't get max clock rate (id=%u)\n",
228 		    clock_id);
229 		return (MSG_ERROR);
230 	}
231 
232 	/* result (Hz) */
233 	rate = (int)msg.body.resp.rate_hz;
234 	DPRINTF("clock = %d(Hz)\n", rate);
235 	return (rate);
236 }
237 
238 static int
239 bcm2835_cpufreq_get_min_clock_rate(struct bcm2835_cpufreq_softc *sc,
240     uint32_t clock_id)
241 {
242 	struct msg_get_min_clock_rate msg;
243 	int rate;
244 	int err;
245 
246 	/*
247 	 * Get min clock rate
248 	 *   Tag: 0x00030007
249 	 *   Request:
250 	 *     Length: 4
251 	 *     Value:
252 	 *       u32: clock id
253 	 *   Response:
254 	 *     Length: 8
255 	 *     Value:
256 	 *       u32: clock id
257 	 *       u32: rate (in Hz)
258 	 */
259 
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;
268 	msg.end_tag = 0;
269 
270 	/* call mailbox property */
271 	err = bcm2835_mbox_property(&msg, sizeof(msg));
272 	if (err) {
273 		device_printf(sc->dev, "can't get min clock rate (id=%u)\n",
274 		    clock_id);
275 		return (MSG_ERROR);
276 	}
277 
278 	/* result (Hz) */
279 	rate = (int)msg.body.resp.rate_hz;
280 	DPRINTF("clock = %d(Hz)\n", rate);
281 	return (rate);
282 }
283 
284 static int
285 bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc,
286     uint32_t clock_id, uint32_t rate_hz)
287 {
288 	struct msg_set_clock_rate msg;
289 	int rate;
290 	int err;
291 
292 	/*
293 	 * Set clock rate
294 	 *   Tag: 0x00038002
295 	 *   Request:
296 	 *     Length: 8
297 	 *     Value:
298 	 *       u32: clock id
299 	 *       u32: rate (in Hz)
300 	 *   Response:
301 	 *     Length: 8
302 	 *     Value:
303 	 *       u32: clock id
304 	 *       u32: rate (in Hz)
305 	 */
306 
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;
316 	msg.end_tag = 0;
317 
318 	/* call mailbox property */
319 	err = bcm2835_mbox_property(&msg, sizeof(msg));
320 	if (err) {
321 		device_printf(sc->dev, "can't set clock rate (id=%u)\n",
322 		    clock_id);
323 		return (MSG_ERROR);
324 	}
325 
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);
330 
331 		/*
332 		 * XXX: the core clock is unable to change at once,
333 		 * to change certainly, write it twice now.
334 		 */
335 
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;
345 		msg.end_tag = 0;
346 
347 		/* call mailbox property */
348 		err = bcm2835_mbox_property(&msg, sizeof(msg));
349 		if (err) {
350 			device_printf(sc->dev,
351 			    "can't set clock rate (id=%u)\n", clock_id);
352 			return (MSG_ERROR);
353 		}
354 	}
355 
356 	/* result (Hz) */
357 	rate = (int)msg.body.resp.rate_hz;
358 	DPRINTF("clock = %d(Hz)\n", rate);
359 	return (rate);
360 }
361 
362 static int
363 bcm2835_cpufreq_get_turbo(struct bcm2835_cpufreq_softc *sc)
364 {
365 	struct msg_get_turbo msg;
366 	int level;
367 	int err;
368 
369 	/*
370 	 * Get turbo
371 	 *   Tag: 0x00030009
372 	 *   Request:
373 	 *     Length: 4
374 	 *     Value:
375 	 *       u32: id
376 	 *   Response:
377 	 *     Length: 8
378 	 *     Value:
379 	 *       u32: id
380 	 *       u32: level
381 	 */
382 
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);
390 	msg.body.req.id = 0;
391 	msg.end_tag = 0;
392 
393 	/* call mailbox property */
394 	err = bcm2835_mbox_property(&msg, sizeof(msg));
395 	if (err) {
396 		device_printf(sc->dev, "can't get turbo\n");
397 		return (MSG_ERROR);
398 	}
399 
400 	/* result 0=non-turbo, 1=turbo */
401 	level = (int)msg.body.resp.level;
402 	DPRINTF("level = %d\n", level);
403 	return (level);
404 }
405 
406 static int
407 bcm2835_cpufreq_set_turbo(struct bcm2835_cpufreq_softc *sc, uint32_t level)
408 {
409 	struct msg_set_turbo msg;
410 	int value;
411 	int err;
412 
413 	/*
414 	 * Set turbo
415 	 *   Tag: 0x00038009
416 	 *   Request:
417 	 *     Length: 8
418 	 *     Value:
419 	 *       u32: id
420 	 *       u32: level
421 	 *   Response:
422 	 *     Length: 8
423 	 *     Value:
424 	 *       u32: id
425 	 *       u32: level
426 	 */
427 
428 	/* replace unknown value to OFF */
429 	if (level != BCM2835_MBOX_TURBO_ON && level != BCM2835_MBOX_TURBO_OFF)
430 		level = BCM2835_MBOX_TURBO_OFF;
431 
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);
439 	msg.body.req.id = 0;
440 	msg.body.req.level = level;
441 	msg.end_tag = 0;
442 
443 	/* call mailbox property */
444 	err = bcm2835_mbox_property(&msg, sizeof(msg));
445 	if (err) {
446 		device_printf(sc->dev, "can't set turbo\n");
447 		return (MSG_ERROR);
448 	}
449 
450 	/* result 0=non-turbo, 1=turbo */
451 	value = (int)msg.body.resp.level;
452 	DPRINTF("level = %d\n", value);
453 	return (value);
454 }
455 
456 static int
457 bcm2835_cpufreq_get_voltage(struct bcm2835_cpufreq_softc *sc,
458     uint32_t voltage_id)
459 {
460 	struct msg_get_voltage msg;
461 	int value;
462 	int err;
463 
464 	/*
465 	 * Get voltage
466 	 *   Tag: 0x00030003
467 	 *   Request:
468 	 *     Length: 4
469 	 *     Value:
470 	 *       u32: voltage id
471 	 *   Response:
472 	 *     Length: 8
473 	 *     Value:
474 	 *       u32: voltage id
475 	 *       u32: value (offset from 1.2V in units of 0.025V)
476 	 */
477 
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;
486 	msg.end_tag = 0;
487 
488 	/* call mailbox property */
489 	err = bcm2835_mbox_property(&msg, sizeof(msg));
490 	if (err) {
491 		device_printf(sc->dev, "can't get voltage\n");
492 		return (MSG_ERROR);
493 	}
494 
495 	/* result (offset from 1.2V) */
496 	value = (int)msg.body.resp.value;
497 	DPRINTF("value = %d\n", value);
498 	return (value);
499 }
500 
501 static int
502 bcm2835_cpufreq_get_max_voltage(struct bcm2835_cpufreq_softc *sc,
503     uint32_t voltage_id)
504 {
505 	struct msg_get_max_voltage msg;
506 	int value;
507 	int err;
508 
509 	/*
510 	 * Get voltage
511 	 *   Tag: 0x00030005
512 	 *   Request:
513 	 *     Length: 4
514 	 *     Value:
515 	 *       u32: voltage id
516 	 *   Response:
517 	 *     Length: 8
518 	 *     Value:
519 	 *       u32: voltage id
520 	 *       u32: value (offset from 1.2V in units of 0.025V)
521 	 */
522 
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;
531 	msg.end_tag = 0;
532 
533 	/* call mailbox property */
534 	err = bcm2835_mbox_property(&msg, sizeof(msg));
535 	if (err) {
536 		device_printf(sc->dev, "can't get max voltage\n");
537 		return (MSG_ERROR);
538 	}
539 
540 	/* result (offset from 1.2V) */
541 	value = (int)msg.body.resp.value;
542 	DPRINTF("value = %d\n", value);
543 	return (value);
544 }
545 static int
546 bcm2835_cpufreq_get_min_voltage(struct bcm2835_cpufreq_softc *sc,
547     uint32_t voltage_id)
548 {
549 	struct msg_get_min_voltage msg;
550 	int value;
551 	int err;
552 
553 	/*
554 	 * Get voltage
555 	 *   Tag: 0x00030008
556 	 *   Request:
557 	 *     Length: 4
558 	 *     Value:
559 	 *       u32: voltage id
560 	 *   Response:
561 	 *     Length: 8
562 	 *     Value:
563 	 *       u32: voltage id
564 	 *       u32: value (offset from 1.2V in units of 0.025V)
565 	 */
566 
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;
575 	msg.end_tag = 0;
576 
577 	/* call mailbox property */
578 	err = bcm2835_mbox_property(&msg, sizeof(msg));
579 	if (err) {
580 		device_printf(sc->dev, "can't get min voltage\n");
581 		return (MSG_ERROR);
582 	}
583 
584 	/* result (offset from 1.2V) */
585 	value = (int)msg.body.resp.value;
586 	DPRINTF("value = %d\n", value);
587 	return (value);
588 }
589 
590 static int
591 bcm2835_cpufreq_set_voltage(struct bcm2835_cpufreq_softc *sc,
592     uint32_t voltage_id, int32_t value)
593 {
594 	struct msg_set_voltage msg;
595 	int err;
596 
597 	/*
598 	 * Set voltage
599 	 *   Tag: 0x00038003
600 	 *   Request:
601 	 *     Length: 4
602 	 *     Value:
603 	 *       u32: voltage id
604 	 *       u32: value (offset from 1.2V in units of 0.025V)
605 	 *   Response:
606 	 *     Length: 8
607 	 *     Value:
608 	 *       u32: voltage id
609 	 *       u32: value (offset from 1.2V in units of 0.025V)
610 	 */
611 
612 	/*
613 	 * over_voltage:
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).
616 	 */
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);
620 		return (MSG_ERROR);
621 	}
622 
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;
632 	msg.end_tag = 0;
633 
634 	/* call mailbox property */
635 	err = bcm2835_mbox_property(&msg, sizeof(msg));
636 	if (err) {
637 		device_printf(sc->dev, "can't set voltage\n");
638 		return (MSG_ERROR);
639 	}
640 
641 	/* result (offset from 1.2V) */
642 	value = (int)msg.body.resp.value;
643 	DPRINTF("value = %d\n", value);
644 	return (value);
645 }
646 
647 static int
648 bcm2835_cpufreq_get_temperature(struct bcm2835_cpufreq_softc *sc)
649 {
650 	struct msg_get_temperature msg;
651 	int value;
652 	int err;
653 
654 	/*
655 	 * Get temperature
656 	 *   Tag: 0x00030006
657 	 *   Request:
658 	 *     Length: 4
659 	 *     Value:
660 	 *       u32: temperature id
661 	 *   Response:
662 	 *     Length: 8
663 	 *     Value:
664 	 *       u32: temperature id
665 	 *       u32: value
666 	 */
667 
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;
676 	msg.end_tag = 0;
677 
678 	/* call mailbox property */
679 	err = bcm2835_mbox_property(&msg, sizeof(msg));
680 	if (err) {
681 		device_printf(sc->dev, "can't get temperature\n");
682 		return (MSG_ERROR);
683 	}
684 
685 	/* result (temperature of degree C) */
686 	value = (int)msg.body.resp.value;
687 	DPRINTF("value = %d\n", value);
688 	return (value);
689 }
690 
691 
692 
693 static int
694 sysctl_bcm2835_cpufreq_arm_freq(SYSCTL_HANDLER_ARGS)
695 {
696 	struct bcm2835_cpufreq_softc *sc = arg1;
697 	int val;
698 	int err;
699 
700 	/* get realtime value */
701 	VC_LOCK(sc);
702 	val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM);
703 	VC_UNLOCK(sc);
704 	if (val == MSG_ERROR)
705 		return (EIO);
706 
707 	err = sysctl_handle_int(oidp, &val, 0, req);
708 	if (err || !req->newptr) /* error || read request */
709 		return (err);
710 
711 	/* write request */
712 	VC_LOCK(sc);
713 	err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
714 	    val);
715 	VC_UNLOCK(sc);
716 	if (err == MSG_ERROR) {
717 		device_printf(sc->dev, "set clock arm_freq error\n");
718 		return (EIO);
719 	}
720 	DELAY(TRANSITION_LATENCY);
721 
722 	return (0);
723 }
724 
725 static int
726 sysctl_bcm2835_cpufreq_core_freq(SYSCTL_HANDLER_ARGS)
727 {
728 	struct bcm2835_cpufreq_softc *sc = arg1;
729 	int val;
730 	int err;
731 
732 	/* get realtime value */
733 	VC_LOCK(sc);
734 	val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE);
735 	VC_UNLOCK(sc);
736 	if (val == MSG_ERROR)
737 		return (EIO);
738 
739 	err = sysctl_handle_int(oidp, &val, 0, req);
740 	if (err || !req->newptr) /* error || read request */
741 		return (err);
742 
743 	/* write request */
744 	VC_LOCK(sc);
745 	err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
746 	    val);
747 	if (err == MSG_ERROR) {
748 		VC_UNLOCK(sc);
749 		device_printf(sc->dev, "set clock core_freq error\n");
750 		return (EIO);
751 	}
752 	VC_UNLOCK(sc);
753 	DELAY(TRANSITION_LATENCY);
754 
755 	return (0);
756 }
757 
758 static int
759 sysctl_bcm2835_cpufreq_sdram_freq(SYSCTL_HANDLER_ARGS)
760 {
761 	struct bcm2835_cpufreq_softc *sc = arg1;
762 	int val;
763 	int err;
764 
765 	/* get realtime value */
766 	VC_LOCK(sc);
767 	val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM);
768 	VC_UNLOCK(sc);
769 	if (val == MSG_ERROR)
770 		return (EIO);
771 
772 	err = sysctl_handle_int(oidp, &val, 0, req);
773 	if (err || !req->newptr) /* error || read request */
774 		return (err);
775 
776 	/* write request */
777 	VC_LOCK(sc);
778 	err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM,
779 	    val);
780 	VC_UNLOCK(sc);
781 	if (err == MSG_ERROR) {
782 		device_printf(sc->dev, "set clock sdram_freq error\n");
783 		return (EIO);
784 	}
785 	DELAY(TRANSITION_LATENCY);
786 
787 	return (0);
788 }
789 
790 static int
791 sysctl_bcm2835_cpufreq_turbo(SYSCTL_HANDLER_ARGS)
792 {
793 	struct bcm2835_cpufreq_softc *sc = arg1;
794 	int val;
795 	int err;
796 
797 	/* get realtime value */
798 	VC_LOCK(sc);
799 	val = bcm2835_cpufreq_get_turbo(sc);
800 	VC_UNLOCK(sc);
801 	if (val == MSG_ERROR)
802 		return (EIO);
803 
804 	err = sysctl_handle_int(oidp, &val, 0, req);
805 	if (err || !req->newptr) /* error || read request */
806 		return (err);
807 
808 	/* write request */
809 	if (val > 0)
810 		sc->turbo_mode = BCM2835_MBOX_TURBO_ON;
811 	else
812 		sc->turbo_mode = BCM2835_MBOX_TURBO_OFF;
813 
814 	VC_LOCK(sc);
815 	err = bcm2835_cpufreq_set_turbo(sc, sc->turbo_mode);
816 	VC_UNLOCK(sc);
817 	if (err == MSG_ERROR) {
818 		device_printf(sc->dev, "set turbo error\n");
819 		return (EIO);
820 	}
821 	DELAY(TRANSITION_LATENCY);
822 
823 	return (0);
824 }
825 
826 static int
827 sysctl_bcm2835_cpufreq_voltage_core(SYSCTL_HANDLER_ARGS)
828 {
829 	struct bcm2835_cpufreq_softc *sc = arg1;
830 	int val;
831 	int err;
832 
833 	/* get realtime value */
834 	VC_LOCK(sc);
835 	val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE);
836 	VC_UNLOCK(sc);
837 	if (val == MSG_ERROR)
838 		return (EIO);
839 
840 	err = sysctl_handle_int(oidp, &val, 0, req);
841 	if (err || !req->newptr) /* error || read request */
842 		return (err);
843 
844 	/* write request */
845 	if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
846 		return (EINVAL);
847 	sc->voltage_core = val;
848 
849 	VC_LOCK(sc);
850 	err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE,
851 	    sc->voltage_core);
852 	VC_UNLOCK(sc);
853 	if (err == MSG_ERROR) {
854 		device_printf(sc->dev, "set voltage core error\n");
855 		return (EIO);
856 	}
857 	DELAY(TRANSITION_LATENCY);
858 
859 	return (0);
860 }
861 
862 static int
863 sysctl_bcm2835_cpufreq_voltage_sdram_c(SYSCTL_HANDLER_ARGS)
864 {
865 	struct bcm2835_cpufreq_softc *sc = arg1;
866 	int val;
867 	int err;
868 
869 	/* get realtime value */
870 	VC_LOCK(sc);
871 	val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
872 	VC_UNLOCK(sc);
873 	if (val == MSG_ERROR)
874 		return (EIO);
875 
876 	err = sysctl_handle_int(oidp, &val, 0, req);
877 	if (err || !req->newptr) /* error || read request */
878 		return (err);
879 
880 	/* write request */
881 	if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
882 		return (EINVAL);
883 	sc->voltage_sdram_c = val;
884 
885 	VC_LOCK(sc);
886 	err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C,
887 	   sc->voltage_sdram_c);
888 	VC_UNLOCK(sc);
889 	if (err == MSG_ERROR) {
890 		device_printf(sc->dev, "set voltage sdram_c error\n");
891 		return (EIO);
892 	}
893 	DELAY(TRANSITION_LATENCY);
894 
895 	return (0);
896 }
897 
898 static int
899 sysctl_bcm2835_cpufreq_voltage_sdram_i(SYSCTL_HANDLER_ARGS)
900 {
901 	struct bcm2835_cpufreq_softc *sc = arg1;
902 	int val;
903 	int err;
904 
905 	/* get realtime value */
906 	VC_LOCK(sc);
907 	val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
908 	VC_UNLOCK(sc);
909 	if (val == MSG_ERROR)
910 		return (EIO);
911 
912 	err = sysctl_handle_int(oidp, &val, 0, req);
913 	if (err || !req->newptr) /* error || read request */
914 		return (err);
915 
916 	/* write request */
917 	if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
918 		return (EINVAL);
919 	sc->voltage_sdram_i = val;
920 
921 	VC_LOCK(sc);
922 	err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I,
923 	    sc->voltage_sdram_i);
924 	VC_UNLOCK(sc);
925 	if (err == MSG_ERROR) {
926 		device_printf(sc->dev, "set voltage sdram_i error\n");
927 		return (EIO);
928 	}
929 	DELAY(TRANSITION_LATENCY);
930 
931 	return (0);
932 }
933 
934 static int
935 sysctl_bcm2835_cpufreq_voltage_sdram_p(SYSCTL_HANDLER_ARGS)
936 {
937 	struct bcm2835_cpufreq_softc *sc = arg1;
938 	int val;
939 	int err;
940 
941 	/* get realtime value */
942 	VC_LOCK(sc);
943 	val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
944 	VC_UNLOCK(sc);
945 	if (val == MSG_ERROR)
946 		return (EIO);
947 
948 	err = sysctl_handle_int(oidp, &val, 0, req);
949 	if (err || !req->newptr) /* error || read request */
950 		return (err);
951 
952 	/* write request */
953 	if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
954 		return (EINVAL);
955 	sc->voltage_sdram_p = val;
956 
957 	VC_LOCK(sc);
958 	err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P,
959 	    sc->voltage_sdram_p);
960 	VC_UNLOCK(sc);
961 	if (err == MSG_ERROR) {
962 		device_printf(sc->dev, "set voltage sdram_p error\n");
963 		return (EIO);
964 	}
965 	DELAY(TRANSITION_LATENCY);
966 
967 	return (0);
968 }
969 
970 static int
971 sysctl_bcm2835_cpufreq_voltage_sdram(SYSCTL_HANDLER_ARGS)
972 {
973 	struct bcm2835_cpufreq_softc *sc = arg1;
974 	int val;
975 	int err;
976 
977 	/* multiple write only */
978 	if (!req->newptr)
979 		return (EINVAL);
980 	val = 0;
981 	err = sysctl_handle_int(oidp, &val, 0, req);
982 	if (err)
983 		return (err);
984 
985 	/* write request */
986 	if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
987 		return (EINVAL);
988 	sc->voltage_sdram = val;
989 
990 	VC_LOCK(sc);
991 	err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C,
992 	    val);
993 	if (err == MSG_ERROR) {
994 		VC_UNLOCK(sc);
995 		device_printf(sc->dev, "set voltage sdram_c error\n");
996 		return (EIO);
997 	}
998 	err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I,
999 	    val);
1000 	if (err == MSG_ERROR) {
1001 		VC_UNLOCK(sc);
1002 		device_printf(sc->dev, "set voltage sdram_i error\n");
1003 		return (EIO);
1004 	}
1005 	err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P,
1006 	    val);
1007 	if (err == MSG_ERROR) {
1008 		VC_UNLOCK(sc);
1009 		device_printf(sc->dev, "set voltage sdram_p error\n");
1010 		return (EIO);
1011 	}
1012 	VC_UNLOCK(sc);
1013 	DELAY(TRANSITION_LATENCY);
1014 
1015 	return (0);
1016 }
1017 
1018 static int
1019 sysctl_bcm2835_cpufreq_temperature(SYSCTL_HANDLER_ARGS)
1020 {
1021 	struct bcm2835_cpufreq_softc *sc = arg1;
1022 	int val;
1023 	int err;
1024 
1025 	/* get realtime value */
1026 	VC_LOCK(sc);
1027 	val = bcm2835_cpufreq_get_temperature(sc);
1028 	VC_UNLOCK(sc);
1029 	if (val == MSG_ERROR)
1030 		return (EIO);
1031 
1032 	err = sysctl_handle_int(oidp, &val, 0, req);
1033 	if (err || !req->newptr) /* error || read request */
1034 		return (err);
1035 
1036 	/* write request */
1037 	return (EINVAL);
1038 }
1039 
1040 static int
1041 sysctl_bcm2835_devcpu_temperature(SYSCTL_HANDLER_ARGS)
1042 {
1043 	struct bcm2835_cpufreq_softc *sc = arg1;
1044 	int val;
1045 	int err;
1046 
1047 	/* get realtime value */
1048 	VC_LOCK(sc);
1049 	val = bcm2835_cpufreq_get_temperature(sc);
1050 	VC_UNLOCK(sc);
1051 	if (val == MSG_ERROR)
1052 		return (EIO);
1053 
1054 	/* 1/1000 celsius (raw) to 1/10 kelvin */
1055 	val = val / 100 + TZ_ZEROC;
1056 
1057 	err = sysctl_handle_int(oidp, &val, 0, req);
1058 	if (err || !req->newptr) /* error || read request */
1059 		return (err);
1060 
1061 	/* write request */
1062 	return (EINVAL);
1063 }
1064 
1065 
1066 static void
1067 bcm2835_cpufreq_init(void *arg)
1068 {
1069 	struct bcm2835_cpufreq_softc *sc = arg;
1070 	struct sysctl_ctx_list *ctx;
1071 	device_t cpu;
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;
1081 
1082 	VC_LOCK(sc);
1083 
1084 	/* current clock */
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);
1091 
1092 	/* max/min clock */
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);
1105 
1106 	/* turbo mode */
1107 	turbo = bcm2835_cpufreq_get_turbo(sc);
1108 	if (turbo > 0)
1109 		sc->turbo_mode = BCM2835_MBOX_TURBO_ON;
1110 	else
1111 		sc->turbo_mode = BCM2835_MBOX_TURBO_OFF;
1112 
1113 	/* voltage */
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);
1122 
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;
1129 
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);
1147 
1148 	/* temperature */
1149 	temperature = bcm2835_cpufreq_get_temperature(sc);
1150 
1151 	/* show result */
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");
1158 
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));
1164 
1165 		device_printf(sc->dev,
1166 		    "current Core %dmV, SDRAM_C %dmV, SDRAM_I %dmV, "
1167 		    "SDRAM_P %dmV\n",
1168 		    OFFSET2MVOLT(voltage_core), OFFSET2MVOLT(voltage_sdram_c),
1169 		    OFFSET2MVOLT(voltage_sdram_i),
1170 		    OFFSET2MVOLT(voltage_sdram_p));
1171 
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));
1183 
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");
1192 	}
1193 
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);
1203 
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,
1207 		    arm_max_freq);
1208 		DELAY(TRANSITION_LATENCY);
1209 		bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
1210 		    core_max_freq);
1211 		DELAY(TRANSITION_LATENCY);
1212 		bcm2835_cpufreq_set_clock_rate(sc,
1213 		    BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_max_freq);
1214 		DELAY(TRANSITION_LATENCY);
1215 	} else {
1216 		bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
1217 		    arm_min_freq);
1218 		DELAY(TRANSITION_LATENCY);
1219 		bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
1220 		    core_min_freq);
1221 		DELAY(TRANSITION_LATENCY);
1222 		bcm2835_cpufreq_set_clock_rate(sc,
1223 		    BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_min_freq);
1224 		DELAY(TRANSITION_LATENCY);
1225 	}
1226 
1227 	VC_UNLOCK(sc);
1228 
1229 	/* add human readable temperature to dev.cpu node */
1230 	cpu = device_get_parent(sc->dev);
1231 	if (cpu != NULL) {
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");
1238 	}
1239 
1240 	/* release this hook (continue boot) */
1241 	config_intrhook_disestablish(&sc->init_hook);
1242 }
1243 
1244 static void
1245 bcm2835_cpufreq_identify(driver_t *driver, device_t parent)
1246 {
1247 
1248 	DPRINTF("driver=%p, parent=%p\n", driver, parent);
1249 	if (device_find_child(parent, "bcm2835_cpufreq", -1) != NULL)
1250 		return;
1251 	if (BUS_ADD_CHILD(parent, 0, "bcm2835_cpufreq", -1) == NULL)
1252 		device_printf(parent, "add child failed\n");
1253 }
1254 
1255 static int
1256 bcm2835_cpufreq_probe(device_t dev)
1257 {
1258 
1259 	if (device_get_unit(dev) != 0)
1260 		return (ENXIO);
1261 	device_set_desc(dev, "CPU Frequency Control");
1262 
1263 	return (0);
1264 }
1265 
1266 static int
1267 bcm2835_cpufreq_attach(device_t dev)
1268 {
1269 	struct bcm2835_cpufreq_softc *sc;
1270 	struct sysctl_oid *oid;
1271 
1272 	/* set self dev */
1273 	sc = device_get_softc(dev);
1274 	sc->dev = dev;
1275 
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;
1285 
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, "");
1293 
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)");
1307 
1308 		/* Turbo state */
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");
1313 
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)");
1324 
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)");
1339 
1340 		/* Temperature */
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)");
1345 	}
1346 
1347 	/* ARM->VC lock */
1348 	sema_init(&vc_sema, 1, "vcsema");
1349 
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;
1353 
1354 	if (config_intrhook_establish(&sc->init_hook) != 0) {
1355 		device_printf(dev, "config_intrhook_establish failed\n");
1356 		return (ENOMEM);
1357 	}
1358 
1359 	/* this device is controlled by cpufreq(4) */
1360 	cpufreq_register(dev);
1361 
1362 	return (0);
1363 }
1364 
1365 static int
1366 bcm2835_cpufreq_detach(device_t dev)
1367 {
1368 	struct bcm2835_cpufreq_softc *sc;
1369 
1370 	sc = device_get_softc(dev);
1371 
1372 	sema_destroy(&vc_sema);
1373 
1374 	return (cpufreq_unregister(dev));
1375 }
1376 
1377 static int
1378 bcm2835_cpufreq_set(device_t dev, const struct cf_setting *cf)
1379 {
1380 	struct bcm2835_cpufreq_softc *sc;
1381 	uint32_t rate_hz, rem;
1382 	int cur_freq, resp_freq, arm_freq, min_freq, core_freq;
1383 
1384 	if (cf == NULL || cf->freq < 0)
1385 		return (EINVAL);
1386 
1387 	sc = device_get_softc(dev);
1388 
1389 	/* setting clock (Hz) */
1390 	rate_hz = (uint32_t)MHZ2HZ(cf->freq);
1391 	rem = rate_hz % HZSTEP;
1392 	rate_hz -= rem;
1393 	if (rate_hz == 0)
1394 		return (EINVAL);
1395 
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;
1401 
1402 	if (rate_hz < MHZ2HZ(min_freq) || rate_hz > MHZ2HZ(sc->arm_max_freq))
1403 		return (EINVAL);
1404 
1405 	/* set new value and verify it */
1406 	VC_LOCK(sc);
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);
1414 
1415 	/*
1416 	 * if non-turbo and lower than or equal min_freq,
1417 	 * clock down core and sdram to default first.
1418 	 */
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);
1431 		} else {
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);
1444 			}
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);
1453 		}
1454 	}
1455 
1456 	VC_UNLOCK(sc);
1457 
1458 	if (resp_freq < 0 || arm_freq < 0 || resp_freq != arm_freq) {
1459 		device_printf(dev, "wrong freq\n");
1460 		return (EIO);
1461 	}
1462 	DPRINTF("cpufreq: %d -> %d\n", cur_freq, arm_freq);
1463 
1464 	return (0);
1465 }
1466 
1467 static int
1468 bcm2835_cpufreq_get(device_t dev, struct cf_setting *cf)
1469 {
1470 	struct bcm2835_cpufreq_softc *sc;
1471 	int arm_freq;
1472 
1473 	if (cf == NULL)
1474 		return (EINVAL);
1475 
1476 	sc = device_get_softc(dev);
1477 	memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
1478 	cf->dev = NULL;
1479 
1480 	/* get cuurent value */
1481 	VC_LOCK(sc);
1482 	arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
1483 	    BCM2835_MBOX_CLOCK_ID_ARM);
1484 	VC_UNLOCK(sc);
1485 	if (arm_freq < 0) {
1486 		device_printf(dev, "can't get clock\n");
1487 		return (EINVAL);
1488 	}
1489 
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. */
1499 	cf->dev = dev;
1500 
1501 	return (0);
1502 }
1503 
1504 static int
1505 bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets,
1506     int *count)
1507 {
1508 	struct bcm2835_cpufreq_softc *sc;
1509 	int freq, min_freq, volts, rem;
1510 	int idx;
1511 
1512 	sc = device_get_softc(dev);
1513 	freq = sc->arm_max_freq;
1514 	min_freq = sc->arm_min_freq;
1515 
1516 	/* adjust head freq to STEP */
1517 	rem = freq % MHZSTEP;
1518 	freq -= rem;
1519 	if (freq < min_freq)
1520 		freq = min_freq;
1521 
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;
1526 
1527 #ifdef SOC_BCM2836
1528 	/* XXX RPi2 have only 900/600MHz */
1529 	idx = 0;
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;
1535 	idx++;
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;
1541 		idx++;
1542 	}
1543 #else
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;
1548 		else
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;
1554 		freq -= MHZSTEP;
1555 	}
1556 #endif
1557 	*count = idx;
1558 
1559 	return (0);
1560 }
1561 
1562 static int
1563 bcm2835_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count)
1564 {
1565 	struct bcm2835_cpufreq_softc *sc;
1566 
1567 	if (sets == NULL || count == NULL)
1568 		return (EINVAL);
1569 
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");
1573 		return (EINVAL);
1574 	}
1575 
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);
1580 
1581 	return (0);
1582 }
1583 
1584 static int
1585 bcm2835_cpufreq_type(device_t dev, int *type)
1586 {
1587 
1588 	if (type == NULL)
1589 		return (EINVAL);
1590 	*type = CPUFREQ_TYPE_ABSOLUTE;
1591 
1592 	return (0);
1593 }
1594 
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),
1601 
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),
1607 
1608 	DEVMETHOD_END
1609 };
1610 
1611 static devclass_t bcm2835_cpufreq_devclass;
1612 static driver_t bcm2835_cpufreq_driver = {
1613 	"bcm2835_cpufreq",
1614 	bcm2835_cpufreq_methods,
1615 	sizeof(struct bcm2835_cpufreq_softc),
1616 };
1617 
1618 DRIVER_MODULE(bcm2835_cpufreq, cpu, bcm2835_cpufreq_driver,
1619     bcm2835_cpufreq_devclass, 0, 0);
1620