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