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