diff options
-rw-r--r-- | drivers/regulator/anatop-regulator.c | 45 |
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 | ||
39 | struct anatop_regulator { | 40 | struct 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) | |||
103 | static int anatop_regmap_enable(struct regulator_dev *reg) | 105 | static 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 | ||
110 | static int anatop_regmap_disable(struct regulator_dev *reg) | 114 | static 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 | ||
151 | static 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 | |||
166 | static 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 | |||
147 | static struct regulator_ops anatop_rops = { | 180 | static 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 | ||
165 | static int anatop_regulator_probe(struct platform_device *pdev) | 200 | static 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 | } |