bcm2835_cpufreq.c revision 302408
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: stable/11/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c 300421 2016-05-22 13:58:32Z loos $");
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		2731
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 */
95static struct sema vc_sema;
96
97static struct sysctl_ctx_list bcm2835_sysctl_ctx;
98
99struct 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
122static int cpufreq_verbose = 0;
123TUNABLE_INT("hw.bcm2835.cpufreq.verbose", &cpufreq_verbose);
124static int cpufreq_lowest_freq = DEFAULT_LOWEST_FREQ;
125TUNABLE_INT("hw.bcm2835.cpufreq.lowest_freq", &cpufreq_lowest_freq);
126
127#ifdef PROP_DEBUG
128static void
129bcm2835_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
146static int
147bcm2835_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
192static int
193bcm2835_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
238static int
239bcm2835_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
284static int
285bcm2835_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
362static int
363bcm2835_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
406static int
407bcm2835_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
456static int
457bcm2835_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
501static int
502bcm2835_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}
545static int
546bcm2835_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
590static int
591bcm2835_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
647static int
648bcm2835_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
693static int
694sysctl_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
725static int
726sysctl_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
758static int
759sysctl_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
790static int
791sysctl_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
826static int
827sysctl_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
862static int
863sysctl_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
898static int
899sysctl_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
934static int
935sysctl_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
970static int
971sysctl_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
1018static int
1019sysctl_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
1040static int
1041sysctl_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
1066static void
1067bcm2835_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
1244static void
1245bcm2835_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
1255static int
1256bcm2835_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
1266static int
1267bcm2835_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
1365static int
1366bcm2835_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
1377static int
1378bcm2835_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
1467static int
1468bcm2835_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
1504static int
1505bcm2835_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
1562static int
1563bcm2835_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
1584static int
1585bcm2835_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
1595static 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
1611static devclass_t bcm2835_cpufreq_devclass;
1612static driver_t bcm2835_cpufreq_driver = {
1613	"bcm2835_cpufreq",
1614	bcm2835_cpufreq_methods,
1615	sizeof(struct bcm2835_cpufreq_softc),
1616};
1617
1618DRIVER_MODULE(bcm2835_cpufreq, cpu, bcm2835_cpufreq_driver,
1619    bcm2835_cpufreq_devclass, 0, 0);
1620