1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2011 5 * Ben Gray <ben.r.gray@gmail.com>. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 /* 34 * Texas Instruments TWL4030/TWL5030/TWL60x0/TPS659x0 Power Management. 35 * 36 * This driver covers the voltages regulators (LDO), allows for enabling & 37 * disabling the voltage output and adjusting the voltage level. 38 * 39 * Voltage regulators can belong to different power groups, in this driver we 40 * put the regulators under our control in the "Application power group". 41 * 42 * 43 * FLATTENED DEVICE TREE (FDT) 44 * Startup override settings can be specified in the FDT, if they are they 45 * should be under the twl parent device and take the following form: 46 * 47 * voltage-regulators = "name1", "millivolts1", 48 * "name2", "millivolts2"; 49 * 50 * Each override should be a pair, the first entry is the name of the regulator 51 * the second is the voltage (in millivolts) to set for the given regulator. 52 * 53 */ 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/kernel.h> 58 #include <sys/lock.h> 59 #include <sys/module.h> 60 #include <sys/bus.h> 61 #include <sys/resource.h> 62 #include <sys/rman.h> 63 #include <sys/sysctl.h> 64 #include <sys/sx.h> 65 #include <sys/malloc.h> 66 67 #include <machine/bus.h> 68 #include <machine/resource.h> 69 #include <machine/intr.h> 70 71 #include <dev/ofw/openfirm.h> 72 #include <dev/ofw/ofw_bus.h> 73 74 #include "twl.h" 75 #include "twl_vreg.h" 76 77 static int twl_vreg_debug = 1; 78 79 80 /* 81 * Power Groups bits for the 4030 and 6030 devices 82 */ 83 #define TWL4030_P3_GRP 0x80 /* Peripherals, power group */ 84 #define TWL4030_P2_GRP 0x40 /* Modem power group */ 85 #define TWL4030_P1_GRP 0x20 /* Application power group (FreeBSD control) */ 86 87 #define TWL6030_P3_GRP 0x04 /* Modem power group */ 88 #define TWL6030_P2_GRP 0x02 /* Connectivity power group */ 89 #define TWL6030_P1_GRP 0x01 /* Application power group (FreeBSD control) */ 90 91 /* 92 * Register offsets within a LDO regulator register set 93 */ 94 #define TWL_VREG_GRP 0x00 /* Regulator GRP register */ 95 #define TWL_VREG_STATE 0x02 96 #define TWL_VREG_VSEL 0x03 /* Voltage select register */ 97 98 #define UNDF 0xFFFF 99 100 static const uint16_t twl6030_voltages[] = { 101 0000, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 102 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 103 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 104 3300, UNDF, UNDF, UNDF, UNDF, UNDF, UNDF, 2750 105 }; 106 107 static const uint16_t twl4030_vaux1_voltages[] = { 108 1500, 1800, 2500, 2800, 3000, 3000, 3000, 3000 109 }; 110 static const uint16_t twl4030_vaux2_voltages[] = { 111 1700, 1700, 1900, 1300, 1500, 1800, 2000, 2500, 112 2100, 2800, 2200, 2300, 2400, 2400, 2400, 2400 113 }; 114 static const uint16_t twl4030_vaux3_voltages[] = { 115 1500, 1800, 2500, 2800, 3000, 3000, 3000, 3000 116 }; 117 static const uint16_t twl4030_vaux4_voltages[] = { 118 700, 1000, 1200, 1300, 1500, 1800, 1850, 2500, 119 2600, 2800, 2850, 3000, 3150, 3150, 3150, 3150 120 }; 121 static const uint16_t twl4030_vmmc1_voltages[] = { 122 1850, 2850, 3000, 3150 123 }; 124 static const uint16_t twl4030_vmmc2_voltages[] = { 125 1000, 1000, 1200, 1300, 1500, 1800, 1850, 2500, 126 2600, 2800, 2850, 3000, 3150, 3150, 3150, 3150 127 }; 128 static const uint16_t twl4030_vpll1_voltages[] = { 129 1000, 1200, 1300, 1800, 2800, 3000, 3000, 3000 130 }; 131 static const uint16_t twl4030_vpll2_voltages[] = { 132 700, 1000, 1200, 1300, 1500, 1800, 1850, 2500, 133 2600, 2800, 2850, 3000, 3150, 3150, 3150, 3150 134 }; 135 static const uint16_t twl4030_vsim_voltages[] = { 136 1000, 1200, 1300, 1800, 2800, 3000, 3000, 3000 137 }; 138 static const uint16_t twl4030_vdac_voltages[] = { 139 1200, 1300, 1800, 1800 140 }; 141 #if 0 /* vdd1, vdd2, vdio, not currently used. */ 142 static const uint16_t twl4030_vdd1_voltages[] = { 143 800, 1450 144 }; 145 static const uint16_t twl4030_vdd2_voltages[] = { 146 800, 1450, 1500 147 }; 148 static const uint16_t twl4030_vio_voltages[] = { 149 1800, 1850 150 }; 151 #endif 152 static const uint16_t twl4030_vintana2_voltages[] = { 153 2500, 2750 154 }; 155 156 /** 157 * Support voltage regulators for the different IC's 158 */ 159 struct twl_regulator { 160 const char *name; 161 uint8_t subdev; 162 uint8_t regbase; 163 164 uint16_t fixedvoltage; 165 166 const uint16_t *voltages; 167 uint32_t num_voltages; 168 }; 169 170 #define TWL_REGULATOR_ADJUSTABLE(name, subdev, reg, voltages) \ 171 { name, subdev, reg, 0, voltages, (sizeof(voltages)/sizeof(voltages[0])) } 172 #define TWL_REGULATOR_FIXED(name, subdev, reg, voltage) \ 173 { name, subdev, reg, voltage, NULL, 0 } 174 175 static const struct twl_regulator twl4030_regulators[] = { 176 TWL_REGULATOR_ADJUSTABLE("vaux1", 0, 0x17, twl4030_vaux1_voltages), 177 TWL_REGULATOR_ADJUSTABLE("vaux2", 0, 0x1B, twl4030_vaux2_voltages), 178 TWL_REGULATOR_ADJUSTABLE("vaux3", 0, 0x1F, twl4030_vaux3_voltages), 179 TWL_REGULATOR_ADJUSTABLE("vaux4", 0, 0x23, twl4030_vaux4_voltages), 180 TWL_REGULATOR_ADJUSTABLE("vmmc1", 0, 0x27, twl4030_vmmc1_voltages), 181 TWL_REGULATOR_ADJUSTABLE("vmmc2", 0, 0x2B, twl4030_vmmc2_voltages), 182 TWL_REGULATOR_ADJUSTABLE("vpll1", 0, 0x2F, twl4030_vpll1_voltages), 183 TWL_REGULATOR_ADJUSTABLE("vpll2", 0, 0x33, twl4030_vpll2_voltages), 184 TWL_REGULATOR_ADJUSTABLE("vsim", 0, 0x37, twl4030_vsim_voltages), 185 TWL_REGULATOR_ADJUSTABLE("vdac", 0, 0x3B, twl4030_vdac_voltages), 186 TWL_REGULATOR_ADJUSTABLE("vintana2", 0, 0x43, twl4030_vintana2_voltages), 187 TWL_REGULATOR_FIXED("vintana1", 0, 0x3F, 1500), 188 TWL_REGULATOR_FIXED("vintdig", 0, 0x47, 1500), 189 TWL_REGULATOR_FIXED("vusb1v5", 0, 0x71, 1500), 190 TWL_REGULATOR_FIXED("vusb1v8", 0, 0x74, 1800), 191 TWL_REGULATOR_FIXED("vusb3v1", 0, 0x77, 3100), 192 { NULL, 0, 0x00, 0, NULL, 0 } 193 }; 194 195 static const struct twl_regulator twl6030_regulators[] = { 196 TWL_REGULATOR_ADJUSTABLE("vaux1", 0, 0x84, twl6030_voltages), 197 TWL_REGULATOR_ADJUSTABLE("vaux2", 0, 0x89, twl6030_voltages), 198 TWL_REGULATOR_ADJUSTABLE("vaux3", 0, 0x8C, twl6030_voltages), 199 TWL_REGULATOR_ADJUSTABLE("vmmc", 0, 0x98, twl6030_voltages), 200 TWL_REGULATOR_ADJUSTABLE("vpp", 0, 0x9C, twl6030_voltages), 201 TWL_REGULATOR_ADJUSTABLE("vusim", 0, 0xA4, twl6030_voltages), 202 TWL_REGULATOR_FIXED("vmem", 0, 0x64, 1800), 203 TWL_REGULATOR_FIXED("vusb", 0, 0xA0, 3300), 204 TWL_REGULATOR_FIXED("v1v8", 0, 0x46, 1800), 205 TWL_REGULATOR_FIXED("v2v1", 0, 0x4C, 2100), 206 TWL_REGULATOR_FIXED("v1v29", 0, 0x40, 1290), 207 TWL_REGULATOR_FIXED("vcxio", 0, 0x90, 1800), 208 TWL_REGULATOR_FIXED("vdac", 0, 0x94, 1800), 209 TWL_REGULATOR_FIXED("vana", 0, 0x80, 2100), 210 { NULL, 0, 0x00, 0, NULL, 0 } 211 }; 212 213 #define TWL_VREG_MAX_NAMELEN 32 214 215 struct twl_regulator_entry { 216 LIST_ENTRY(twl_regulator_entry) entries; 217 char name[TWL_VREG_MAX_NAMELEN]; 218 struct sysctl_oid *oid; 219 uint8_t sub_dev; /* TWL sub-device group */ 220 uint8_t reg_off; /* base register offset for the LDO */ 221 uint16_t fixed_voltage; /* the (milli)voltage if LDO is fixed */ 222 const uint16_t *supp_voltages; /* pointer to an array of possible voltages */ 223 uint32_t num_supp_voltages; /* the number of supplied voltages */ 224 }; 225 226 struct twl_vreg_softc { 227 device_t sc_dev; 228 device_t sc_pdev; 229 struct sx sc_sx; 230 231 struct intr_config_hook sc_init_hook; 232 LIST_HEAD(twl_regulator_list, twl_regulator_entry) sc_vreg_list; 233 }; 234 235 236 #define TWL_VREG_XLOCK(_sc) sx_xlock(&(_sc)->sc_sx) 237 #define TWL_VREG_XUNLOCK(_sc) sx_xunlock(&(_sc)->sc_sx) 238 #define TWL_VREG_SLOCK(_sc) sx_slock(&(_sc)->sc_sx) 239 #define TWL_VREG_SUNLOCK(_sc) sx_sunlock(&(_sc)->sc_sx) 240 #define TWL_VREG_LOCK_INIT(_sc) sx_init(&(_sc)->sc_sx, "twl_vreg") 241 #define TWL_VREG_LOCK_DESTROY(_sc) sx_destroy(&(_sc)->sc_sx); 242 243 #define TWL_VREG_ASSERT_LOCKED(_sc) sx_assert(&(_sc)->sc_sx, SA_LOCKED); 244 245 #define TWL_VREG_LOCK_UPGRADE(_sc) \ 246 do { \ 247 while (!sx_try_upgrade(&(_sc)->sc_sx)) \ 248 pause("twl_vreg_ex", (hz / 100)); \ 249 } while(0) 250 #define TWL_VREG_LOCK_DOWNGRADE(_sc) sx_downgrade(&(_sc)->sc_sx); 251 252 253 254 255 /** 256 * twl_vreg_read_1 - read single register from the TWL device 257 * twl_vreg_write_1 - write a single register in the TWL device 258 * @sc: device context 259 * @clk: the clock device we're reading from / writing to 260 * @off: offset within the clock's register set 261 * @val: the value to write or a pointer to a variable to store the result 262 * 263 * RETURNS: 264 * Zero on success or an error code on failure. 265 */ 266 static inline int 267 twl_vreg_read_1(struct twl_vreg_softc *sc, struct twl_regulator_entry *regulator, 268 uint8_t off, uint8_t *val) 269 { 270 return (twl_read(sc->sc_pdev, regulator->sub_dev, 271 regulator->reg_off + off, val, 1)); 272 } 273 274 static inline int 275 twl_vreg_write_1(struct twl_vreg_softc *sc, struct twl_regulator_entry *regulator, 276 uint8_t off, uint8_t val) 277 { 278 return (twl_write(sc->sc_pdev, regulator->sub_dev, 279 regulator->reg_off + off, &val, 1)); 280 } 281 282 /** 283 * twl_millivolt_to_vsel - gets the vsel bit value to write into the register 284 * for a desired voltage and regulator 285 * @sc: the device soft context 286 * @regulator: pointer to the regulator device 287 * @millivolts: the millivolts to find the bit value for 288 * @vsel: upon return will contain the corresponding register value 289 * 290 * Accepts a (milli)voltage value and tries to find the closest match to the 291 * actual supported voltages for the given regulator. If a match is found 292 * within 100mv of the target, @vsel is written with the match and 0 is 293 * returned. If no voltage match is found the function returns an non-zero 294 * value. 295 * 296 * RETURNS: 297 * Zero on success or an error code on failure. 298 */ 299 static int 300 twl_vreg_millivolt_to_vsel(struct twl_vreg_softc *sc, 301 struct twl_regulator_entry *regulator, int millivolts, uint8_t *vsel) 302 { 303 int delta, smallest_delta; 304 unsigned i, closest_idx; 305 306 TWL_VREG_ASSERT_LOCKED(sc); 307 308 if (regulator->supp_voltages == NULL) 309 return (EINVAL); 310 311 /* Loop over the support voltages and try and find the closest match */ 312 closest_idx = 0; 313 smallest_delta = 0x7fffffff; 314 for (i = 0; i < regulator->num_supp_voltages; i++) { 315 316 /* Ignore undefined values */ 317 if (regulator->supp_voltages[i] == UNDF) 318 continue; 319 320 /* Calculate the difference */ 321 delta = millivolts - (int)regulator->supp_voltages[i]; 322 if (abs(delta) < smallest_delta) { 323 smallest_delta = abs(delta); 324 closest_idx = i; 325 } 326 } 327 328 /* Check we got a voltage that was within 100mv of the actual target, this 329 * is just a value I picked out of thin air. 330 */ 331 if ((smallest_delta > 100) && (closest_idx < 0x100)) 332 return (EINVAL); 333 334 *vsel = closest_idx; 335 return (0); 336 } 337 338 /** 339 * twl_vreg_is_regulator_enabled - returns the enabled status of the regulator 340 * @sc: the device soft context 341 * @regulator: pointer to the regulator device 342 * @enabled: stores the enabled status, zero disabled, non-zero enabled 343 * 344 * LOCKING: 345 * On entry expects the TWL VREG lock to be held. Will upgrade the lock to 346 * exclusive if not already but, if so, it will be downgraded again before 347 * returning. 348 * 349 * RETURNS: 350 * Zero on success or an error code on failure. 351 */ 352 static int 353 twl_vreg_is_regulator_enabled(struct twl_vreg_softc *sc, 354 struct twl_regulator_entry *regulator, int *enabled) 355 { 356 int err; 357 uint8_t grp; 358 uint8_t state; 359 int xlocked; 360 361 if (enabled == NULL) 362 return (EINVAL); 363 364 TWL_VREG_ASSERT_LOCKED(sc); 365 366 xlocked = sx_xlocked(&sc->sc_sx); 367 if (!xlocked) 368 TWL_VREG_LOCK_UPGRADE(sc); 369 370 /* The status reading is different for the different devices */ 371 if (twl_is_4030(sc->sc_pdev)) { 372 373 err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &state); 374 if (err) 375 goto done; 376 377 *enabled = (state & TWL4030_P1_GRP); 378 379 } else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) { 380 381 /* Check the regulator is in the application group */ 382 if (twl_is_6030(sc->sc_pdev)) { 383 err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &grp); 384 if (err) 385 goto done; 386 387 if (!(grp & TWL6030_P1_GRP)) { 388 *enabled = 0; /* disabled */ 389 goto done; 390 } 391 } 392 393 /* Read the application mode state and verify it's ON */ 394 err = twl_vreg_read_1(sc, regulator, TWL_VREG_STATE, &state); 395 if (err) 396 goto done; 397 398 *enabled = ((state & 0x0C) == 0x04); 399 400 } else { 401 err = EINVAL; 402 } 403 404 done: 405 if (!xlocked) 406 TWL_VREG_LOCK_DOWNGRADE(sc); 407 408 return (err); 409 } 410 411 /** 412 * twl_vreg_disable_regulator - disables a voltage regulator 413 * @sc: the device soft context 414 * @regulator: pointer to the regulator device 415 * 416 * Disables the regulator which will stop the output drivers. 417 * 418 * LOCKING: 419 * On entry expects the TWL VREG lock to be held. Will upgrade the lock to 420 * exclusive if not already but, if so, it will be downgraded again before 421 * returning. 422 * 423 * RETURNS: 424 * Zero on success or a positive error code on failure. 425 */ 426 static int 427 twl_vreg_disable_regulator(struct twl_vreg_softc *sc, 428 struct twl_regulator_entry *regulator) 429 { 430 int err = 0; 431 uint8_t grp; 432 int xlocked; 433 434 TWL_VREG_ASSERT_LOCKED(sc); 435 436 xlocked = sx_xlocked(&sc->sc_sx); 437 if (!xlocked) 438 TWL_VREG_LOCK_UPGRADE(sc); 439 440 if (twl_is_4030(sc->sc_pdev)) { 441 442 /* Read the regulator CFG_GRP register */ 443 err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &grp); 444 if (err) 445 goto done; 446 447 /* On the TWL4030 we just need to remove the regulator from all the 448 * power groups. 449 */ 450 grp &= ~(TWL4030_P1_GRP | TWL4030_P2_GRP | TWL4030_P3_GRP); 451 err = twl_vreg_write_1(sc, regulator, TWL_VREG_GRP, grp); 452 453 } else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) { 454 455 /* On TWL6030 we need to make sure we disable power for all groups */ 456 if (twl_is_6030(sc->sc_pdev)) 457 grp = TWL6030_P1_GRP | TWL6030_P2_GRP | TWL6030_P3_GRP; 458 else 459 grp = 0x00; 460 461 /* Write the resource state to "OFF" */ 462 err = twl_vreg_write_1(sc, regulator, TWL_VREG_STATE, (grp << 5)); 463 } 464 465 done: 466 if (!xlocked) 467 TWL_VREG_LOCK_DOWNGRADE(sc); 468 469 return (err); 470 } 471 472 /** 473 * twl_vreg_enable_regulator - enables the voltage regulator 474 * @sc: the device soft context 475 * @regulator: pointer to the regulator device 476 * 477 * Enables the regulator which will enable the voltage out at the currently 478 * set voltage. Set the voltage before calling this function to avoid 479 * driving the voltage too high/low by mistake. 480 * 481 * LOCKING: 482 * On entry expects the TWL VREG lock to be held. Will upgrade the lock to 483 * exclusive if not already but, if so, it will be downgraded again before 484 * returning. 485 * 486 * RETURNS: 487 * Zero on success or a positive error code on failure. 488 */ 489 static int 490 twl_vreg_enable_regulator(struct twl_vreg_softc *sc, 491 struct twl_regulator_entry *regulator) 492 { 493 int err; 494 uint8_t grp; 495 int xlocked; 496 497 TWL_VREG_ASSERT_LOCKED(sc); 498 499 xlocked = sx_xlocked(&sc->sc_sx); 500 if (!xlocked) 501 TWL_VREG_LOCK_UPGRADE(sc); 502 503 504 err = twl_vreg_read_1(sc, regulator, TWL_VREG_GRP, &grp); 505 if (err) 506 goto done; 507 508 /* Enable the regulator by ensuring it's in the application power group 509 * and is in the "on" state. 510 */ 511 if (twl_is_4030(sc->sc_pdev)) { 512 513 /* On the TWL4030 we just need to ensure the regulator is in the right 514 * power domain, don't need to turn on explicitly like TWL6030. 515 */ 516 grp |= TWL4030_P1_GRP; 517 err = twl_vreg_write_1(sc, regulator, TWL_VREG_GRP, grp); 518 519 } else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) { 520 521 if (twl_is_6030(sc->sc_pdev) && !(grp & TWL6030_P1_GRP)) { 522 grp |= TWL6030_P1_GRP; 523 err = twl_vreg_write_1(sc, regulator, TWL_VREG_GRP, grp); 524 if (err) 525 goto done; 526 } 527 528 /* Write the resource state to "ON" */ 529 err = twl_vreg_write_1(sc, regulator, TWL_VREG_STATE, (grp << 5) | 0x01); 530 } 531 532 done: 533 if (!xlocked) 534 TWL_VREG_LOCK_DOWNGRADE(sc); 535 536 return (err); 537 } 538 539 /** 540 * twl_vreg_write_regulator_voltage - sets the voltage level on a regulator 541 * @sc: the device soft context 542 * @regulator: pointer to the regulator structure 543 * @millivolts: the voltage to set 544 * 545 * Sets the voltage output on a given regulator, if the regulator is not 546 * enabled, it will be enabled. 547 * 548 * LOCKING: 549 * On entry expects the TWL VREG lock to be held, may upgrade the lock to 550 * exclusive but if so it will be downgraded once again before returning. 551 * 552 * RETURNS: 553 * Zero on success or an error code on failure. 554 */ 555 static int 556 twl_vreg_write_regulator_voltage(struct twl_vreg_softc *sc, 557 struct twl_regulator_entry *regulator, int millivolts) 558 { 559 int err; 560 uint8_t vsel; 561 int xlocked; 562 563 TWL_VREG_ASSERT_LOCKED(sc); 564 565 /* If millivolts is zero then we simply disable the output */ 566 if (millivolts == 0) 567 return (twl_vreg_disable_regulator(sc, regulator)); 568 569 /* If the regulator has a fixed voltage then check the setting matches 570 * and simply enable. 571 */ 572 if (regulator->supp_voltages == NULL || regulator->num_supp_voltages == 0) { 573 if (millivolts != regulator->fixed_voltage) 574 return (EINVAL); 575 576 return (twl_vreg_enable_regulator(sc, regulator)); 577 } 578 579 /* Get the VSEL value for the given voltage */ 580 err = twl_vreg_millivolt_to_vsel(sc, regulator, millivolts, &vsel); 581 if (err) 582 return (err); 583 584 585 /* Need to upgrade because writing the voltage and enabling should be atomic */ 586 xlocked = sx_xlocked(&sc->sc_sx); 587 if (!xlocked) 588 TWL_VREG_LOCK_UPGRADE(sc); 589 590 591 /* Set voltage and enable (atomically) */ 592 err = twl_vreg_write_1(sc, regulator, TWL_VREG_VSEL, (vsel & 0x1f)); 593 if (!err) { 594 err = twl_vreg_enable_regulator(sc, regulator); 595 } 596 597 if (!xlocked) 598 TWL_VREG_LOCK_DOWNGRADE(sc); 599 600 if ((twl_vreg_debug > 1) && !err) 601 device_printf(sc->sc_dev, "%s : setting voltage to %dmV (vsel: 0x%x)\n", 602 regulator->name, millivolts, vsel); 603 604 return (err); 605 } 606 607 /** 608 * twl_vreg_read_regulator_voltage - reads the voltage on a given regulator 609 * @sc: the device soft context 610 * @regulator: pointer to the regulator structure 611 * @millivolts: upon return will contain the voltage on the regulator 612 * 613 * LOCKING: 614 * On entry expects the TWL VREG lock to be held. It will upgrade the lock to 615 * exclusive if not already, but if so, it will be downgraded again before 616 * returning. 617 * 618 * RETURNS: 619 * Zero on success, or otherwise an error code. 620 */ 621 static int 622 twl_vreg_read_regulator_voltage(struct twl_vreg_softc *sc, 623 struct twl_regulator_entry *regulator, int *millivolts) 624 { 625 int err; 626 int en = 0; 627 int xlocked; 628 uint8_t vsel; 629 630 TWL_VREG_ASSERT_LOCKED(sc); 631 632 /* Need to upgrade the lock because checking enabled state and voltage 633 * should be atomic. 634 */ 635 xlocked = sx_xlocked(&sc->sc_sx); 636 if (!xlocked) 637 TWL_VREG_LOCK_UPGRADE(sc); 638 639 640 /* Check if the regulator is currently enabled */ 641 err = twl_vreg_is_regulator_enabled(sc, regulator, &en); 642 if (err) 643 goto done; 644 645 *millivolts = 0; 646 if (!en) 647 goto done; 648 649 650 /* Not all voltages are adjustable */ 651 if (regulator->supp_voltages == NULL || !regulator->num_supp_voltages) { 652 *millivolts = regulator->fixed_voltage; 653 goto done; 654 } 655 656 /* For variable voltages read the voltage register */ 657 err = twl_vreg_read_1(sc, regulator, TWL_VREG_VSEL, &vsel); 658 if (err) 659 goto done; 660 661 vsel &= (regulator->num_supp_voltages - 1); 662 if (regulator->supp_voltages[vsel] == UNDF) { 663 err = EINVAL; 664 goto done; 665 } 666 667 *millivolts = regulator->supp_voltages[vsel]; 668 669 done: 670 if (!xlocked) 671 TWL_VREG_LOCK_DOWNGRADE(sc); 672 673 if ((twl_vreg_debug > 1) && !err) 674 device_printf(sc->sc_dev, "%s : reading voltage is %dmV (vsel: 0x%x)\n", 675 regulator->name, *millivolts, vsel); 676 677 return (err); 678 } 679 680 /** 681 * twl_vreg_get_voltage - public interface to read the voltage on a regulator 682 * @dev: TWL VREG device 683 * @name: the name of the regulator to read the voltage of 684 * @millivolts: pointer to an integer that upon return will contain the mV 685 * 686 * If the regulator is disabled the function will set the @millivolts to zero. 687 * 688 * LOCKING: 689 * Internally the function takes and releases the TWL VREG lock. 690 * 691 * RETURNS: 692 * Zero on success or a negative error code on failure. 693 */ 694 int 695 twl_vreg_get_voltage(device_t dev, const char *name, int *millivolts) 696 { 697 struct twl_vreg_softc *sc; 698 struct twl_regulator_entry *regulator; 699 int err = EINVAL; 700 701 if (millivolts == NULL) 702 return (EINVAL); 703 704 sc = device_get_softc(dev); 705 706 TWL_VREG_SLOCK(sc); 707 708 LIST_FOREACH(regulator, &sc->sc_vreg_list, entries) { 709 if (strcmp(regulator->name, name) == 0) { 710 err = twl_vreg_read_regulator_voltage(sc, regulator, millivolts); 711 break; 712 } 713 } 714 715 TWL_VREG_SUNLOCK(sc); 716 717 return (err); 718 } 719 720 /** 721 * twl_vreg_set_voltage - public interface to write the voltage on a regulator 722 * @dev: TWL VREG device 723 * @name: the name of the regulator to read the voltage of 724 * @millivolts: the voltage to set in millivolts 725 * 726 * Sets the output voltage on a given regulator. If the regulator is a fixed 727 * voltage reg then the @millivolts value should match the fixed voltage. If 728 * a variable regulator then the @millivolt value must fit within the max/min 729 * range of the given regulator. 730 * 731 * LOCKING: 732 * Internally the function takes and releases the TWL VREG lock. 733 * 734 * RETURNS: 735 * Zero on success or a negative error code on failure. 736 */ 737 int 738 twl_vreg_set_voltage(device_t dev, const char *name, int millivolts) 739 { 740 struct twl_vreg_softc *sc; 741 struct twl_regulator_entry *regulator; 742 int err = EINVAL; 743 744 sc = device_get_softc(dev); 745 746 TWL_VREG_SLOCK(sc); 747 748 LIST_FOREACH(regulator, &sc->sc_vreg_list, entries) { 749 if (strcmp(regulator->name, name) == 0) { 750 err = twl_vreg_write_regulator_voltage(sc, regulator, millivolts); 751 break; 752 } 753 } 754 755 TWL_VREG_SUNLOCK(sc); 756 757 return (err); 758 } 759 760 /** 761 * twl_sysctl_voltage - reads or writes the voltage for a regulator 762 * @SYSCTL_HANDLER_ARGS: arguments for the callback 763 * 764 * Callback for the sysctl entry for the regulator, simply used to return 765 * the voltage on a particular regulator. 766 * 767 * LOCKING: 768 * Takes the TWL_VREG shared lock internally. 769 * 770 * RETURNS: 771 * Zero on success or an error code on failure. 772 */ 773 static int 774 twl_vreg_sysctl_voltage(SYSCTL_HANDLER_ARGS) 775 { 776 struct twl_vreg_softc *sc = (struct twl_vreg_softc*)arg1; 777 struct twl_regulator_entry *regulator; 778 int voltage; 779 int found = 0; 780 781 TWL_VREG_SLOCK(sc); 782 783 /* Find the regulator with the matching name */ 784 LIST_FOREACH(regulator, &sc->sc_vreg_list, entries) { 785 if (strcmp(regulator->name, oidp->oid_name) == 0) { 786 found = 1; 787 break; 788 } 789 } 790 791 /* Sanity check that we found the regulator */ 792 if (!found) { 793 TWL_VREG_SUNLOCK(sc); 794 return (EINVAL); 795 } 796 797 twl_vreg_read_regulator_voltage(sc, regulator, &voltage); 798 799 TWL_VREG_SUNLOCK(sc); 800 801 return sysctl_handle_int(oidp, &voltage, 0, req); 802 } 803 804 /** 805 * twl_add_regulator - adds single voltage regulator sysctls for the device 806 * @sc: device soft context 807 * @name: the name of the regulator 808 * @nsub: the number of the subdevice 809 * @regbase: the base address of the voltage regulator registers 810 * @fixed_voltage: if a fixed voltage regulator this defines it's voltage 811 * @voltages: if a variable voltage regulator, an array of possible voltages 812 * @num_voltages: the number of entries @voltages 813 * 814 * Adds a voltage regulator to the device and also a sysctl interface for the 815 * regulator. 816 * 817 * LOCKING: 818 * The TWL_VEG exclusive lock must be held while this function is called. 819 * 820 * RETURNS: 821 * Pointer to the new regulator entry on success, otherwise on failure NULL. 822 */ 823 static struct twl_regulator_entry* 824 twl_vreg_add_regulator(struct twl_vreg_softc *sc, const char *name, 825 uint8_t nsub, uint8_t regbase, uint16_t fixed_voltage, 826 const uint16_t *voltages, uint32_t num_voltages) 827 { 828 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); 829 struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); 830 struct twl_regulator_entry *new; 831 832 new = malloc(sizeof(struct twl_regulator_entry), M_DEVBUF, M_NOWAIT | M_ZERO); 833 if (new == NULL) 834 return (NULL); 835 836 837 strncpy(new->name, name, TWL_VREG_MAX_NAMELEN); 838 new->name[TWL_VREG_MAX_NAMELEN - 1] = '\0'; 839 840 new->sub_dev = nsub; 841 new->reg_off = regbase; 842 843 new->fixed_voltage = fixed_voltage; 844 845 new->supp_voltages = voltages; 846 new->num_supp_voltages = num_voltages; 847 848 849 /* Add a sysctl entry for the voltage */ 850 new->oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, name, 851 CTLTYPE_INT | CTLFLAG_RD, sc, 0, 852 twl_vreg_sysctl_voltage, "I", "voltage regulator"); 853 854 /* Finally add the regulator to list of supported regulators */ 855 LIST_INSERT_HEAD(&sc->sc_vreg_list, new, entries); 856 857 return (new); 858 } 859 860 /** 861 * twl_vreg_add_regulators - adds any voltage regulators to the device 862 * @sc: device soft context 863 * @chip: the name of the chip used in the hints 864 * @regulators: the list of possible voltage regulators 865 * 866 * Loops over the list of regulators and matches up with the FDT values, 867 * adjusting the actual voltage based on the supplied values. 868 * 869 * LOCKING: 870 * The TWL_VEG exclusive lock must be held while this function is called. 871 * 872 * RETURNS: 873 * Always returns 0. 874 */ 875 static int 876 twl_vreg_add_regulators(struct twl_vreg_softc *sc, 877 const struct twl_regulator *regulators) 878 { 879 int err; 880 int millivolts; 881 const struct twl_regulator *walker; 882 struct twl_regulator_entry *entry; 883 phandle_t child; 884 char rnames[256]; 885 char *name, *voltage; 886 int len = 0, prop_len; 887 888 889 /* Add the regulators from the list */ 890 walker = ®ulators[0]; 891 while (walker->name != NULL) { 892 893 /* Add the regulator to the list */ 894 entry = twl_vreg_add_regulator(sc, walker->name, walker->subdev, 895 walker->regbase, walker->fixedvoltage, 896 walker->voltages, walker->num_voltages); 897 if (entry == NULL) 898 continue; 899 900 walker++; 901 } 902 903 904 /* Check if the FDT is telling us to set any voltages */ 905 child = ofw_bus_get_node(sc->sc_pdev); 906 if (child) { 907 908 prop_len = OF_getprop(child, "voltage-regulators", rnames, sizeof(rnames)); 909 while (len < prop_len) { 910 name = rnames + len; 911 len += strlen(name) + 1; 912 if ((len >= prop_len) || (name[0] == '\0')) 913 break; 914 915 voltage = rnames + len; 916 len += strlen(voltage) + 1; 917 if (voltage[0] == '\0') 918 break; 919 920 millivolts = strtoul(voltage, NULL, 0); 921 922 LIST_FOREACH(entry, &sc->sc_vreg_list, entries) { 923 if (strcmp(entry->name, name) == 0) { 924 twl_vreg_write_regulator_voltage(sc, entry, millivolts); 925 break; 926 } 927 } 928 } 929 } 930 931 932 if (twl_vreg_debug) { 933 LIST_FOREACH(entry, &sc->sc_vreg_list, entries) { 934 err = twl_vreg_read_regulator_voltage(sc, entry, &millivolts); 935 if (!err) 936 device_printf(sc->sc_dev, "%s : %d mV\n", entry->name, millivolts); 937 } 938 } 939 940 return (0); 941 } 942 943 /** 944 * twl_vreg_init - initialises the list of regulators 945 * @dev: the twl_vreg device 946 * 947 * This function is called as an intrhook once interrupts have been enabled, 948 * this is done so that the driver has the option to enable/disable or set 949 * the voltage level based on settings providied in the FDT. 950 * 951 * LOCKING: 952 * Takes the exclusive lock in the function. 953 */ 954 static void 955 twl_vreg_init(void *dev) 956 { 957 struct twl_vreg_softc *sc; 958 959 sc = device_get_softc((device_t)dev); 960 961 TWL_VREG_XLOCK(sc); 962 963 if (twl_is_4030(sc->sc_pdev)) 964 twl_vreg_add_regulators(sc, twl4030_regulators); 965 else if (twl_is_6030(sc->sc_pdev) || twl_is_6025(sc->sc_pdev)) 966 twl_vreg_add_regulators(sc, twl6030_regulators); 967 968 TWL_VREG_XUNLOCK(sc); 969 970 config_intrhook_disestablish(&sc->sc_init_hook); 971 } 972 973 static int 974 twl_vreg_probe(device_t dev) 975 { 976 if (twl_is_4030(device_get_parent(dev))) 977 device_set_desc(dev, "TI TWL4030 PMIC Voltage Regulators"); 978 else if (twl_is_6025(device_get_parent(dev)) || 979 twl_is_6030(device_get_parent(dev))) 980 device_set_desc(dev, "TI TWL6025/TWL6030 PMIC Voltage Regulators"); 981 else 982 return (ENXIO); 983 984 return (0); 985 } 986 987 static int 988 twl_vreg_attach(device_t dev) 989 { 990 struct twl_vreg_softc *sc; 991 992 sc = device_get_softc(dev); 993 sc->sc_dev = dev; 994 sc->sc_pdev = device_get_parent(dev); 995 996 TWL_VREG_LOCK_INIT(sc); 997 998 LIST_INIT(&sc->sc_vreg_list); 999 1000 /* We have to wait until interrupts are enabled. I2C read and write 1001 * only works if the interrupts are available. 1002 */ 1003 sc->sc_init_hook.ich_func = twl_vreg_init; 1004 sc->sc_init_hook.ich_arg = dev; 1005 1006 if (config_intrhook_establish(&sc->sc_init_hook) != 0) 1007 return (ENOMEM); 1008 1009 return (0); 1010 } 1011 1012 static int 1013 twl_vreg_detach(device_t dev) 1014 { 1015 struct twl_vreg_softc *sc; 1016 struct twl_regulator_entry *regulator; 1017 struct twl_regulator_entry *tmp; 1018 1019 sc = device_get_softc(dev); 1020 1021 /* Take the lock and free all the added regulators */ 1022 TWL_VREG_XLOCK(sc); 1023 1024 LIST_FOREACH_SAFE(regulator, &sc->sc_vreg_list, entries, tmp) { 1025 LIST_REMOVE(regulator, entries); 1026 sysctl_remove_oid(regulator->oid, 1, 0); 1027 free(regulator, M_DEVBUF); 1028 } 1029 1030 TWL_VREG_XUNLOCK(sc); 1031 1032 TWL_VREG_LOCK_DESTROY(sc); 1033 1034 return (0); 1035 } 1036 1037 static device_method_t twl_vreg_methods[] = { 1038 DEVMETHOD(device_probe, twl_vreg_probe), 1039 DEVMETHOD(device_attach, twl_vreg_attach), 1040 DEVMETHOD(device_detach, twl_vreg_detach), 1041 1042 {0, 0}, 1043 }; 1044 1045 static driver_t twl_vreg_driver = { 1046 "twl_vreg", 1047 twl_vreg_methods, 1048 sizeof(struct twl_vreg_softc), 1049 }; 1050 1051 static devclass_t twl_vreg_devclass; 1052 1053 DRIVER_MODULE(twl_vreg, twl, twl_vreg_driver, twl_vreg_devclass, 0, 0); 1054 MODULE_VERSION(twl_vreg, 1); 1055