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