diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/Kconfig | 2 | ||||
-rw-r--r-- | drivers/regulator/twl-regulator.c | 116 |
2 files changed, 96 insertions, 22 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index bcbb161bde0..7cfdd65bebb 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -70,7 +70,7 @@ config REGULATOR_MAX1586 for PXA27x chips to control VCC_CORE and VCC_USIM voltages. config REGULATOR_TWL4030 - bool "TI TWL4030/TWL5030/TPS695x0 PMIC" + bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC" depends on TWL4030_CORE help This driver supports the voltage regulators provided by diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 8e1b68a20ef..7ea1c3a3108 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -52,27 +52,38 @@ struct twlreg_info { * The first three registers of all power resource banks help hardware to * manage the various resource groups. */ +/* Common offset in TWL4030/6030 */ #define VREG_GRP 0 +/* TWL4030 register offsets */ #define VREG_TYPE 1 #define VREG_REMAP 2 #define VREG_DEDICATED 3 /* LDO control */ - +/* TWL6030 register offsets */ +#define VREG_TRANS 1 +#define VREG_STATE 2 +#define VREG_VOLTAGE 3 +/* TWL6030 Misc register offsets */ +#define VREG_BC_ALL 1 +#define VREG_BC_REF 2 +#define VREG_BC_PROC 3 +#define VREG_BC_CLK_RST 4 static inline int -twlreg_read(struct twlreg_info *info, unsigned offset) +twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) { u8 value; int status; - status = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, + status = twl_i2c_read_u8(slave_subgp, &value, info->base + offset); return (status < 0) ? status : value; } static inline int -twlreg_write(struct twlreg_info *info, unsigned offset, u8 value) +twlreg_write(struct twlreg_info *info, unsigned slave_subgp, unsigned offset, + u8 value) { - return twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, + return twl_i2c_write_u8(slave_subgp, value, info->base + offset); } @@ -82,17 +93,22 @@ twlreg_write(struct twlreg_info *info, unsigned offset, u8 value) static int twlreg_grp(struct regulator_dev *rdev) { - return twlreg_read(rdev_get_drvdata(rdev), VREG_GRP); + return twlreg_read(rdev_get_drvdata(rdev), TWL_MODULE_PM_RECEIVER, + VREG_GRP); } /* * Enable/disable regulators by joining/leaving the P1 (processor) group. * We assume nobody else is updating the DEV_GRP registers. */ - -#define P3_GRP BIT(7) /* "peripherals" */ -#define P2_GRP BIT(6) /* secondary processor, modem, etc */ -#define P1_GRP BIT(5) /* CPU/Linux */ +/* definition for 4030 family */ +#define P3_GRP_4030 BIT(7) /* "peripherals" */ +#define P2_GRP_4030 BIT(6) /* secondary processor, modem, etc */ +#define P1_GRP_4030 BIT(5) /* CPU/Linux */ +/* definition for 6030 family */ +#define P3_GRP_6030 BIT(2) /* secondary processor, modem, etc */ +#define P2_GRP_6030 BIT(1) /* "peripherals" */ +#define P1_GRP_6030 BIT(0) /* CPU/Linux */ static int twlreg_is_enabled(struct regulator_dev *rdev) { @@ -101,7 +117,11 @@ static int twlreg_is_enabled(struct regulator_dev *rdev) if (state < 0) return state; - return (state & P1_GRP) != 0; + if (twl_class_is_4030()) + state &= P1_GRP_4030; + else + state &= P1_GRP_6030; + return state; } static int twlreg_enable(struct regulator_dev *rdev) @@ -109,12 +129,16 @@ static int twlreg_enable(struct regulator_dev *rdev) struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; - grp = twlreg_read(info, VREG_GRP); + grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; - grp |= P1_GRP; - return twlreg_write(info, VREG_GRP, grp); + if (twl_class_is_4030()) + grp |= P1_GRP_4030; + else + grp |= P1_GRP_6030; + + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); } static int twlreg_disable(struct regulator_dev *rdev) @@ -122,18 +146,25 @@ static int twlreg_disable(struct regulator_dev *rdev) struct twlreg_info *info = rdev_get_drvdata(rdev); int grp; - grp = twlreg_read(info, VREG_GRP); + grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); if (grp < 0) return grp; - grp &= ~P1_GRP; - return twlreg_write(info, VREG_GRP, grp); + if (twl_class_is_4030()) + grp &= ~P1_GRP_4030; + else + grp &= ~P1_GRP_6030; + + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp); } static int twlreg_get_status(struct regulator_dev *rdev) { int state = twlreg_grp(rdev); + if (twl_class_is_6030()) + return 0; /* FIXME return for 6030 regulator */ + if (state < 0) return state; state &= 0x0f; @@ -152,6 +183,9 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) unsigned message; int status; + if (twl_class_is_6030()) + return 0; /* FIXME return for 6030 regulator */ + /* We can only set the mode through state machine commands... */ switch (mode) { case REGULATOR_MODE_NORMAL: @@ -168,7 +202,7 @@ static int twlreg_set_mode(struct regulator_dev *rdev, unsigned mode) status = twlreg_grp(rdev); if (status < 0) return status; - if (!(status & (P3_GRP | P2_GRP | P1_GRP))) + if (!(status & (P3_GRP_4030 | P2_GRP_4030 | P1_GRP_4030))) return -EACCES; status = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, @@ -260,7 +294,29 @@ static const u16 VSIM_VSEL_table[] = { static const u16 VDAC_VSEL_table[] = { 1200, 1300, 1800, 1800, }; - +static const u16 VAUX1_6030_VSEL_table[] = { + 1000, 1300, 1800, 2500, + 2800, 2900, 3000, 3000, +}; +static const u16 VAUX2_6030_VSEL_table[] = { + 1200, 1800, 2500, 2750, + 2800, 2800, 2800, 2800, +}; +static const u16 VAUX3_6030_VSEL_table[] = { + 1000, 1200, 1300, 1800, + 2500, 2800, 3000, 3000, +}; +static const u16 VMMC_VSEL_table[] = { + 1200, 1800, 2800, 2900, + 3000, 3000, 3000, 3000, +}; +static const u16 VPP_VSEL_table[] = { + 1800, 1900, 2000, 2100, + 2200, 2300, 2400, 2500, +}; +static const u16 VUSIM_VSEL_table[] = { + 1200, 1800, 2500, 2900, +}; static int twlldo_list_voltage(struct regulator_dev *rdev, unsigned index) { @@ -288,7 +344,8 @@ twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) /* use the first in-range value */ if (min_uV <= uV && uV <= max_uV) - return twlreg_write(info, VREG_DEDICATED, vsel); + return twlreg_write(info, TWL_MODULE_PM_RECEIVER, + VREG_VOLTAGE, vsel); } return -EDOM; @@ -297,7 +354,8 @@ twlldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) static int twlldo_get_voltage(struct regulator_dev *rdev) { struct twlreg_info *info = rdev_get_drvdata(rdev); - int vsel = twlreg_read(info, VREG_DEDICATED); + int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, + VREG_VOLTAGE); if (vsel < 0) return vsel; @@ -360,6 +418,10 @@ static struct regulator_ops twlfixed_ops = { TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030) #define TWL4030_FIXED_LDO(label, offset, mVolts, num) \ TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030) +#define TWL6030_ADJUSTABLE_LDO(label, offset, num) \ + TWL_ADJUSTABLE_LDO(label, offset, num, TWL6030) +#define TWL6030_FIXED_LDO(label, offset, mVolts, num) \ + TWL_FIXED_LDO(label, offset, mVolts, num, TWL6030) #define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \ .base = offset, \ @@ -420,6 +482,18 @@ static struct twlreg_info twl_regs[] = { TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), /* VUSBCP is managed *only* by the USB subchip */ + + /* 6030 REG with base as PMC Slave Misc : 0x0030 */ + TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1), + TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2), + TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3), + TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4), + TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5), + TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7), + TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15), + TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16), + TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17), + TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18) }; static int twlreg_probe(struct platform_device *pdev) |