diff options
-rw-r--r-- | drivers/regulator/max77802.c | 93 |
1 files changed, 46 insertions, 47 deletions
diff --git a/drivers/regulator/max77802.c b/drivers/regulator/max77802.c index 6eabb954ec7c..dae2c1acd879 100644 --- a/drivers/regulator/max77802.c +++ b/drivers/regulator/max77802.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #define MAX77802_RAMP_RATE_SHIFT_4BIT 4 | 50 | #define MAX77802_RAMP_RATE_SHIFT_4BIT 4 |
51 | 51 | ||
52 | #define MAX77802_OFF_PWRREQ 0x1 | 52 | #define MAX77802_OFF_PWRREQ 0x1 |
53 | #define MAX77802_LP_PWRREQ 0x2 | ||
53 | 54 | ||
54 | /* MAX77802 has two register formats: 2-bit and 4-bit */ | 55 | /* MAX77802 has two register formats: 2-bit and 4-bit */ |
55 | static const unsigned int ramp_table_77802_2bit[] = { | 56 | static const unsigned int ramp_table_77802_2bit[] = { |
@@ -148,71 +149,68 @@ static unsigned max77802_get_mode(struct regulator_dev *rdev) | |||
148 | return max77802_map_mode(max77802->opmode[id]); | 149 | return max77802_map_mode(max77802->opmode[id]); |
149 | } | 150 | } |
150 | 151 | ||
151 | /* | 152 | /** |
152 | * Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state | 153 | * max77802_set_suspend_mode - set regulator opmode when the system is suspended |
153 | * (Enable Control Logic1 by PWRREQ) | 154 | * @rdev: regulator to change mode |
155 | * @mode: operating mode to be set | ||
156 | * | ||
157 | * Will set the operating mode for the regulators during system suspend. | ||
158 | * This function is valid for the three different enable control logics: | ||
154 | * | 159 | * |
155 | * LDOs 2, 4-19, 22-35. | 160 | * Enable Control Logic1 by PWRREQ (BUCK 2-4 and LDOs 2, 4-19, 22-35) |
161 | * Enable Control Logic2 by PWRREQ (LDOs 1, 20, 21) | ||
162 | * Enable Control Logic3 by PWRREQ (LDO 3) | ||
156 | * | 163 | * |
164 | * If setting the regulator mode fails, the function only warns but does | ||
165 | * not return an error code to avoid the regulator core to stop setting | ||
166 | * the operating mode for the remaining regulators. | ||
157 | */ | 167 | */ |
158 | static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev, | 168 | static int max77802_set_suspend_mode(struct regulator_dev *rdev, |
159 | unsigned int mode) | 169 | unsigned int mode) |
160 | { | 170 | { |
161 | struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); | 171 | struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); |
162 | int id = rdev_get_id(rdev); | 172 | int id = rdev_get_id(rdev); |
163 | unsigned int val; | 173 | unsigned int val; |
164 | int shift = max77802_get_opmode_shift(id); | 174 | int shift = max77802_get_opmode_shift(id); |
165 | 175 | ||
166 | switch (mode) { | 176 | /* |
167 | case REGULATOR_MODE_IDLE: /* ON in LP Mode */ | 177 | * If the regulator has been disabled for suspend |
168 | val = MAX77802_OPMODE_LP; | 178 | * then is invalid to try setting a suspend mode. |
169 | break; | 179 | */ |
170 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ | 180 | if (!max77802->opmode[id] == MAX77802_OFF_PWRREQ) { |
171 | val = MAX77802_OPMODE_NORMAL; | 181 | dev_warn(&rdev->dev, "%s: is disabled, mode: 0x%x not set\n", |
172 | break; | ||
173 | case REGULATOR_MODE_STANDBY: /* ON/OFF by PWRREQ */ | ||
174 | val = MAX77802_OPMODE_STANDBY; | ||
175 | break; | ||
176 | default: | ||
177 | dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", | ||
178 | rdev->desc->name, mode); | 182 | rdev->desc->name, mode); |
179 | return -EINVAL; | 183 | return 0; |
180 | } | 184 | } |
181 | 185 | ||
182 | max77802->opmode[id] = val; | ||
183 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | ||
184 | rdev->desc->enable_mask, val << shift); | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * Mode 1 (Output[ON/OFF] by PWRREQ) is not supported on some LDOs | ||
189 | * (Enable Control Logic2 by PWRREQ) | ||
190 | * | ||
191 | * LDOs 1, 20, 21, and 3, | ||
192 | * | ||
193 | */ | ||
194 | static int max77802_ldo_set_suspend_mode_logic2(struct regulator_dev *rdev, | ||
195 | unsigned int mode) | ||
196 | { | ||
197 | struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); | ||
198 | int id = rdev_get_id(rdev); | ||
199 | unsigned int val; | ||
200 | int shift = max77802_get_opmode_shift(id); | ||
201 | |||
202 | switch (mode) { | 186 | switch (mode) { |
203 | case REGULATOR_MODE_IDLE: /* ON in LP Mode */ | 187 | case REGULATOR_MODE_STANDBY: |
204 | val = MAX77802_OPMODE_LP; | 188 | /* |
205 | break; | 189 | * If the regulator opmode is normal then enable |
206 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ | 190 | * ON in Low Power Mode by PWRREQ. If the mode is |
207 | val = MAX77802_OPMODE_NORMAL; | 191 | * already Low Power then no action is required. |
192 | */ | ||
193 | if (max77802->opmode[id] == MAX77802_OPMODE_NORMAL) | ||
194 | val = MAX77802_LP_PWRREQ; | ||
195 | else | ||
196 | return 0; | ||
208 | break; | 197 | break; |
198 | case REGULATOR_MODE_NORMAL: | ||
199 | /* | ||
200 | * If the regulator operating mode is Low Power then | ||
201 | * normal is not a valid opmode in suspend. If the | ||
202 | * mode is already normal then no action is required. | ||
203 | */ | ||
204 | if (max77802->opmode[id] == MAX77802_OPMODE_LP) | ||
205 | dev_warn(&rdev->dev, "%s: in Low Power: 0x%x invalid\n", | ||
206 | rdev->desc->name, mode); | ||
207 | return 0; | ||
209 | default: | 208 | default: |
210 | dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", | 209 | dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", |
211 | rdev->desc->name, mode); | 210 | rdev->desc->name, mode); |
212 | return -EINVAL; | 211 | return -EINVAL; |
213 | } | 212 | } |
214 | 213 | ||
215 | max77802->opmode[id] = val; | ||
216 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | 214 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
217 | rdev->desc->enable_mask, val << shift); | 215 | rdev->desc->enable_mask, val << shift); |
218 | } | 216 | } |
@@ -297,7 +295,7 @@ static struct regulator_ops max77802_ldo_ops_logic1 = { | |||
297 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | 295 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
298 | .set_suspend_enable = max77802_enable, | 296 | .set_suspend_enable = max77802_enable, |
299 | .set_suspend_disable = max77802_set_suspend_disable, | 297 | .set_suspend_disable = max77802_set_suspend_disable, |
300 | .set_suspend_mode = max77802_ldo_set_suspend_mode_logic1, | 298 | .set_suspend_mode = max77802_set_suspend_mode, |
301 | }; | 299 | }; |
302 | 300 | ||
303 | /* | 301 | /* |
@@ -314,7 +312,7 @@ static struct regulator_ops max77802_ldo_ops_logic2 = { | |||
314 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | 312 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
315 | .set_mode = max77802_set_mode, | 313 | .set_mode = max77802_set_mode, |
316 | .get_mode = max77802_get_mode, | 314 | .get_mode = max77802_get_mode, |
317 | .set_suspend_mode = max77802_ldo_set_suspend_mode_logic2, | 315 | .set_suspend_mode = max77802_set_suspend_mode, |
318 | }; | 316 | }; |
319 | 317 | ||
320 | /* BUCKS 1, 6 */ | 318 | /* BUCKS 1, 6 */ |
@@ -345,6 +343,7 @@ static struct regulator_ops max77802_buck_234_ops = { | |||
345 | .set_ramp_delay = max77802_set_ramp_delay_2bit, | 343 | .set_ramp_delay = max77802_set_ramp_delay_2bit, |
346 | .set_suspend_enable = max77802_enable, | 344 | .set_suspend_enable = max77802_enable, |
347 | .set_suspend_disable = max77802_set_suspend_disable, | 345 | .set_suspend_disable = max77802_set_suspend_disable, |
346 | .set_suspend_mode = max77802_set_suspend_mode, | ||
348 | }; | 347 | }; |
349 | 348 | ||
350 | /* BUCKs 5, 7-10 */ | 349 | /* BUCKs 5, 7-10 */ |