diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/Kconfig | 7 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
-rw-r--r-- | drivers/regulator/arizona-ldo1.c | 130 | ||||
-rw-r--r-- | drivers/regulator/arizona-micsupp.c | 2 | ||||
-rw-r--r-- | drivers/regulator/as3711-regulator.c | 369 | ||||
-rw-r--r-- | drivers/regulator/core.c | 55 | ||||
-rw-r--r-- | drivers/regulator/da9052-regulator.c | 10 | ||||
-rw-r--r-- | drivers/regulator/wm831x-dcdc.c | 2 |
8 files changed, 554 insertions, 22 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index a162573d4944..e6fcf20c3cd3 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -460,5 +460,12 @@ config REGULATOR_WM8994 | |||
460 | This driver provides support for the voltage regulators on the | 460 | This driver provides support for the voltage regulators on the |
461 | WM8994 CODEC. | 461 | WM8994 CODEC. |
462 | 462 | ||
463 | config REGULATOR_AS3711 | ||
464 | tristate "AS3711 PMIC" | ||
465 | depends on MFD_AS3711 | ||
466 | help | ||
467 | This driver provides support for the voltage regulators on the | ||
468 | AS3711 PMIC | ||
469 | |||
463 | endif | 470 | endif |
464 | 471 | ||
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 4b754e958aed..993151d6fdf9 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o | |||
16 | obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o | 16 | obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o |
17 | obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o | 17 | obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o |
18 | obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o | 18 | obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o |
19 | obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o | ||
19 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o | 20 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o |
20 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o | 21 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o |
21 | obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o | 22 | obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o |
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index d184aa35abcb..739faf99b9e2 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c | |||
@@ -34,6 +34,108 @@ struct arizona_ldo1 { | |||
34 | struct regulator_init_data init_data; | 34 | struct regulator_init_data init_data; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev, | ||
38 | unsigned int selector) | ||
39 | { | ||
40 | if (selector >= rdev->desc->n_voltages) | ||
41 | return -EINVAL; | ||
42 | |||
43 | if (selector == rdev->desc->n_voltages - 1) | ||
44 | return 1800000; | ||
45 | else | ||
46 | return rdev->desc->min_uV + (rdev->desc->uV_step * selector); | ||
47 | } | ||
48 | |||
49 | static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev, | ||
50 | int min_uV, int max_uV) | ||
51 | { | ||
52 | int sel; | ||
53 | |||
54 | sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); | ||
55 | if (sel >= rdev->desc->n_voltages) | ||
56 | sel = rdev->desc->n_voltages - 1; | ||
57 | |||
58 | return sel; | ||
59 | } | ||
60 | |||
61 | static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev, | ||
62 | unsigned sel) | ||
63 | { | ||
64 | struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); | ||
65 | struct regmap *regmap = ldo->arizona->regmap; | ||
66 | unsigned int val; | ||
67 | int ret; | ||
68 | |||
69 | if (sel == rdev->desc->n_voltages - 1) | ||
70 | val = ARIZONA_LDO1_HI_PWR; | ||
71 | else | ||
72 | val = 0; | ||
73 | |||
74 | ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2, | ||
75 | ARIZONA_LDO1_HI_PWR, val); | ||
76 | if (ret != 0) | ||
77 | return ret; | ||
78 | |||
79 | ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1, | ||
80 | ARIZONA_SUBSYS_MAX_FREQ, val); | ||
81 | if (ret != 0) | ||
82 | return ret; | ||
83 | |||
84 | if (val) | ||
85 | return 0; | ||
86 | |||
87 | val = sel << ARIZONA_LDO1_VSEL_SHIFT; | ||
88 | |||
89 | return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1, | ||
90 | ARIZONA_LDO1_VSEL_MASK, val); | ||
91 | } | ||
92 | |||
93 | static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev) | ||
94 | { | ||
95 | struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev); | ||
96 | struct regmap *regmap = ldo->arizona->regmap; | ||
97 | unsigned int val; | ||
98 | int ret; | ||
99 | |||
100 | ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val); | ||
101 | if (ret != 0) | ||
102 | return ret; | ||
103 | |||
104 | if (val & ARIZONA_LDO1_HI_PWR) | ||
105 | return rdev->desc->n_voltages - 1; | ||
106 | |||
107 | ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val); | ||
108 | if (ret != 0) | ||
109 | return ret; | ||
110 | |||
111 | return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT; | ||
112 | } | ||
113 | |||
114 | static struct regulator_ops arizona_ldo1_hc_ops = { | ||
115 | .list_voltage = arizona_ldo1_hc_list_voltage, | ||
116 | .map_voltage = arizona_ldo1_hc_map_voltage, | ||
117 | .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel, | ||
118 | .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel, | ||
119 | .get_bypass = regulator_get_bypass_regmap, | ||
120 | .set_bypass = regulator_set_bypass_regmap, | ||
121 | }; | ||
122 | |||
123 | static const struct regulator_desc arizona_ldo1_hc = { | ||
124 | .name = "LDO1", | ||
125 | .supply_name = "LDOVDD", | ||
126 | .type = REGULATOR_VOLTAGE, | ||
127 | .ops = &arizona_ldo1_hc_ops, | ||
128 | |||
129 | .bypass_reg = ARIZONA_LDO1_CONTROL_1, | ||
130 | .bypass_mask = ARIZONA_LDO1_BYPASS, | ||
131 | .min_uV = 900000, | ||
132 | .uV_step = 50000, | ||
133 | .n_voltages = 8, | ||
134 | .enable_time = 500, | ||
135 | |||
136 | .owner = THIS_MODULE, | ||
137 | }; | ||
138 | |||
37 | static struct regulator_ops arizona_ldo1_ops = { | 139 | static struct regulator_ops arizona_ldo1_ops = { |
38 | .list_voltage = regulator_list_voltage_linear, | 140 | .list_voltage = regulator_list_voltage_linear, |
39 | .map_voltage = regulator_map_voltage_linear, | 141 | .map_voltage = regulator_map_voltage_linear, |
@@ -55,11 +157,22 @@ static const struct regulator_desc arizona_ldo1 = { | |||
55 | .bypass_mask = ARIZONA_LDO1_BYPASS, | 157 | .bypass_mask = ARIZONA_LDO1_BYPASS, |
56 | .min_uV = 900000, | 158 | .min_uV = 900000, |
57 | .uV_step = 50000, | 159 | .uV_step = 50000, |
58 | .n_voltages = 6, | 160 | .n_voltages = 7, |
161 | .enable_time = 500, | ||
59 | 162 | ||
60 | .owner = THIS_MODULE, | 163 | .owner = THIS_MODULE, |
61 | }; | 164 | }; |
62 | 165 | ||
166 | static const struct regulator_init_data arizona_ldo1_dvfs = { | ||
167 | .constraints = { | ||
168 | .min_uV = 1200000, | ||
169 | .max_uV = 1800000, | ||
170 | .valid_ops_mask = REGULATOR_CHANGE_STATUS | | ||
171 | REGULATOR_CHANGE_VOLTAGE, | ||
172 | }, | ||
173 | .num_consumer_supplies = 1, | ||
174 | }; | ||
175 | |||
63 | static const struct regulator_init_data arizona_ldo1_default = { | 176 | static const struct regulator_init_data arizona_ldo1_default = { |
64 | .constraints = { | 177 | .constraints = { |
65 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 178 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
@@ -70,6 +183,7 @@ static const struct regulator_init_data arizona_ldo1_default = { | |||
70 | static __devinit int arizona_ldo1_probe(struct platform_device *pdev) | 183 | static __devinit int arizona_ldo1_probe(struct platform_device *pdev) |
71 | { | 184 | { |
72 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 185 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
186 | const struct regulator_desc *desc; | ||
73 | struct regulator_config config = { }; | 187 | struct regulator_config config = { }; |
74 | struct arizona_ldo1 *ldo1; | 188 | struct arizona_ldo1 *ldo1; |
75 | int ret; | 189 | int ret; |
@@ -87,7 +201,17 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev) | |||
87 | * default init_data for it. This will be overridden with | 201 | * default init_data for it. This will be overridden with |
88 | * platform data if provided. | 202 | * platform data if provided. |
89 | */ | 203 | */ |
90 | ldo1->init_data = arizona_ldo1_default; | 204 | switch (arizona->type) { |
205 | case WM5102: | ||
206 | desc = &arizona_ldo1_hc; | ||
207 | ldo1->init_data = arizona_ldo1_dvfs; | ||
208 | break; | ||
209 | default: | ||
210 | desc = &arizona_ldo1; | ||
211 | ldo1->init_data = arizona_ldo1_default; | ||
212 | break; | ||
213 | } | ||
214 | |||
91 | ldo1->init_data.consumer_supplies = &ldo1->supply; | 215 | ldo1->init_data.consumer_supplies = &ldo1->supply; |
92 | ldo1->supply.supply = "DCVDD"; | 216 | ldo1->supply.supply = "DCVDD"; |
93 | ldo1->supply.dev_name = dev_name(arizona->dev); | 217 | ldo1->supply.dev_name = dev_name(arizona->dev); |
@@ -102,7 +226,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev) | |||
102 | else | 226 | else |
103 | config.init_data = &ldo1->init_data; | 227 | config.init_data = &ldo1->init_data; |
104 | 228 | ||
105 | ldo1->regulator = regulator_register(&arizona_ldo1, &config); | 229 | ldo1->regulator = regulator_register(desc, &config); |
106 | if (IS_ERR(ldo1->regulator)) { | 230 | if (IS_ERR(ldo1->regulator)) { |
107 | ret = PTR_ERR(ldo1->regulator); | 231 | ret = PTR_ERR(ldo1->regulator); |
108 | dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n", | 232 | dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n", |
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index d9b1f82cc5bd..93d0604e64b4 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c | |||
@@ -101,6 +101,8 @@ static const struct regulator_desc arizona_micsupp = { | |||
101 | .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, | 101 | .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, |
102 | .bypass_mask = ARIZONA_CPMIC_BYPASS, | 102 | .bypass_mask = ARIZONA_CPMIC_BYPASS, |
103 | 103 | ||
104 | .enable_time = 3000, | ||
105 | |||
104 | .owner = THIS_MODULE, | 106 | .owner = THIS_MODULE, |
105 | }; | 107 | }; |
106 | 108 | ||
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c new file mode 100644 index 000000000000..2f1341db38a0 --- /dev/null +++ b/drivers/regulator/as3711-regulator.c | |||
@@ -0,0 +1,369 @@ | |||
1 | /* | ||
2 | * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies | ||
3 | * | ||
4 | * Copyright (C) 2012 Renesas Electronics Corporation | ||
5 | * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation | ||
10 | */ | ||
11 | |||
12 | #include <linux/err.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/mfd/as3711.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/regmap.h> | ||
18 | #include <linux/regulator/driver.h> | ||
19 | #include <linux/slab.h> | ||
20 | |||
21 | struct as3711_regulator_info { | ||
22 | struct regulator_desc desc; | ||
23 | unsigned int max_uV; | ||
24 | }; | ||
25 | |||
26 | struct as3711_regulator { | ||
27 | struct as3711_regulator_info *reg_info; | ||
28 | struct regulator_dev *rdev; | ||
29 | }; | ||
30 | |||
31 | static int as3711_list_voltage_sd(struct regulator_dev *rdev, | ||
32 | unsigned int selector) | ||
33 | { | ||
34 | if (selector >= rdev->desc->n_voltages) | ||
35 | return -EINVAL; | ||
36 | |||
37 | if (!selector) | ||
38 | return 0; | ||
39 | if (selector < 0x41) | ||
40 | return 600000 + selector * 12500; | ||
41 | if (selector < 0x71) | ||
42 | return 1400000 + (selector - 0x40) * 25000; | ||
43 | return 2600000 + (selector - 0x70) * 50000; | ||
44 | } | ||
45 | |||
46 | static int as3711_list_voltage_aldo(struct regulator_dev *rdev, | ||
47 | unsigned int selector) | ||
48 | { | ||
49 | if (selector >= rdev->desc->n_voltages) | ||
50 | return -EINVAL; | ||
51 | |||
52 | if (selector < 0x10) | ||
53 | return 1200000 + selector * 50000; | ||
54 | return 1800000 + (selector - 0x10) * 100000; | ||
55 | } | ||
56 | |||
57 | static int as3711_list_voltage_dldo(struct regulator_dev *rdev, | ||
58 | unsigned int selector) | ||
59 | { | ||
60 | if (selector >= rdev->desc->n_voltages || | ||
61 | (selector > 0x10 && selector < 0x20)) | ||
62 | return -EINVAL; | ||
63 | |||
64 | if (selector < 0x11) | ||
65 | return 900000 + selector * 50000; | ||
66 | return 1750000 + (selector - 0x20) * 50000; | ||
67 | } | ||
68 | |||
69 | static int as3711_bound_check(struct regulator_dev *rdev, | ||
70 | int *min_uV, int *max_uV) | ||
71 | { | ||
72 | struct as3711_regulator *reg = rdev_get_drvdata(rdev); | ||
73 | struct as3711_regulator_info *info = reg->reg_info; | ||
74 | |||
75 | dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__, | ||
76 | *min_uV, rdev->desc->min_uV, info->max_uV); | ||
77 | |||
78 | if (*max_uV < *min_uV || | ||
79 | *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV) | ||
80 | return -EINVAL; | ||
81 | |||
82 | if (rdev->desc->n_voltages == 1) | ||
83 | return 0; | ||
84 | |||
85 | if (*max_uV > info->max_uV) | ||
86 | *max_uV = info->max_uV; | ||
87 | |||
88 | if (*min_uV < rdev->desc->min_uV) | ||
89 | *min_uV = rdev->desc->min_uV; | ||
90 | |||
91 | return *min_uV; | ||
92 | } | ||
93 | |||
94 | static int as3711_sel_check(int min, int max, int bottom, int step) | ||
95 | { | ||
96 | int sel, voltage; | ||
97 | |||
98 | /* Round up min, when dividing: keeps us within the range */ | ||
99 | sel = DIV_ROUND_UP(min - bottom, step); | ||
100 | voltage = sel * step + bottom; | ||
101 | pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__, | ||
102 | min, max, bottom, step, sel); | ||
103 | if (voltage > max) | ||
104 | return -EINVAL; | ||
105 | |||
106 | return sel; | ||
107 | } | ||
108 | |||
109 | static int as3711_map_voltage_sd(struct regulator_dev *rdev, | ||
110 | int min_uV, int max_uV) | ||
111 | { | ||
112 | int ret; | ||
113 | |||
114 | ret = as3711_bound_check(rdev, &min_uV, &max_uV); | ||
115 | if (ret <= 0) | ||
116 | return ret; | ||
117 | |||
118 | if (min_uV <= 1400000) | ||
119 | return as3711_sel_check(min_uV, max_uV, 600000, 12500); | ||
120 | |||
121 | if (min_uV <= 2600000) | ||
122 | return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40; | ||
123 | |||
124 | return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and | ||
129 | * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes: | ||
130 | * FAST: sdX_fast=1 | ||
131 | * NORMAL: low_noise=1 | ||
132 | * IDLE: low_noise=0 | ||
133 | */ | ||
134 | |||
135 | static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode) | ||
136 | { | ||
137 | unsigned int fast_bit = rdev->desc->enable_mask, | ||
138 | low_noise_bit = fast_bit << 4; | ||
139 | u8 val; | ||
140 | |||
141 | switch (mode) { | ||
142 | case REGULATOR_MODE_FAST: | ||
143 | val = fast_bit | low_noise_bit; | ||
144 | break; | ||
145 | case REGULATOR_MODE_NORMAL: | ||
146 | val = low_noise_bit; | ||
147 | break; | ||
148 | case REGULATOR_MODE_IDLE: | ||
149 | val = 0; | ||
150 | break; | ||
151 | default: | ||
152 | return -EINVAL; | ||
153 | } | ||
154 | |||
155 | return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1, | ||
156 | low_noise_bit | fast_bit, val); | ||
157 | } | ||
158 | |||
159 | static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev) | ||
160 | { | ||
161 | unsigned int fast_bit = rdev->desc->enable_mask, | ||
162 | low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit; | ||
163 | unsigned int val; | ||
164 | int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val); | ||
165 | |||
166 | if (ret < 0) | ||
167 | return ret; | ||
168 | |||
169 | if ((val & mask) == mask) | ||
170 | return REGULATOR_MODE_FAST; | ||
171 | |||
172 | if ((val & mask) == low_noise_bit) | ||
173 | return REGULATOR_MODE_NORMAL; | ||
174 | |||
175 | if (!(val & mask)) | ||
176 | return REGULATOR_MODE_IDLE; | ||
177 | |||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | static int as3711_map_voltage_aldo(struct regulator_dev *rdev, | ||
182 | int min_uV, int max_uV) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | ret = as3711_bound_check(rdev, &min_uV, &max_uV); | ||
187 | if (ret <= 0) | ||
188 | return ret; | ||
189 | |||
190 | if (min_uV <= 1800000) | ||
191 | return as3711_sel_check(min_uV, max_uV, 1200000, 50000); | ||
192 | |||
193 | return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10; | ||
194 | } | ||
195 | |||
196 | static int as3711_map_voltage_dldo(struct regulator_dev *rdev, | ||
197 | int min_uV, int max_uV) | ||
198 | { | ||
199 | int ret; | ||
200 | |||
201 | ret = as3711_bound_check(rdev, &min_uV, &max_uV); | ||
202 | if (ret <= 0) | ||
203 | return ret; | ||
204 | |||
205 | if (min_uV <= 1700000) | ||
206 | return as3711_sel_check(min_uV, max_uV, 900000, 50000); | ||
207 | |||
208 | return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20; | ||
209 | } | ||
210 | |||
211 | static struct regulator_ops as3711_sd_ops = { | ||
212 | .is_enabled = regulator_is_enabled_regmap, | ||
213 | .enable = regulator_enable_regmap, | ||
214 | .disable = regulator_disable_regmap, | ||
215 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
216 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
217 | .list_voltage = as3711_list_voltage_sd, | ||
218 | .map_voltage = as3711_map_voltage_sd, | ||
219 | .get_mode = as3711_get_mode_sd, | ||
220 | .set_mode = as3711_set_mode_sd, | ||
221 | }; | ||
222 | |||
223 | static struct regulator_ops as3711_aldo_ops = { | ||
224 | .is_enabled = regulator_is_enabled_regmap, | ||
225 | .enable = regulator_enable_regmap, | ||
226 | .disable = regulator_disable_regmap, | ||
227 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
228 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
229 | .list_voltage = as3711_list_voltage_aldo, | ||
230 | .map_voltage = as3711_map_voltage_aldo, | ||
231 | }; | ||
232 | |||
233 | static struct regulator_ops as3711_dldo_ops = { | ||
234 | .is_enabled = regulator_is_enabled_regmap, | ||
235 | .enable = regulator_enable_regmap, | ||
236 | .disable = regulator_disable_regmap, | ||
237 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
238 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
239 | .list_voltage = as3711_list_voltage_dldo, | ||
240 | .map_voltage = as3711_map_voltage_dldo, | ||
241 | }; | ||
242 | |||
243 | #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \ | ||
244 | [AS3711_REGULATOR_ ## _id] = { \ | ||
245 | .desc = { \ | ||
246 | .name = "as3711-regulator-" # _id, \ | ||
247 | .id = AS3711_REGULATOR_ ## _id, \ | ||
248 | .n_voltages = (_vmask + 1), \ | ||
249 | .ops = &as3711_ ## _sfx ## _ops, \ | ||
250 | .type = REGULATOR_VOLTAGE, \ | ||
251 | .owner = THIS_MODULE, \ | ||
252 | .vsel_reg = AS3711_ ## _id ## _VOLTAGE, \ | ||
253 | .vsel_mask = _vmask << _vshift, \ | ||
254 | .enable_reg = AS3711_ ## _en_reg, \ | ||
255 | .enable_mask = BIT(_en_bit), \ | ||
256 | .min_uV = _min_uV, \ | ||
257 | }, \ | ||
258 | .max_uV = _max_uV, \ | ||
259 | } | ||
260 | |||
261 | static struct as3711_regulator_info as3711_reg_info[] = { | ||
262 | AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd), | ||
263 | AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd), | ||
264 | AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd), | ||
265 | AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd), | ||
266 | AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), | ||
267 | AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo), | ||
268 | AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), | ||
269 | AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), | ||
270 | AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), | ||
271 | AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), | ||
272 | AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), | ||
273 | AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo), | ||
274 | /* StepUp output voltage depends on supplying regulator */ | ||
275 | }; | ||
276 | |||
277 | #define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info) | ||
278 | |||
279 | static int as3711_regulator_probe(struct platform_device *pdev) | ||
280 | { | ||
281 | struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev); | ||
282 | struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent); | ||
283 | struct regulator_init_data *reg_data; | ||
284 | struct regulator_config config = {.dev = &pdev->dev,}; | ||
285 | struct as3711_regulator *reg = NULL; | ||
286 | struct as3711_regulator *regs; | ||
287 | struct regulator_dev *rdev; | ||
288 | struct as3711_regulator_info *ri; | ||
289 | int ret; | ||
290 | int id; | ||
291 | |||
292 | if (!pdata) | ||
293 | dev_dbg(&pdev->dev, "No platform data...\n"); | ||
294 | |||
295 | regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM * | ||
296 | sizeof(struct as3711_regulator), GFP_KERNEL); | ||
297 | if (!regs) { | ||
298 | dev_err(&pdev->dev, "Memory allocation failed exiting..\n"); | ||
299 | return -ENOMEM; | ||
300 | } | ||
301 | |||
302 | for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) { | ||
303 | reg_data = pdata ? pdata->init_data[id] : NULL; | ||
304 | |||
305 | /* No need to register if there is no regulator data */ | ||
306 | if (!ri->desc.name) | ||
307 | continue; | ||
308 | |||
309 | reg = ®s[id]; | ||
310 | reg->reg_info = ri; | ||
311 | |||
312 | config.init_data = reg_data; | ||
313 | config.driver_data = reg; | ||
314 | config.regmap = as3711->regmap; | ||
315 | |||
316 | rdev = regulator_register(&ri->desc, &config); | ||
317 | if (IS_ERR(rdev)) { | ||
318 | dev_err(&pdev->dev, "Failed to register regulator %s\n", | ||
319 | ri->desc.name); | ||
320 | ret = PTR_ERR(rdev); | ||
321 | goto eregreg; | ||
322 | } | ||
323 | reg->rdev = rdev; | ||
324 | } | ||
325 | platform_set_drvdata(pdev, regs); | ||
326 | return 0; | ||
327 | |||
328 | eregreg: | ||
329 | while (--id >= 0) | ||
330 | regulator_unregister(regs[id].rdev); | ||
331 | |||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | static int as3711_regulator_remove(struct platform_device *pdev) | ||
336 | { | ||
337 | struct as3711_regulator *regs = platform_get_drvdata(pdev); | ||
338 | int id; | ||
339 | |||
340 | for (id = 0; id < AS3711_REGULATOR_NUM; ++id) | ||
341 | regulator_unregister(regs[id].rdev); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static struct platform_driver as3711_regulator_driver = { | ||
346 | .driver = { | ||
347 | .name = "as3711-regulator", | ||
348 | .owner = THIS_MODULE, | ||
349 | }, | ||
350 | .probe = as3711_regulator_probe, | ||
351 | .remove = as3711_regulator_remove, | ||
352 | }; | ||
353 | |||
354 | static int __init as3711_regulator_init(void) | ||
355 | { | ||
356 | return platform_driver_register(&as3711_regulator_driver); | ||
357 | } | ||
358 | subsys_initcall(as3711_regulator_init); | ||
359 | |||
360 | static void __exit as3711_regulator_exit(void) | ||
361 | { | ||
362 | platform_driver_unregister(&as3711_regulator_driver); | ||
363 | } | ||
364 | module_exit(as3711_regulator_exit); | ||
365 | |||
366 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
367 | MODULE_DESCRIPTION("AS3711 regulator driver"); | ||
368 | MODULE_ALIAS("platform:as3711-regulator"); | ||
369 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5c4829cba6a6..59e08633372a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -1381,22 +1381,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id) | |||
1381 | } | 1381 | } |
1382 | EXPORT_SYMBOL_GPL(regulator_get_exclusive); | 1382 | EXPORT_SYMBOL_GPL(regulator_get_exclusive); |
1383 | 1383 | ||
1384 | /** | 1384 | /* Locks held by regulator_put() */ |
1385 | * regulator_put - "free" the regulator source | 1385 | static void _regulator_put(struct regulator *regulator) |
1386 | * @regulator: regulator source | ||
1387 | * | ||
1388 | * Note: drivers must ensure that all regulator_enable calls made on this | ||
1389 | * regulator source are balanced by regulator_disable calls prior to calling | ||
1390 | * this function. | ||
1391 | */ | ||
1392 | void regulator_put(struct regulator *regulator) | ||
1393 | { | 1386 | { |
1394 | struct regulator_dev *rdev; | 1387 | struct regulator_dev *rdev; |
1395 | 1388 | ||
1396 | if (regulator == NULL || IS_ERR(regulator)) | 1389 | if (regulator == NULL || IS_ERR(regulator)) |
1397 | return; | 1390 | return; |
1398 | 1391 | ||
1399 | mutex_lock(®ulator_list_mutex); | ||
1400 | rdev = regulator->rdev; | 1392 | rdev = regulator->rdev; |
1401 | 1393 | ||
1402 | debugfs_remove_recursive(regulator->debugfs); | 1394 | debugfs_remove_recursive(regulator->debugfs); |
@@ -1412,6 +1404,20 @@ void regulator_put(struct regulator *regulator) | |||
1412 | rdev->exclusive = 0; | 1404 | rdev->exclusive = 0; |
1413 | 1405 | ||
1414 | module_put(rdev->owner); | 1406 | module_put(rdev->owner); |
1407 | } | ||
1408 | |||
1409 | /** | ||
1410 | * regulator_put - "free" the regulator source | ||
1411 | * @regulator: regulator source | ||
1412 | * | ||
1413 | * Note: drivers must ensure that all regulator_enable calls made on this | ||
1414 | * regulator source are balanced by regulator_disable calls prior to calling | ||
1415 | * this function. | ||
1416 | */ | ||
1417 | void regulator_put(struct regulator *regulator) | ||
1418 | { | ||
1419 | mutex_lock(®ulator_list_mutex); | ||
1420 | _regulator_put(regulator); | ||
1415 | mutex_unlock(®ulator_list_mutex); | 1421 | mutex_unlock(®ulator_list_mutex); |
1416 | } | 1422 | } |
1417 | EXPORT_SYMBOL_GPL(regulator_put); | 1423 | EXPORT_SYMBOL_GPL(regulator_put); |
@@ -1861,6 +1867,28 @@ int regulator_is_enabled(struct regulator *regulator) | |||
1861 | EXPORT_SYMBOL_GPL(regulator_is_enabled); | 1867 | EXPORT_SYMBOL_GPL(regulator_is_enabled); |
1862 | 1868 | ||
1863 | /** | 1869 | /** |
1870 | * regulator_can_change_voltage - check if regulator can change voltage | ||
1871 | * @regulator: regulator source | ||
1872 | * | ||
1873 | * Returns positive if the regulator driver backing the source/client | ||
1874 | * can change its voltage, false otherwise. Usefull for detecting fixed | ||
1875 | * or dummy regulators and disabling voltage change logic in the client | ||
1876 | * driver. | ||
1877 | */ | ||
1878 | int regulator_can_change_voltage(struct regulator *regulator) | ||
1879 | { | ||
1880 | struct regulator_dev *rdev = regulator->rdev; | ||
1881 | |||
1882 | if (rdev->constraints && | ||
1883 | rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE && | ||
1884 | rdev->desc->n_voltages > 1) | ||
1885 | return 1; | ||
1886 | |||
1887 | return 0; | ||
1888 | } | ||
1889 | EXPORT_SYMBOL_GPL(regulator_can_change_voltage); | ||
1890 | |||
1891 | /** | ||
1864 | * regulator_count_voltages - count regulator_list_voltage() selectors | 1892 | * regulator_count_voltages - count regulator_list_voltage() selectors |
1865 | * @regulator: regulator source | 1893 | * @regulator: regulator source |
1866 | * | 1894 | * |
@@ -1974,7 +2002,7 @@ int regulator_is_supported_voltage(struct regulator *regulator, | |||
1974 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { | 2002 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { |
1975 | ret = regulator_get_voltage(regulator); | 2003 | ret = regulator_get_voltage(regulator); |
1976 | if (ret >= 0) | 2004 | if (ret >= 0) |
1977 | return (min_uV >= ret && ret <= max_uV); | 2005 | return (min_uV <= ret && ret <= max_uV); |
1978 | else | 2006 | else |
1979 | return ret; | 2007 | return ret; |
1980 | } | 2008 | } |
@@ -3365,7 +3393,7 @@ regulator_register(const struct regulator_desc *regulator_desc, | |||
3365 | if (ret != 0) { | 3393 | if (ret != 0) { |
3366 | rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", | 3394 | rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", |
3367 | config->ena_gpio, ret); | 3395 | config->ena_gpio, ret); |
3368 | goto clean; | 3396 | goto wash; |
3369 | } | 3397 | } |
3370 | 3398 | ||
3371 | rdev->ena_gpio = config->ena_gpio; | 3399 | rdev->ena_gpio = config->ena_gpio; |
@@ -3445,10 +3473,11 @@ unset_supplies: | |||
3445 | 3473 | ||
3446 | scrub: | 3474 | scrub: |
3447 | if (rdev->supply) | 3475 | if (rdev->supply) |
3448 | regulator_put(rdev->supply); | 3476 | _regulator_put(rdev->supply); |
3449 | if (rdev->ena_gpio) | 3477 | if (rdev->ena_gpio) |
3450 | gpio_free(rdev->ena_gpio); | 3478 | gpio_free(rdev->ena_gpio); |
3451 | kfree(rdev->constraints); | 3479 | kfree(rdev->constraints); |
3480 | wash: | ||
3452 | device_unregister(&rdev->dev); | 3481 | device_unregister(&rdev->dev); |
3453 | /* device core frees rdev */ | 3482 | /* device core frees rdev */ |
3454 | rdev = ERR_PTR(ret); | 3483 | rdev = ERR_PTR(ret); |
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 27355b1199e5..0a2586a39e6a 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c | |||
@@ -129,17 +129,17 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA, | |||
129 | else if (offset == 0) | 129 | else if (offset == 0) |
130 | row = 1; | 130 | row = 1; |
131 | 131 | ||
132 | if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] || | ||
133 | max_uA < da9052_current_limits[row][DA9052_MIN_UA]) | ||
134 | return -EINVAL; | ||
135 | |||
136 | for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) { | 132 | for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) { |
137 | if (da9052_current_limits[row][i] <= max_uA) { | 133 | if ((min_uA <= da9052_current_limits[row][i]) && |
134 | (da9052_current_limits[row][i] <= max_uA)) { | ||
138 | reg_val = i; | 135 | reg_val = i; |
139 | break; | 136 | break; |
140 | } | 137 | } |
141 | } | 138 | } |
142 | 139 | ||
140 | if (i < 0) | ||
141 | return -EINVAL; | ||
142 | |||
143 | /* Determine the even or odd position of the buck current limit | 143 | /* Determine the even or odd position of the buck current limit |
144 | * register field | 144 | * register field |
145 | */ | 145 | */ |
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 782c228a19bd..416fe0a37f56 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c | |||
@@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev, | |||
290 | if (vsel > dcdc->dvs_vsel) { | 290 | if (vsel > dcdc->dvs_vsel) { |
291 | ret = wm831x_set_bits(wm831x, dvs_reg, | 291 | ret = wm831x_set_bits(wm831x, dvs_reg, |
292 | WM831X_DC1_DVS_VSEL_MASK, | 292 | WM831X_DC1_DVS_VSEL_MASK, |
293 | dcdc->dvs_vsel); | 293 | vsel); |
294 | if (ret == 0) | 294 | if (ret == 0) |
295 | dcdc->dvs_vsel = vsel; | 295 | dcdc->dvs_vsel = vsel; |
296 | else | 296 | else |