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