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