1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org> 5 * Copyright (c) 2017 The FreeBSD Foundation 6 * All rights reserved. 7 * 8 * Portions of this software were developed by Landon Fuller 9 * under sponsorship from the FreeBSD Foundation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 19 * redistribution must be conditioned upon including a substantially 20 * similar Disclaimer requirement for further binary redistribution. 21 * 22 * NO WARRANTY 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 26 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 27 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 28 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 33 * THE POSSIBILITY OF SUCH DAMAGES. 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <sys/param.h> 40 #include <sys/kernel.h> 41 #include <sys/lock.h> 42 #include <sys/bus.h> 43 #include <sys/malloc.h> 44 #include <sys/module.h> 45 #include <sys/mutex.h> 46 #include <sys/sysctl.h> 47 #include <sys/systm.h> 48 49 #include <machine/bus.h> 50 #include <machine/resource.h> 51 52 #include <dev/bhnd/bhndreg.h> 53 #include <dev/bhnd/bhndvar.h> 54 #include <dev/bhnd/cores/chipc/chipc.h> 55 56 #include "bhnd_nvram_map.h" 57 58 #include "bhnd_pmureg.h" 59 #include "bhnd_pmuvar.h" 60 61 #include "bhnd_pmu_private.h" 62 63 /* 64 * Broadcom PMU driver. 65 * 66 * On modern BHND chipsets, the PMU, GCI, and SRENG (Save/Restore Engine?) 67 * register blocks are found within a dedicated PMU core (attached via 68 * the AHB 'always on bus'). 69 * 70 * On earlier chipsets, these register blocks are found at the same 71 * offsets within the ChipCommon core. 72 */ 73 74 devclass_t bhnd_pmu_devclass; /**< bhnd(4) PMU device class */ 75 76 static int bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS); 77 static int bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS); 78 static int bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS); 79 80 static uint32_t bhnd_pmu_read_4(bus_size_t reg, void *ctx); 81 static void bhnd_pmu_write_4(bus_size_t reg, uint32_t val, void *ctx); 82 static uint32_t bhnd_pmu_read_chipst(void *ctx); 83 84 static const struct bhnd_pmu_io bhnd_pmu_res_io = { 85 .rd4 = bhnd_pmu_read_4, 86 .wr4 = bhnd_pmu_write_4, 87 .rd_chipst = bhnd_pmu_read_chipst 88 }; 89 90 /** 91 * Default bhnd_pmu driver implementation of DEVICE_PROBE(). 92 */ 93 int 94 bhnd_pmu_probe(device_t dev) 95 { 96 return (BUS_PROBE_DEFAULT); 97 } 98 99 /** 100 * Default bhnd_pmu driver implementation of DEVICE_ATTACH(). 101 * 102 * @param dev PMU device. 103 * @param res The PMU device registers. The driver will maintain a borrowed 104 * reference to this resource for the lifetime of the device. 105 */ 106 int 107 bhnd_pmu_attach(device_t dev, struct bhnd_resource *res) 108 { 109 struct bhnd_pmu_softc *sc; 110 struct sysctl_ctx_list *ctx; 111 struct sysctl_oid *tree; 112 devclass_t bhnd_class; 113 device_t core, bus; 114 int error; 115 116 sc = device_get_softc(dev); 117 sc->dev = dev; 118 sc->res = res; 119 120 /* Fetch capability flags */ 121 sc->caps = bhnd_bus_read_4(sc->res, BHND_PMU_CAP); 122 123 /* Find the bus and bus-attached core */ 124 bhnd_class = devclass_find("bhnd"); 125 core = sc->dev; 126 while ((bus = device_get_parent(core)) != NULL) { 127 if (device_get_devclass(bus) == bhnd_class) 128 break; 129 130 core = bus; 131 } 132 133 if (core == NULL) { 134 device_printf(sc->dev, "bhnd bus not found\n"); 135 return (ENXIO); 136 } 137 138 /* Fetch chip and board info */ 139 sc->cid = *bhnd_get_chipid(core); 140 if ((error = bhnd_read_board_info(core, &sc->board))) { 141 device_printf(sc->dev, "error fetching board info: %d\n", 142 error); 143 return (ENXIO); 144 } 145 146 /* Initialize query state */ 147 error = bhnd_pmu_query_init(&sc->query, dev, sc->cid, &bhnd_pmu_res_io, 148 sc); 149 if (error) 150 return (error); 151 sc->io = sc->query.io; 152 sc->io_ctx = sc->query.io_ctx; 153 154 BPMU_LOCK_INIT(sc); 155 156 /* Allocate our own core clkctl state directly; we use this to wait on 157 * PMU state transitions, avoiding a cyclic dependency between bhnd(4)'s 158 * clkctl handling and registration of this device as a PMU */ 159 sc->clkctl = bhnd_alloc_core_clkctl(core, dev, sc->res, BHND_CLK_CTL_ST, 160 BHND_PMU_MAX_TRANSITION_DLY); 161 if (sc->clkctl == NULL) { 162 device_printf(sc->dev, "failed to allocate clkctl for %s\n", 163 device_get_nameunit(core)); 164 error = ENOMEM; 165 goto failed; 166 } 167 168 /* Locate ChipCommon device */ 169 sc->chipc_dev = bhnd_retain_provider(dev, BHND_SERVICE_CHIPC); 170 if (sc->chipc_dev == NULL) { 171 device_printf(sc->dev, "chipcommon device not found\n"); 172 error = ENXIO; 173 goto failed; 174 } 175 176 /* Initialize PMU */ 177 if ((error = bhnd_pmu_init(sc))) { 178 device_printf(sc->dev, "PMU init failed: %d\n", error); 179 goto failed; 180 } 181 182 /* Register ourselves with the bus */ 183 if ((error = bhnd_register_provider(dev, BHND_SERVICE_PMU))) { 184 device_printf(sc->dev, "failed to register PMU with bus : %d\n", 185 error); 186 goto failed; 187 } 188 189 /* Set up sysctl nodes */ 190 ctx = device_get_sysctl_ctx(dev); 191 tree = device_get_sysctl_tree(dev); 192 193 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 194 "bus_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0, 195 bhnd_pmu_sysctl_bus_freq, "IU", "Bus clock frequency"); 196 197 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 198 "cpu_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0, 199 bhnd_pmu_sysctl_cpu_freq, "IU", "CPU clock frequency"); 200 201 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 202 "mem_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0, 203 bhnd_pmu_sysctl_mem_freq, "IU", "Memory clock frequency"); 204 205 return (0); 206 207 failed: 208 BPMU_LOCK_DESTROY(sc); 209 bhnd_pmu_query_fini(&sc->query); 210 211 if (sc->clkctl != NULL) 212 bhnd_free_core_clkctl(sc->clkctl); 213 214 if (sc->chipc_dev != NULL) { 215 bhnd_release_provider(sc->dev, sc->chipc_dev, 216 BHND_SERVICE_CHIPC); 217 } 218 219 return (error); 220 } 221 222 /** 223 * Default bhnd_pmu driver implementation of DEVICE_DETACH(). 224 */ 225 int 226 bhnd_pmu_detach(device_t dev) 227 { 228 struct bhnd_pmu_softc *sc; 229 int error; 230 231 sc = device_get_softc(dev); 232 233 if ((error = bhnd_deregister_provider(dev, BHND_SERVICE_ANY))) 234 return (error); 235 236 BPMU_LOCK_DESTROY(sc); 237 bhnd_pmu_query_fini(&sc->query); 238 bhnd_free_core_clkctl(sc->clkctl); 239 bhnd_release_provider(sc->dev, sc->chipc_dev, BHND_SERVICE_CHIPC); 240 241 return (0); 242 } 243 244 /** 245 * Default bhnd_pmu driver implementation of DEVICE_SUSPEND(). 246 */ 247 int 248 bhnd_pmu_suspend(device_t dev) 249 { 250 return (0); 251 } 252 253 /** 254 * Default bhnd_pmu driver implementation of DEVICE_RESUME(). 255 */ 256 int 257 bhnd_pmu_resume(device_t dev) 258 { 259 struct bhnd_pmu_softc *sc; 260 int error; 261 262 sc = device_get_softc(dev); 263 264 /* Re-initialize PMU */ 265 if ((error = bhnd_pmu_init(sc))) { 266 device_printf(sc->dev, "PMU init failed: %d\n", error); 267 return (error); 268 } 269 270 return (0); 271 } 272 273 static int 274 bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS) 275 { 276 struct bhnd_pmu_softc *sc; 277 uint32_t freq; 278 279 sc = arg1; 280 281 BPMU_LOCK(sc); 282 freq = bhnd_pmu_si_clock(&sc->query); 283 BPMU_UNLOCK(sc); 284 285 return (sysctl_handle_32(oidp, NULL, freq, req)); 286 } 287 288 static int 289 bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS) 290 { 291 struct bhnd_pmu_softc *sc; 292 uint32_t freq; 293 294 sc = arg1; 295 296 BPMU_LOCK(sc); 297 freq = bhnd_pmu_cpu_clock(&sc->query); 298 BPMU_UNLOCK(sc); 299 300 return (sysctl_handle_32(oidp, NULL, freq, req)); 301 } 302 303 static int 304 bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS) 305 { 306 struct bhnd_pmu_softc *sc; 307 uint32_t freq; 308 309 sc = arg1; 310 311 BPMU_LOCK(sc); 312 freq = bhnd_pmu_mem_clock(&sc->query); 313 BPMU_UNLOCK(sc); 314 315 return (sysctl_handle_32(oidp, NULL, freq, req)); 316 } 317 318 /** 319 * Default bhnd_pmu driver implementation of BHND_PMU_READ_CHIPCTRL(). 320 */ 321 static uint32_t 322 bhnd_pmu_read_chipctrl_method(device_t dev, uint32_t reg) 323 { 324 struct bhnd_pmu_softc *sc; 325 uint32_t rval; 326 327 sc = device_get_softc(dev); 328 329 BPMU_LOCK(sc); 330 rval = BHND_PMU_CCTRL_READ(sc, reg); 331 BPMU_UNLOCK(sc); 332 333 return (rval); 334 } 335 336 /** 337 * Default bhnd_pmu driver implementation of BHND_PMU_WRITE_CHIPCTRL(). 338 */ 339 static void 340 bhnd_pmu_write_chipctrl_method(device_t dev, uint32_t reg, uint32_t value, 341 uint32_t mask) 342 { 343 struct bhnd_pmu_softc *sc = device_get_softc(dev); 344 345 BPMU_LOCK(sc); 346 BHND_PMU_CCTRL_WRITE(sc, reg, value, mask); 347 BPMU_UNLOCK(sc); 348 } 349 350 /** 351 * Default bhnd_pmu driver implementation of BHND_PMU_READ_REGCTRL(). 352 */ 353 static uint32_t 354 bhnd_pmu_read_regctrl_method(device_t dev, uint32_t reg) 355 { 356 struct bhnd_pmu_softc *sc; 357 uint32_t rval; 358 359 sc = device_get_softc(dev); 360 361 BPMU_LOCK(sc); 362 rval = BHND_PMU_REGCTRL_READ(sc, reg); 363 BPMU_UNLOCK(sc); 364 365 return (rval); 366 } 367 368 /** 369 * Default bhnd_pmu driver implementation of BHND_PMU_WRITE_REGCTRL(). 370 */ 371 static void 372 bhnd_pmu_write_regctrl_method(device_t dev, uint32_t reg, uint32_t value, 373 uint32_t mask) 374 { 375 struct bhnd_pmu_softc *sc = device_get_softc(dev); 376 377 BPMU_LOCK(sc); 378 BHND_PMU_REGCTRL_WRITE(sc, reg, value, mask); 379 BPMU_UNLOCK(sc); 380 } 381 382 /** 383 * Default bhnd_pmu driver implementation of BHND_PMU_READ_PLLCTRL(). 384 */ 385 static uint32_t 386 bhnd_pmu_read_pllctrl_method(device_t dev, uint32_t reg) 387 { 388 struct bhnd_pmu_softc *sc; 389 uint32_t rval; 390 391 sc = device_get_softc(dev); 392 393 BPMU_LOCK(sc); 394 rval = BHND_PMU_PLL_READ(sc, reg); 395 BPMU_UNLOCK(sc); 396 397 return (rval); 398 } 399 400 /** 401 * Default bhnd_pmu driver implementation of BHND_PMU_WRITE_PLLCTRL(). 402 */ 403 static void 404 bhnd_pmu_write_pllctrl_method(device_t dev, uint32_t reg, uint32_t value, 405 uint32_t mask) 406 { 407 struct bhnd_pmu_softc *sc = device_get_softc(dev); 408 409 BPMU_LOCK(sc); 410 BHND_PMU_PLL_WRITE(sc, reg, value, mask); 411 BPMU_UNLOCK(sc); 412 } 413 414 /** 415 * Default bhnd_pmu driver implementation of BHND_PMU_SET_VOLTAGE_RAW(). 416 */ 417 static int 418 bhnd_pmu_set_voltage_raw_method(device_t dev, bhnd_pmu_regulator regulator, 419 uint32_t value) 420 { 421 struct bhnd_pmu_softc *sc; 422 int error; 423 424 sc = device_get_softc(dev); 425 426 switch (regulator) { 427 case BHND_REGULATOR_PAREF_LDO: 428 if (value > UINT8_MAX) 429 return (EINVAL); 430 431 BPMU_LOCK(sc); 432 error = bhnd_pmu_set_ldo_voltage(sc, SET_LDO_VOLTAGE_PAREF, 433 value); 434 BPMU_UNLOCK(sc); 435 436 return (error); 437 438 default: 439 return (ENODEV); 440 } 441 } 442 443 /** 444 * Default bhnd_pmu driver implementation of BHND_PMU_ENABLE_REGULATOR(). 445 */ 446 static int 447 bhnd_pmu_enable_regulator_method(device_t dev, bhnd_pmu_regulator regulator) 448 { 449 struct bhnd_pmu_softc *sc; 450 int error; 451 452 sc = device_get_softc(dev); 453 454 switch (regulator) { 455 case BHND_REGULATOR_PAREF_LDO: 456 BPMU_LOCK(sc); 457 error = bhnd_pmu_paref_ldo_enable(sc, true); 458 BPMU_UNLOCK(sc); 459 460 return (error); 461 462 default: 463 return (ENODEV); 464 } 465 } 466 467 /** 468 * Default bhnd_pmu driver implementation of BHND_PMU_DISABLE_REGULATOR(). 469 */ 470 static int 471 bhnd_pmu_disable_regulator_method(device_t dev, bhnd_pmu_regulator regulator) 472 { 473 struct bhnd_pmu_softc *sc; 474 int error; 475 476 sc = device_get_softc(dev); 477 478 switch (regulator) { 479 case BHND_REGULATOR_PAREF_LDO: 480 BPMU_LOCK(sc); 481 error = bhnd_pmu_paref_ldo_enable(sc, false); 482 BPMU_UNLOCK(sc); 483 484 return (error); 485 486 default: 487 return (ENODEV); 488 } 489 } 490 491 492 /** 493 * Default bhnd_pmu driver implementation of BHND_PMU_GET_CLOCK_LATENCY(). 494 */ 495 static int 496 bhnd_pmu_get_clock_latency_method(device_t dev, bhnd_clock clock, 497 u_int *latency) 498 { 499 struct bhnd_pmu_softc *sc; 500 u_int pwrup_delay; 501 int error; 502 503 sc = device_get_softc(dev); 504 505 switch (clock) { 506 case BHND_CLOCK_HT: 507 BPMU_LOCK(sc); 508 error = bhnd_pmu_fast_pwrup_delay(sc, &pwrup_delay); 509 BPMU_UNLOCK(sc); 510 511 if (error) 512 return (error); 513 514 *latency = pwrup_delay; 515 return (0); 516 517 default: 518 return (ENODEV); 519 } 520 } 521 522 /** 523 * Default bhnd_pmu driver implementation of BHND_PMU_GET_CLOCK_FREQ(). 524 */ 525 static int 526 bhnd_pmu_get_clock_freq_method(device_t dev, bhnd_clock clock, uint32_t *freq) 527 { 528 struct bhnd_pmu_softc *sc = device_get_softc(dev); 529 530 BPMU_LOCK(sc); 531 switch (clock) { 532 case BHND_CLOCK_HT: 533 *freq = bhnd_pmu_si_clock(&sc->query); 534 break; 535 536 case BHND_CLOCK_ALP: 537 *freq = bhnd_pmu_alp_clock(&sc->query); 538 break; 539 540 case BHND_CLOCK_ILP: 541 *freq = bhnd_pmu_ilp_clock(&sc->query); 542 break; 543 544 case BHND_CLOCK_DYN: 545 default: 546 BPMU_UNLOCK(sc); 547 return (ENODEV); 548 } 549 550 BPMU_UNLOCK(sc); 551 return (0); 552 } 553 554 /** 555 * Default bhnd_pmu driver implementation of BHND_PMU_REQUEST_SPURAVOID(). 556 */ 557 static int 558 bhnd_pmu_request_spuravoid_method(device_t dev, bhnd_pmu_spuravoid spuravoid) 559 { 560 struct bhnd_pmu_softc *sc; 561 int error; 562 563 sc = device_get_softc(dev); 564 565 BPMU_LOCK(sc); 566 error = bhnd_pmu_set_spuravoid(sc, spuravoid); 567 BPMU_UNLOCK(sc); 568 569 return (error); 570 } 571 572 /** 573 * Default bhnd_pmu driver implementation of BHND_PMU_GET_TRANSITION_LATENCY(). 574 */ 575 static u_int 576 bhnd_pmu_get_max_transition_latency_method(device_t dev) 577 { 578 return (BHND_PMU_MAX_TRANSITION_DLY); 579 } 580 581 /* bhnd_pmu_query read_4 callback */ 582 static uint32_t 583 bhnd_pmu_read_4(bus_size_t reg, void *ctx) 584 { 585 struct bhnd_pmu_softc *sc = ctx; 586 return (bhnd_bus_read_4(sc->res, reg)); 587 } 588 589 /* bhnd_pmu_query write_4 callback */ 590 static void 591 bhnd_pmu_write_4(bus_size_t reg, uint32_t val, void *ctx) 592 { 593 struct bhnd_pmu_softc *sc = ctx; 594 return (bhnd_bus_write_4(sc->res, reg, val)); 595 } 596 597 /* bhnd_pmu_query read_chipst callback */ 598 static uint32_t 599 bhnd_pmu_read_chipst(void *ctx) 600 { 601 struct bhnd_pmu_softc *sc = ctx; 602 return (BHND_CHIPC_READ_CHIPST(sc->chipc_dev)); 603 } 604 605 static device_method_t bhnd_pmu_methods[] = { 606 /* Device interface */ 607 DEVMETHOD(device_probe, bhnd_pmu_probe), 608 DEVMETHOD(device_detach, bhnd_pmu_detach), 609 DEVMETHOD(device_suspend, bhnd_pmu_suspend), 610 DEVMETHOD(device_resume, bhnd_pmu_resume), 611 612 /* BHND PMU interface */ 613 DEVMETHOD(bhnd_pmu_read_chipctrl, bhnd_pmu_read_chipctrl_method), 614 DEVMETHOD(bhnd_pmu_write_chipctrl, bhnd_pmu_write_chipctrl_method), 615 DEVMETHOD(bhnd_pmu_read_regctrl, bhnd_pmu_read_regctrl_method), 616 DEVMETHOD(bhnd_pmu_write_regctrl, bhnd_pmu_write_regctrl_method), 617 DEVMETHOD(bhnd_pmu_read_pllctrl, bhnd_pmu_read_pllctrl_method), 618 DEVMETHOD(bhnd_pmu_write_pllctrl, bhnd_pmu_write_pllctrl_method), 619 DEVMETHOD(bhnd_pmu_set_voltage_raw, bhnd_pmu_set_voltage_raw_method), 620 DEVMETHOD(bhnd_pmu_enable_regulator, bhnd_pmu_enable_regulator_method), 621 DEVMETHOD(bhnd_pmu_disable_regulator, bhnd_pmu_disable_regulator_method), 622 623 DEVMETHOD(bhnd_pmu_get_clock_latency, bhnd_pmu_get_clock_latency_method), 624 DEVMETHOD(bhnd_pmu_get_clock_freq, bhnd_pmu_get_clock_freq_method), 625 626 DEVMETHOD(bhnd_pmu_get_max_transition_latency, bhnd_pmu_get_max_transition_latency_method), 627 DEVMETHOD(bhnd_pmu_request_spuravoid, bhnd_pmu_request_spuravoid_method), 628 629 DEVMETHOD_END 630 }; 631 632 DEFINE_CLASS_0(bhnd_pmu, bhnd_pmu_driver, bhnd_pmu_methods, sizeof(struct bhnd_pmu_softc)); 633 MODULE_VERSION(bhnd_pmu, 1); 634