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