From 59ee140e5bded65b281bf0fafb9f2a6d849fb3e3 Mon Sep 17 00:00:00 2001 From: Alex Frid Date: Sat, 19 Feb 2011 22:32:51 -0800 Subject: ARM: tegra: cardhu: Enable VDD_CPU external control Original-Change-Id: Ie2b9c7bb441c72c105ca3205bdd42a8dcd76d9ef Reviewed-on: http://git-master/r/20230 Reviewed-by: Hoang Pham Reviewed-by: Aleksandr Frid Tested-by: Aleksandr Frid Reviewed-by: Yu-Huan Hsu Change-Id: I9896c0568ee5103a2608cf4abcab36f592a83f21 --- arch/arm/mach-tegra/board-cardhu-power.c | 34 ++++---- drivers/regulator/tps6591x-regulator.c | 118 ++++++++++++++++++++++----- include/linux/regulator/tps6591x-regulator.h | 7 ++ 3 files changed, 122 insertions(+), 37 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-power.c b/arch/arm/mach-tegra/board-cardhu-power.c index 7aec78614bd1..2181c45a44c0 100644 --- a/arch/arm/mach-tegra/board-cardhu-power.c +++ b/arch/arm/mach-tegra/board-cardhu-power.c @@ -136,7 +136,7 @@ static struct regulator_consumer_supply tps6591x_ldo8_supply[] = { }; #define TPS_PDATA_INIT_SUPPLY(_id, _minmv, _maxmv, _supply_reg, _always_on, \ - _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply) \ + _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply, _ectrl) \ static struct tps6591x_regulator_platform_data pdata_##_id = \ { \ .regulator = { \ @@ -159,11 +159,12 @@ static struct regulator_consumer_supply tps6591x_ldo8_supply[] = { }, \ .init_uV = _init_uV * 1000, \ .init_enable = _init_enable, \ - .init_apply = _init_apply \ + .init_apply = _init_apply, \ + .ectrl = _ectrl \ } #define TPS_PDATA_INIT(_id, _minmv, _maxmv, _supply_reg, _always_on, \ - _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply) \ + _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply, _ectrl) \ static struct tps6591x_regulator_platform_data pdata_##_id = \ { \ .regulator = { \ @@ -185,24 +186,25 @@ static struct regulator_consumer_supply tps6591x_ldo8_supply[] = { }, \ .init_uV = _init_uV * 1000, \ .init_enable = _init_enable, \ - .init_apply = _init_apply \ + .init_apply = _init_apply, \ + .ectrl = _ectrl \ } -TPS_PDATA_INIT(vdd1, 600, 1500, 0, 1, 1, 0, -1, 0, 0); -TPS_PDATA_INIT(vdd2, 600, 1500, 0, 1, 1, 0, -1, 0, 0); -TPS_PDATA_INIT(vddctrl, 600, 1400, 0, 1, 1, 0, -1, 0, 0); -TPS_PDATA_INIT(vio, 1500, 3300, 0, 1, 1, 0, -1, 0, 0); +TPS_PDATA_INIT(vdd1, 600, 1500, 0, 1, 1, 0, -1, 0, 0, 0); +TPS_PDATA_INIT(vdd2, 600, 1500, 0, 1, 1, 0, -1, 0, 0, 0); +TPS_PDATA_INIT(vddctrl, 600, 1400, 0, 1, 1, 0, -1, 0, 0, EXT_CTRL_EN1); +TPS_PDATA_INIT(vio, 1500, 3300, 0, 1, 1, 0, -1, 0, 0, 0); -TPS_PDATA_INIT_SUPPLY(ldo1, 1000, 3300, VDD_2, 0, 0, 0, -1, 0, 0); -TPS_PDATA_INIT_SUPPLY(ldo2, 1000, 3300, VDD_2, 0, 0, 0, -1, 0, 0); +TPS_PDATA_INIT_SUPPLY(ldo1, 1000, 3300, VDD_2, 0, 0, 0, -1, 0, 0, 0); +TPS_PDATA_INIT_SUPPLY(ldo2, 1000, 3300, VDD_2, 0, 0, 0, -1, 0, 0, 0); -TPS_PDATA_INIT(ldo3, 1000, 3300, 0, 0, 0, 0, -1, 0, 0); -TPS_PDATA_INIT(ldo4, 1000, 3300, 0, 0, 0, 0, -1, 0, 0); -TPS_PDATA_INIT(ldo5, 1000, 3300, 0, 0, 0, 0, -1, 0, 0); +TPS_PDATA_INIT(ldo3, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0); +TPS_PDATA_INIT(ldo4, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0); +TPS_PDATA_INIT(ldo5, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0); -TPS_PDATA_INIT_SUPPLY(ldo6, 1000, 3300, VIO, 0, 0, 0, -1, 0, 0); -TPS_PDATA_INIT_SUPPLY(ldo7, 1000, 3300, VIO, 0, 0, 0, -1, 0, 0); -TPS_PDATA_INIT_SUPPLY(ldo8, 1000, 3300, VIO, 0, 0, 0, -1, 0, 0); +TPS_PDATA_INIT_SUPPLY(ldo6, 1000, 3300, VIO, 0, 0, 0, -1, 0, 0, 0); +TPS_PDATA_INIT_SUPPLY(ldo7, 1000, 3300, VIO, 0, 0, 0, -1, 0, 0, 0); +TPS_PDATA_INIT_SUPPLY(ldo8, 1000, 3300, VIO, 0, 0, 0, -1, 0, 0, 0); /* Currently tps6591x-rtc driver is not available need to enable once driver is ready */ /* static struct tps6591x_rtc_platform_data rtc_data = { diff --git a/drivers/regulator/tps6591x-regulator.c b/drivers/regulator/tps6591x-regulator.c index 6931d92ee27f..0ff61a375313 100755 --- a/drivers/regulator/tps6591x-regulator.c +++ b/drivers/regulator/tps6591x-regulator.c @@ -50,8 +50,14 @@ #define TPS6591X_LDO6_ADD 0x35 #define TPS6591X_LDO7_ADD 0x34 #define TPS6591X_LDO8_ADD 0x33 +#define TPS6591X_EN1_LDO_ADD 0x45 +#define TPS6591X_EN1_SMPS_ADD 0x46 +#define TPS6591X_EN2_LDO_ADD 0x47 +#define TPS6591X_EN2_SMPS_ADD 0x48 #define TPS6591X_INVALID_ADD 0xFF +#define EN1_EN2_OFFSET 2 + struct tps6591x_register_info { unsigned char addr; unsigned char nbits; @@ -71,6 +77,7 @@ struct tps6591x_regulator { struct tps6591x_register_info supply_reg; struct tps6591x_register_info op_reg; struct tps6591x_register_info sr_reg; + struct tps6591x_register_info en1_reg; int *voltages; }; @@ -80,6 +87,52 @@ static inline struct device *to_tps6591x_dev(struct regulator_dev *rdev) return rdev_get_dev(rdev)->parent->parent; } +static int __tps6591x_ext_control_set(struct device *parent, + struct tps6591x_regulator *ri, + enum tps6591x_ext_control ectrl) +{ + int ret; + uint8_t mask, reg_val, addr; + + /* For regulator that has separate operational and sleep register make + sure that operational is used and clear sleep register to turn + regulator off when external control is inactive */ + if (ri->supply_type == supply_type_sr_op_reg) { + ret = tps6591x_read(parent, ri->op_reg.addr, ®_val); + if (ret) + return ret; + + if (reg_val & 0x80) { /* boot has used sr - switch to op */ + ret = tps6591x_read(parent, ri->sr_reg.addr, ®_val); + if (ret) + return ret; + + mask = ((1 << ri->sr_reg.nbits) - 1) + << ri->sr_reg.shift_bits; + reg_val &= mask; + ret = tps6591x_write(parent, ri->op_reg.addr, reg_val); + if (ret) + return ret; + } + ret = tps6591x_write(parent, ri->sr_reg.addr, 0); + if (ret) + return ret; + } + + switch (ectrl) { + case EXT_CTRL_EN1: + addr = ri->en1_reg.addr; + break; + case EXT_CTRL_EN2: + addr = ri->en1_reg.addr + EN1_EN2_OFFSET; + break; + default: + return -EINVAL; + } + mask = ((1 << ri->en1_reg.nbits) - 1) << ri->en1_reg.shift_bits; + return tps6591x_update(parent, addr, mask, mask); +} + static int __tps6591x_vio_set_voltage(struct device *parent, struct tps6591x_regulator *ri, int min_uV, int max_uV) @@ -441,7 +494,7 @@ static int tps6591x_vdd_voltages[] = { #define TPS6591X_REGULATOR(_id, vdata, _ops, s_addr, s_nbits, s_shift, \ s_type, op_addr, op_nbits, op_shift, sr_addr, \ - sr_nbits, sr_shift) \ + sr_nbits, sr_shift, en1_addr, en1_shift) \ .desc = { \ .name = tps6591x_rails(_id), \ .ops = &tps6591x_regulator_##_ops, \ @@ -466,51 +519,63 @@ static int tps6591x_vdd_voltages[] = { .nbits = sr_nbits, \ .shift_bits = sr_shift, \ }, \ + .en1_reg = { \ + .addr = TPS6591X_##en1_addr##_ADD, \ + .nbits = 1, \ + .shift_bits = en1_shift, \ + }, \ .voltages = tps6591x_##vdata##_voltages, -#define TPS6591X_VIO(_id, vdata, s_addr, s_nbits, s_shift, s_type) \ +#define TPS6591X_VIO(_id, vdata, s_addr, s_nbits, s_shift, s_type, \ + en1_shift) \ { \ TPS6591X_REGULATOR(_id, vdata, vio_ops, s_addr, s_nbits, \ - s_shift, s_type, INVALID, 0, 0, INVALID, 0, 0) \ + s_shift, s_type, INVALID, 0, 0, INVALID, 0, 0, \ + EN1_SMPS, en1_shift) \ } -#define TPS6591X_LDO1(_id, vdata, s_addr, s_nbits, s_shift, s_type) \ +#define TPS6591X_LDO1(_id, vdata, s_addr, s_nbits, s_shift, s_type, \ + en1_shift) \ { \ TPS6591X_REGULATOR(_id, vdata, ldo1_ops, s_addr, s_nbits, \ - s_shift, s_type, INVALID, 0, 0, INVALID, 0, 0) \ + s_shift, s_type, INVALID, 0, 0, INVALID, 0, 0, \ + EN1_LDO, en1_shift) \ } -#define TPS6591X_LDO3(_id, vdata, s_addr, s_nbits, s_shift, s_type) \ +#define TPS6591X_LDO3(_id, vdata, s_addr, s_nbits, s_shift, s_type, \ + en1_shift) \ { \ TPS6591X_REGULATOR(_id, vdata, ldo3_ops, s_addr, s_nbits, \ - s_shift, s_type, INVALID, 0, 0, INVALID, 0, 0) \ + s_shift, s_type, INVALID, 0, 0, INVALID, 0, 0, \ + EN1_LDO, en1_shift) \ } #define TPS6591X_VDD(_id, vdata, s_addr, s_nbits, s_shift, s_type, \ op_addr, op_nbits, op_shift, sr_addr, sr_nbits, \ - sr_shift) \ + sr_shift, en1_shift) \ { \ TPS6591X_REGULATOR(_id, vdata, vdd_ops, s_addr, s_nbits, \ s_shift, s_type, op_addr, op_nbits, op_shift, \ - sr_addr, sr_nbits, sr_shift) \ + sr_addr, sr_nbits, sr_shift, EN1_SMPS, \ + en1_shift) \ } static struct tps6591x_regulator tps6591x_regulator[] = { - TPS6591X_VIO(VIO, vio, VIO, 2, 2, single_reg), - TPS6591X_LDO1(LDO_1, ldo124, LDO1, 6, 2, single_reg), - TPS6591X_LDO1(LDO_2, ldo124, LDO2, 6, 2, single_reg), - TPS6591X_LDO3(LDO_3, ldo35678, LDO3, 5, 2, single_reg), - TPS6591X_LDO1(LDO_4, ldo124, LDO4, 6, 2, single_reg), - TPS6591X_LDO3(LDO_5, ldo35678, LDO5, 5, 2, single_reg), - TPS6591X_LDO3(LDO_6, ldo35678, LDO6, 5, 2, single_reg), - TPS6591X_LDO3(LDO_7, ldo35678, LDO7, 5, 2, single_reg), - TPS6591X_LDO3(LDO_8, ldo35678, LDO8, 5, 2, single_reg), + TPS6591X_VIO(VIO, vio, VIO, 2, 2, single_reg, 0), + TPS6591X_LDO1(LDO_1, ldo124, LDO1, 6, 2, single_reg, 1), + TPS6591X_LDO1(LDO_2, ldo124, LDO2, 6, 2, single_reg, 2), + TPS6591X_LDO3(LDO_3, ldo35678, LDO3, 5, 2, single_reg, 7), + TPS6591X_LDO1(LDO_4, ldo124, LDO4, 6, 2, single_reg, 6), + TPS6591X_LDO3(LDO_5, ldo35678, LDO5, 5, 2, single_reg, 3), + TPS6591X_LDO3(LDO_6, ldo35678, LDO6, 5, 2, single_reg, 0), + TPS6591X_LDO3(LDO_7, ldo35678, LDO7, 5, 2, single_reg, 5), + TPS6591X_LDO3(LDO_8, ldo35678, LDO8, 5, 2, single_reg, 4), TPS6591X_VDD(VDD_1, vdd, VDD1, 2, 0, sr_op_reg, VDD1_OP, - 7, 0, VDD1_SR, 7, 0), + 7, 0, VDD1_SR, 7, 0, 1), TPS6591X_VDD(VDD_2, vdd, VDD2, 2, 0, sr_op_reg, VDD2_OP, - 7, 0, VDD2_SR, 7, 0), + 7, 0, VDD2_SR, 7, 0, 2), TPS6591X_VDD(VDDCTRL, vdd, VDDCTRL, 2, 0, sr_op_reg, - VDDCTRL_OP, 7, 0, VDDCTRL_SR, 7, 0), + VDDCTRL_OP, 7, 0, VDDCTRL_SR, 7, 0, 3), }; static inline int tps6591x_regulator_preinit(struct device *parent, @@ -519,6 +584,17 @@ static inline int tps6591x_regulator_preinit(struct device *parent, { int ret; + if (tps6591x_pdata->ectrl != EXT_CTRL_NONE) { + ret = __tps6591x_ext_control_set( + parent, ri, tps6591x_pdata->ectrl); + if (ret < 0) { + pr_err("Not able to configure external control %d" + " for rail %d err %d\n", tps6591x_pdata->ectrl, + ri->desc.id, ret); + return ret; + } + } + if (!tps6591x_pdata->init_apply) return 0; diff --git a/include/linux/regulator/tps6591x-regulator.h b/include/linux/regulator/tps6591x-regulator.h index ade9978b3cb6..970736bc5c31 100644 --- a/include/linux/regulator/tps6591x-regulator.h +++ b/include/linux/regulator/tps6591x-regulator.h @@ -26,6 +26,12 @@ #include +enum tps6591x_ext_control { + EXT_CTRL_NONE = 0x0, + EXT_CTRL_EN1, + EXT_CTRL_EN2 +}; + /* * struct tps6591x_regulator_platform_data - tps6591x regulator platform data. * @@ -40,6 +46,7 @@ struct tps6591x_regulator_platform_data { int init_uV; unsigned init_enable:1; unsigned init_apply:1; + enum tps6591x_ext_control ectrl; }; #endif /* __REGULATOR_TPS6591X_H */ -- cgit v1.2.3