diff options
| -rw-r--r-- | drivers/regulator/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/regulator/twl-regulator.c | 116 | ||||
| -rw-r--r-- | include/linux/i2c/twl.h | 34 |
3 files changed, 130 insertions, 22 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index bcbb161bde0b..7cfdd65bebb4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
| @@ -70,7 +70,7 @@ config REGULATOR_MAX1586 | |||
| 70 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. | 70 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. |
| 71 | 71 | ||
| 72 | config REGULATOR_TWL4030 | 72 | config REGULATOR_TWL4030 |
| 73 | bool "TI TWL4030/TWL5030/TPS695x0 PMIC" | 73 | bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" |
| 74 | depends on TWL4030_CORE | 74 | depends on TWL4030_CORE |
| 75 | help | 75 | help |
| 76 | This driver supports the voltage regulators provided by | 76 | This driver supports the voltage regulators provided by |
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 8e1b68a20ef0..7ea1c3a31081 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c | |||
| @@ -52,27 +52,38 @@ struct twlreg_info { | |||
| 52 | * The first three registers of all power resource banks help hardware to | 52 | * The first three registers of all power resource banks help hardware to |
| 53 | * manage the various resource groups. | 53 | * manage the various resource groups. |
| 54 | */ | 54 | */ |
| 55 | /* Common offset in TWL4030/6030 */ | ||
| 55 | #define VREG_GRP 0 | 56 | #define VREG_GRP 0 |
| 57 | /* TWL4030 register offsets */ | ||
| 56 | #define VREG_TYPE 1 | 58 | #define VREG_TYPE 1 |
| 57 | #define VREG_REMAP 2 | 59 | #define VREG_REMAP 2 |
| 58 | #define VREG_DEDICATED 3 /* LDO control */ | 60 | #define VREG_DEDICATED 3 /* LDO control */ |
| 59 | 61 | /* TWL6030 register offsets */ | |
| 62 | #define VREG_TRANS 1 | ||
| 63 | #define VREG_STATE 2 | ||
| 64 | #define VREG_VOLTAGE 3 | ||
| 65 | /* TWL6030 Misc register offsets */ | ||
| 66 | #define VREG_BC_ALL 1 | ||
| 67 | #define VREG_BC_REF 2 | ||
| 68 | #define VREG_BC_PROC 3 | ||
| 69 | #define VREG_BC_CLK_RST 4 | ||
| 60 | 70 | ||
| 61 | static inline int | 71 | static inline int |
| 62 | twlreg_read(struct twlreg_info *info, unsigned offset) | 72 | twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) |
| 63 | { | 73 | { |
| 64 | u8 value; | 74 | u8 value; |
| 65 | int status; | 75 | int status; |
| 66 | 76 | ||
| 67 | status = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, | 77 | status = twl_i2c_read_u8(slave_subgp, |
| 68 | &value, info->base + offset); | 78 | &value, info->base + offset); |
| 69 | return (status < 0) ? status : value; | 79 | return (status < 0) ? status : value; |
| 70 | } | 80 | } |
| 71 | 81 | ||
| 72 | static inline int | 82 | static inline int |
| 73 | twlreg_write(struct twlreg_info *info, unsigned offset, u8 value) | 83 | twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset, |
| 84 | u8 value) | ||
| 74 | { | 85 | { |
| 75 | return twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, | 86 | return twl_i2c_write_u8(slave_subgp, |
| 76 | value, info->base + offset); | 87 | value, info->base + offset); |
| 77 | } | 88 | } |
| 78 | 89 | ||
| @@ -82,17 +93,22 @@ twlreg_write(struct twlreg_info *info, unsigned offset, u8 value) | |||
| 82 | 93 | ||
| 83 | static int twlreg_grp(struct regulator_dev *rdev) | 94 | static int twlreg_grp(struct regulator_dev *rdev) |
| 84 | { | 95 | { |
| 85 | return twlreg_read(rdev_get_drvdata(rdev), VREG_GRP); | 96 | return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_RECEIVER, |
| 97 | VREG_GRP); | ||
| 86 | } | 98 | } |
| 87 | 99 | ||
| 88 | /* | 100 | /* |
| 89 | * Enable/disable regulators by joining/leaving the P1 (processor) group. | 101 | * Enable/disable regulators by joining/leaving the P1 (processor) group. |
| 90 | * We assume nobody else is updating the DEV_GRP registers. | 102 | * We assume nobody else is updating the DEV_GRP registers. |
| 91 | */ | 103 | */ |
| 92 | 104 | /* definition for 4030 family */ | |
| 93 | #define P3_GRP BIT(7) /* "peripherals" */ | 105 | #define P3_GRP_4030 BIT(7) /* "peripherals" */ |
| 94 | #define P2_GRP BIT(6) /* secondary processor, modem, etc */ | 106 | #define P2_GRP_4030 BIT(6) /* secondary processor, modem, etc */ |
| 95 | #define P1_GRP BIT(5) /* CPU/Linux */ | 107 | #define P1_GRP_4030 BIT(5) /* CPU/Linux */ |
| 108 | /* definition for 6030 family */ | ||
| 109 | #define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */ | ||
| 110 | #define P2_GRP_6030 BIT(1) /* "peripherals" */ | ||
| 111 | #define P1_GRP_6030 BIT(0) /* CPU/Linux */ | ||
| 96 | 112 | ||
| 97 | static int twlreg_is_enabled(struct regulator_dev *rdev) | 113 | static int twlreg_is_enabled(struct regulator_dev *rdev) |
| 98 | { | 114 | { |
| @@ -101,7 +117,11 @@ static int twlreg_is_enabled(struct regulator_dev *rdev) | |||
| 101 | if (state < 0) | 117 | if (state < 0) |
| 102 | return state; | 118 | return state; |
| 103 | 119 | ||
| 104 | return (state & P1_GRP) != 0; | 120 | if (twl_class_is_4030()) |
| 121 | state &= P1_GRP_4030; | ||
| 122 | else | ||
| 123 | state &= P1_GRP_6030; | ||
| 124 | return state; | ||
| 105 | } | 125 | } |
| 106 | 126 | ||
| 107 | static int twlreg_enable(struct regulator_dev *rdev) | 127 | static int twlreg_enable(struct regulator_dev *rdev) |
| @@ -109,12 +129,16 @@ static int twlreg_enable(struct regulator_dev *rdev) | |||
| 109 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 129 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
| 110 | int grp; | 130 | int grp; |
| 111 | 131 | ||
| 112 | grp = twlreg_read(info, VREG_GRP); | 132 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); |
| 113 | if (grp < 0) | 133 | if (grp < 0) |
| 114 | return grp; | 134 | return grp; |
| 115 | 135 | ||
| 116 | grp |= P1_GRP; | 136 | if (twl_class_is_4030()) |
| 117 | return twlreg_write(info, VREG_GRP, grp); | 137 | grp |= P1_GRP_4030; |
| 138 | else | ||
| 139 | grp |= P1_GRP_6030; | ||
| 140 | |||
| 141 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | ||
| 118 | } | 142 | } |
| 119 | 143 | ||
| 120 | static int twlreg_disable(struct regulator_dev *rdev) | 144 | static int twlreg_disable(struct regulator_dev *rdev) |
| @@ -122,18 +146,25 @@ static int twlreg_disable(struct regulator_dev *rdev) | |||
| 122 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 146 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
| 123 | int grp; | 147 | int grp; |
| 124 | 148 | ||
| 125 | grp = twlreg_read(info, VREG_GRP); | 149 | grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); |
| 126 | if (grp < 0) | 150 | if (grp < 0) |
| 127 | return grp; | 151 | return grp; |
| 128 | 152 | ||
| 129 | grp &= ~P1_GRP; | 153 | if (twl_class_is_4030()) |
| 130 | return twlreg_write(info, VREG_GRP, grp); | 154 | grp &= ~P1_GRP_4030; |
| 155 | else | ||
| 156 | grp &= ~P1_GRP_6030; | ||
| 157 | |||
| 158 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); | ||
| 131 | } | 159 | } |
| 132 | 160 | ||
| 133 | static int twlreg_get_status(struct regulator_dev *rdev) | 161 | static int twlreg_get_status(struct regulator_dev *rdev) |
| 134 | { | 162 | { |
| 135 | int state = twlreg_grp(rdev); | 163 | int state = twlreg_grp(rdev); |
| 136 | 164 | ||
| 165 | if (twl_class_is_6030()) | ||
| 166 | return 0; /* FIXME return for 6030 regulator */ | ||
| 167 | |||
| 137 | if (state < 0) | 168 | if (state < 0) |
| 138 | return state; | 169 | return state; |
| 139 | state &= 0x0f; | 170 | state &= 0x0f; |
| @@ -152,6 +183,9 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) | |||
| 152 | unsigned message; | 183 | unsigned message; |
| 153 | int status; | 184 | int status; |
| 154 | 185 | ||
| 186 | if (twl_class_is_6030()) | ||
| 187 | return 0; /* FIXME return for 6030 regulator */ | ||
| 188 | |||
| 155 | /* We can only set the mode through state machine commands... */ | 189 | /* We can only set the mode through state machine commands... */ |
| 156 | switch (mode) { | 190 | switch (mode) { |
| 157 | case REGULATOR_MODE_NORMAL: | 191 | case REGULATOR_MODE_NORMAL: |
| @@ -168,7 +202,7 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) | |||
| 168 | status = twlreg_grp(rdev); | 202 | status = twlreg_grp(rdev); |
| 169 | if (status < 0) | 203 | if (status < 0) |
| 170 | return status; | 204 | return status; |
| 171 | if (!(status & (P3_GRP | P2_GRP | P1_GRP))) | 205 | if (!(status & (P3_GRP_4030 | P2_GRP_4030 | P1_GRP_4030))) |
| 172 | return -EACCES; | 206 | return -EACCES; |
| 173 | 207 | ||
| 174 | status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, | 208 | status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, |
| @@ -260,7 +294,29 @@ static const u16 VSIM_VSEL_table[] = { | |||
| 260 | static const u16 VDAC_VSEL_table[] = { | 294 | static const u16 VDAC_VSEL_table[] = { |
| 261 | 1200, 1300, 1800, 1800, | 295 | 1200, 1300, 1800, 1800, |
| 262 | }; | 296 | }; |
| 263 | 297 | static const u16 VAUX1_6030_VSEL_table[] = { | |
| 298 | 1000, 1300, 1800, 2500, | ||
| 299 | 2800, 2900, 3000, 3000, | ||
| 300 | }; | ||
| 301 | static const u16 VAUX2_6030_VSEL_table[] = { | ||
| 302 | 1200, 1800, 2500, 2750, | ||
| 303 | 2800, 2800, 2800, 2800, | ||
| 304 | }; | ||
| 305 | static const u16 VAUX3_6030_VSEL_table[] = { | ||
| 306 | 1000, 1200, 1300, 1800, | ||
| 307 | 2500, 2800, 3000, 3000, | ||
| 308 | }; | ||
| 309 | static const u16 VMMC_VSEL_table[] = { | ||
| 310 | 1200, 1800, 2800, 2900, | ||
| 311 | 3000, 3000, 3000, 3000, | ||
| 312 | }; | ||
| 313 | static const u16 VPP_VSEL_table[] = { | ||
| 314 | 1800, 1900, 2000, 2100, | ||
| 315 | 2200, 2300, 2400, 2500, | ||
| 316 | }; | ||
| 317 | static const u16 VUSIM_VSEL_table[] = { | ||
| 318 | 1200, 1800, 2500, 2900, | ||
| 319 | }; | ||
| 264 | 320 | ||
| 265 | static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index) | 321 | static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index) |
| 266 | { | 322 | { |
| @@ -288,7 +344,8 @@ twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
| 288 | 344 | ||
| 289 | /* use the first in-range value */ | 345 | /* use the first in-range value */ |
| 290 | if (min_uV <= uV && uV <= max_uV) | 346 | if (min_uV <= uV && uV <= max_uV) |
| 291 | return twlreg_write(info, VREG_DEDICATED, vsel); | 347 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, |
| 348 | VREG_VOLTAGE, vsel); | ||
| 292 | } | 349 | } |
| 293 | 350 | ||
| 294 | return -EDOM; | 351 | return -EDOM; |
| @@ -297,7 +354,8 @@ twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
| 297 | static int twlldo_get_voltage(struct regulator_dev *rdev) | 354 | static int twlldo_get_voltage(struct regulator_dev *rdev) |
| 298 | { | 355 | { |
| 299 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 356 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
| 300 | int vsel = twlreg_read(info, VREG_DEDICATED); | 357 | int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, |
| 358 | VREG_VOLTAGE); | ||
| 301 | 359 | ||
| 302 | if (vsel < 0) | 360 | if (vsel < 0) |
| 303 | return vsel; | 361 | return vsel; |
| @@ -360,6 +418,10 @@ static struct regulator_ops twlfixed_ops = { | |||
| 360 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030) | 418 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030) |
| 361 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num) \ | 419 | #define TWL4030_FIXED_LDO(label, offset, mVolts, num) \ |
| 362 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030) | 420 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030) |
| 421 | #define TWL6030_ADJUSTABLE_LDO(label, offset, num) \ | ||
| 422 | TWL_ADJUSTABLE_LDO(label, offset, num, TWL6030) | ||
| 423 | #define TWL6030_FIXED_LDO(label, offset, mVolts, num) \ | ||
| 424 | TWL_FIXED_LDO(label, offset, mVolts, num, TWL6030) | ||
| 363 | 425 | ||
| 364 | #define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \ | 426 | #define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \ |
| 365 | .base = offset, \ | 427 | .base = offset, \ |
| @@ -420,6 +482,18 @@ static struct twlreg_info twl_regs[] = { | |||
| 420 | TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), | 482 | TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), |
| 421 | TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), | 483 | TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), |
| 422 | /* VUSBCP is managed *only* by the USB subchip */ | 484 | /* VUSBCP is managed *only* by the USB subchip */ |
| 485 | |||
| 486 | /* 6030 REG with base as PMC Slave Misc : 0x0030 */ | ||
| 487 | TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1), | ||
| 488 | TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2), | ||
| 489 | TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3), | ||
| 490 | TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4), | ||
| 491 | TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5), | ||
| 492 | TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7), | ||
| 493 | TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15), | ||
| 494 | TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16), | ||
| 495 | TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17), | ||
| 496 | TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18) | ||
| 423 | }; | 497 | }; |
| 424 | 498 | ||
| 425 | static int twlreg_probe(struct platform_device *pdev) | 499 | static int twlreg_probe(struct platform_device *pdev) |
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 8e7405d9c624..7679e87df177 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h | |||
| @@ -427,6 +427,12 @@ int twl6030_interrupt_mask(u8 bit_mask, u8 offset); | |||
| 427 | #define MSG_SINGULAR(devgrp, id, state) \ | 427 | #define MSG_SINGULAR(devgrp, id, state) \ |
| 428 | ((devgrp) << 13 | 0 << 12 | (id) << 4 | (state)) | 428 | ((devgrp) << 13 | 0 << 12 | (id) << 4 | (state)) |
| 429 | 429 | ||
| 430 | #define MSG_BROADCAST_ALL(devgrp, state) \ | ||
| 431 | ((devgrp) << 5 | (state)) | ||
| 432 | |||
| 433 | #define MSG_BROADCAST_REF MSG_BROADCAST_ALL | ||
| 434 | #define MSG_BROADCAST_PROV MSG_BROADCAST_ALL | ||
| 435 | #define MSG_BROADCAST__CLK_RST MSG_BROADCAST_ALL | ||
| 430 | /*----------------------------------------------------------------------*/ | 436 | /*----------------------------------------------------------------------*/ |
| 431 | 437 | ||
| 432 | struct twl4030_clock_init_data { | 438 | struct twl4030_clock_init_data { |
| @@ -602,6 +608,7 @@ int twl4030_sih_setup(int module); | |||
| 602 | * VIO is generally fixed. | 608 | * VIO is generally fixed. |
| 603 | */ | 609 | */ |
| 604 | 610 | ||
| 611 | /* TWL4030 SMPS/LDO's */ | ||
| 605 | /* EXTERNAL dc-to-dc buck converters */ | 612 | /* EXTERNAL dc-to-dc buck converters */ |
| 606 | #define TWL4030_REG_VDD1 0 | 613 | #define TWL4030_REG_VDD1 0 |
| 607 | #define TWL4030_REG_VDD2 1 | 614 | #define TWL4030_REG_VDD2 1 |
| @@ -628,4 +635,31 @@ int twl4030_sih_setup(int module); | |||
| 628 | #define TWL4030_REG_VUSB1V8 18 | 635 | #define TWL4030_REG_VUSB1V8 18 |
| 629 | #define TWL4030_REG_VUSB3V1 19 | 636 | #define TWL4030_REG_VUSB3V1 19 |
| 630 | 637 | ||
| 638 | /* TWL6030 SMPS/LDO's */ | ||
| 639 | /* EXTERNAL dc-to-dc buck convertor contollable via SR */ | ||
| 640 | #define TWL6030_REG_VDD1 30 | ||
| 641 | #define TWL6030_REG_VDD2 31 | ||
| 642 | #define TWL6030_REG_VDD3 32 | ||
| 643 | |||
| 644 | /* Non SR compliant dc-to-dc buck convertors */ | ||
| 645 | #define TWL6030_REG_VMEM 33 | ||
| 646 | #define TWL6030_REG_V2V1 34 | ||
| 647 | #define TWL6030_REG_V1V29 35 | ||
| 648 | #define TWL6030_REG_V1V8 36 | ||
| 649 | |||
| 650 | /* EXTERNAL LDOs */ | ||
| 651 | #define TWL6030_REG_VAUX1_6030 37 | ||
| 652 | #define TWL6030_REG_VAUX2_6030 38 | ||
| 653 | #define TWL6030_REG_VAUX3_6030 39 | ||
| 654 | #define TWL6030_REG_VMMC 40 | ||
| 655 | #define TWL6030_REG_VPP 41 | ||
| 656 | #define TWL6030_REG_VUSIM 42 | ||
| 657 | #define TWL6030_REG_VANA 43 | ||
| 658 | #define TWL6030_REG_VCXIO 44 | ||
| 659 | #define TWL6030_REG_VDAC 45 | ||
| 660 | #define TWL6030_REG_VUSB 46 | ||
| 661 | |||
| 662 | /* INTERNAL LDOs */ | ||
| 663 | #define TWL6030_REG_VRTC 47 | ||
| 664 | |||
| 631 | #endif /* End of __TWL4030_H */ | 665 | #endif /* End of __TWL4030_H */ |
