xref: /openbmc/u-boot/drivers/power/axp221.c (revision 5296cb1d)
1 /*
2  * AXP221 and AXP223 driver
3  *
4  * IMPORTANT when making changes to this file check that the registers
5  * used are the same for the axp221 and axp223.
6  *
7  * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
8  * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
9  *
10  * SPDX-License-Identifier:	GPL-2.0+
11  */
12 
13 #include <common.h>
14 #include <errno.h>
15 #include <asm/arch/p2wi.h>
16 #include <asm/arch/rsb.h>
17 #include <asm/arch/gpio.h>
18 #include <axp221.h>
19 
20 /*
21  * The axp221 uses the p2wi bus, the axp223 is identical (for all registers
22  * used sofar) but uses the rsb bus. These functions abstract this.
23  */
24 static int pmic_bus_init(void)
25 {
26 #ifdef CONFIG_MACH_SUN6I
27 	p2wi_init();
28 	return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
29 					AXP221_INIT_DATA);
30 #else
31 	int ret;
32 
33 	ret = rsb_init();
34 	if (ret)
35 		return ret;
36 
37 	return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
38 #endif
39 }
40 
41 static int pmic_bus_read(const u8 addr, u8 *data)
42 {
43 #ifdef CONFIG_MACH_SUN6I
44 	return p2wi_read(addr, data);
45 #else
46 	return rsb_read(AXP223_RUNTIME_ADDR, addr, data);
47 #endif
48 }
49 
50 static int pmic_bus_write(const u8 addr, u8 data)
51 {
52 #ifdef CONFIG_MACH_SUN6I
53 	return p2wi_write(addr, data);
54 #else
55 	return rsb_write(AXP223_RUNTIME_ADDR, addr, data);
56 #endif
57 }
58 
59 static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
60 {
61 	if (mvolt < min)
62 		mvolt = min;
63 	else if (mvolt > max)
64 		mvolt = max;
65 
66 	return (mvolt - min) / div;
67 }
68 
69 static int axp221_setbits(u8 reg, u8 bits)
70 {
71 	int ret;
72 	u8 val;
73 
74 	ret = pmic_bus_read(reg, &val);
75 	if (ret)
76 		return ret;
77 
78 	val |= bits;
79 	return pmic_bus_write(reg, val);
80 }
81 
82 static int axp221_clrbits(u8 reg, u8 bits)
83 {
84 	int ret;
85 	u8 val;
86 
87 	ret = pmic_bus_read(reg, &val);
88 	if (ret)
89 		return ret;
90 
91 	val &= ~bits;
92 	return pmic_bus_write(reg, val);
93 }
94 
95 int axp221_set_dcdc1(unsigned int mvolt)
96 {
97 	int ret;
98 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
99 
100 	if (mvolt == 0)
101 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
102 				      AXP221_OUTPUT_CTRL1_DCDC1_EN);
103 
104 	ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
105 	if (ret)
106 		return ret;
107 
108 	ret = axp221_setbits(AXP221_OUTPUT_CTRL2,
109 			     AXP221_OUTPUT_CTRL2_DCDC1SW_EN);
110 	if (ret)
111 		return ret;
112 
113 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
114 			      AXP221_OUTPUT_CTRL1_DCDC1_EN);
115 }
116 
117 int axp221_set_dcdc2(unsigned int mvolt)
118 {
119 	int ret;
120 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
121 
122 	if (mvolt == 0)
123 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
124 				      AXP221_OUTPUT_CTRL1_DCDC2_EN);
125 
126 	ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
127 	if (ret)
128 		return ret;
129 
130 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
131 			      AXP221_OUTPUT_CTRL1_DCDC2_EN);
132 }
133 
134 int axp221_set_dcdc3(unsigned int mvolt)
135 {
136 	int ret;
137 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
138 
139 	if (mvolt == 0)
140 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
141 				      AXP221_OUTPUT_CTRL1_DCDC3_EN);
142 
143 	ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
144 	if (ret)
145 		return ret;
146 
147 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
148 			      AXP221_OUTPUT_CTRL1_DCDC3_EN);
149 }
150 
151 int axp221_set_dcdc4(unsigned int mvolt)
152 {
153 	int ret;
154 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
155 
156 	if (mvolt == 0)
157 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
158 				      AXP221_OUTPUT_CTRL1_DCDC4_EN);
159 
160 	ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
161 	if (ret)
162 		return ret;
163 
164 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
165 			      AXP221_OUTPUT_CTRL1_DCDC4_EN);
166 }
167 
168 int axp221_set_dcdc5(unsigned int mvolt)
169 {
170 	int ret;
171 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
172 
173 	if (mvolt == 0)
174 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
175 				      AXP221_OUTPUT_CTRL1_DCDC5_EN);
176 
177 	ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
178 	if (ret)
179 		return ret;
180 
181 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
182 			      AXP221_OUTPUT_CTRL1_DCDC5_EN);
183 }
184 
185 int axp221_set_dldo1(unsigned int mvolt)
186 {
187 	int ret;
188 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
189 
190 	if (mvolt == 0)
191 		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
192 				      AXP221_OUTPUT_CTRL2_DLDO1_EN);
193 
194 	ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
195 	if (ret)
196 		return ret;
197 
198 	return axp221_setbits(AXP221_OUTPUT_CTRL2,
199 			      AXP221_OUTPUT_CTRL2_DLDO1_EN);
200 }
201 
202 int axp221_set_dldo2(unsigned int mvolt)
203 {
204 	int ret;
205 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
206 
207 	if (mvolt == 0)
208 		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
209 				      AXP221_OUTPUT_CTRL2_DLDO2_EN);
210 
211 	ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
212 	if (ret)
213 		return ret;
214 
215 	return axp221_setbits(AXP221_OUTPUT_CTRL2,
216 			      AXP221_OUTPUT_CTRL2_DLDO2_EN);
217 }
218 
219 int axp221_set_dldo3(unsigned int mvolt)
220 {
221 	int ret;
222 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
223 
224 	if (mvolt == 0)
225 		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
226 				      AXP221_OUTPUT_CTRL2_DLDO3_EN);
227 
228 	ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
229 	if (ret)
230 		return ret;
231 
232 	return axp221_setbits(AXP221_OUTPUT_CTRL2,
233 			      AXP221_OUTPUT_CTRL2_DLDO3_EN);
234 }
235 
236 int axp221_set_dldo4(unsigned int mvolt)
237 {
238 	int ret;
239 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
240 
241 	if (mvolt == 0)
242 		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
243 				      AXP221_OUTPUT_CTRL2_DLDO4_EN);
244 
245 	ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
246 	if (ret)
247 		return ret;
248 
249 	return axp221_setbits(AXP221_OUTPUT_CTRL2,
250 			      AXP221_OUTPUT_CTRL2_DLDO4_EN);
251 }
252 
253 int axp221_set_aldo1(unsigned int mvolt)
254 {
255 	int ret;
256 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
257 
258 	if (mvolt == 0)
259 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
260 				      AXP221_OUTPUT_CTRL1_ALDO1_EN);
261 
262 	ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
263 	if (ret)
264 		return ret;
265 
266 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
267 			      AXP221_OUTPUT_CTRL1_ALDO1_EN);
268 }
269 
270 int axp221_set_aldo2(unsigned int mvolt)
271 {
272 	int ret;
273 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
274 
275 	if (mvolt == 0)
276 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
277 				      AXP221_OUTPUT_CTRL1_ALDO2_EN);
278 
279 	ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
280 	if (ret)
281 		return ret;
282 
283 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
284 			      AXP221_OUTPUT_CTRL1_ALDO2_EN);
285 }
286 
287 int axp221_set_aldo3(unsigned int mvolt)
288 {
289 	int ret;
290 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
291 
292 	if (mvolt == 0)
293 		return axp221_clrbits(AXP221_OUTPUT_CTRL3,
294 				      AXP221_OUTPUT_CTRL3_ALDO3_EN);
295 
296 	ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
297 	if (ret)
298 		return ret;
299 
300 	return axp221_setbits(AXP221_OUTPUT_CTRL3,
301 			      AXP221_OUTPUT_CTRL3_ALDO3_EN);
302 }
303 
304 int axp221_set_eldo(int eldo_num, unsigned int mvolt)
305 {
306 	int ret;
307 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
308 	u8 addr, bits;
309 
310 	switch (eldo_num) {
311 	case 3:
312 		addr = AXP221_ELDO3_CTRL;
313 		bits = AXP221_OUTPUT_CTRL2_ELDO3_EN;
314 		break;
315 	case 2:
316 		addr = AXP221_ELDO2_CTRL;
317 		bits = AXP221_OUTPUT_CTRL2_ELDO2_EN;
318 		break;
319 	case 1:
320 		addr = AXP221_ELDO1_CTRL;
321 		bits = AXP221_OUTPUT_CTRL2_ELDO1_EN;
322 		break;
323 	default:
324 		return -EINVAL;
325 	}
326 
327 	if (mvolt == 0)
328 		return axp221_clrbits(AXP221_OUTPUT_CTRL2, bits);
329 
330 	ret = pmic_bus_write(addr, cfg);
331 	if (ret)
332 		return ret;
333 
334 	return axp221_setbits(AXP221_OUTPUT_CTRL2, bits);
335 }
336 
337 int axp221_init(void)
338 {
339 	/* This cannot be 0 because it is used in SPL before BSS is ready */
340 	static int needs_init = 1;
341 	u8 axp_chip_id;
342 	int ret;
343 
344 	if (!needs_init)
345 		return 0;
346 
347 	ret = pmic_bus_init();
348 	if (ret)
349 		return ret;
350 
351 	ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
352 	if (ret)
353 		return ret;
354 
355 	if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17))
356 		return -ENODEV;
357 
358 	needs_init = 0;
359 	return 0;
360 }
361 
362 int axp221_get_sid(unsigned int *sid)
363 {
364 	u8 *dest = (u8 *)sid;
365 	int i, ret;
366 
367 	ret = axp221_init();
368 	if (ret)
369 		return ret;
370 
371 	ret = pmic_bus_write(AXP221_PAGE, 1);
372 	if (ret)
373 		return ret;
374 
375 	for (i = 0; i < 16; i++) {
376 		ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
377 		if (ret)
378 			return ret;
379 	}
380 
381 	pmic_bus_write(AXP221_PAGE, 0);
382 
383 	for (i = 0; i < 4; i++)
384 		sid[i] = be32_to_cpu(sid[i]);
385 
386 	return 0;
387 }
388 
389 int axp_gpio_direction_input(unsigned int pin)
390 {
391 	switch (pin) {
392 	case SUNXI_GPIO_AXP0_VBUS_DETECT:
393 		return 0;
394 	default:
395 		return -EINVAL;
396 	}
397 }
398 
399 int axp_gpio_direction_output(unsigned int pin, unsigned int val)
400 {
401 	int ret;
402 
403 	switch (pin) {
404 	case SUNXI_GPIO_AXP0_VBUS_ENABLE:
405 		ret = axp221_clrbits(AXP221_MISC_CTRL,
406 				     AXP221_MISC_CTRL_N_VBUSEN_FUNC);
407 		if (ret)
408 			return ret;
409 
410 		return axp_gpio_set_value(pin, val);
411 	default:
412 		return -EINVAL;
413 	}
414 }
415 
416 int axp_gpio_get_value(unsigned int pin)
417 {
418 	int ret;
419 	u8 val;
420 
421 	switch (pin) {
422 	case SUNXI_GPIO_AXP0_VBUS_DETECT:
423 		ret = pmic_bus_read(AXP221_POWER_STATUS, &val);
424 		if (ret)
425 			return ret;
426 
427 		return !!(val & AXP221_POWER_STATUS_VBUS_AVAIL);
428 	default:
429 		return -EINVAL;
430 	}
431 }
432 
433 int axp_gpio_set_value(unsigned int pin, unsigned int val)
434 {
435 	int ret;
436 
437 	switch (pin) {
438 	case SUNXI_GPIO_AXP0_VBUS_ENABLE:
439 		if (val)
440 			ret = axp221_setbits(AXP221_VBUS_IPSOUT,
441 					     AXP221_VBUS_IPSOUT_DRIVEBUS);
442 		else
443 			ret = axp221_clrbits(AXP221_VBUS_IPSOUT,
444 					     AXP221_VBUS_IPSOUT_DRIVEBUS);
445 
446 		if (ret)
447 			return ret;
448 	}
449 
450 	return 0;
451 }
452