aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/regulator/anatop-regulator.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index dff120a38e40..38e8122c4b09 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -35,6 +35,7 @@
35#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */ 35#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */
36 36
37#define LDO_POWER_GATE 0x00 37#define LDO_POWER_GATE 0x00
38#define LDO_FET_FULL_ON 0x1f
38 39
39struct anatop_regulator { 40struct anatop_regulator {
40 const char *name; 41 const char *name;
@@ -50,6 +51,7 @@ struct anatop_regulator {
50 int max_voltage; 51 int max_voltage;
51 struct regulator_desc rdesc; 52 struct regulator_desc rdesc;
52 struct regulator_init_data *initdata; 53 struct regulator_init_data *initdata;
54 bool bypass;
53 int sel; 55 int sel;
54}; 56};
55 57
@@ -103,8 +105,10 @@ static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
103static int anatop_regmap_enable(struct regulator_dev *reg) 105static int anatop_regmap_enable(struct regulator_dev *reg)
104{ 106{
105 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); 107 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
108 int sel;
106 109
107 return regulator_set_voltage_sel_regmap(reg, anatop_reg->sel); 110 sel = anatop_reg->bypass ? LDO_FET_FULL_ON : anatop_reg->sel;
111 return regulator_set_voltage_sel_regmap(reg, sel);
108} 112}
109 113
110static int anatop_regmap_disable(struct regulator_dev *reg) 114static int anatop_regmap_disable(struct regulator_dev *reg)
@@ -123,7 +127,7 @@ static int anatop_regmap_core_set_voltage_sel(struct regulator_dev *reg,
123 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); 127 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
124 int ret; 128 int ret;
125 129
126 if (!anatop_regmap_is_enabled(reg)) { 130 if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg)) {
127 anatop_reg->sel = selector; 131 anatop_reg->sel = selector;
128 return 0; 132 return 0;
129 } 133 }
@@ -138,12 +142,41 @@ static int anatop_regmap_core_get_voltage_sel(struct regulator_dev *reg)
138{ 142{
139 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); 143 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
140 144
141 if (!anatop_regmap_is_enabled(reg)) 145 if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg))
142 return anatop_reg->sel; 146 return anatop_reg->sel;
143 147
144 return regulator_get_voltage_sel_regmap(reg); 148 return regulator_get_voltage_sel_regmap(reg);
145} 149}
146 150
151static int anatop_regmap_get_bypass(struct regulator_dev *reg, bool *enable)
152{
153 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
154 int sel;
155
156 sel = regulator_get_voltage_sel_regmap(reg);
157 if (sel == LDO_FET_FULL_ON)
158 WARN_ON(!anatop_reg->bypass);
159 else if (sel != LDO_POWER_GATE)
160 WARN_ON(anatop_reg->bypass);
161
162 *enable = anatop_reg->bypass;
163 return 0;
164}
165
166static int anatop_regmap_set_bypass(struct regulator_dev *reg, bool enable)
167{
168 struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
169 int sel;
170
171 if (enable == anatop_reg->bypass)
172 return 0;
173
174 sel = enable ? LDO_FET_FULL_ON : anatop_reg->sel;
175 anatop_reg->bypass = enable;
176
177 return regulator_set_voltage_sel_regmap(reg, sel);
178}
179
147static struct regulator_ops anatop_rops = { 180static struct regulator_ops anatop_rops = {
148 .set_voltage_sel = anatop_regmap_set_voltage_sel, 181 .set_voltage_sel = anatop_regmap_set_voltage_sel,
149 .get_voltage_sel = anatop_regmap_get_voltage_sel, 182 .get_voltage_sel = anatop_regmap_get_voltage_sel,
@@ -160,6 +193,8 @@ static struct regulator_ops anatop_core_rops = {
160 .get_voltage_sel = anatop_regmap_core_get_voltage_sel, 193 .get_voltage_sel = anatop_regmap_core_get_voltage_sel,
161 .list_voltage = regulator_list_voltage_linear, 194 .list_voltage = regulator_list_voltage_linear,
162 .map_voltage = regulator_map_voltage_linear, 195 .map_voltage = regulator_map_voltage_linear,
196 .get_bypass = anatop_regmap_get_bypass,
197 .set_bypass = anatop_regmap_set_bypass,
163}; 198};
164 199
165static int anatop_regulator_probe(struct platform_device *pdev) 200static int anatop_regulator_probe(struct platform_device *pdev)
@@ -265,6 +300,10 @@ static int anatop_regulator_probe(struct platform_device *pdev)
265 } 300 }
266 301
267 sreg->sel = (val & rdesc->vsel_mask) >> sreg->vol_bit_shift; 302 sreg->sel = (val & rdesc->vsel_mask) >> sreg->vol_bit_shift;
303 if (sreg->sel == LDO_FET_FULL_ON) {
304 sreg->sel = 0;
305 sreg->bypass = true;
306 }
268 } else { 307 } else {
269 rdesc->ops = &anatop_rops; 308 rdesc->ops = &anatop_rops;
270 } 309 }