xref: /rk3399_rockchip-uboot/drivers/power/axp221.c (revision 6906df1ab8d64a4e21d38ea538d6cd383a089e1d)
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>
155c7f10fdSOliver Schinagl #include <asm/arch/p2wi.h>
16bdcdf846SHans de Goede #include <asm/arch/rsb.h>
175c7f10fdSOliver Schinagl #include <axp221.h>
185c7f10fdSOliver Schinagl 
19bdcdf846SHans de Goede /*
20bdcdf846SHans de Goede  * The axp221 uses the p2wi bus, the axp223 is identical (for all registers
21bdcdf846SHans de Goede  * used sofar) but uses the rsb bus. These functions abstract this.
22bdcdf846SHans de Goede  */
23bdcdf846SHans de Goede static int pmic_bus_init(void)
24bdcdf846SHans de Goede {
25bdcdf846SHans de Goede #ifdef CONFIG_MACH_SUN6I
26bdcdf846SHans de Goede 	p2wi_init();
27bdcdf846SHans de Goede 	return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
28bdcdf846SHans de Goede 					AXP221_INIT_DATA);
29bdcdf846SHans de Goede #else
30bdcdf846SHans de Goede 	int ret;
31bdcdf846SHans de Goede 
32bdcdf846SHans de Goede 	rsb_init();
33bdcdf846SHans de Goede 
34bdcdf846SHans de Goede 	ret = rsb_set_device_mode(AXP223_DEVICE_MODE_DATA);
35bdcdf846SHans de Goede 	if (ret)
36bdcdf846SHans de Goede 		return ret;
37bdcdf846SHans de Goede 
38bdcdf846SHans de Goede 	return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
39bdcdf846SHans de Goede #endif
40bdcdf846SHans de Goede }
41bdcdf846SHans de Goede 
42bdcdf846SHans de Goede static int pmic_bus_read(const u8 addr, u8 *data)
43bdcdf846SHans de Goede {
44bdcdf846SHans de Goede #ifdef CONFIG_MACH_SUN6I
45bdcdf846SHans de Goede 	return p2wi_read(addr, data);
46bdcdf846SHans de Goede #else
47bdcdf846SHans de Goede 	return rsb_read(AXP223_RUNTIME_ADDR, addr, data);
48bdcdf846SHans de Goede #endif
49bdcdf846SHans de Goede }
50bdcdf846SHans de Goede 
51bdcdf846SHans de Goede static int pmic_bus_write(const u8 addr, u8 data)
52bdcdf846SHans de Goede {
53bdcdf846SHans de Goede #ifdef CONFIG_MACH_SUN6I
54bdcdf846SHans de Goede 	return p2wi_write(addr, data);
55bdcdf846SHans de Goede #else
56bdcdf846SHans de Goede 	return rsb_write(AXP223_RUNTIME_ADDR, addr, data);
57bdcdf846SHans de Goede #endif
58bdcdf846SHans de Goede }
59bdcdf846SHans de Goede 
605c7f10fdSOliver Schinagl static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
615c7f10fdSOliver Schinagl {
625c7f10fdSOliver Schinagl 	if (mvolt < min)
635c7f10fdSOliver Schinagl 		mvolt = min;
645c7f10fdSOliver Schinagl 	else if (mvolt > max)
655c7f10fdSOliver Schinagl 		mvolt = max;
665c7f10fdSOliver Schinagl 
675c7f10fdSOliver Schinagl 	return (mvolt - min) / div;
685c7f10fdSOliver Schinagl }
695c7f10fdSOliver Schinagl 
705c7f10fdSOliver Schinagl static int axp221_setbits(u8 reg, u8 bits)
715c7f10fdSOliver Schinagl {
725c7f10fdSOliver Schinagl 	int ret;
735c7f10fdSOliver Schinagl 	u8 val;
745c7f10fdSOliver Schinagl 
75bdcdf846SHans de Goede 	ret = pmic_bus_read(reg, &val);
765c7f10fdSOliver Schinagl 	if (ret)
775c7f10fdSOliver Schinagl 		return ret;
785c7f10fdSOliver Schinagl 
795c7f10fdSOliver Schinagl 	val |= bits;
80bdcdf846SHans de Goede 	return pmic_bus_write(reg, val);
815c7f10fdSOliver Schinagl }
825c7f10fdSOliver Schinagl 
8350e0d5e6SHans de Goede static int axp221_clrbits(u8 reg, u8 bits)
8450e0d5e6SHans de Goede {
8550e0d5e6SHans de Goede 	int ret;
8650e0d5e6SHans de Goede 	u8 val;
8750e0d5e6SHans de Goede 
8850e0d5e6SHans de Goede 	ret = pmic_bus_read(reg, &val);
8950e0d5e6SHans de Goede 	if (ret)
9050e0d5e6SHans de Goede 		return ret;
9150e0d5e6SHans de Goede 
9250e0d5e6SHans de Goede 	val &= ~bits;
9350e0d5e6SHans de Goede 	return pmic_bus_write(reg, val);
9450e0d5e6SHans de Goede }
9550e0d5e6SHans de Goede 
965c7f10fdSOliver Schinagl int axp221_set_dcdc1(unsigned int mvolt)
975c7f10fdSOliver Schinagl {
985c7f10fdSOliver Schinagl 	int ret;
995c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
1005c7f10fdSOliver Schinagl 
10150e0d5e6SHans de Goede 	if (mvolt == 0)
10250e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
10350e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL1_DCDC1_EN);
10450e0d5e6SHans de Goede 
105bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
1065c7f10fdSOliver Schinagl 	if (ret)
1075c7f10fdSOliver Schinagl 		return ret;
1085c7f10fdSOliver Schinagl 
10950e0d5e6SHans de Goede 	ret = axp221_setbits(AXP221_OUTPUT_CTRL2,
11050e0d5e6SHans de Goede 			     AXP221_OUTPUT_CTRL2_DCDC1SW_EN);
11150e0d5e6SHans de Goede 	if (ret)
11250e0d5e6SHans de Goede 		return ret;
11350e0d5e6SHans de Goede 
11450e0d5e6SHans de Goede 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
11550e0d5e6SHans de Goede 			      AXP221_OUTPUT_CTRL1_DCDC1_EN);
1165c7f10fdSOliver Schinagl }
1175c7f10fdSOliver Schinagl 
1185c7f10fdSOliver Schinagl int axp221_set_dcdc2(unsigned int mvolt)
1195c7f10fdSOliver Schinagl {
12050e0d5e6SHans de Goede 	int ret;
1215c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
1225c7f10fdSOliver Schinagl 
12350e0d5e6SHans de Goede 	if (mvolt == 0)
12450e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
12550e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL1_DCDC2_EN);
12650e0d5e6SHans de Goede 
12750e0d5e6SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
12850e0d5e6SHans de Goede 	if (ret)
12950e0d5e6SHans de Goede 		return ret;
13050e0d5e6SHans de Goede 
13150e0d5e6SHans de Goede 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
13250e0d5e6SHans de Goede 			      AXP221_OUTPUT_CTRL1_DCDC2_EN);
1335c7f10fdSOliver Schinagl }
1345c7f10fdSOliver Schinagl 
1355c7f10fdSOliver Schinagl int axp221_set_dcdc3(unsigned int mvolt)
1365c7f10fdSOliver Schinagl {
13750e0d5e6SHans de Goede 	int ret;
1385c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
1395c7f10fdSOliver Schinagl 
14050e0d5e6SHans de Goede 	if (mvolt == 0)
14150e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
14250e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL1_DCDC3_EN);
14350e0d5e6SHans de Goede 
14450e0d5e6SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
14550e0d5e6SHans de Goede 	if (ret)
14650e0d5e6SHans de Goede 		return ret;
14750e0d5e6SHans de Goede 
14850e0d5e6SHans de Goede 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
14950e0d5e6SHans de Goede 			      AXP221_OUTPUT_CTRL1_DCDC3_EN);
1505c7f10fdSOliver Schinagl }
1515c7f10fdSOliver Schinagl 
1525c7f10fdSOliver Schinagl int axp221_set_dcdc4(unsigned int mvolt)
1535c7f10fdSOliver Schinagl {
15450e0d5e6SHans de Goede 	int ret;
1555c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
1565c7f10fdSOliver Schinagl 
15750e0d5e6SHans de Goede 	if (mvolt == 0)
15850e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
15950e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL1_DCDC4_EN);
16050e0d5e6SHans de Goede 
16150e0d5e6SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
16250e0d5e6SHans de Goede 	if (ret)
16350e0d5e6SHans de Goede 		return ret;
16450e0d5e6SHans de Goede 
16550e0d5e6SHans de Goede 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
16650e0d5e6SHans de Goede 			      AXP221_OUTPUT_CTRL1_DCDC4_EN);
1675c7f10fdSOliver Schinagl }
1685c7f10fdSOliver Schinagl 
1695c7f10fdSOliver Schinagl int axp221_set_dcdc5(unsigned int mvolt)
1705c7f10fdSOliver Schinagl {
17150e0d5e6SHans de Goede 	int ret;
1725c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
1735c7f10fdSOliver Schinagl 
17450e0d5e6SHans de Goede 	if (mvolt == 0)
17550e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
17650e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL1_DCDC5_EN);
17750e0d5e6SHans de Goede 
17850e0d5e6SHans de Goede 	ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
17950e0d5e6SHans de Goede 	if (ret)
18050e0d5e6SHans de Goede 		return ret;
18150e0d5e6SHans de Goede 
18250e0d5e6SHans de Goede 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
18350e0d5e6SHans de Goede 			      AXP221_OUTPUT_CTRL1_DCDC5_EN);
1845c7f10fdSOliver Schinagl }
1855c7f10fdSOliver Schinagl 
1865c7f10fdSOliver Schinagl int axp221_set_dldo1(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)
19250e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
19350e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL2_DLDO1_EN);
19450e0d5e6SHans de Goede 
195bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
1965c7f10fdSOliver Schinagl 	if (ret)
1975c7f10fdSOliver Schinagl 		return ret;
1985c7f10fdSOliver Schinagl 
1995c7f10fdSOliver Schinagl 	return axp221_setbits(AXP221_OUTPUT_CTRL2,
2005c7f10fdSOliver Schinagl 			      AXP221_OUTPUT_CTRL2_DLDO1_EN);
2015c7f10fdSOliver Schinagl }
2025c7f10fdSOliver Schinagl 
2035c7f10fdSOliver Schinagl int axp221_set_dldo2(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)
20950e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
21050e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL2_DLDO2_EN);
21150e0d5e6SHans de Goede 
212bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
2135c7f10fdSOliver Schinagl 	if (ret)
2145c7f10fdSOliver Schinagl 		return ret;
2155c7f10fdSOliver Schinagl 
2165c7f10fdSOliver Schinagl 	return axp221_setbits(AXP221_OUTPUT_CTRL2,
2175c7f10fdSOliver Schinagl 			      AXP221_OUTPUT_CTRL2_DLDO2_EN);
2185c7f10fdSOliver Schinagl }
2195c7f10fdSOliver Schinagl 
2205c7f10fdSOliver Schinagl int axp221_set_dldo3(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)
22650e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
22750e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL2_DLDO3_EN);
22850e0d5e6SHans de Goede 
229bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
2305c7f10fdSOliver Schinagl 	if (ret)
2315c7f10fdSOliver Schinagl 		return ret;
2325c7f10fdSOliver Schinagl 
2335c7f10fdSOliver Schinagl 	return axp221_setbits(AXP221_OUTPUT_CTRL2,
2345c7f10fdSOliver Schinagl 			      AXP221_OUTPUT_CTRL2_DLDO3_EN);
2355c7f10fdSOliver Schinagl }
2365c7f10fdSOliver Schinagl 
2375c7f10fdSOliver Schinagl int axp221_set_dldo4(unsigned int mvolt)
2385c7f10fdSOliver Schinagl {
2395c7f10fdSOliver Schinagl 	int ret;
2405c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
2415c7f10fdSOliver Schinagl 
24250e0d5e6SHans de Goede 	if (mvolt == 0)
24350e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
24450e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL2_DLDO4_EN);
24550e0d5e6SHans de Goede 
246bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
2475c7f10fdSOliver Schinagl 	if (ret)
2485c7f10fdSOliver Schinagl 		return ret;
2495c7f10fdSOliver Schinagl 
2505c7f10fdSOliver Schinagl 	return axp221_setbits(AXP221_OUTPUT_CTRL2,
2515c7f10fdSOliver Schinagl 			      AXP221_OUTPUT_CTRL2_DLDO4_EN);
2525c7f10fdSOliver Schinagl }
2535c7f10fdSOliver Schinagl 
2545c7f10fdSOliver Schinagl int axp221_set_aldo1(unsigned int mvolt)
2555c7f10fdSOliver Schinagl {
2565c7f10fdSOliver Schinagl 	int ret;
2575c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
2585c7f10fdSOliver Schinagl 
25950e0d5e6SHans de Goede 	if (mvolt == 0)
26050e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
26150e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL1_ALDO1_EN);
26250e0d5e6SHans de Goede 
263bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
2645c7f10fdSOliver Schinagl 	if (ret)
2655c7f10fdSOliver Schinagl 		return ret;
2665c7f10fdSOliver Schinagl 
2675c7f10fdSOliver Schinagl 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
2685c7f10fdSOliver Schinagl 			      AXP221_OUTPUT_CTRL1_ALDO1_EN);
2695c7f10fdSOliver Schinagl }
2705c7f10fdSOliver Schinagl 
2715c7f10fdSOliver Schinagl int axp221_set_aldo2(unsigned int mvolt)
2725c7f10fdSOliver Schinagl {
2735c7f10fdSOliver Schinagl 	int ret;
2745c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
2755c7f10fdSOliver Schinagl 
27650e0d5e6SHans de Goede 	if (mvolt == 0)
27750e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
27850e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL1_ALDO2_EN);
27950e0d5e6SHans de Goede 
280bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
2815c7f10fdSOliver Schinagl 	if (ret)
2825c7f10fdSOliver Schinagl 		return ret;
2835c7f10fdSOliver Schinagl 
2845c7f10fdSOliver Schinagl 	return axp221_setbits(AXP221_OUTPUT_CTRL1,
2855c7f10fdSOliver Schinagl 			      AXP221_OUTPUT_CTRL1_ALDO2_EN);
2865c7f10fdSOliver Schinagl }
2875c7f10fdSOliver Schinagl 
2885c7f10fdSOliver Schinagl int axp221_set_aldo3(unsigned int mvolt)
2895c7f10fdSOliver Schinagl {
2905c7f10fdSOliver Schinagl 	int ret;
2915c7f10fdSOliver Schinagl 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
2925c7f10fdSOliver Schinagl 
29350e0d5e6SHans de Goede 	if (mvolt == 0)
29450e0d5e6SHans de Goede 		return axp221_clrbits(AXP221_OUTPUT_CTRL3,
29550e0d5e6SHans de Goede 				      AXP221_OUTPUT_CTRL3_ALDO3_EN);
29650e0d5e6SHans de Goede 
297bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
2985c7f10fdSOliver Schinagl 	if (ret)
2995c7f10fdSOliver Schinagl 		return ret;
3005c7f10fdSOliver Schinagl 
3015c7f10fdSOliver Schinagl 	return axp221_setbits(AXP221_OUTPUT_CTRL3,
3025c7f10fdSOliver Schinagl 			      AXP221_OUTPUT_CTRL3_ALDO3_EN);
3035c7f10fdSOliver Schinagl }
3045c7f10fdSOliver Schinagl 
305*6906df1aSSiarhei Siamashka int axp221_set_eldo(int eldo_num, unsigned int mvolt)
306*6906df1aSSiarhei Siamashka {
307*6906df1aSSiarhei Siamashka 	int ret;
308*6906df1aSSiarhei Siamashka 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
309*6906df1aSSiarhei Siamashka 	u8 addr, bits;
310*6906df1aSSiarhei Siamashka 
311*6906df1aSSiarhei Siamashka 	switch (eldo_num) {
312*6906df1aSSiarhei Siamashka 	case 3:
313*6906df1aSSiarhei Siamashka 		addr = AXP221_ELDO3_CTRL;
314*6906df1aSSiarhei Siamashka 		bits = AXP221_OUTPUT_CTRL2_ELDO3_EN;
315*6906df1aSSiarhei Siamashka 		break;
316*6906df1aSSiarhei Siamashka 	case 2:
317*6906df1aSSiarhei Siamashka 		addr = AXP221_ELDO2_CTRL;
318*6906df1aSSiarhei Siamashka 		bits = AXP221_OUTPUT_CTRL2_ELDO2_EN;
319*6906df1aSSiarhei Siamashka 		break;
320*6906df1aSSiarhei Siamashka 	case 1:
321*6906df1aSSiarhei Siamashka 		addr = AXP221_ELDO1_CTRL;
322*6906df1aSSiarhei Siamashka 		bits = AXP221_OUTPUT_CTRL2_ELDO1_EN;
323*6906df1aSSiarhei Siamashka 		break;
324*6906df1aSSiarhei Siamashka 	default:
325*6906df1aSSiarhei Siamashka 		return -EINVAL;
326*6906df1aSSiarhei Siamashka 	}
327*6906df1aSSiarhei Siamashka 
328*6906df1aSSiarhei Siamashka 	if (mvolt == 0)
329*6906df1aSSiarhei Siamashka 		return axp221_clrbits(AXP221_OUTPUT_CTRL2, bits);
330*6906df1aSSiarhei Siamashka 
331*6906df1aSSiarhei Siamashka 	ret = pmic_bus_write(addr, cfg);
332*6906df1aSSiarhei Siamashka 	if (ret)
333*6906df1aSSiarhei Siamashka 		return ret;
334*6906df1aSSiarhei Siamashka 
335*6906df1aSSiarhei Siamashka 	return axp221_setbits(AXP221_OUTPUT_CTRL2, bits);
336*6906df1aSSiarhei Siamashka }
337*6906df1aSSiarhei Siamashka 
3385c7f10fdSOliver Schinagl int axp221_init(void)
3395c7f10fdSOliver Schinagl {
3403c781190SHans de Goede 	/* This cannot be 0 because it is used in SPL before BSS is ready */
3413c781190SHans de Goede 	static int needs_init = 1;
3425c7f10fdSOliver Schinagl 	u8 axp_chip_id;
3435c7f10fdSOliver Schinagl 	int ret;
3445c7f10fdSOliver Schinagl 
3453c781190SHans de Goede 	if (!needs_init)
3463c781190SHans de Goede 		return 0;
3473c781190SHans de Goede 
348bdcdf846SHans de Goede 	ret = pmic_bus_init();
3495c7f10fdSOliver Schinagl 	if (ret)
3505c7f10fdSOliver Schinagl 		return ret;
3515c7f10fdSOliver Schinagl 
352bdcdf846SHans de Goede 	ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
3535c7f10fdSOliver Schinagl 	if (ret)
3545c7f10fdSOliver Schinagl 		return ret;
3555c7f10fdSOliver Schinagl 
3565c7f10fdSOliver Schinagl 	if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17))
3575c7f10fdSOliver Schinagl 		return -ENODEV;
3585c7f10fdSOliver Schinagl 
3593c781190SHans de Goede 	needs_init = 0;
3605c7f10fdSOliver Schinagl 	return 0;
3615c7f10fdSOliver Schinagl }
362f3fba566SHans de Goede 
363f3fba566SHans de Goede int axp221_get_sid(unsigned int *sid)
364f3fba566SHans de Goede {
365f3fba566SHans de Goede 	u8 *dest = (u8 *)sid;
366f3fba566SHans de Goede 	int i, ret;
367f3fba566SHans de Goede 
368f3fba566SHans de Goede 	ret = axp221_init();
369f3fba566SHans de Goede 	if (ret)
370f3fba566SHans de Goede 		return ret;
371f3fba566SHans de Goede 
372bdcdf846SHans de Goede 	ret = pmic_bus_write(AXP221_PAGE, 1);
373f3fba566SHans de Goede 	if (ret)
374f3fba566SHans de Goede 		return ret;
375f3fba566SHans de Goede 
376f3fba566SHans de Goede 	for (i = 0; i < 16; i++) {
377bdcdf846SHans de Goede 		ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
378f3fba566SHans de Goede 		if (ret)
379f3fba566SHans de Goede 			return ret;
380f3fba566SHans de Goede 	}
381f3fba566SHans de Goede 
382bdcdf846SHans de Goede 	pmic_bus_write(AXP221_PAGE, 0);
383f3fba566SHans de Goede 
384f3fba566SHans de Goede 	for (i = 0; i < 4; i++)
385f3fba566SHans de Goede 		sid[i] = be32_to_cpu(sid[i]);
386f3fba566SHans de Goede 
387f3fba566SHans de Goede 	return 0;
388f3fba566SHans de Goede }
3892abac621SHans de Goede 
3902abac621SHans de Goede static int axp_drivebus_setup(void)
3912abac621SHans de Goede {
3922abac621SHans de Goede 	int ret;
3932abac621SHans de Goede 
3942abac621SHans de Goede 	ret = axp221_init();
3952abac621SHans de Goede 	if (ret)
3962abac621SHans de Goede 		return ret;
3972abac621SHans de Goede 
3982abac621SHans de Goede 	/* Set N_VBUSEN pin to output / DRIVEBUS function */
3992abac621SHans de Goede 	return axp221_clrbits(AXP221_MISC_CTRL, AXP221_MISC_CTRL_N_VBUSEN_FUNC);
4002abac621SHans de Goede }
4012abac621SHans de Goede 
4022abac621SHans de Goede int axp_drivebus_enable(void)
4032abac621SHans de Goede {
4042abac621SHans de Goede 	int ret;
4052abac621SHans de Goede 
4062abac621SHans de Goede 	ret = axp_drivebus_setup();
4072abac621SHans de Goede 	if (ret)
4082abac621SHans de Goede 		return ret;
4092abac621SHans de Goede 
4102abac621SHans de Goede 	/* Set DRIVEBUS high */
4112abac621SHans de Goede 	return axp221_setbits(AXP221_VBUS_IPSOUT, AXP221_VBUS_IPSOUT_DRIVEBUS);
4122abac621SHans de Goede }
4132abac621SHans de Goede 
4142abac621SHans de Goede int axp_drivebus_disable(void)
4152abac621SHans de Goede {
4162abac621SHans de Goede 	int ret;
4172abac621SHans de Goede 
4182abac621SHans de Goede 	ret = axp_drivebus_setup();
4192abac621SHans de Goede 	if (ret)
4202abac621SHans de Goede 		return ret;
4212abac621SHans de Goede 
4222abac621SHans de Goede 	/* Set DRIVEBUS low */
4232abac621SHans de Goede 	return axp221_clrbits(AXP221_VBUS_IPSOUT, AXP221_VBUS_IPSOUT_DRIVEBUS);
4242abac621SHans de Goede }
425