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