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