diff options
Diffstat (limited to 'drivers/regulator/as3711-regulator.c')
-rw-r--r-- | drivers/regulator/as3711-regulator.c | 163 |
1 files changed, 31 insertions, 132 deletions
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c index 3da6bd6950cf..8406cd745da2 100644 --- a/drivers/regulator/as3711-regulator.c +++ b/drivers/regulator/as3711-regulator.c | |||
@@ -30,102 +30,6 @@ struct as3711_regulator { | |||
30 | struct regulator_dev *rdev; | 30 | struct regulator_dev *rdev; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | static int as3711_list_voltage_sd(struct regulator_dev *rdev, | ||
34 | unsigned int selector) | ||
35 | { | ||
36 | if (selector >= rdev->desc->n_voltages) | ||
37 | return -EINVAL; | ||
38 | |||
39 | if (!selector) | ||
40 | return 0; | ||
41 | if (selector < 0x41) | ||
42 | return 600000 + selector * 12500; | ||
43 | if (selector < 0x71) | ||
44 | return 1400000 + (selector - 0x40) * 25000; | ||
45 | return 2600000 + (selector - 0x70) * 50000; | ||
46 | } | ||
47 | |||
48 | static int as3711_list_voltage_aldo(struct regulator_dev *rdev, | ||
49 | unsigned int selector) | ||
50 | { | ||
51 | if (selector >= rdev->desc->n_voltages) | ||
52 | return -EINVAL; | ||
53 | |||
54 | if (selector < 0x10) | ||
55 | return 1200000 + selector * 50000; | ||
56 | return 1800000 + (selector - 0x10) * 100000; | ||
57 | } | ||
58 | |||
59 | static int as3711_list_voltage_dldo(struct regulator_dev *rdev, | ||
60 | unsigned int selector) | ||
61 | { | ||
62 | if (selector >= rdev->desc->n_voltages || | ||
63 | (selector > 0x10 && selector < 0x20)) | ||
64 | return -EINVAL; | ||
65 | |||
66 | if (selector < 0x11) | ||
67 | return 900000 + selector * 50000; | ||
68 | return 1750000 + (selector - 0x20) * 50000; | ||
69 | } | ||
70 | |||
71 | static int as3711_bound_check(struct regulator_dev *rdev, | ||
72 | int *min_uV, int *max_uV) | ||
73 | { | ||
74 | struct as3711_regulator *reg = rdev_get_drvdata(rdev); | ||
75 | struct as3711_regulator_info *info = reg->reg_info; | ||
76 | |||
77 | dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__, | ||
78 | *min_uV, rdev->desc->min_uV, info->max_uV); | ||
79 | |||
80 | if (*max_uV < *min_uV || | ||
81 | *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV) | ||
82 | return -EINVAL; | ||
83 | |||
84 | if (rdev->desc->n_voltages == 1) | ||
85 | return 0; | ||
86 | |||
87 | if (*max_uV > info->max_uV) | ||
88 | *max_uV = info->max_uV; | ||
89 | |||
90 | if (*min_uV < rdev->desc->min_uV) | ||
91 | *min_uV = rdev->desc->min_uV; | ||
92 | |||
93 | return *min_uV; | ||
94 | } | ||
95 | |||
96 | static int as3711_sel_check(int min, int max, int bottom, int step) | ||
97 | { | ||
98 | int sel, voltage; | ||
99 | |||
100 | /* Round up min, when dividing: keeps us within the range */ | ||
101 | sel = DIV_ROUND_UP(min - bottom, step); | ||
102 | voltage = sel * step + bottom; | ||
103 | pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__, | ||
104 | min, max, bottom, step, sel); | ||
105 | if (voltage > max) | ||
106 | return -EINVAL; | ||
107 | |||
108 | return sel; | ||
109 | } | ||
110 | |||
111 | static int as3711_map_voltage_sd(struct regulator_dev *rdev, | ||
112 | int min_uV, int max_uV) | ||
113 | { | ||
114 | int ret; | ||
115 | |||
116 | ret = as3711_bound_check(rdev, &min_uV, &max_uV); | ||
117 | if (ret <= 0) | ||
118 | return ret; | ||
119 | |||
120 | if (min_uV <= 1400000) | ||
121 | return as3711_sel_check(min_uV, max_uV, 600000, 12500); | ||
122 | |||
123 | if (min_uV <= 2600000) | ||
124 | return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40; | ||
125 | |||
126 | return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70; | ||
127 | } | ||
128 | |||
129 | /* | 33 | /* |
130 | * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and | 34 | * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and |
131 | * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes: | 35 | * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes: |
@@ -180,44 +84,14 @@ static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev) | |||
180 | return -EINVAL; | 84 | return -EINVAL; |
181 | } | 85 | } |
182 | 86 | ||
183 | static int as3711_map_voltage_aldo(struct regulator_dev *rdev, | ||
184 | int min_uV, int max_uV) | ||
185 | { | ||
186 | int ret; | ||
187 | |||
188 | ret = as3711_bound_check(rdev, &min_uV, &max_uV); | ||
189 | if (ret <= 0) | ||
190 | return ret; | ||
191 | |||
192 | if (min_uV <= 1800000) | ||
193 | return as3711_sel_check(min_uV, max_uV, 1200000, 50000); | ||
194 | |||
195 | return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10; | ||
196 | } | ||
197 | |||
198 | static int as3711_map_voltage_dldo(struct regulator_dev *rdev, | ||
199 | int min_uV, int max_uV) | ||
200 | { | ||
201 | int ret; | ||
202 | |||
203 | ret = as3711_bound_check(rdev, &min_uV, &max_uV); | ||
204 | if (ret <= 0) | ||
205 | return ret; | ||
206 | |||
207 | if (min_uV <= 1700000) | ||
208 | return as3711_sel_check(min_uV, max_uV, 900000, 50000); | ||
209 | |||
210 | return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20; | ||
211 | } | ||
212 | |||
213 | static struct regulator_ops as3711_sd_ops = { | 87 | static struct regulator_ops as3711_sd_ops = { |
214 | .is_enabled = regulator_is_enabled_regmap, | 88 | .is_enabled = regulator_is_enabled_regmap, |
215 | .enable = regulator_enable_regmap, | 89 | .enable = regulator_enable_regmap, |
216 | .disable = regulator_disable_regmap, | 90 | .disable = regulator_disable_regmap, |
217 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 91 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
218 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 92 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
219 | .list_voltage = as3711_list_voltage_sd, | 93 | .list_voltage = regulator_list_voltage_linear_range, |
220 | .map_voltage = as3711_map_voltage_sd, | 94 | .map_voltage = regulator_map_voltage_linear_range, |
221 | .get_mode = as3711_get_mode_sd, | 95 | .get_mode = as3711_get_mode_sd, |
222 | .set_mode = as3711_set_mode_sd, | 96 | .set_mode = as3711_set_mode_sd, |
223 | }; | 97 | }; |
@@ -228,8 +102,8 @@ static struct regulator_ops as3711_aldo_ops = { | |||
228 | .disable = regulator_disable_regmap, | 102 | .disable = regulator_disable_regmap, |
229 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 103 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
230 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 104 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
231 | .list_voltage = as3711_list_voltage_aldo, | 105 | .list_voltage = regulator_list_voltage_linear_range, |
232 | .map_voltage = as3711_map_voltage_aldo, | 106 | .map_voltage = regulator_map_voltage_linear_range, |
233 | }; | 107 | }; |
234 | 108 | ||
235 | static struct regulator_ops as3711_dldo_ops = { | 109 | static struct regulator_ops as3711_dldo_ops = { |
@@ -238,8 +112,31 @@ static struct regulator_ops as3711_dldo_ops = { | |||
238 | .disable = regulator_disable_regmap, | 112 | .disable = regulator_disable_regmap, |
239 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 113 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
240 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 114 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
241 | .list_voltage = as3711_list_voltage_dldo, | 115 | .list_voltage = regulator_list_voltage_linear_range, |
242 | .map_voltage = as3711_map_voltage_dldo, | 116 | .map_voltage = regulator_map_voltage_linear_range, |
117 | }; | ||
118 | |||
119 | static const struct regulator_linear_range as3711_sd_ranges[] = { | ||
120 | { .min_uV = 612500, .max_uV = 1400000, | ||
121 | .min_sel = 0x1, .max_sel = 0x40, .uV_step = 12500 }, | ||
122 | { .min_uV = 1425000, .max_uV = 2600000, | ||
123 | .min_sel = 0x41, .max_sel = 0x70, .uV_step = 25000 }, | ||
124 | { .min_uV = 2650000, .max_uV = 3350000, | ||
125 | .min_sel = 0x71, .max_sel = 0x7f, .uV_step = 50000 }, | ||
126 | }; | ||
127 | |||
128 | static const struct regulator_linear_range as3711_aldo_ranges[] = { | ||
129 | { .min_uV = 1200000, .max_uV = 1950000, | ||
130 | .min_sel = 0, .max_sel = 0xf, .uV_step = 50000 }, | ||
131 | { .min_uV = 1800000, .max_uV = 3300000, | ||
132 | .min_sel = 0x10, .max_sel = 0x1f, .uV_step = 100000 }, | ||
133 | }; | ||
134 | |||
135 | static const struct regulator_linear_range as3711_dldo_ranges[] = { | ||
136 | { .min_uV = 900000, .max_uV = 1700000, | ||
137 | .min_sel = 0, .max_sel = 0x10, .uV_step = 50000 }, | ||
138 | { .min_uV = 1750000, .max_uV = 3300000, | ||
139 | .min_sel = 0x20, .max_sel = 0x3f, .uV_step = 50000 }, | ||
243 | }; | 140 | }; |
244 | 141 | ||
245 | #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \ | 142 | #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \ |
@@ -256,6 +153,8 @@ static struct regulator_ops as3711_dldo_ops = { | |||
256 | .enable_reg = AS3711_ ## _en_reg, \ | 153 | .enable_reg = AS3711_ ## _en_reg, \ |
257 | .enable_mask = BIT(_en_bit), \ | 154 | .enable_mask = BIT(_en_bit), \ |
258 | .min_uV = _min_uV, \ | 155 | .min_uV = _min_uV, \ |
156 | .linear_ranges = as3711_ ## _sfx ## _ranges, \ | ||
157 | .n_linear_ranges = ARRAY_SIZE(as3711_ ## _sfx ## _ranges), \ | ||
259 | }, \ | 158 | }, \ |
260 | .max_uV = _max_uV, \ | 159 | .max_uV = _max_uV, \ |
261 | } | 160 | } |