1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * tps65023-regulator.c |
4 | * |
5 | * Supports TPS65023 Regulator |
6 | * |
7 | * Copyright (C) 2009 Texas Instrument Incorporated - https://www.ti.com/ |
8 | */ |
9 | |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/init.h> |
13 | #include <linux/err.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/regulator/driver.h> |
16 | #include <linux/regulator/machine.h> |
17 | #include <linux/i2c.h> |
18 | #include <linux/slab.h> |
19 | #include <linux/regmap.h> |
20 | |
21 | /* Register definitions */ |
22 | #define TPS65023_REG_VERSION 0 |
23 | #define TPS65023_REG_PGOODZ 1 |
24 | #define TPS65023_REG_MASK 2 |
25 | #define TPS65023_REG_REG_CTRL 3 |
26 | #define TPS65023_REG_CON_CTRL 4 |
27 | #define TPS65023_REG_CON_CTRL2 5 |
28 | #define TPS65023_REG_DEF_CORE 6 |
29 | #define TPS65023_REG_DEFSLEW 7 |
30 | #define TPS65023_REG_LDO_CTRL 8 |
31 | |
32 | /* PGOODZ bitfields */ |
33 | #define TPS65023_PGOODZ_PWRFAILZ BIT(7) |
34 | #define TPS65023_PGOODZ_LOWBATTZ BIT(6) |
35 | #define TPS65023_PGOODZ_VDCDC1 BIT(5) |
36 | #define TPS65023_PGOODZ_VDCDC2 BIT(4) |
37 | #define TPS65023_PGOODZ_VDCDC3 BIT(3) |
38 | #define TPS65023_PGOODZ_LDO2 BIT(2) |
39 | #define TPS65023_PGOODZ_LDO1 BIT(1) |
40 | |
41 | /* MASK bitfields */ |
42 | #define TPS65023_MASK_PWRFAILZ BIT(7) |
43 | #define TPS65023_MASK_LOWBATTZ BIT(6) |
44 | #define TPS65023_MASK_VDCDC1 BIT(5) |
45 | #define TPS65023_MASK_VDCDC2 BIT(4) |
46 | #define TPS65023_MASK_VDCDC3 BIT(3) |
47 | #define TPS65023_MASK_LDO2 BIT(2) |
48 | #define TPS65023_MASK_LDO1 BIT(1) |
49 | |
50 | /* REG_CTRL bitfields */ |
51 | #define TPS65023_REG_CTRL_VDCDC1_EN BIT(5) |
52 | #define TPS65023_REG_CTRL_VDCDC2_EN BIT(4) |
53 | #define TPS65023_REG_CTRL_VDCDC3_EN BIT(3) |
54 | #define TPS65023_REG_CTRL_LDO2_EN BIT(2) |
55 | #define TPS65023_REG_CTRL_LDO1_EN BIT(1) |
56 | |
57 | /* REG_CTRL2 bitfields */ |
58 | #define TPS65023_REG_CTRL2_GO BIT(7) |
59 | #define TPS65023_REG_CTRL2_CORE_ADJ BIT(6) |
60 | #define TPS65023_REG_CTRL2_DCDC2 BIT(2) |
61 | #define TPS65023_REG_CTRL2_DCDC1 BIT(1) |
62 | #define TPS65023_REG_CTRL2_DCDC3 BIT(0) |
63 | |
64 | /* Number of step-down converters available */ |
65 | #define TPS65023_NUM_DCDC 3 |
66 | /* Number of LDO voltage regulators available */ |
67 | #define TPS65023_NUM_LDO 2 |
68 | /* Number of total regulators available */ |
69 | #define TPS65023_NUM_REGULATOR (TPS65023_NUM_DCDC + TPS65023_NUM_LDO) |
70 | |
71 | /* DCDCs */ |
72 | #define TPS65023_DCDC_1 0 |
73 | #define TPS65023_DCDC_2 1 |
74 | #define TPS65023_DCDC_3 2 |
75 | /* LDOs */ |
76 | #define TPS65023_LDO_1 3 |
77 | #define TPS65023_LDO_2 4 |
78 | |
79 | #define TPS65023_MAX_REG_ID TPS65023_LDO_2 |
80 | |
81 | #define TPS65023_REGULATOR_DCDC(_num, _t, _em) \ |
82 | { \ |
83 | .name = "VDCDC"#_num, \ |
84 | .of_match = of_match_ptr("VDCDC"#_num), \ |
85 | .regulators_node = of_match_ptr("regulators"), \ |
86 | .id = TPS65023_DCDC_##_num, \ |
87 | .n_voltages = ARRAY_SIZE(_t), \ |
88 | .ops = &tps65023_dcdc_ops, \ |
89 | .type = REGULATOR_VOLTAGE, \ |
90 | .owner = THIS_MODULE, \ |
91 | .volt_table = _t, \ |
92 | .vsel_reg = TPS65023_REG_DEF_CORE, \ |
93 | .vsel_mask = ARRAY_SIZE(_t) - 1, \ |
94 | .enable_mask = _em, \ |
95 | .enable_reg = TPS65023_REG_REG_CTRL, \ |
96 | .apply_reg = TPS65023_REG_CON_CTRL2, \ |
97 | .apply_bit = TPS65023_REG_CTRL2_GO, \ |
98 | } \ |
99 | |
100 | #define TPS65023_REGULATOR_LDO(_num, _t, _vm) \ |
101 | { \ |
102 | .name = "LDO"#_num, \ |
103 | .of_match = of_match_ptr("LDO"#_num), \ |
104 | .regulators_node = of_match_ptr("regulators"), \ |
105 | .id = TPS65023_LDO_##_num, \ |
106 | .n_voltages = ARRAY_SIZE(_t), \ |
107 | .ops = &tps65023_ldo_ops, \ |
108 | .type = REGULATOR_VOLTAGE, \ |
109 | .owner = THIS_MODULE, \ |
110 | .volt_table = _t, \ |
111 | .vsel_reg = TPS65023_REG_LDO_CTRL, \ |
112 | .vsel_mask = _vm, \ |
113 | .enable_mask = 1 << (_num), \ |
114 | .enable_reg = TPS65023_REG_REG_CTRL, \ |
115 | } \ |
116 | |
117 | /* Supported voltage values for regulators */ |
118 | static const unsigned int VCORE_VSEL_table[] = { |
119 | 800000, 825000, 850000, 875000, |
120 | 900000, 925000, 950000, 975000, |
121 | 1000000, 1025000, 1050000, 1075000, |
122 | 1100000, 1125000, 1150000, 1175000, |
123 | 1200000, 1225000, 1250000, 1275000, |
124 | 1300000, 1325000, 1350000, 1375000, |
125 | 1400000, 1425000, 1450000, 1475000, |
126 | 1500000, 1525000, 1550000, 1600000, |
127 | }; |
128 | |
129 | static const unsigned int DCDC_FIXED_3300000_VSEL_table[] = { |
130 | 3300000, |
131 | }; |
132 | |
133 | static const unsigned int DCDC_FIXED_1800000_VSEL_table[] = { |
134 | 1800000, |
135 | }; |
136 | |
137 | /* Supported voltage values for LDO regulators for tps65020 */ |
138 | static const unsigned int TPS65020_LDO_VSEL_table[] = { |
139 | 1000000, 1050000, 1100000, 1300000, |
140 | 1800000, 2500000, 3000000, 3300000, |
141 | }; |
142 | |
143 | /* Supported voltage values for LDO regulators |
144 | * for tps65021 and tps65023 */ |
145 | static const unsigned int TPS65023_LDO1_VSEL_table[] = { |
146 | 1000000, 1100000, 1300000, 1800000, |
147 | 2200000, 2600000, 2800000, 3150000, |
148 | }; |
149 | |
150 | static const unsigned int TPS65023_LDO2_VSEL_table[] = { |
151 | 1050000, 1200000, 1300000, 1800000, |
152 | 2500000, 2800000, 3000000, 3300000, |
153 | }; |
154 | |
155 | /* PMIC details */ |
156 | struct tps_pmic { |
157 | struct regulator_dev *rdev[TPS65023_NUM_REGULATOR]; |
158 | const struct tps_driver_data *driver_data; |
159 | struct regmap *regmap; |
160 | }; |
161 | |
162 | /* Struct passed as driver data */ |
163 | struct tps_driver_data { |
164 | const struct regulator_desc *desc; |
165 | u8 core_regulator; |
166 | }; |
167 | |
168 | static int tps65023_dcdc_get_voltage_sel(struct regulator_dev *dev) |
169 | { |
170 | struct tps_pmic *tps = rdev_get_drvdata(rdev: dev); |
171 | int dcdc = rdev_get_id(rdev: dev); |
172 | |
173 | if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) |
174 | return -EINVAL; |
175 | |
176 | if (dcdc != tps->driver_data->core_regulator) |
177 | return 0; |
178 | |
179 | return regulator_get_voltage_sel_regmap(rdev: dev); |
180 | } |
181 | |
182 | static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev, |
183 | unsigned selector) |
184 | { |
185 | struct tps_pmic *tps = rdev_get_drvdata(rdev: dev); |
186 | int dcdc = rdev_get_id(rdev: dev); |
187 | |
188 | if (dcdc != tps->driver_data->core_regulator) |
189 | return -EINVAL; |
190 | |
191 | return regulator_set_voltage_sel_regmap(rdev: dev, sel: selector); |
192 | } |
193 | |
194 | /* Operations permitted on VDCDCx */ |
195 | static const struct regulator_ops tps65023_dcdc_ops = { |
196 | .is_enabled = regulator_is_enabled_regmap, |
197 | .enable = regulator_enable_regmap, |
198 | .disable = regulator_disable_regmap, |
199 | .get_voltage_sel = tps65023_dcdc_get_voltage_sel, |
200 | .set_voltage_sel = tps65023_dcdc_set_voltage_sel, |
201 | .list_voltage = regulator_list_voltage_table, |
202 | .map_voltage = regulator_map_voltage_ascend, |
203 | }; |
204 | |
205 | /* Operations permitted on LDOx */ |
206 | static const struct regulator_ops tps65023_ldo_ops = { |
207 | .is_enabled = regulator_is_enabled_regmap, |
208 | .enable = regulator_enable_regmap, |
209 | .disable = regulator_disable_regmap, |
210 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
211 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
212 | .list_voltage = regulator_list_voltage_table, |
213 | .map_voltage = regulator_map_voltage_ascend, |
214 | }; |
215 | |
216 | static const struct regmap_config tps65023_regmap_config = { |
217 | .reg_bits = 8, |
218 | .val_bits = 8, |
219 | }; |
220 | |
221 | static const struct regulator_desc tps65020_regulators[] = { |
222 | TPS65023_REGULATOR_DCDC(1, DCDC_FIXED_3300000_VSEL_table, 0x20), |
223 | TPS65023_REGULATOR_DCDC(2, DCDC_FIXED_1800000_VSEL_table, 0x10), |
224 | TPS65023_REGULATOR_DCDC(3, VCORE_VSEL_table, 0x08), |
225 | TPS65023_REGULATOR_LDO(1, TPS65020_LDO_VSEL_table, 0x07), |
226 | TPS65023_REGULATOR_LDO(2, TPS65020_LDO_VSEL_table, 0x70), |
227 | }; |
228 | |
229 | static const struct regulator_desc tps65021_regulators[] = { |
230 | TPS65023_REGULATOR_DCDC(1, DCDC_FIXED_3300000_VSEL_table, 0x20), |
231 | TPS65023_REGULATOR_DCDC(2, DCDC_FIXED_1800000_VSEL_table, 0x10), |
232 | TPS65023_REGULATOR_DCDC(3, VCORE_VSEL_table, 0x08), |
233 | TPS65023_REGULATOR_LDO(1, TPS65023_LDO1_VSEL_table, 0x07), |
234 | TPS65023_REGULATOR_LDO(2, TPS65023_LDO2_VSEL_table, 0x70), |
235 | }; |
236 | |
237 | static const struct regulator_desc tps65023_regulators[] = { |
238 | TPS65023_REGULATOR_DCDC(1, VCORE_VSEL_table, 0x20), |
239 | TPS65023_REGULATOR_DCDC(2, DCDC_FIXED_3300000_VSEL_table, 0x10), |
240 | TPS65023_REGULATOR_DCDC(3, DCDC_FIXED_1800000_VSEL_table, 0x08), |
241 | TPS65023_REGULATOR_LDO(1, TPS65023_LDO1_VSEL_table, 0x07), |
242 | TPS65023_REGULATOR_LDO(2, TPS65023_LDO2_VSEL_table, 0x70), |
243 | }; |
244 | |
245 | static struct tps_driver_data tps65020_drv_data = { |
246 | .desc = tps65020_regulators, |
247 | .core_regulator = TPS65023_DCDC_3, |
248 | }; |
249 | |
250 | static struct tps_driver_data tps65021_drv_data = { |
251 | .desc = tps65021_regulators, |
252 | .core_regulator = TPS65023_DCDC_3, |
253 | }; |
254 | |
255 | static struct tps_driver_data tps65023_drv_data = { |
256 | .desc = tps65023_regulators, |
257 | .core_regulator = TPS65023_DCDC_1, |
258 | }; |
259 | |
260 | static int tps_65023_probe(struct i2c_client *client) |
261 | { |
262 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
263 | struct regulator_init_data *init_data = dev_get_platdata(dev: &client->dev); |
264 | struct regulator_config config = { }; |
265 | struct tps_pmic *tps; |
266 | int i; |
267 | int error; |
268 | |
269 | tps = devm_kzalloc(dev: &client->dev, size: sizeof(*tps), GFP_KERNEL); |
270 | if (!tps) |
271 | return -ENOMEM; |
272 | |
273 | tps->driver_data = (struct tps_driver_data *)id->driver_data; |
274 | |
275 | tps->regmap = devm_regmap_init_i2c(client, &tps65023_regmap_config); |
276 | if (IS_ERR(ptr: tps->regmap)) { |
277 | error = PTR_ERR(ptr: tps->regmap); |
278 | dev_err(&client->dev, "Failed to allocate register map: %d\n" , |
279 | error); |
280 | return error; |
281 | } |
282 | |
283 | /* common for all regulators */ |
284 | config.dev = &client->dev; |
285 | config.driver_data = tps; |
286 | config.regmap = tps->regmap; |
287 | |
288 | for (i = 0; i < TPS65023_NUM_REGULATOR; i++) { |
289 | if (init_data) |
290 | config.init_data = &init_data[i]; |
291 | |
292 | /* Register the regulators */ |
293 | tps->rdev[i] = devm_regulator_register(dev: &client->dev, |
294 | regulator_desc: &tps->driver_data->desc[i], config: &config); |
295 | if (IS_ERR(ptr: tps->rdev[i])) { |
296 | dev_err(&client->dev, "failed to register %s\n" , |
297 | id->name); |
298 | return PTR_ERR(ptr: tps->rdev[i]); |
299 | } |
300 | } |
301 | |
302 | i2c_set_clientdata(client, data: tps); |
303 | |
304 | /* Enable setting output voltage by I2C */ |
305 | regmap_update_bits(map: tps->regmap, TPS65023_REG_CON_CTRL2, |
306 | TPS65023_REG_CTRL2_CORE_ADJ, val: 0); |
307 | |
308 | return 0; |
309 | } |
310 | |
311 | static const struct of_device_id __maybe_unused tps65023_of_match[] = { |
312 | { .compatible = "ti,tps65020" , .data = &tps65020_drv_data}, |
313 | { .compatible = "ti,tps65021" , .data = &tps65021_drv_data}, |
314 | { .compatible = "ti,tps65023" , .data = &tps65023_drv_data}, |
315 | {}, |
316 | }; |
317 | MODULE_DEVICE_TABLE(of, tps65023_of_match); |
318 | |
319 | static const struct i2c_device_id tps_65023_id[] = { |
320 | { |
321 | .name = "tps65023" , |
322 | .driver_data = (kernel_ulong_t)&tps65023_drv_data |
323 | }, { |
324 | .name = "tps65021" , |
325 | .driver_data = (kernel_ulong_t)&tps65021_drv_data |
326 | }, { |
327 | .name = "tps65020" , |
328 | .driver_data = (kernel_ulong_t)&tps65020_drv_data |
329 | }, |
330 | { }, |
331 | }; |
332 | MODULE_DEVICE_TABLE(i2c, tps_65023_id); |
333 | |
334 | static struct i2c_driver tps_65023_i2c_driver = { |
335 | .driver = { |
336 | .name = "tps65023" , |
337 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
338 | .of_match_table = of_match_ptr(tps65023_of_match), |
339 | }, |
340 | .probe = tps_65023_probe, |
341 | .id_table = tps_65023_id, |
342 | }; |
343 | |
344 | static int __init tps_65023_init(void) |
345 | { |
346 | return i2c_add_driver(&tps_65023_i2c_driver); |
347 | } |
348 | subsys_initcall(tps_65023_init); |
349 | |
350 | static void __exit tps_65023_cleanup(void) |
351 | { |
352 | i2c_del_driver(driver: &tps_65023_i2c_driver); |
353 | } |
354 | module_exit(tps_65023_cleanup); |
355 | |
356 | MODULE_AUTHOR("Texas Instruments" ); |
357 | MODULE_DESCRIPTION("TPS65023 voltage regulator driver" ); |
358 | MODULE_LICENSE("GPL v2" ); |
359 | |