aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorRuss Dill <Russ.Dill@ti.com>2016-06-24 04:28:07 -0400
committerMark Brown <broonie@kernel.org>2016-06-27 12:56:43 -0400
commit3de56099591a4042556a2d05d4703387ad950c6f (patch)
tree40cf8dec1a8084cc745d3ed5245c7f7753a99f1d /drivers/regulator
parent1a695a905c18548062509178b98bc91e67510864 (diff)
regulator: tps65217: Enable suspend configuration
The TPS65217 has a pre-defined power-up / power-down sequence which in a typical application does not need to be changed. However, it is possible to define custom sequences under I2C control. The power-up sequence is defined by strobes and delay times. Each output rail is assigned to a strobe to determine the order in which the rails are enabled. Every regulator of tps65217 PMIC has sequence registers and every regulator has a default strobe value and gets disabled when a particular power down sequence occurs. To keep a regulator on during suspend we write value 0 to strobe so that the regulator is out of all sequencers and is not impacted by any power down sequence. Hence saving the default strobe value during probe so that when we want to regulator to be enabled during suspend we write 0 to strobe and when we want it to get disabled during suspend we write the default saved strobe value. This allows platform data to specify which power rails should be on or off during RTC only suspend. This is necessary to keep DDR state while in RTC only suspend. Signed-off-by: Russ Dill <Russ.Dill@ti.com> [Enhanced commit log and added dynamic allocation for strobes] Signed-off-by: Keerthy <j-keerthy@ti.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/tps65217-regulator.c69
1 files changed, 60 insertions, 9 deletions
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index adbe4fc5cf07..2d12b9af3540 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -28,7 +28,7 @@
28#include <linux/mfd/tps65217.h> 28#include <linux/mfd/tps65217.h>
29 29
30#define TPS65217_REGULATOR(_name, _id, _of_match, _ops, _n, _vr, _vm, _em, \ 30#define TPS65217_REGULATOR(_name, _id, _of_match, _ops, _n, _vr, _vm, _em, \
31 _t, _lr, _nlr) \ 31 _t, _lr, _nlr, _sr, _sm) \
32 { \ 32 { \
33 .name = _name, \ 33 .name = _name, \
34 .id = _id, \ 34 .id = _id, \
@@ -45,6 +45,8 @@
45 .volt_table = _t, \ 45 .volt_table = _t, \
46 .linear_ranges = _lr, \ 46 .linear_ranges = _lr, \
47 .n_linear_ranges = _nlr, \ 47 .n_linear_ranges = _nlr, \
48 .bypass_reg = _sr, \
49 .bypass_mask = _sm, \
48 } \ 50 } \
49 51
50static const unsigned int LDO1_VSEL_table[] = { 52static const unsigned int LDO1_VSEL_table[] = {
@@ -118,6 +120,35 @@ static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
118 return ret; 120 return ret;
119} 121}
120 122
123static int tps65217_pmic_set_suspend_enable(struct regulator_dev *dev)
124{
125 struct tps65217 *tps = rdev_get_drvdata(dev);
126 unsigned int rid = rdev_get_id(dev);
127
128 if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
129 return -EINVAL;
130
131 return tps65217_clear_bits(tps, dev->desc->bypass_reg,
132 dev->desc->bypass_mask,
133 TPS65217_PROTECT_L1);
134}
135
136static int tps65217_pmic_set_suspend_disable(struct regulator_dev *dev)
137{
138 struct tps65217 *tps = rdev_get_drvdata(dev);
139 unsigned int rid = rdev_get_id(dev);
140
141 if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
142 return -EINVAL;
143
144 if (!tps->strobes[rid])
145 return -EINVAL;
146
147 return tps65217_set_bits(tps, dev->desc->bypass_reg,
148 dev->desc->bypass_mask,
149 tps->strobes[rid], TPS65217_PROTECT_L1);
150}
151
121/* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */ 152/* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */
122static struct regulator_ops tps65217_pmic_ops = { 153static struct regulator_ops tps65217_pmic_ops = {
123 .is_enabled = regulator_is_enabled_regmap, 154 .is_enabled = regulator_is_enabled_regmap,
@@ -127,6 +158,8 @@ static struct regulator_ops tps65217_pmic_ops = {
127 .set_voltage_sel = tps65217_pmic_set_voltage_sel, 158 .set_voltage_sel = tps65217_pmic_set_voltage_sel,
128 .list_voltage = regulator_list_voltage_linear_range, 159 .list_voltage = regulator_list_voltage_linear_range,
129 .map_voltage = regulator_map_voltage_linear_range, 160 .map_voltage = regulator_map_voltage_linear_range,
161 .set_suspend_enable = tps65217_pmic_set_suspend_enable,
162 .set_suspend_disable = tps65217_pmic_set_suspend_disable,
130}; 163};
131 164
132/* Operations permitted on LDO1 */ 165/* Operations permitted on LDO1 */
@@ -138,41 +171,50 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = {
138 .set_voltage_sel = tps65217_pmic_set_voltage_sel, 171 .set_voltage_sel = tps65217_pmic_set_voltage_sel,
139 .list_voltage = regulator_list_voltage_table, 172 .list_voltage = regulator_list_voltage_table,
140 .map_voltage = regulator_map_voltage_ascend, 173 .map_voltage = regulator_map_voltage_ascend,
174 .set_suspend_enable = tps65217_pmic_set_suspend_enable,
175 .set_suspend_disable = tps65217_pmic_set_suspend_disable,
141}; 176};
142 177
143static const struct regulator_desc regulators[] = { 178static const struct regulator_desc regulators[] = {
144 TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, "dcdc1", 179 TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, "dcdc1",
145 tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC1, 180 tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC1,
146 TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC1_EN, 181 TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC1_EN,
147 NULL, tps65217_uv1_ranges, 2), 182 NULL, tps65217_uv1_ranges, 2, TPS65217_REG_SEQ1,
183 TPS65217_SEQ1_DC1_SEQ_MASK),
148 TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, "dcdc2", 184 TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, "dcdc2",
149 tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC2, 185 tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC2,
150 TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC2_EN, 186 TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC2_EN,
151 NULL, tps65217_uv1_ranges, 187 NULL, tps65217_uv1_ranges,
152 ARRAY_SIZE(tps65217_uv1_ranges)), 188 ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ1,
189 TPS65217_SEQ1_DC2_SEQ_MASK),
153 TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, "dcdc3", 190 TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, "dcdc3",
154 tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC3, 191 tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC3,
155 TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC3_EN, 192 TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC3_EN,
156 NULL, tps65217_uv1_ranges, 1), 193 NULL, tps65217_uv1_ranges, 1, TPS65217_REG_SEQ2,
194 TPS65217_SEQ2_DC3_SEQ_MASK),
157 TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, "ldo1", 195 TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, "ldo1",
158 tps65217_pmic_ldo1_ops, 16, TPS65217_REG_DEFLDO1, 196 tps65217_pmic_ldo1_ops, 16, TPS65217_REG_DEFLDO1,
159 TPS65217_DEFLDO1_LDO1_MASK, TPS65217_ENABLE_LDO1_EN, 197 TPS65217_DEFLDO1_LDO1_MASK, TPS65217_ENABLE_LDO1_EN,
160 LDO1_VSEL_table, NULL, 0), 198 LDO1_VSEL_table, NULL, 0, TPS65217_REG_SEQ2,
199 TPS65217_SEQ2_LDO1_SEQ_MASK),
161 TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, "ldo2", tps65217_pmic_ops, 200 TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, "ldo2", tps65217_pmic_ops,
162 64, TPS65217_REG_DEFLDO2, 201 64, TPS65217_REG_DEFLDO2,
163 TPS65217_DEFLDO2_LDO2_MASK, TPS65217_ENABLE_LDO2_EN, 202 TPS65217_DEFLDO2_LDO2_MASK, TPS65217_ENABLE_LDO2_EN,
164 NULL, tps65217_uv1_ranges, 203 NULL, tps65217_uv1_ranges,
165 ARRAY_SIZE(tps65217_uv1_ranges)), 204 ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ3,
205 TPS65217_SEQ3_LDO2_SEQ_MASK),
166 TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, "ldo3", tps65217_pmic_ops, 206 TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, "ldo3", tps65217_pmic_ops,
167 32, TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK, 207 32, TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK,
168 TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN, 208 TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
169 NULL, tps65217_uv2_ranges, 209 NULL, tps65217_uv2_ranges,
170 ARRAY_SIZE(tps65217_uv2_ranges)), 210 ARRAY_SIZE(tps65217_uv2_ranges), TPS65217_REG_SEQ3,
211 TPS65217_SEQ3_LDO3_SEQ_MASK),
171 TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, "ldo4", tps65217_pmic_ops, 212 TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, "ldo4", tps65217_pmic_ops,
172 32, TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK, 213 32, TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK,
173 TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN, 214 TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
174 NULL, tps65217_uv2_ranges, 215 NULL, tps65217_uv2_ranges,
175 ARRAY_SIZE(tps65217_uv2_ranges)), 216 ARRAY_SIZE(tps65217_uv2_ranges), TPS65217_REG_SEQ4,
217 TPS65217_SEQ4_LDO4_SEQ_MASK),
176}; 218};
177 219
178static int tps65217_regulator_probe(struct platform_device *pdev) 220static int tps65217_regulator_probe(struct platform_device *pdev)
@@ -181,13 +223,18 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
181 struct tps65217_board *pdata = dev_get_platdata(tps->dev); 223 struct tps65217_board *pdata = dev_get_platdata(tps->dev);
182 struct regulator_dev *rdev; 224 struct regulator_dev *rdev;
183 struct regulator_config config = { }; 225 struct regulator_config config = { };
184 int i; 226 int i, ret;
227 unsigned int val;
185 228
186 if (tps65217_chip_id(tps) != TPS65217) { 229 if (tps65217_chip_id(tps) != TPS65217) {
187 dev_err(&pdev->dev, "Invalid tps chip version\n"); 230 dev_err(&pdev->dev, "Invalid tps chip version\n");
188 return -ENODEV; 231 return -ENODEV;
189 } 232 }
190 233
234 /* Allocate memory for strobes */
235 tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) *
236 TPS65217_NUM_REGULATOR, GFP_KERNEL);
237
191 platform_set_drvdata(pdev, tps); 238 platform_set_drvdata(pdev, tps);
192 239
193 for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { 240 for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
@@ -205,6 +252,10 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
205 pdev->name); 252 pdev->name);
206 return PTR_ERR(rdev); 253 return PTR_ERR(rdev);
207 } 254 }
255
256 /* Store default strobe info */
257 ret = tps65217_reg_read(tps, regulators[i].bypass_reg, &val);
258 tps->strobes[i] = val & regulators[i].bypass_mask;
208 } 259 }
209 260
210 return 0; 261 return 0;