summaryrefslogtreecommitdiff
path: root/drivers/regulator/tps6591x-regulator.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-02-19 22:32:51 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:43:11 -0800
commit0dcd9bffd87634f48535dcafd227d6ad1616f806 (patch)
treea1ce30f8e7ffcdf2a752a94bf1719363c1475e56 /drivers/regulator/tps6591x-regulator.c
parent933e339fc6259cb3b8460a75b59c32c351382f80 (diff)
ARM: tegra: cardhu: Enable VDD_CPU external control
Original-Change-Id: Ie2b9c7bb441c72c105ca3205bdd42a8dcd76d9ef Reviewed-on: http://git-master/r/20230 Reviewed-by: Hoang Pham <hopham@nvidia.com> Reviewed-by: Aleksandr Frid <afrid@nvidia.com> Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Original-Change-Id: I9896c0568ee5103a2608cf4abcab36f592a83f21 Rebase-Id: Rdc56b3cade05c916acceb73ff15097325680f881
Diffstat (limited to 'drivers/regulator/tps6591x-regulator.c')
-rwxr-xr-xdrivers/regulator/tps6591x-regulator.c118
1 files changed, 97 insertions, 21 deletions
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, &reg_val);
+ if (ret)
+ return ret;
+
+ if (reg_val & 0x80) { /* boot has used sr - switch to op */
+ ret = tps6591x_read(parent, ri->sr_reg.addr, &reg_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;