diff options
author | Krzysztof Kozlowski <k.kozlowski@samsung.com> | 2015-01-05 06:48:43 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-01-08 15:15:45 -0500 |
commit | 3307e9025d29105ecc5fa1144508715cdddba195 (patch) | |
tree | 1acfb15c7c98260b0ba571b59f75683a374d768c /drivers/regulator/max77686.c | |
parent | bfa21a0dfe6915dc85953b5d40ea9dae5fdf205f (diff) |
regulator: max77686: Add GPIO control
Add enable control over GPIO for regulators supporting this: LDO20,
LDO21, LDO22, buck8 and buck9.
This is needed for proper (and full) configuration of the Maxim 77686
PMIC without creating redundant 'regulator-fixed' entries.
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator/max77686.c')
-rw-r--r-- | drivers/regulator/max77686.c | 70 |
1 files changed, 65 insertions, 5 deletions
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index 10d206266ac2..15fb1416bfbd 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/bug.h> | 26 | #include <linux/bug.h> |
27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
28 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
29 | #include <linux/of_gpio.h> | ||
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
31 | #include <linux/regulator/driver.h> | 32 | #include <linux/regulator/driver.h> |
@@ -46,6 +47,11 @@ | |||
46 | #define MAX77686_DVS_UVSTEP 12500 | 47 | #define MAX77686_DVS_UVSTEP 12500 |
47 | 48 | ||
48 | /* | 49 | /* |
50 | * Value for configuring buck[89] and LDO{20,21,22} as GPIO control. | ||
51 | * It is the same as 'off' for other regulators. | ||
52 | */ | ||
53 | #define MAX77686_GPIO_CONTROL 0x0 | ||
54 | /* | ||
49 | * Values used for configuring LDOs and bucks. | 55 | * Values used for configuring LDOs and bucks. |
50 | * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26 | 56 | * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26 |
51 | */ | 57 | */ |
@@ -82,6 +88,8 @@ enum max77686_ramp_rate { | |||
82 | }; | 88 | }; |
83 | 89 | ||
84 | struct max77686_data { | 90 | struct max77686_data { |
91 | u64 gpio_enabled:MAX77686_REGULATORS; | ||
92 | |||
85 | /* Array indexed by regulator id */ | 93 | /* Array indexed by regulator id */ |
86 | unsigned int opmode[MAX77686_REGULATORS]; | 94 | unsigned int opmode[MAX77686_REGULATORS]; |
87 | }; | 95 | }; |
@@ -100,6 +108,26 @@ static unsigned int max77686_get_opmode_shift(int id) | |||
100 | } | 108 | } |
101 | } | 109 | } |
102 | 110 | ||
111 | /* | ||
112 | * When regulator is configured for GPIO control then it | ||
113 | * replaces "normal" mode. Any change from low power mode to normal | ||
114 | * should actually change to GPIO control. | ||
115 | * Map normal mode to proper value for such regulators. | ||
116 | */ | ||
117 | static unsigned int max77686_map_normal_mode(struct max77686_data *max77686, | ||
118 | int id) | ||
119 | { | ||
120 | switch (id) { | ||
121 | case MAX77686_BUCK8: | ||
122 | case MAX77686_BUCK9: | ||
123 | case MAX77686_LDO20 ... MAX77686_LDO22: | ||
124 | if (max77686->gpio_enabled & (1 << id)) | ||
125 | return MAX77686_GPIO_CONTROL; | ||
126 | } | ||
127 | |||
128 | return MAX77686_NORMAL; | ||
129 | } | ||
130 | |||
103 | /* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */ | 131 | /* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */ |
104 | static int max77686_set_suspend_disable(struct regulator_dev *rdev) | 132 | static int max77686_set_suspend_disable(struct regulator_dev *rdev) |
105 | { | 133 | { |
@@ -136,7 +164,7 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev, | |||
136 | val = MAX77686_LDO_LOWPOWER_PWRREQ; | 164 | val = MAX77686_LDO_LOWPOWER_PWRREQ; |
137 | break; | 165 | break; |
138 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ | 166 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ |
139 | val = MAX77686_NORMAL; | 167 | val = max77686_map_normal_mode(max77686, id); |
140 | break; | 168 | break; |
141 | default: | 169 | default: |
142 | pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", | 170 | pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", |
@@ -160,7 +188,7 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, | |||
160 | { | 188 | { |
161 | unsigned int val; | 189 | unsigned int val; |
162 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); | 190 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); |
163 | int ret; | 191 | int ret, id = rdev_get_id(rdev); |
164 | 192 | ||
165 | switch (mode) { | 193 | switch (mode) { |
166 | case REGULATOR_MODE_STANDBY: /* switch off */ | 194 | case REGULATOR_MODE_STANDBY: /* switch off */ |
@@ -170,7 +198,7 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, | |||
170 | val = MAX77686_LDO_LOWPOWER_PWRREQ; | 198 | val = MAX77686_LDO_LOWPOWER_PWRREQ; |
171 | break; | 199 | break; |
172 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ | 200 | case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ |
173 | val = MAX77686_NORMAL; | 201 | val = max77686_map_normal_mode(max77686, id); |
174 | break; | 202 | break; |
175 | default: | 203 | default: |
176 | pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", | 204 | pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", |
@@ -184,7 +212,7 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, | |||
184 | if (ret) | 212 | if (ret) |
185 | return ret; | 213 | return ret; |
186 | 214 | ||
187 | max77686->opmode[rdev_get_id(rdev)] = val; | 215 | max77686->opmode[id] = val; |
188 | return 0; | 216 | return 0; |
189 | } | 217 | } |
190 | 218 | ||
@@ -197,7 +225,7 @@ static int max77686_enable(struct regulator_dev *rdev) | |||
197 | shift = max77686_get_opmode_shift(id); | 225 | shift = max77686_get_opmode_shift(id); |
198 | 226 | ||
199 | if (max77686->opmode[id] == MAX77686_OFF_PWRREQ) | 227 | if (max77686->opmode[id] == MAX77686_OFF_PWRREQ) |
200 | max77686->opmode[id] = MAX77686_NORMAL; | 228 | max77686->opmode[id] = max77686_map_normal_mode(max77686, id); |
201 | 229 | ||
202 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | 230 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
203 | rdev->desc->enable_mask, | 231 | rdev->desc->enable_mask, |
@@ -229,6 +257,36 @@ static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | |||
229 | MAX77686_RAMP_RATE_MASK, ramp_value << 6); | 257 | MAX77686_RAMP_RATE_MASK, ramp_value << 6); |
230 | } | 258 | } |
231 | 259 | ||
260 | static int max77686_of_parse_cb(struct device_node *np, | ||
261 | const struct regulator_desc *desc, | ||
262 | struct regulator_config *config) | ||
263 | { | ||
264 | struct max77686_data *max77686 = config->driver_data; | ||
265 | |||
266 | switch (desc->id) { | ||
267 | case MAX77686_BUCK8: | ||
268 | case MAX77686_BUCK9: | ||
269 | case MAX77686_LDO20 ... MAX77686_LDO22: | ||
270 | config->ena_gpio = of_get_named_gpio(np, | ||
271 | "maxim,ena-gpios", 0); | ||
272 | config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH; | ||
273 | config->ena_gpio_initialized = true; | ||
274 | break; | ||
275 | default: | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | if (gpio_is_valid(config->ena_gpio)) { | ||
280 | max77686->gpio_enabled |= (1 << desc->id); | ||
281 | |||
282 | return regmap_update_bits(config->regmap, desc->enable_reg, | ||
283 | desc->enable_mask, | ||
284 | MAX77686_GPIO_CONTROL); | ||
285 | } | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
232 | static struct regulator_ops max77686_ops = { | 290 | static struct regulator_ops max77686_ops = { |
233 | .list_voltage = regulator_list_voltage_linear, | 291 | .list_voltage = regulator_list_voltage_linear, |
234 | .map_voltage = regulator_map_voltage_linear, | 292 | .map_voltage = regulator_map_voltage_linear, |
@@ -283,6 +341,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { | |||
283 | .name = "LDO"#num, \ | 341 | .name = "LDO"#num, \ |
284 | .of_match = of_match_ptr("LDO"#num), \ | 342 | .of_match = of_match_ptr("LDO"#num), \ |
285 | .regulators_node = of_match_ptr("voltage-regulators"), \ | 343 | .regulators_node = of_match_ptr("voltage-regulators"), \ |
344 | .of_parse_cb = max77686_of_parse_cb, \ | ||
286 | .id = MAX77686_LDO##num, \ | 345 | .id = MAX77686_LDO##num, \ |
287 | .ops = &max77686_ops, \ | 346 | .ops = &max77686_ops, \ |
288 | .type = REGULATOR_VOLTAGE, \ | 347 | .type = REGULATOR_VOLTAGE, \ |
@@ -355,6 +414,7 @@ static struct regulator_ops max77686_buck_dvs_ops = { | |||
355 | .name = "BUCK"#num, \ | 414 | .name = "BUCK"#num, \ |
356 | .of_match = of_match_ptr("BUCK"#num), \ | 415 | .of_match = of_match_ptr("BUCK"#num), \ |
357 | .regulators_node = of_match_ptr("voltage-regulators"), \ | 416 | .regulators_node = of_match_ptr("voltage-regulators"), \ |
417 | .of_parse_cb = max77686_of_parse_cb, \ | ||
358 | .id = MAX77686_BUCK##num, \ | 418 | .id = MAX77686_BUCK##num, \ |
359 | .ops = &max77686_ops, \ | 419 | .ops = &max77686_ops, \ |
360 | .type = REGULATOR_VOLTAGE, \ | 420 | .type = REGULATOR_VOLTAGE, \ |