xref: /OK3568_Linux_fs/u-boot/drivers/power/axp818.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * AXP818 driver based on AXP221 driver
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * (C) Copyright 2015 Vishnu Patekar <vishnuptekar0510@gmail.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Based on axp221.c
8*4882a593Smuzhiyun  * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
9*4882a593Smuzhiyun  * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <common.h>
15*4882a593Smuzhiyun #include <errno.h>
16*4882a593Smuzhiyun #include <asm/arch/gpio.h>
17*4882a593Smuzhiyun #include <asm/arch/pmic_bus.h>
18*4882a593Smuzhiyun #include <axp_pmic.h>
19*4882a593Smuzhiyun 
axp818_mvolt_to_cfg(int mvolt,int min,int max,int div)20*4882a593Smuzhiyun static u8 axp818_mvolt_to_cfg(int mvolt, int min, int max, int div)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun 	if (mvolt < min)
23*4882a593Smuzhiyun 		mvolt = min;
24*4882a593Smuzhiyun 	else if (mvolt > max)
25*4882a593Smuzhiyun 		mvolt = max;
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun 	return  (mvolt - min) / div;
28*4882a593Smuzhiyun }
29*4882a593Smuzhiyun 
axp_set_dcdc1(unsigned int mvolt)30*4882a593Smuzhiyun int axp_set_dcdc1(unsigned int mvolt)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun 	int ret;
33*4882a593Smuzhiyun 	u8 cfg = axp818_mvolt_to_cfg(mvolt, 1600, 3400, 100);
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	if (mvolt == 0)
36*4882a593Smuzhiyun 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1,
37*4882a593Smuzhiyun 					AXP818_OUTPUT_CTRL1_DCDC1_EN);
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	ret = pmic_bus_write(AXP818_DCDC1_CTRL, cfg);
40*4882a593Smuzhiyun 	if (ret)
41*4882a593Smuzhiyun 		return ret;
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL1,
44*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL1_DCDC1_EN);
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun 
axp_set_dcdc2(unsigned int mvolt)47*4882a593Smuzhiyun int axp_set_dcdc2(unsigned int mvolt)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	int ret;
50*4882a593Smuzhiyun 	u8 cfg;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	if (mvolt >= 1220)
53*4882a593Smuzhiyun 		cfg = 70 + axp818_mvolt_to_cfg(mvolt, 1220, 1300, 20);
54*4882a593Smuzhiyun 	else
55*4882a593Smuzhiyun 		cfg = axp818_mvolt_to_cfg(mvolt, 500, 1200, 10);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	if (mvolt == 0)
58*4882a593Smuzhiyun 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1,
59*4882a593Smuzhiyun 					AXP818_OUTPUT_CTRL1_DCDC2_EN);
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	ret = pmic_bus_write(AXP818_DCDC2_CTRL, cfg);
62*4882a593Smuzhiyun 	if (ret)
63*4882a593Smuzhiyun 		return ret;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL1,
66*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL1_DCDC2_EN);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun 
axp_set_dcdc3(unsigned int mvolt)69*4882a593Smuzhiyun int axp_set_dcdc3(unsigned int mvolt)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	int ret;
72*4882a593Smuzhiyun 	u8 cfg;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	if (mvolt >= 1220)
75*4882a593Smuzhiyun 		cfg = 70 + axp818_mvolt_to_cfg(mvolt, 1220, 1300, 20);
76*4882a593Smuzhiyun 	else
77*4882a593Smuzhiyun 		cfg = axp818_mvolt_to_cfg(mvolt, 500, 1200, 10);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	if (mvolt == 0)
80*4882a593Smuzhiyun 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1,
81*4882a593Smuzhiyun 					AXP818_OUTPUT_CTRL1_DCDC3_EN);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	ret = pmic_bus_write(AXP818_DCDC3_CTRL, cfg);
84*4882a593Smuzhiyun 	if (ret)
85*4882a593Smuzhiyun 		return ret;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL1,
88*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL1_DCDC3_EN);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
axp_set_dcdc5(unsigned int mvolt)91*4882a593Smuzhiyun int axp_set_dcdc5(unsigned int mvolt)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	int ret;
94*4882a593Smuzhiyun 	u8 cfg;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	if (mvolt >= 1140)
97*4882a593Smuzhiyun 		cfg = 32 + axp818_mvolt_to_cfg(mvolt, 1140, 1840, 20);
98*4882a593Smuzhiyun 	else
99*4882a593Smuzhiyun 		cfg = axp818_mvolt_to_cfg(mvolt, 800, 1120, 10);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	if (mvolt == 0)
102*4882a593Smuzhiyun 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1,
103*4882a593Smuzhiyun 					AXP818_OUTPUT_CTRL1_DCDC5_EN);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	ret = pmic_bus_write(AXP818_DCDC5_CTRL, cfg);
106*4882a593Smuzhiyun 	if (ret)
107*4882a593Smuzhiyun 		return ret;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL1,
110*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL1_DCDC5_EN);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
axp_set_aldo(int aldo_num,unsigned int mvolt)113*4882a593Smuzhiyun int axp_set_aldo(int aldo_num, unsigned int mvolt)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	int ret;
116*4882a593Smuzhiyun 	u8 cfg;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	if (aldo_num < 1 || aldo_num > 3)
119*4882a593Smuzhiyun 		return -EINVAL;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	if (mvolt == 0)
122*4882a593Smuzhiyun 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL3,
123*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1));
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	cfg = axp818_mvolt_to_cfg(mvolt, 700, 3300, 100);
126*4882a593Smuzhiyun 	ret = pmic_bus_write(AXP818_ALDO1_CTRL + (aldo_num - 1), cfg);
127*4882a593Smuzhiyun 	if (ret)
128*4882a593Smuzhiyun 		return ret;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL3,
131*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1));
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun /* TODO: re-work other AXP drivers to consolidate ALDO functions. */
axp_set_aldo1(unsigned int mvolt)135*4882a593Smuzhiyun int axp_set_aldo1(unsigned int mvolt)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	return axp_set_aldo(1, mvolt);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
axp_set_aldo2(unsigned int mvolt)140*4882a593Smuzhiyun int axp_set_aldo2(unsigned int mvolt)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	return axp_set_aldo(2, mvolt);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
axp_set_aldo3(unsigned int mvolt)145*4882a593Smuzhiyun int axp_set_aldo3(unsigned int mvolt)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	return axp_set_aldo(3, mvolt);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
axp_set_dldo(int dldo_num,unsigned int mvolt)150*4882a593Smuzhiyun int axp_set_dldo(int dldo_num, unsigned int mvolt)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun 	int ret;
153*4882a593Smuzhiyun 	u8 cfg;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	if (dldo_num < 1 || dldo_num > 4)
156*4882a593Smuzhiyun 		return -EINVAL;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	if (mvolt == 0)
159*4882a593Smuzhiyun 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2,
160*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	cfg = axp818_mvolt_to_cfg(mvolt, 700, 3300, 100);
163*4882a593Smuzhiyun 	if (dldo_num == 2 && mvolt > 3300)
164*4882a593Smuzhiyun 		cfg += 1 + axp818_mvolt_to_cfg(mvolt, 3400, 4200, 200);
165*4882a593Smuzhiyun 	ret = pmic_bus_write(AXP818_ELDO1_CTRL + (dldo_num - 1), cfg);
166*4882a593Smuzhiyun 	if (ret)
167*4882a593Smuzhiyun 		return ret;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL2,
170*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
axp_set_eldo(int eldo_num,unsigned int mvolt)173*4882a593Smuzhiyun int axp_set_eldo(int eldo_num, unsigned int mvolt)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun 	int ret;
176*4882a593Smuzhiyun 	u8 cfg;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	if (eldo_num < 1 || eldo_num > 3)
179*4882a593Smuzhiyun 		return -EINVAL;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	if (mvolt == 0)
182*4882a593Smuzhiyun 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2,
183*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	cfg = axp818_mvolt_to_cfg(mvolt, 700, 1900, 50);
186*4882a593Smuzhiyun 	ret = pmic_bus_write(AXP818_ELDO1_CTRL + (eldo_num - 1), cfg);
187*4882a593Smuzhiyun 	if (ret)
188*4882a593Smuzhiyun 		return ret;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL2,
191*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
axp_set_fldo(int fldo_num,unsigned int mvolt)194*4882a593Smuzhiyun int axp_set_fldo(int fldo_num, unsigned int mvolt)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	int ret;
197*4882a593Smuzhiyun 	u8 cfg;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	if (fldo_num < 1 || fldo_num > 3)
200*4882a593Smuzhiyun 		return -EINVAL;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	if (mvolt == 0)
203*4882a593Smuzhiyun 		return pmic_bus_clrbits(AXP818_OUTPUT_CTRL3,
204*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1));
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	if (fldo_num < 3) {
207*4882a593Smuzhiyun 		cfg = axp818_mvolt_to_cfg(mvolt, 700, 1450, 50);
208*4882a593Smuzhiyun 		ret = pmic_bus_write(AXP818_FLDO1_CTRL + (fldo_num - 1), cfg);
209*4882a593Smuzhiyun 	} else {
210*4882a593Smuzhiyun 		/*
211*4882a593Smuzhiyun 		 * Special case for FLDO3, which is DCDC5 / 2 or FLDOIN / 2
212*4882a593Smuzhiyun 		 * Since FLDOIN is unknown, test against DCDC5.
213*4882a593Smuzhiyun 		 */
214*4882a593Smuzhiyun 		if (mvolt * 2 == CONFIG_AXP_DCDC5_VOLT)
215*4882a593Smuzhiyun 			ret = pmic_bus_clrbits(AXP818_FLDO2_3_CTRL,
216*4882a593Smuzhiyun 					       AXP818_FLDO2_3_CTRL_FLDO3_VOL);
217*4882a593Smuzhiyun 		else
218*4882a593Smuzhiyun 			ret = pmic_bus_setbits(AXP818_FLDO2_3_CTRL,
219*4882a593Smuzhiyun 					       AXP818_FLDO2_3_CTRL_FLDO3_VOL);
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun 	if (ret)
222*4882a593Smuzhiyun 		return ret;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	return pmic_bus_setbits(AXP818_OUTPUT_CTRL3,
225*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1));
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
axp_set_sw(bool on)228*4882a593Smuzhiyun int axp_set_sw(bool on)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	if (on)
231*4882a593Smuzhiyun 		return pmic_bus_setbits(AXP818_OUTPUT_CTRL2,
232*4882a593Smuzhiyun 					AXP818_OUTPUT_CTRL2_SW_EN);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2,
235*4882a593Smuzhiyun 				AXP818_OUTPUT_CTRL2_SW_EN);
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun 
axp_init(void)238*4882a593Smuzhiyun int axp_init(void)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	u8 axp_chip_id;
241*4882a593Smuzhiyun 	int ret;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	ret = pmic_bus_init();
244*4882a593Smuzhiyun 	if (ret)
245*4882a593Smuzhiyun 		return ret;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	ret = pmic_bus_read(AXP818_CHIP_ID, &axp_chip_id);
248*4882a593Smuzhiyun 	if (ret)
249*4882a593Smuzhiyun 		return ret;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	if (!(axp_chip_id == 0x51))
252*4882a593Smuzhiyun 		return -ENODEV;
253*4882a593Smuzhiyun 	else
254*4882a593Smuzhiyun 		return ret;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	return 0;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
do_poweroff(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])259*4882a593Smuzhiyun int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	pmic_bus_write(AXP818_SHUTDOWN, AXP818_SHUTDOWN_POWEROFF);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	/* infinite loop during shutdown */
264*4882a593Smuzhiyun 	while (1) {}
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	/* not reached */
267*4882a593Smuzhiyun 	return 0;
268*4882a593Smuzhiyun }
269