aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/tps65910-regulator.c
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-01-28 04:37:57 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-30 08:31:01 -0500
commit1e0c66f49762fa1866ab20b1feb6e86a9aa4838f (patch)
tree9828db399f8826e4a2c7329f5179c2d5bddee255 /drivers/regulator/tps65910-regulator.c
parent2343933921efd553dea888fc844abb653824c4c8 (diff)
regulator: tps65910: Sleep control through external inputs
Add support for sleep controls of different regulator through external inputs EN1, EN2 or EN3. Each regulator's output will be active when its external input is high and turns to OFF/Low power mode when its external input is low. The configuration parameters for sleep control is provided through board specific platform data. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator/tps65910-regulator.c')
-rw-r--r--drivers/regulator/tps65910-regulator.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index 1d13cf997afb..9092b7f998c1 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -26,6 +26,9 @@
26#include <linux/mfd/tps65910.h> 26#include <linux/mfd/tps65910.h>
27 27
28#define TPS65910_SUPPLY_STATE_ENABLED 0x1 28#define TPS65910_SUPPLY_STATE_ENABLED 0x1
29#define EXT_SLEEP_CONTROL (TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1 | \
30 TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2 | \
31 TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3)
29 32
30/* supported VIO voltages in milivolts */ 33/* supported VIO voltages in milivolts */
31static const u16 VIO_VSEL_table[] = { 34static const u16 VIO_VSEL_table[] = {
@@ -252,6 +255,39 @@ static struct tps_info tps65911_regs[] = {
252 }, 255 },
253}; 256};
254 257
258#define EXT_CONTROL_REG_BITS(id, regs_offs, bits) (((regs_offs) << 8) | (bits))
259static unsigned int tps65910_ext_sleep_control[] = {
260 0,
261 EXT_CONTROL_REG_BITS(VIO, 1, 0),
262 EXT_CONTROL_REG_BITS(VDD1, 1, 1),
263 EXT_CONTROL_REG_BITS(VDD2, 1, 2),
264 EXT_CONTROL_REG_BITS(VDD3, 1, 3),
265 EXT_CONTROL_REG_BITS(VDIG1, 0, 1),
266 EXT_CONTROL_REG_BITS(VDIG2, 0, 2),
267 EXT_CONTROL_REG_BITS(VPLL, 0, 6),
268 EXT_CONTROL_REG_BITS(VDAC, 0, 7),
269 EXT_CONTROL_REG_BITS(VAUX1, 0, 3),
270 EXT_CONTROL_REG_BITS(VAUX2, 0, 4),
271 EXT_CONTROL_REG_BITS(VAUX33, 0, 5),
272 EXT_CONTROL_REG_BITS(VMMC, 0, 0),
273};
274
275static unsigned int tps65911_ext_sleep_control[] = {
276 0,
277 EXT_CONTROL_REG_BITS(VIO, 1, 0),
278 EXT_CONTROL_REG_BITS(VDD1, 1, 1),
279 EXT_CONTROL_REG_BITS(VDD2, 1, 2),
280 EXT_CONTROL_REG_BITS(VDDCTRL, 1, 3),
281 EXT_CONTROL_REG_BITS(LDO1, 0, 1),
282 EXT_CONTROL_REG_BITS(LDO2, 0, 2),
283 EXT_CONTROL_REG_BITS(LDO3, 0, 7),
284 EXT_CONTROL_REG_BITS(LDO4, 0, 6),
285 EXT_CONTROL_REG_BITS(LDO5, 0, 3),
286 EXT_CONTROL_REG_BITS(LDO6, 0, 0),
287 EXT_CONTROL_REG_BITS(LDO7, 0, 5),
288 EXT_CONTROL_REG_BITS(LDO8, 0, 4),
289};
290
255struct tps65910_reg { 291struct tps65910_reg {
256 struct regulator_desc *desc; 292 struct regulator_desc *desc;
257 struct tps65910 *mfd; 293 struct tps65910 *mfd;
@@ -261,6 +297,8 @@ struct tps65910_reg {
261 int num_regulators; 297 int num_regulators;
262 int mode; 298 int mode;
263 int (*get_ctrl_reg)(int); 299 int (*get_ctrl_reg)(int);
300 unsigned int *ext_sleep_control;
301 unsigned int board_ext_control[TPS65910_NUM_REGS];
264}; 302};
265 303
266static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg) 304static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg)
@@ -861,6 +899,131 @@ static struct regulator_ops tps65911_ops = {
861 .list_voltage = tps65911_list_voltage, 899 .list_voltage = tps65911_list_voltage,
862}; 900};
863 901
902static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
903 int id, int ext_sleep_config)
904{
905 struct tps65910 *mfd = pmic->mfd;
906 u8 regoffs = (pmic->ext_sleep_control[id] >> 8) & 0xFF;
907 u8 bit_pos = (1 << pmic->ext_sleep_control[id] & 0xFF);
908 int ret;
909
910 /*
911 * Regulator can not be control from multiple external input EN1, EN2
912 * and EN3 together.
913 */
914 if (ext_sleep_config & EXT_SLEEP_CONTROL) {
915 int en_count;
916 en_count = ((ext_sleep_config &
917 TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1) != 0);
918 en_count += ((ext_sleep_config &
919 TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2) != 0);
920 en_count += ((ext_sleep_config &
921 TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3) != 0);
922 if (en_count > 1) {
923 dev_err(mfd->dev,
924 "External sleep control flag is not proper\n");
925 return -EINVAL;
926 }
927 }
928
929 pmic->board_ext_control[id] = ext_sleep_config;
930
931 /* External EN1 control */
932 if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1)
933 ret = tps65910_set_bits(mfd,
934 TPS65910_EN1_LDO_ASS + regoffs, bit_pos);
935 else
936 ret = tps65910_clear_bits(mfd,
937 TPS65910_EN1_LDO_ASS + regoffs, bit_pos);
938 if (ret < 0) {
939 dev_err(mfd->dev,
940 "Error in configuring external control EN1\n");
941 return ret;
942 }
943
944 /* External EN2 control */
945 if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2)
946 ret = tps65910_set_bits(mfd,
947 TPS65910_EN2_LDO_ASS + regoffs, bit_pos);
948 else
949 ret = tps65910_clear_bits(mfd,
950 TPS65910_EN2_LDO_ASS + regoffs, bit_pos);
951 if (ret < 0) {
952 dev_err(mfd->dev,
953 "Error in configuring external control EN2\n");
954 return ret;
955 }
956
957 /* External EN3 control for TPS65910 LDO only */
958 if ((tps65910_chip_id(mfd) == TPS65910) &&
959 (id >= TPS65910_REG_VDIG1)) {
960 if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3)
961 ret = tps65910_set_bits(mfd,
962 TPS65910_EN3_LDO_ASS + regoffs, bit_pos);
963 else
964 ret = tps65910_clear_bits(mfd,
965 TPS65910_EN3_LDO_ASS + regoffs, bit_pos);
966 if (ret < 0) {
967 dev_err(mfd->dev,
968 "Error in configuring external control EN3\n");
969 return ret;
970 }
971 }
972
973 /* Return if no external control is selected */
974 if (!(ext_sleep_config & EXT_SLEEP_CONTROL)) {
975 /* Clear all sleep controls */
976 ret = tps65910_clear_bits(mfd,
977 TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos);
978 if (!ret)
979 ret = tps65910_clear_bits(mfd,
980 TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
981 if (ret < 0)
982 dev_err(mfd->dev,
983 "Error in configuring SLEEP register\n");
984 return ret;
985 }
986
987 /*
988 * For regulator that has separate operational and sleep register make
989 * sure that operational is used and clear sleep register to turn
990 * regulator off when external control is inactive
991 */
992 if ((id == TPS65910_REG_VDD1) ||
993 (id == TPS65910_REG_VDD2) ||
994 ((id == TPS65911_REG_VDDCTRL) &&
995 (tps65910_chip_id(mfd) == TPS65911))) {
996 int op_reg_add = pmic->get_ctrl_reg(id) + 1;
997 int sr_reg_add = pmic->get_ctrl_reg(id) + 2;
998 int opvsel = tps65910_reg_read(pmic, op_reg_add);
999 int srvsel = tps65910_reg_read(pmic, sr_reg_add);
1000 if (opvsel & VDD1_OP_CMD_MASK) {
1001 u8 reg_val = srvsel & VDD1_OP_SEL_MASK;
1002 ret = tps65910_reg_write(pmic, op_reg_add, reg_val);
1003 if (ret < 0) {
1004 dev_err(mfd->dev,
1005 "Error in configuring op register\n");
1006 return ret;
1007 }
1008 }
1009 ret = tps65910_reg_write(pmic, sr_reg_add, 0);
1010 if (ret < 0) {
1011 dev_err(mfd->dev, "Error in settting sr register\n");
1012 return ret;
1013 }
1014 }
1015
1016 ret = tps65910_clear_bits(mfd,
1017 TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos);
1018 if (!ret)
1019 ret = tps65910_set_bits(mfd,
1020 TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
1021 if (ret < 0)
1022 dev_err(mfd->dev,
1023 "Error in configuring SLEEP register\n");
1024 return ret;
1025}
1026
864static __devinit int tps65910_probe(struct platform_device *pdev) 1027static __devinit int tps65910_probe(struct platform_device *pdev)
865{ 1028{
866 struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); 1029 struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
@@ -891,11 +1054,13 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
891 case TPS65910: 1054 case TPS65910:
892 pmic->get_ctrl_reg = &tps65910_get_ctrl_register; 1055 pmic->get_ctrl_reg = &tps65910_get_ctrl_register;
893 pmic->num_regulators = ARRAY_SIZE(tps65910_regs); 1056 pmic->num_regulators = ARRAY_SIZE(tps65910_regs);
1057 pmic->ext_sleep_control = tps65910_ext_sleep_control;
894 info = tps65910_regs; 1058 info = tps65910_regs;
895 break; 1059 break;
896 case TPS65911: 1060 case TPS65911:
897 pmic->get_ctrl_reg = &tps65911_get_ctrl_register; 1061 pmic->get_ctrl_reg = &tps65911_get_ctrl_register;
898 pmic->num_regulators = ARRAY_SIZE(tps65911_regs); 1062 pmic->num_regulators = ARRAY_SIZE(tps65911_regs);
1063 pmic->ext_sleep_control = tps65911_ext_sleep_control;
899 info = tps65911_regs; 1064 info = tps65911_regs;
900 break; 1065 break;
901 default: 1066 default:
@@ -958,6 +1123,16 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
958 pmic->desc[i].ops = &tps65911_ops; 1123 pmic->desc[i].ops = &tps65911_ops;
959 } 1124 }
960 1125
1126 err = tps65910_set_ext_sleep_config(pmic, i,
1127 pmic_plat_data->regulator_ext_sleep_control[i]);
1128 /*
1129 * Failing on regulator for configuring externally control
1130 * is not a serious issue, just throw warning.
1131 */
1132 if (err < 0)
1133 dev_warn(tps65910->dev,
1134 "Failed to initialise ext control config\n");
1135
961 pmic->desc[i].type = REGULATOR_VOLTAGE; 1136 pmic->desc[i].type = REGULATOR_VOLTAGE;
962 pmic->desc[i].owner = THIS_MODULE; 1137 pmic->desc[i].owner = THIS_MODULE;
963 1138
@@ -1004,6 +1179,36 @@ static int __devexit tps65910_remove(struct platform_device *pdev)
1004 return 0; 1179 return 0;
1005} 1180}
1006 1181
1182static void tps65910_shutdown(struct platform_device *pdev)
1183{
1184 struct tps65910_reg *pmic = platform_get_drvdata(pdev);
1185 int i;
1186
1187 /*
1188 * Before bootloader jumps to kernel, it makes sure that required
1189 * external control signals are in desired state so that given rails
1190 * can be configure accordingly.
1191 * If rails are configured to be controlled from external control
1192 * then before shutting down/rebooting the system, the external
1193 * control configuration need to be remove from the rails so that
1194 * its output will be available as per register programming even
1195 * if external controls are removed. This is require when the POR
1196 * value of the control signals are not in active state and before
1197 * bootloader initializes it, the system requires the rail output
1198 * to be active for booting.
1199 */
1200 for (i = 0; i < pmic->num_regulators; i++) {
1201 int err;
1202 if (!pmic->rdev[i])
1203 continue;
1204
1205 err = tps65910_set_ext_sleep_config(pmic, i, 0);
1206 if (err < 0)
1207 dev_err(&pdev->dev,
1208 "Error in clearing external control\n");
1209 }
1210}
1211
1007static struct platform_driver tps65910_driver = { 1212static struct platform_driver tps65910_driver = {
1008 .driver = { 1213 .driver = {
1009 .name = "tps65910-pmic", 1214 .name = "tps65910-pmic",
@@ -1011,6 +1216,7 @@ static struct platform_driver tps65910_driver = {
1011 }, 1216 },
1012 .probe = tps65910_probe, 1217 .probe = tps65910_probe,
1013 .remove = __devexit_p(tps65910_remove), 1218 .remove = __devexit_p(tps65910_remove),
1219 .shutdown = tps65910_shutdown,
1014}; 1220};
1015 1221
1016static int __init tps65910_init(void) 1222static int __init tps65910_init(void)