xref: /openbmc/u-boot/drivers/power/axp221.c (revision 6944aff1)
15c7f10fdSOliver Schinagl /*
2bdcdf846SHans de Goede  * AXP221 and AXP223 driver
3bdcdf846SHans de Goede  *
4bdcdf846SHans de Goede  * IMPORTANT when making changes to this file check that the registers
5bdcdf846SHans de Goede  * used are the same for the axp221 and axp223.
6bdcdf846SHans de Goede  *
7bdcdf846SHans de Goede  * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
85c7f10fdSOliver Schinagl  * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
95c7f10fdSOliver Schinagl  *
105c7f10fdSOliver Schinagl  * SPDX-License-Identifier:	GPL-2.0+
115c7f10fdSOliver Schinagl  */
125c7f10fdSOliver Schinagl 
135c7f10fdSOliver Schinagl #include <common.h>
145c7f10fdSOliver Schinagl #include <errno.h>
151d624a4fSHans de Goede #include <asm/arch/pmic_bus.h>
16*6944aff1SHans de Goede #include <axp_pmic.h>
175c7f10fdSOliver Schinagl 
185c7f10fdSOliver Schinagl static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
195c7f10fdSOliver Schinagl {
205c7f10fdSOliver Schinagl 	if (mvolt < min)
215c7f10fdSOliver Schinagl 		mvolt = min;
225c7f10fdSOliver Schinagl 	else if (mvolt > max)
235c7f10fdSOliver Schinagl 		mvolt = max;
245c7f10fdSOliver Schinagl 
255c7f10fdSOliver Schinagl 	return (mvolt - min) / div;
265c7f10fdSOliver Schinagl }
275c7f10fdSOliver Schinagl 
28*6944aff1SHans de Goede int axp_set_dcdc1(unsigned int mvolt)
295c7f10fdSOliver Schinagl {
305c7f10fdSOliver Schinagl 	int ret;
315c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
325c7f10fdSOliver Schinagl 
3350e0d5e6SHans de Goede 	if (mvolt == 0)
341d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
3550e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL1_DCDC1_EN);
3650e0d5e6SHans de Goede 
37bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
385c7f10fdSOliver Schinagl 	if (ret)
395c7f10fdSOliver Schinagl 		return ret;
405c7f10fdSOliver Schinagl 
411d624a4fSHans de Goede 	ret = pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
4250e0d5e6SHans de Goede 			       AXP221_OUTPUT_CTRL2_DCDC1SW_EN);
4350e0d5e6SHans de Goede 	if (ret)
4450e0d5e6SHans de Goede 		return ret;
4550e0d5e6SHans de Goede 
461d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
4750e0d5e6SHans de Goede 				AXP221_OUTPUT_CTRL1_DCDC1_EN);
485c7f10fdSOliver Schinagl }
495c7f10fdSOliver Schinagl 
50*6944aff1SHans de Goede int axp_set_dcdc2(unsigned int mvolt)
515c7f10fdSOliver Schinagl {
5250e0d5e6SHans de Goede 	int ret;
535c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
545c7f10fdSOliver Schinagl 
5550e0d5e6SHans de Goede 	if (mvolt == 0)
561d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
5750e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL1_DCDC2_EN);
5850e0d5e6SHans de Goede 
5950e0d5e6SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
6050e0d5e6SHans de Goede 	if (ret)
6150e0d5e6SHans de Goede 		return ret;
6250e0d5e6SHans de Goede 
631d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
6450e0d5e6SHans de Goede 				AXP221_OUTPUT_CTRL1_DCDC2_EN);
655c7f10fdSOliver Schinagl }
665c7f10fdSOliver Schinagl 
67*6944aff1SHans de Goede int axp_set_dcdc3(unsigned int mvolt)
685c7f10fdSOliver Schinagl {
6950e0d5e6SHans de Goede 	int ret;
705c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
715c7f10fdSOliver Schinagl 
7250e0d5e6SHans de Goede 	if (mvolt == 0)
731d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
7450e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL1_DCDC3_EN);
7550e0d5e6SHans de Goede 
7650e0d5e6SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
7750e0d5e6SHans de Goede 	if (ret)
7850e0d5e6SHans de Goede 		return ret;
7950e0d5e6SHans de Goede 
801d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
8150e0d5e6SHans de Goede 				AXP221_OUTPUT_CTRL1_DCDC3_EN);
825c7f10fdSOliver Schinagl }
835c7f10fdSOliver Schinagl 
84*6944aff1SHans de Goede int axp_set_dcdc4(unsigned int mvolt)
855c7f10fdSOliver Schinagl {
8650e0d5e6SHans de Goede 	int ret;
875c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
885c7f10fdSOliver Schinagl 
8950e0d5e6SHans de Goede 	if (mvolt == 0)
901d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
9150e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL1_DCDC4_EN);
9250e0d5e6SHans de Goede 
9350e0d5e6SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
9450e0d5e6SHans de Goede 	if (ret)
9550e0d5e6SHans de Goede 		return ret;
9650e0d5e6SHans de Goede 
971d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
9850e0d5e6SHans de Goede 				AXP221_OUTPUT_CTRL1_DCDC4_EN);
995c7f10fdSOliver Schinagl }
1005c7f10fdSOliver Schinagl 
101*6944aff1SHans de Goede int axp_set_dcdc5(unsigned int mvolt)
1025c7f10fdSOliver Schinagl {
10350e0d5e6SHans de Goede 	int ret;
1045c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
1055c7f10fdSOliver Schinagl 
10650e0d5e6SHans de Goede 	if (mvolt == 0)
1071d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
10850e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL1_DCDC5_EN);
10950e0d5e6SHans de Goede 
11050e0d5e6SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
11150e0d5e6SHans de Goede 	if (ret)
11250e0d5e6SHans de Goede 		return ret;
11350e0d5e6SHans de Goede 
1141d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
11550e0d5e6SHans de Goede 				AXP221_OUTPUT_CTRL1_DCDC5_EN);
1165c7f10fdSOliver Schinagl }
1175c7f10fdSOliver Schinagl 
118*6944aff1SHans de Goede int axp_set_dldo1(unsigned int mvolt)
1195c7f10fdSOliver Schinagl {
1205c7f10fdSOliver Schinagl 	int ret;
1215c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
1225c7f10fdSOliver Schinagl 
12350e0d5e6SHans de Goede 	if (mvolt == 0)
1241d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
12550e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL2_DLDO1_EN);
12650e0d5e6SHans de Goede 
127bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
1285c7f10fdSOliver Schinagl 	if (ret)
1295c7f10fdSOliver Schinagl 		return ret;
1305c7f10fdSOliver Schinagl 
1311d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
1325c7f10fdSOliver Schinagl 				AXP221_OUTPUT_CTRL2_DLDO1_EN);
1335c7f10fdSOliver Schinagl }
1345c7f10fdSOliver Schinagl 
135*6944aff1SHans de Goede int axp_set_dldo2(unsigned int mvolt)
1365c7f10fdSOliver Schinagl {
1375c7f10fdSOliver Schinagl 	int ret;
1385c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
1395c7f10fdSOliver Schinagl 
14050e0d5e6SHans de Goede 	if (mvolt == 0)
1411d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
14250e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL2_DLDO2_EN);
14350e0d5e6SHans de Goede 
144bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
1455c7f10fdSOliver Schinagl 	if (ret)
1465c7f10fdSOliver Schinagl 		return ret;
1475c7f10fdSOliver Schinagl 
1481d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
1495c7f10fdSOliver Schinagl 				AXP221_OUTPUT_CTRL2_DLDO2_EN);
1505c7f10fdSOliver Schinagl }
1515c7f10fdSOliver Schinagl 
152*6944aff1SHans de Goede int axp_set_dldo3(unsigned int mvolt)
1535c7f10fdSOliver Schinagl {
1545c7f10fdSOliver Schinagl 	int ret;
1555c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
1565c7f10fdSOliver Schinagl 
15750e0d5e6SHans de Goede 	if (mvolt == 0)
1581d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
15950e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL2_DLDO3_EN);
16050e0d5e6SHans de Goede 
161bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
1625c7f10fdSOliver Schinagl 	if (ret)
1635c7f10fdSOliver Schinagl 		return ret;
1645c7f10fdSOliver Schinagl 
1651d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
1665c7f10fdSOliver Schinagl 				AXP221_OUTPUT_CTRL2_DLDO3_EN);
1675c7f10fdSOliver Schinagl }
1685c7f10fdSOliver Schinagl 
169*6944aff1SHans de Goede int axp_set_dldo4(unsigned int mvolt)
1705c7f10fdSOliver Schinagl {
1715c7f10fdSOliver Schinagl 	int ret;
1725c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
1735c7f10fdSOliver Schinagl 
17450e0d5e6SHans de Goede 	if (mvolt == 0)
1751d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
17650e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL2_DLDO4_EN);
17750e0d5e6SHans de Goede 
178bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
1795c7f10fdSOliver Schinagl 	if (ret)
1805c7f10fdSOliver Schinagl 		return ret;
1815c7f10fdSOliver Schinagl 
1821d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
1835c7f10fdSOliver Schinagl 				AXP221_OUTPUT_CTRL2_DLDO4_EN);
1845c7f10fdSOliver Schinagl }
1855c7f10fdSOliver Schinagl 
186*6944aff1SHans de Goede int axp_set_aldo1(unsigned int mvolt)
1875c7f10fdSOliver Schinagl {
1885c7f10fdSOliver Schinagl 	int ret;
1895c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
1905c7f10fdSOliver Schinagl 
19150e0d5e6SHans de Goede 	if (mvolt == 0)
1921d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
19350e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL1_ALDO1_EN);
19450e0d5e6SHans de Goede 
195bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
1965c7f10fdSOliver Schinagl 	if (ret)
1975c7f10fdSOliver Schinagl 		return ret;
1985c7f10fdSOliver Schinagl 
1991d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
2005c7f10fdSOliver Schinagl 				AXP221_OUTPUT_CTRL1_ALDO1_EN);
2015c7f10fdSOliver Schinagl }
2025c7f10fdSOliver Schinagl 
203*6944aff1SHans de Goede int axp_set_aldo2(unsigned int mvolt)
2045c7f10fdSOliver Schinagl {
2055c7f10fdSOliver Schinagl 	int ret;
2065c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
2075c7f10fdSOliver Schinagl 
20850e0d5e6SHans de Goede 	if (mvolt == 0)
2091d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
21050e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL1_ALDO2_EN);
21150e0d5e6SHans de Goede 
212bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
2135c7f10fdSOliver Schinagl 	if (ret)
2145c7f10fdSOliver Schinagl 		return ret;
2155c7f10fdSOliver Schinagl 
2161d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
2175c7f10fdSOliver Schinagl 				AXP221_OUTPUT_CTRL1_ALDO2_EN);
2185c7f10fdSOliver Schinagl }
2195c7f10fdSOliver Schinagl 
220*6944aff1SHans de Goede int axp_set_aldo3(unsigned int mvolt)
2215c7f10fdSOliver Schinagl {
2225c7f10fdSOliver Schinagl 	int ret;
2235c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
2245c7f10fdSOliver Schinagl 
22550e0d5e6SHans de Goede 	if (mvolt == 0)
2261d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL3,
22750e0d5e6SHans de Goede 					AXP221_OUTPUT_CTRL3_ALDO3_EN);
22850e0d5e6SHans de Goede 
229bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
2305c7f10fdSOliver Schinagl 	if (ret)
2315c7f10fdSOliver Schinagl 		return ret;
2325c7f10fdSOliver Schinagl 
2331d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL3,
2345c7f10fdSOliver Schinagl 				AXP221_OUTPUT_CTRL3_ALDO3_EN);
2355c7f10fdSOliver Schinagl }
2365c7f10fdSOliver Schinagl 
237*6944aff1SHans de Goede int axp_set_eldo(int eldo_num, unsigned int mvolt)
2386906df1aSSiarhei Siamashka {
2396906df1aSSiarhei Siamashka 	int ret;
2406906df1aSSiarhei Siamashka 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
2416906df1aSSiarhei Siamashka 	u8 addr, bits;
2426906df1aSSiarhei Siamashka 
2436906df1aSSiarhei Siamashka 	switch (eldo_num) {
2446906df1aSSiarhei Siamashka 	case 3:
2456906df1aSSiarhei Siamashka 		addr = AXP221_ELDO3_CTRL;
2466906df1aSSiarhei Siamashka 		bits = AXP221_OUTPUT_CTRL2_ELDO3_EN;
2476906df1aSSiarhei Siamashka 		break;
2486906df1aSSiarhei Siamashka 	case 2:
2496906df1aSSiarhei Siamashka 		addr = AXP221_ELDO2_CTRL;
2506906df1aSSiarhei Siamashka 		bits = AXP221_OUTPUT_CTRL2_ELDO2_EN;
2516906df1aSSiarhei Siamashka 		break;
2526906df1aSSiarhei Siamashka 	case 1:
2536906df1aSSiarhei Siamashka 		addr = AXP221_ELDO1_CTRL;
2546906df1aSSiarhei Siamashka 		bits = AXP221_OUTPUT_CTRL2_ELDO1_EN;
2556906df1aSSiarhei Siamashka 		break;
2566906df1aSSiarhei Siamashka 	default:
2576906df1aSSiarhei Siamashka 		return -EINVAL;
2586906df1aSSiarhei Siamashka 	}
2596906df1aSSiarhei Siamashka 
2606906df1aSSiarhei Siamashka 	if (mvolt == 0)
2611d624a4fSHans de Goede 		return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, bits);
2626906df1aSSiarhei Siamashka 
2636906df1aSSiarhei Siamashka 	ret = pmic_bus_write(addr, cfg);
2646906df1aSSiarhei Siamashka 	if (ret)
2656906df1aSSiarhei Siamashka 		return ret;
2666906df1aSSiarhei Siamashka 
2671d624a4fSHans de Goede 	return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, bits);
2686906df1aSSiarhei Siamashka }
2696906df1aSSiarhei Siamashka 
270*6944aff1SHans de Goede int axp_init(void)
2715c7f10fdSOliver Schinagl {
2723c781190SHans de Goede 	/* This cannot be 0 because it is used in SPL before BSS is ready */
2733c781190SHans de Goede 	static int needs_init = 1;
2745c7f10fdSOliver Schinagl 	u8 axp_chip_id;
2755c7f10fdSOliver Schinagl 	int ret;
2765c7f10fdSOliver Schinagl 
2773c781190SHans de Goede 	if (!needs_init)
2783c781190SHans de Goede 		return 0;
2793c781190SHans de Goede 
280bdcdf846SHans de Goede 	ret = pmic_bus_init();
2815c7f10fdSOliver Schinagl 	if (ret)
2825c7f10fdSOliver Schinagl 		return ret;
2835c7f10fdSOliver Schinagl 
284bdcdf846SHans de Goede 	ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
2855c7f10fdSOliver Schinagl 	if (ret)
2865c7f10fdSOliver Schinagl 		return ret;
2875c7f10fdSOliver Schinagl 
2885c7f10fdSOliver Schinagl 	if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17))
2895c7f10fdSOliver Schinagl 		return -ENODEV;
2905c7f10fdSOliver Schinagl 
2913c781190SHans de Goede 	needs_init = 0;
2925c7f10fdSOliver Schinagl 	return 0;
2935c7f10fdSOliver Schinagl }
294f3fba566SHans de Goede 
295*6944aff1SHans de Goede int axp_get_sid(unsigned int *sid)
296f3fba566SHans de Goede {
297f3fba566SHans de Goede 	u8 *dest = (u8 *)sid;
298f3fba566SHans de Goede 	int i, ret;
299f3fba566SHans de Goede 
300*6944aff1SHans de Goede 	ret = pmic_bus_init();
301f3fba566SHans de Goede 	if (ret)
302f3fba566SHans de Goede 		return ret;
303f3fba566SHans de Goede 
304bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_PAGE, 1);
305f3fba566SHans de Goede 	if (ret)
306f3fba566SHans de Goede 		return ret;
307f3fba566SHans de Goede 
308f3fba566SHans de Goede 	for (i = 0; i < 16; i++) {
309bdcdf846SHans de Goede 		ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
310f3fba566SHans de Goede 		if (ret)
311f3fba566SHans de Goede 			return ret;
312f3fba566SHans de Goede 	}
313f3fba566SHans de Goede 
314bdcdf846SHans de Goede 	pmic_bus_write(AXP221_PAGE, 0);
315f3fba566SHans de Goede 
316f3fba566SHans de Goede 	for (i = 0; i < 4; i++)
317f3fba566SHans de Goede 		sid[i] = be32_to_cpu(sid[i]);
318f3fba566SHans de Goede 
319f3fba566SHans de Goede 	return 0;
320f3fba566SHans de Goede }
321