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