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/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 static const uint16_t twl4030_vdd1_voltages[] = { 142 800, 1450 143 }; 144 static const uint16_t twl4030_vdd2_voltages[] = { 145 800, 1450, 1500 146 }; 147 static const uint16_t twl4030_vio_voltages[] = { 148 1800, 1850 149 }; 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