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