Commit | Line | Data |
---|---|---|
f17ccc5d JN |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // | |
3 | // Regulator driver for tps6594 PMIC | |
4 | // | |
5 | // Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ | |
6 | ||
7 | #include <linux/device.h> | |
8 | #include <linux/err.h> | |
9 | #include <linux/init.h> | |
10 | #include <linux/kernel.h> | |
11 | #include <linux/module.h> | |
12 | #include <linux/of_device.h> | |
13 | #include <linux/platform_device.h> | |
14 | #include <linux/regmap.h> | |
15 | #include <linux/regulator/driver.h> | |
16 | #include <linux/regulator/machine.h> | |
17 | #include <linux/regulator/of_regulator.h> | |
18 | ||
19 | #include <linux/mfd/tps6594.h> | |
20 | ||
21 | #define BUCK_NB 5 | |
22 | #define LDO_NB 4 | |
23 | #define MULTI_PHASE_NB 4 | |
24 | #define REGS_INT_NB 4 | |
25 | ||
26 | enum tps6594_regulator_id { | |
27 | /* DCDC's */ | |
28 | TPS6594_BUCK_1, | |
29 | TPS6594_BUCK_2, | |
30 | TPS6594_BUCK_3, | |
31 | TPS6594_BUCK_4, | |
32 | TPS6594_BUCK_5, | |
33 | ||
34 | /* LDOs */ | |
35 | TPS6594_LDO_1, | |
36 | TPS6594_LDO_2, | |
37 | TPS6594_LDO_3, | |
38 | TPS6594_LDO_4, | |
39 | }; | |
40 | ||
41 | enum tps6594_multi_regulator_id { | |
42 | /* Multi-phase DCDC's */ | |
43 | TPS6594_BUCK_12, | |
44 | TPS6594_BUCK_34, | |
45 | TPS6594_BUCK_123, | |
46 | TPS6594_BUCK_1234, | |
47 | }; | |
48 | ||
49 | struct tps6594_regulator_irq_type { | |
50 | const char *irq_name; | |
51 | const char *regulator_name; | |
52 | const char *event_name; | |
53 | unsigned long event; | |
54 | }; | |
55 | ||
56 | static struct tps6594_regulator_irq_type tps6594_ext_regulator_irq_types[] = { | |
57 | { TPS6594_IRQ_NAME_VCCA_OV, "VCCA", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
58 | { TPS6594_IRQ_NAME_VCCA_UV, "VCCA", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
59 | { TPS6594_IRQ_NAME_VMON1_OV, "VMON1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
60 | { TPS6594_IRQ_NAME_VMON1_UV, "VMON1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
61 | { TPS6594_IRQ_NAME_VMON1_RV, "VMON1", "residual voltage", | |
62 | REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
63 | { TPS6594_IRQ_NAME_VMON2_OV, "VMON2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
64 | { TPS6594_IRQ_NAME_VMON2_UV, "VMON2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
65 | { TPS6594_IRQ_NAME_VMON2_RV, "VMON2", "residual voltage", | |
66 | REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
67 | }; | |
68 | ||
69 | struct tps6594_regulator_irq_data { | |
70 | struct device *dev; | |
71 | struct tps6594_regulator_irq_type *type; | |
72 | struct regulator_dev *rdev; | |
73 | }; | |
74 | ||
75 | struct tps6594_ext_regulator_irq_data { | |
76 | struct device *dev; | |
77 | struct tps6594_regulator_irq_type *type; | |
78 | }; | |
79 | ||
80 | #define TPS6594_REGULATOR(_name, _of, _id, _type, _ops, _n, _vr, _vm, _er, \ | |
81 | _em, _cr, _cm, _lr, _nlr, _delay, _fuv, \ | |
82 | _ct, _ncl, _bpm) \ | |
83 | { \ | |
84 | .name = _name, \ | |
85 | .of_match = _of, \ | |
86 | .regulators_node = of_match_ptr("regulators"), \ | |
87 | .supply_name = _of, \ | |
88 | .id = _id, \ | |
89 | .ops = &(_ops), \ | |
90 | .n_voltages = _n, \ | |
91 | .type = _type, \ | |
92 | .owner = THIS_MODULE, \ | |
93 | .vsel_reg = _vr, \ | |
94 | .vsel_mask = _vm, \ | |
95 | .csel_reg = _cr, \ | |
96 | .csel_mask = _cm, \ | |
97 | .curr_table = _ct, \ | |
98 | .n_current_limits = _ncl, \ | |
99 | .enable_reg = _er, \ | |
100 | .enable_mask = _em, \ | |
101 | .volt_table = NULL, \ | |
102 | .linear_ranges = _lr, \ | |
103 | .n_linear_ranges = _nlr, \ | |
104 | .ramp_delay = _delay, \ | |
105 | .fixed_uV = _fuv, \ | |
106 | .bypass_reg = _vr, \ | |
107 | .bypass_mask = _bpm, \ | |
108 | } \ | |
109 | ||
110 | static const struct linear_range bucks_ranges[] = { | |
111 | REGULATOR_LINEAR_RANGE(300000, 0x0, 0xe, 20000), | |
112 | REGULATOR_LINEAR_RANGE(600000, 0xf, 0x72, 5000), | |
113 | REGULATOR_LINEAR_RANGE(1100000, 0x73, 0xaa, 10000), | |
114 | REGULATOR_LINEAR_RANGE(1660000, 0xab, 0xff, 20000), | |
115 | }; | |
116 | ||
117 | static const struct linear_range ldos_1_2_3_ranges[] = { | |
118 | REGULATOR_LINEAR_RANGE(600000, 0x4, 0x3a, 50000), | |
119 | }; | |
120 | ||
121 | static const struct linear_range ldos_4_ranges[] = { | |
122 | REGULATOR_LINEAR_RANGE(1200000, 0x20, 0x74, 25000), | |
123 | }; | |
124 | ||
125 | /* Operations permitted on BUCK1/2/3/4/5 */ | |
126 | static const struct regulator_ops tps6594_bucks_ops = { | |
127 | .is_enabled = regulator_is_enabled_regmap, | |
128 | .enable = regulator_enable_regmap, | |
129 | .disable = regulator_disable_regmap, | |
130 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | |
131 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | |
132 | .list_voltage = regulator_list_voltage_linear_range, | |
133 | .map_voltage = regulator_map_voltage_linear_range, | |
134 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | |
135 | ||
136 | }; | |
137 | ||
138 | /* Operations permitted on LDO1/2/3 */ | |
139 | static const struct regulator_ops tps6594_ldos_1_2_3_ops = { | |
140 | .is_enabled = regulator_is_enabled_regmap, | |
141 | .enable = regulator_enable_regmap, | |
142 | .disable = regulator_disable_regmap, | |
143 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | |
144 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | |
145 | .list_voltage = regulator_list_voltage_linear_range, | |
146 | .map_voltage = regulator_map_voltage_linear_range, | |
147 | .set_bypass = regulator_set_bypass_regmap, | |
148 | .get_bypass = regulator_get_bypass_regmap, | |
149 | }; | |
150 | ||
151 | /* Operations permitted on LDO4 */ | |
152 | static const struct regulator_ops tps6594_ldos_4_ops = { | |
153 | .is_enabled = regulator_is_enabled_regmap, | |
154 | .enable = regulator_enable_regmap, | |
155 | .disable = regulator_disable_regmap, | |
156 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | |
157 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | |
158 | .list_voltage = regulator_list_voltage_linear_range, | |
159 | .map_voltage = regulator_map_voltage_linear_range, | |
160 | }; | |
161 | ||
162 | static const struct regulator_desc buck_regs[] = { | |
163 | TPS6594_REGULATOR("BUCK1", "buck1", TPS6594_BUCK_1, | |
164 | REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, | |
165 | TPS6594_REG_BUCKX_VOUT_1(0), | |
166 | TPS6594_MASK_BUCKS_VSET, | |
167 | TPS6594_REG_BUCKX_CTRL(0), | |
168 | TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, | |
169 | 4, 0, 0, NULL, 0, 0), | |
170 | TPS6594_REGULATOR("BUCK2", "buck2", TPS6594_BUCK_2, | |
171 | REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, | |
172 | TPS6594_REG_BUCKX_VOUT_1(1), | |
173 | TPS6594_MASK_BUCKS_VSET, | |
174 | TPS6594_REG_BUCKX_CTRL(1), | |
175 | TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, | |
176 | 4, 0, 0, NULL, 0, 0), | |
177 | TPS6594_REGULATOR("BUCK3", "buck3", TPS6594_BUCK_3, | |
178 | REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, | |
179 | TPS6594_REG_BUCKX_VOUT_1(2), | |
180 | TPS6594_MASK_BUCKS_VSET, | |
181 | TPS6594_REG_BUCKX_CTRL(2), | |
182 | TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, | |
183 | 4, 0, 0, NULL, 0, 0), | |
184 | TPS6594_REGULATOR("BUCK4", "buck4", TPS6594_BUCK_4, | |
185 | REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, | |
186 | TPS6594_REG_BUCKX_VOUT_1(3), | |
187 | TPS6594_MASK_BUCKS_VSET, | |
188 | TPS6594_REG_BUCKX_CTRL(3), | |
189 | TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, | |
190 | 4, 0, 0, NULL, 0, 0), | |
191 | TPS6594_REGULATOR("BUCK5", "buck5", TPS6594_BUCK_5, | |
192 | REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, | |
193 | TPS6594_REG_BUCKX_VOUT_1(4), | |
194 | TPS6594_MASK_BUCKS_VSET, | |
195 | TPS6594_REG_BUCKX_CTRL(4), | |
196 | TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, | |
197 | 4, 0, 0, NULL, 0, 0), | |
198 | }; | |
199 | ||
200 | static struct tps6594_regulator_irq_type tps6594_buck1_irq_types[] = { | |
201 | { TPS6594_IRQ_NAME_BUCK1_OV, "BUCK1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
202 | { TPS6594_IRQ_NAME_BUCK1_UV, "BUCK1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
203 | { TPS6594_IRQ_NAME_BUCK1_SC, "BUCK1", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, | |
204 | { TPS6594_IRQ_NAME_BUCK1_ILIM, "BUCK1", "reach ilim, overcurrent", | |
205 | REGULATOR_EVENT_OVER_CURRENT }, | |
206 | }; | |
207 | ||
208 | static struct tps6594_regulator_irq_type tps6594_buck2_irq_types[] = { | |
209 | { TPS6594_IRQ_NAME_BUCK2_OV, "BUCK2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
210 | { TPS6594_IRQ_NAME_BUCK2_UV, "BUCK2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
211 | { TPS6594_IRQ_NAME_BUCK2_SC, "BUCK2", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, | |
212 | { TPS6594_IRQ_NAME_BUCK2_ILIM, "BUCK2", "reach ilim, overcurrent", | |
213 | REGULATOR_EVENT_OVER_CURRENT }, | |
214 | }; | |
215 | ||
216 | static struct tps6594_regulator_irq_type tps6594_buck3_irq_types[] = { | |
217 | { TPS6594_IRQ_NAME_BUCK3_OV, "BUCK3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
218 | { TPS6594_IRQ_NAME_BUCK3_UV, "BUCK3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
219 | { TPS6594_IRQ_NAME_BUCK3_SC, "BUCK3", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, | |
220 | { TPS6594_IRQ_NAME_BUCK3_ILIM, "BUCK3", "reach ilim, overcurrent", | |
221 | REGULATOR_EVENT_OVER_CURRENT }, | |
222 | }; | |
223 | ||
224 | static struct tps6594_regulator_irq_type tps6594_buck4_irq_types[] = { | |
225 | { TPS6594_IRQ_NAME_BUCK4_OV, "BUCK4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
226 | { TPS6594_IRQ_NAME_BUCK4_UV, "BUCK4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
227 | { TPS6594_IRQ_NAME_BUCK4_SC, "BUCK4", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, | |
228 | { TPS6594_IRQ_NAME_BUCK4_ILIM, "BUCK4", "reach ilim, overcurrent", | |
229 | REGULATOR_EVENT_OVER_CURRENT }, | |
230 | }; | |
231 | ||
232 | static struct tps6594_regulator_irq_type tps6594_buck5_irq_types[] = { | |
233 | { TPS6594_IRQ_NAME_BUCK5_OV, "BUCK5", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
234 | { TPS6594_IRQ_NAME_BUCK5_UV, "BUCK5", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
235 | { TPS6594_IRQ_NAME_BUCK5_SC, "BUCK5", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, | |
236 | { TPS6594_IRQ_NAME_BUCK5_ILIM, "BUCK5", "reach ilim, overcurrent", | |
237 | REGULATOR_EVENT_OVER_CURRENT }, | |
238 | }; | |
239 | ||
240 | static struct tps6594_regulator_irq_type tps6594_ldo1_irq_types[] = { | |
241 | { TPS6594_IRQ_NAME_LDO1_OV, "LDO1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
242 | { TPS6594_IRQ_NAME_LDO1_UV, "LDO1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
243 | { TPS6594_IRQ_NAME_LDO1_SC, "LDO1", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, | |
244 | { TPS6594_IRQ_NAME_LDO1_ILIM, "LDO1", "reach ilim, overcurrent", | |
245 | REGULATOR_EVENT_OVER_CURRENT }, | |
246 | }; | |
247 | ||
248 | static struct tps6594_regulator_irq_type tps6594_ldo2_irq_types[] = { | |
249 | { TPS6594_IRQ_NAME_LDO2_OV, "LDO2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
250 | { TPS6594_IRQ_NAME_LDO2_UV, "LDO2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
251 | { TPS6594_IRQ_NAME_LDO2_SC, "LDO2", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, | |
252 | { TPS6594_IRQ_NAME_LDO2_ILIM, "LDO2", "reach ilim, overcurrent", | |
253 | REGULATOR_EVENT_OVER_CURRENT }, | |
254 | }; | |
255 | ||
256 | static struct tps6594_regulator_irq_type tps6594_ldo3_irq_types[] = { | |
257 | { TPS6594_IRQ_NAME_LDO3_OV, "LDO3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
258 | { TPS6594_IRQ_NAME_LDO3_UV, "LDO3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
259 | { TPS6594_IRQ_NAME_LDO3_SC, "LDO3", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, | |
260 | { TPS6594_IRQ_NAME_LDO3_ILIM, "LDO3", "reach ilim, overcurrent", | |
261 | REGULATOR_EVENT_OVER_CURRENT }, | |
262 | }; | |
263 | ||
264 | static struct tps6594_regulator_irq_type tps6594_ldo4_irq_types[] = { | |
265 | { TPS6594_IRQ_NAME_LDO4_OV, "LDO4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, | |
266 | { TPS6594_IRQ_NAME_LDO4_UV, "LDO4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, | |
267 | { TPS6594_IRQ_NAME_LDO4_SC, "LDO4", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, | |
268 | { TPS6594_IRQ_NAME_LDO4_ILIM, "LDO4", "reach ilim, overcurrent", | |
269 | REGULATOR_EVENT_OVER_CURRENT }, | |
270 | }; | |
271 | ||
272 | static struct tps6594_regulator_irq_type *tps6594_bucks_irq_types[] = { | |
273 | tps6594_buck1_irq_types, | |
274 | tps6594_buck2_irq_types, | |
275 | tps6594_buck3_irq_types, | |
276 | tps6594_buck4_irq_types, | |
277 | tps6594_buck5_irq_types, | |
278 | }; | |
279 | ||
280 | static struct tps6594_regulator_irq_type *tps6594_ldos_irq_types[] = { | |
281 | tps6594_ldo1_irq_types, | |
282 | tps6594_ldo2_irq_types, | |
283 | tps6594_ldo3_irq_types, | |
284 | tps6594_ldo4_irq_types, | |
285 | }; | |
286 | ||
287 | static const struct regulator_desc multi_regs[] = { | |
288 | TPS6594_REGULATOR("BUCK12", "buck12", TPS6594_BUCK_1, | |
289 | REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, | |
290 | TPS6594_REG_BUCKX_VOUT_1(1), | |
291 | TPS6594_MASK_BUCKS_VSET, | |
292 | TPS6594_REG_BUCKX_CTRL(1), | |
293 | TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, | |
294 | 4, 4000, 0, NULL, 0, 0), | |
295 | TPS6594_REGULATOR("BUCK34", "buck34", TPS6594_BUCK_3, | |
296 | REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, | |
297 | TPS6594_REG_BUCKX_VOUT_1(3), | |
298 | TPS6594_MASK_BUCKS_VSET, | |
299 | TPS6594_REG_BUCKX_CTRL(3), | |
300 | TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, | |
301 | 4, 0, 0, NULL, 0, 0), | |
302 | TPS6594_REGULATOR("BUCK123", "buck123", TPS6594_BUCK_1, | |
303 | REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, | |
304 | TPS6594_REG_BUCKX_VOUT_1(1), | |
305 | TPS6594_MASK_BUCKS_VSET, | |
306 | TPS6594_REG_BUCKX_CTRL(1), | |
307 | TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, | |
308 | 4, 4000, 0, NULL, 0, 0), | |
309 | TPS6594_REGULATOR("BUCK1234", "buck1234", TPS6594_BUCK_1, | |
310 | REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, | |
311 | TPS6594_REG_BUCKX_VOUT_1(1), | |
312 | TPS6594_MASK_BUCKS_VSET, | |
313 | TPS6594_REG_BUCKX_CTRL(1), | |
314 | TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges, | |
315 | 4, 4000, 0, NULL, 0, 0), | |
316 | }; | |
317 | ||
318 | static const struct regulator_desc ldo_regs[] = { | |
319 | TPS6594_REGULATOR("LDO1", "ldo1", TPS6594_LDO_1, | |
320 | REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, | |
321 | TPS6594_REG_LDOX_VOUT(0), | |
322 | TPS6594_MASK_LDO123_VSET, | |
323 | TPS6594_REG_LDOX_CTRL(0), | |
324 | TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges, | |
325 | 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS), | |
326 | TPS6594_REGULATOR("LDO2", "ldo2", TPS6594_LDO_2, | |
327 | REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, | |
328 | TPS6594_REG_LDOX_VOUT(1), | |
329 | TPS6594_MASK_LDO123_VSET, | |
330 | TPS6594_REG_LDOX_CTRL(1), | |
331 | TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges, | |
332 | 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS), | |
333 | TPS6594_REGULATOR("LDO3", "ldo3", TPS6594_LDO_3, | |
334 | REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET, | |
335 | TPS6594_REG_LDOX_VOUT(2), | |
336 | TPS6594_MASK_LDO123_VSET, | |
337 | TPS6594_REG_LDOX_CTRL(2), | |
338 | TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges, | |
339 | 1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS), | |
340 | TPS6594_REGULATOR("LDO4", "ldo4", TPS6594_LDO_4, | |
341 | REGULATOR_VOLTAGE, tps6594_ldos_4_ops, TPS6594_MASK_LDO4_VSET >> 1, | |
342 | TPS6594_REG_LDOX_VOUT(3), | |
343 | TPS6594_MASK_LDO4_VSET, | |
344 | TPS6594_REG_LDOX_CTRL(3), | |
345 | TPS6594_BIT_LDO_EN, 0, 0, ldos_4_ranges, | |
346 | 1, 0, 0, NULL, 0, 0), | |
347 | }; | |
348 | ||
349 | static irqreturn_t tps6594_regulator_irq_handler(int irq, void *data) | |
350 | { | |
351 | struct tps6594_regulator_irq_data *irq_data = data; | |
352 | ||
353 | if (irq_data->type->event_name[0] == '\0') { | |
354 | /* This is the timeout interrupt no specific regulator */ | |
355 | dev_err(irq_data->dev, | |
356 | "System was put in shutdown due to timeout during an active or standby transition.\n"); | |
357 | return IRQ_HANDLED; | |
358 | } | |
359 | ||
360 | dev_err(irq_data->dev, "Error IRQ trap %s for %s\n", | |
361 | irq_data->type->event_name, irq_data->type->regulator_name); | |
362 | ||
363 | regulator_notifier_call_chain(irq_data->rdev, | |
364 | irq_data->type->event, NULL); | |
365 | ||
366 | return IRQ_HANDLED; | |
367 | } | |
368 | ||
369 | static int tps6594_request_reg_irqs(struct platform_device *pdev, | |
370 | struct regulator_dev *rdev, | |
371 | struct tps6594_regulator_irq_data *irq_data, | |
372 | struct tps6594_regulator_irq_type *tps6594_regs_irq_types, | |
373 | int *irq_idx) | |
374 | { | |
375 | struct tps6594_regulator_irq_type *irq_type; | |
376 | struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); | |
377 | int j; | |
378 | int irq; | |
379 | int error; | |
380 | ||
381 | for (j = 0; j < REGS_INT_NB; j++) { | |
382 | irq_type = &tps6594_regs_irq_types[j]; | |
383 | irq = platform_get_irq_byname(pdev, irq_type->irq_name); | |
384 | if (irq < 0) | |
385 | return -EINVAL; | |
386 | ||
387 | irq_data[*irq_idx + j].dev = tps->dev; | |
388 | irq_data[*irq_idx + j].type = irq_type; | |
389 | irq_data[*irq_idx + j].rdev = rdev; | |
390 | ||
391 | error = devm_request_threaded_irq(tps->dev, irq, NULL, | |
392 | tps6594_regulator_irq_handler, | |
393 | IRQF_ONESHOT, | |
394 | irq_type->irq_name, | |
395 | &irq_data[*irq_idx]); | |
396 | (*irq_idx)++; | |
397 | if (error) { | |
398 | dev_err(tps->dev, "tps6594 failed to request %s IRQ %d: %d\n", | |
399 | irq_type->irq_name, irq, error); | |
400 | return error; | |
401 | } | |
402 | } | |
403 | return 0; | |
404 | } | |
405 | ||
406 | static int tps6594_regulator_probe(struct platform_device *pdev) | |
407 | { | |
408 | struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); | |
409 | struct regulator_dev *rdev; | |
410 | struct device_node *np = NULL; | |
411 | struct device_node *np_pmic_parent = NULL; | |
412 | struct regulator_config config = {}; | |
413 | struct tps6594_regulator_irq_data *irq_data; | |
414 | struct tps6594_ext_regulator_irq_data *irq_ext_reg_data; | |
415 | struct tps6594_regulator_irq_type *irq_type; | |
416 | u8 buck_configured[BUCK_NB] = { 0 }; | |
417 | u8 buck_multi[MULTI_PHASE_NB] = { 0 }; | |
418 | static const char * const multiphases[] = {"buck12", "buck123", "buck1234", "buck34"}; | |
419 | static const char *npname; | |
420 | int error, i, irq, multi, delta; | |
421 | int irq_idx = 0; | |
422 | int buck_idx = 0; | |
423 | int ext_reg_irq_nb = 2; | |
424 | ||
425 | enum { | |
426 | MULTI_BUCK12, | |
427 | MULTI_BUCK123, | |
428 | MULTI_BUCK1234, | |
429 | MULTI_BUCK12_34, | |
430 | MULTI_FIRST = MULTI_BUCK12, | |
431 | MULTI_LAST = MULTI_BUCK12_34, | |
432 | MULTI_NUM = MULTI_LAST - MULTI_FIRST + 1 | |
433 | }; | |
434 | ||
435 | config.dev = tps->dev; | |
436 | config.driver_data = tps; | |
437 | config.regmap = tps->regmap; | |
438 | ||
439 | /* | |
440 | * Switch case defines different possible multi phase config | |
441 | * This is based on dts buck node name. | |
442 | * Buck node name must be chosen accordingly. | |
443 | * Default case is no Multiphase buck. | |
444 | * In case of Multiphase configuration, value should be defined for | |
445 | * buck_configured to avoid creating bucks for every buck in multiphase | |
446 | */ | |
447 | for (multi = MULTI_FIRST; multi < MULTI_NUM; multi++) { | |
448 | np = of_find_node_by_name(tps->dev->of_node, multiphases[multi]); | |
449 | npname = of_node_full_name(np); | |
450 | np_pmic_parent = of_get_parent(of_get_parent(np)); | |
451 | if (of_node_cmp(of_node_full_name(np_pmic_parent), tps->dev->of_node->full_name)) | |
452 | continue; | |
453 | delta = strcmp(npname, multiphases[multi]); | |
454 | if (!delta) { | |
455 | switch (multi) { | |
456 | case MULTI_BUCK12: | |
457 | buck_multi[0] = 1; | |
458 | buck_configured[0] = 1; | |
459 | buck_configured[1] = 1; | |
460 | break; | |
461 | /* multiphase buck34 is supported only with buck12 */ | |
462 | case MULTI_BUCK12_34: | |
463 | buck_multi[0] = 1; | |
464 | buck_multi[1] = 1; | |
465 | buck_configured[0] = 1; | |
466 | buck_configured[1] = 1; | |
467 | buck_configured[2] = 1; | |
468 | buck_configured[3] = 1; | |
469 | break; | |
470 | case MULTI_BUCK123: | |
471 | buck_multi[2] = 1; | |
472 | buck_configured[0] = 1; | |
473 | buck_configured[1] = 1; | |
474 | buck_configured[2] = 1; | |
475 | break; | |
476 | case MULTI_BUCK1234: | |
477 | buck_multi[3] = 1; | |
478 | buck_configured[0] = 1; | |
479 | buck_configured[1] = 1; | |
480 | buck_configured[2] = 1; | |
481 | buck_configured[3] = 1; | |
482 | break; | |
483 | } | |
484 | } | |
485 | } | |
486 | ||
487 | if (tps->chip_id == LP8764) | |
488 | /* There is only 4 buck on LP8764 */ | |
489 | buck_configured[4] = 1; | |
490 | ||
491 | irq_data = devm_kmalloc_array(tps->dev, | |
492 | REGS_INT_NB * sizeof(struct tps6594_regulator_irq_data), | |
493 | ARRAY_SIZE(tps6594_bucks_irq_types) + | |
494 | ARRAY_SIZE(tps6594_ldos_irq_types), | |
495 | GFP_KERNEL); | |
496 | if (!irq_data) | |
497 | return -ENOMEM; | |
498 | ||
499 | for (i = 0; i < MULTI_PHASE_NB; i++) { | |
500 | if (buck_multi[i] == 0) | |
501 | continue; | |
502 | ||
503 | rdev = devm_regulator_register(&pdev->dev, &multi_regs[i], &config); | |
504 | if (IS_ERR(rdev)) | |
505 | return dev_err_probe(tps->dev, PTR_ERR(rdev), | |
506 | "failed to register %s regulator\n", | |
507 | pdev->name); | |
508 | ||
509 | /* config multiphase buck12+buck34 */ | |
510 | if (i == 1) | |
511 | buck_idx = 2; | |
512 | error = tps6594_request_reg_irqs(pdev, rdev, irq_data, | |
513 | tps6594_bucks_irq_types[buck_idx], &irq_idx); | |
514 | if (error) | |
515 | return error; | |
516 | error = tps6594_request_reg_irqs(pdev, rdev, irq_data, | |
517 | tps6594_bucks_irq_types[buck_idx + 1], &irq_idx); | |
518 | if (error) | |
519 | return error; | |
520 | ||
521 | if (i == 2 || i == 3) { | |
522 | error = tps6594_request_reg_irqs(pdev, rdev, irq_data, | |
523 | tps6594_bucks_irq_types[buck_idx + 2], | |
524 | &irq_idx); | |
525 | if (error) | |
526 | return error; | |
527 | } | |
528 | if (i == 3) { | |
529 | error = tps6594_request_reg_irqs(pdev, rdev, irq_data, | |
530 | tps6594_bucks_irq_types[buck_idx + 3], | |
531 | &irq_idx); | |
532 | if (error) | |
533 | return error; | |
534 | } | |
535 | } | |
536 | ||
537 | for (i = 0; i < BUCK_NB; i++) { | |
538 | if (buck_configured[i] == 1) | |
539 | continue; | |
540 | ||
541 | rdev = devm_regulator_register(&pdev->dev, &buck_regs[i], &config); | |
542 | if (IS_ERR(rdev)) | |
543 | return dev_err_probe(tps->dev, PTR_ERR(rdev), | |
544 | "failed to register %s regulator\n", | |
545 | pdev->name); | |
546 | ||
547 | error = tps6594_request_reg_irqs(pdev, rdev, irq_data, | |
548 | tps6594_bucks_irq_types[i], &irq_idx); | |
549 | if (error) | |
550 | return error; | |
551 | } | |
552 | ||
553 | /* LP8764 dosen't have LDO */ | |
554 | if (tps->chip_id != LP8764) { | |
555 | for (i = 0; i < ARRAY_SIZE(ldo_regs); i++) { | |
556 | rdev = devm_regulator_register(&pdev->dev, &ldo_regs[i], &config); | |
557 | if (IS_ERR(rdev)) | |
558 | return dev_err_probe(tps->dev, PTR_ERR(rdev), | |
559 | "failed to register %s regulator\n", | |
560 | pdev->name); | |
561 | ||
562 | error = tps6594_request_reg_irqs(pdev, rdev, irq_data, | |
563 | tps6594_ldos_irq_types[i], | |
564 | &irq_idx); | |
565 | if (error) | |
566 | return error; | |
567 | } | |
568 | } | |
569 | ||
570 | if (tps->chip_id == LP8764) | |
571 | ext_reg_irq_nb = ARRAY_SIZE(tps6594_ext_regulator_irq_types); | |
572 | ||
573 | irq_ext_reg_data = devm_kmalloc_array(tps->dev, | |
574 | ext_reg_irq_nb, | |
575 | sizeof(struct tps6594_ext_regulator_irq_data), | |
576 | GFP_KERNEL); | |
577 | if (!irq_ext_reg_data) | |
578 | return -ENOMEM; | |
579 | ||
580 | for (i = 0; i < ext_reg_irq_nb; ++i) { | |
581 | irq_type = &tps6594_ext_regulator_irq_types[i]; | |
582 | ||
583 | irq = platform_get_irq_byname(pdev, irq_type->irq_name); | |
584 | if (irq < 0) | |
585 | return -EINVAL; | |
586 | ||
587 | irq_ext_reg_data[i].dev = tps->dev; | |
588 | irq_ext_reg_data[i].type = irq_type; | |
589 | ||
590 | error = devm_request_threaded_irq(tps->dev, irq, NULL, | |
591 | tps6594_regulator_irq_handler, | |
592 | IRQF_ONESHOT, | |
593 | irq_type->irq_name, | |
594 | &irq_ext_reg_data[i]); | |
595 | if (error) | |
596 | return dev_err_probe(tps->dev, error, | |
597 | "failed to request %s IRQ %d\n", | |
598 | irq_type->irq_name, irq); | |
599 | } | |
600 | return 0; | |
601 | } | |
602 | ||
603 | static struct platform_driver tps6594_regulator_driver = { | |
604 | .driver = { | |
605 | .name = "tps6594-regulator", | |
606 | }, | |
607 | .probe = tps6594_regulator_probe, | |
608 | }; | |
609 | ||
610 | module_platform_driver(tps6594_regulator_driver); | |
611 | ||
612 | MODULE_ALIAS("platform:tps6594-regulator"); | |
613 | MODULE_AUTHOR("Jerome Neanne <jneanne@baylibre.com>"); | |
614 | MODULE_DESCRIPTION("TPS6594 voltage regulator driver"); | |
615 | MODULE_LICENSE("GPL"); |