xref: /openbmc/u-boot/drivers/power/axp809.c (revision e8f80a5a)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2795857dfSChen-Yu Tsai /*
3795857dfSChen-Yu Tsai  * AXP809 driver based on AXP221 driver
4795857dfSChen-Yu Tsai  *
5795857dfSChen-Yu Tsai  *
6795857dfSChen-Yu Tsai  * (C) Copyright 2016 Chen-Yu Tsai <wens@csie.org>
7795857dfSChen-Yu Tsai  *
8795857dfSChen-Yu Tsai  * Based on axp221.c
9795857dfSChen-Yu Tsai  * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
10795857dfSChen-Yu Tsai  * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
11795857dfSChen-Yu Tsai  */
12795857dfSChen-Yu Tsai 
13795857dfSChen-Yu Tsai #include <common.h>
14795857dfSChen-Yu Tsai #include <errno.h>
15795857dfSChen-Yu Tsai #include <asm/arch/gpio.h>
16795857dfSChen-Yu Tsai #include <asm/arch/pmic_bus.h>
17795857dfSChen-Yu Tsai #include <axp_pmic.h>
18795857dfSChen-Yu Tsai 
axp809_mvolt_to_cfg(int mvolt,int min,int max,int div)19795857dfSChen-Yu Tsai static u8 axp809_mvolt_to_cfg(int mvolt, int min, int max, int div)
20795857dfSChen-Yu Tsai {
21795857dfSChen-Yu Tsai 	if (mvolt < min)
22795857dfSChen-Yu Tsai 		mvolt = min;
23795857dfSChen-Yu Tsai 	else if (mvolt > max)
24795857dfSChen-Yu Tsai 		mvolt = max;
25795857dfSChen-Yu Tsai 
26795857dfSChen-Yu Tsai 	return (mvolt - min) / div;
27795857dfSChen-Yu Tsai }
28795857dfSChen-Yu Tsai 
axp_set_dcdc1(unsigned int mvolt)29795857dfSChen-Yu Tsai int axp_set_dcdc1(unsigned int mvolt)
30795857dfSChen-Yu Tsai {
31795857dfSChen-Yu Tsai 	int ret;
32795857dfSChen-Yu Tsai 	u8 cfg = axp809_mvolt_to_cfg(mvolt, 1600, 3400, 100);
33795857dfSChen-Yu Tsai 
34795857dfSChen-Yu Tsai 	if (mvolt == 0)
35795857dfSChen-Yu Tsai 		return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
36795857dfSChen-Yu Tsai 					AXP809_OUTPUT_CTRL1_DCDC1_EN);
37795857dfSChen-Yu Tsai 
38795857dfSChen-Yu Tsai 	ret = pmic_bus_write(AXP809_DCDC1_CTRL, cfg);
39795857dfSChen-Yu Tsai 	if (ret)
40795857dfSChen-Yu Tsai 		return ret;
41795857dfSChen-Yu Tsai 
42795857dfSChen-Yu Tsai 	ret = pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
43795857dfSChen-Yu Tsai 			       AXP809_OUTPUT_CTRL2_DC1SW_EN);
44795857dfSChen-Yu Tsai 	if (ret)
45795857dfSChen-Yu Tsai 		return ret;
46795857dfSChen-Yu Tsai 
47795857dfSChen-Yu Tsai 	return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
48795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL1_DCDC1_EN);
49795857dfSChen-Yu Tsai }
50795857dfSChen-Yu Tsai 
axp_set_dcdc2(unsigned int mvolt)51795857dfSChen-Yu Tsai int axp_set_dcdc2(unsigned int mvolt)
52795857dfSChen-Yu Tsai {
53795857dfSChen-Yu Tsai 	int ret;
54795857dfSChen-Yu Tsai 	u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
55795857dfSChen-Yu Tsai 
56795857dfSChen-Yu Tsai 	if (mvolt == 0)
57795857dfSChen-Yu Tsai 		return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
58795857dfSChen-Yu Tsai 					AXP809_OUTPUT_CTRL1_DCDC2_EN);
59795857dfSChen-Yu Tsai 
60795857dfSChen-Yu Tsai 	ret = pmic_bus_write(AXP809_DCDC2_CTRL, cfg);
61795857dfSChen-Yu Tsai 	if (ret)
62795857dfSChen-Yu Tsai 		return ret;
63795857dfSChen-Yu Tsai 
64795857dfSChen-Yu Tsai 	return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
65795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL1_DCDC2_EN);
66795857dfSChen-Yu Tsai }
67795857dfSChen-Yu Tsai 
axp_set_dcdc3(unsigned int mvolt)68795857dfSChen-Yu Tsai int axp_set_dcdc3(unsigned int mvolt)
69795857dfSChen-Yu Tsai {
70795857dfSChen-Yu Tsai 	int ret;
71795857dfSChen-Yu Tsai 	u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1860, 20);
72795857dfSChen-Yu Tsai 
73795857dfSChen-Yu Tsai 	if (mvolt == 0)
74795857dfSChen-Yu Tsai 		return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
75795857dfSChen-Yu Tsai 					AXP809_OUTPUT_CTRL1_DCDC3_EN);
76795857dfSChen-Yu Tsai 
77795857dfSChen-Yu Tsai 	ret = pmic_bus_write(AXP809_DCDC3_CTRL, cfg);
78795857dfSChen-Yu Tsai 	if (ret)
79795857dfSChen-Yu Tsai 		return ret;
80795857dfSChen-Yu Tsai 
81795857dfSChen-Yu Tsai 	return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
82795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL1_DCDC3_EN);
83795857dfSChen-Yu Tsai }
84795857dfSChen-Yu Tsai 
axp_set_dcdc4(unsigned int mvolt)85795857dfSChen-Yu Tsai int axp_set_dcdc4(unsigned int mvolt)
86795857dfSChen-Yu Tsai {
87795857dfSChen-Yu Tsai 	int ret;
88795857dfSChen-Yu Tsai 	u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
89795857dfSChen-Yu Tsai 
90795857dfSChen-Yu Tsai 	if (mvolt >= 1540)
91795857dfSChen-Yu Tsai 		cfg = 0x30 + axp809_mvolt_to_cfg(mvolt, 1800, 2600, 100);
92795857dfSChen-Yu Tsai 
93795857dfSChen-Yu Tsai 	if (mvolt == 0)
94795857dfSChen-Yu Tsai 		return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
95795857dfSChen-Yu Tsai 					AXP809_OUTPUT_CTRL1_DCDC4_EN);
96795857dfSChen-Yu Tsai 
97795857dfSChen-Yu Tsai 	ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg);
98795857dfSChen-Yu Tsai 	if (ret)
99795857dfSChen-Yu Tsai 		return ret;
100795857dfSChen-Yu Tsai 
101795857dfSChen-Yu Tsai 	return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
102795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL1_DCDC4_EN);
103795857dfSChen-Yu Tsai }
104795857dfSChen-Yu Tsai 
axp_set_dcdc5(unsigned int mvolt)105795857dfSChen-Yu Tsai int axp_set_dcdc5(unsigned int mvolt)
106795857dfSChen-Yu Tsai {
107795857dfSChen-Yu Tsai 	int ret;
108795857dfSChen-Yu Tsai 	u8 cfg = axp809_mvolt_to_cfg(mvolt, 1000, 2550, 50);
109795857dfSChen-Yu Tsai 
110795857dfSChen-Yu Tsai 	if (mvolt == 0)
111795857dfSChen-Yu Tsai 		return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
112795857dfSChen-Yu Tsai 					AXP809_OUTPUT_CTRL1_DCDC5_EN);
113795857dfSChen-Yu Tsai 
114795857dfSChen-Yu Tsai 	ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg);
115795857dfSChen-Yu Tsai 	if (ret)
116795857dfSChen-Yu Tsai 		return ret;
117795857dfSChen-Yu Tsai 
118795857dfSChen-Yu Tsai 	return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
119795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL1_DCDC5_EN);
120795857dfSChen-Yu Tsai }
121795857dfSChen-Yu Tsai 
axp_set_aldo(int aldo_num,unsigned int mvolt)122795857dfSChen-Yu Tsai int axp_set_aldo(int aldo_num, unsigned int mvolt)
123795857dfSChen-Yu Tsai {
124795857dfSChen-Yu Tsai 	int ret;
125795857dfSChen-Yu Tsai 	u8 cfg;
126795857dfSChen-Yu Tsai 
127795857dfSChen-Yu Tsai 	if (aldo_num < 1 || aldo_num > 3)
128795857dfSChen-Yu Tsai 		return -EINVAL;
129795857dfSChen-Yu Tsai 
130795857dfSChen-Yu Tsai 	if (mvolt == 0 && aldo_num == 3)
131795857dfSChen-Yu Tsai 		return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
132795857dfSChen-Yu Tsai 					AXP809_OUTPUT_CTRL2_ALDO3_EN);
133795857dfSChen-Yu Tsai 	if (mvolt == 0)
134795857dfSChen-Yu Tsai 		return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
135795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1));
136795857dfSChen-Yu Tsai 
137795857dfSChen-Yu Tsai 	cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
138795857dfSChen-Yu Tsai 	ret = pmic_bus_write(AXP809_ALDO1_CTRL + (aldo_num - 1), cfg);
139795857dfSChen-Yu Tsai 	if (ret)
140795857dfSChen-Yu Tsai 		return ret;
141795857dfSChen-Yu Tsai 
142795857dfSChen-Yu Tsai 	if (aldo_num == 3)
143795857dfSChen-Yu Tsai 		return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
144795857dfSChen-Yu Tsai 					AXP809_OUTPUT_CTRL2_ALDO3_EN);
1453cc293e2SRask Ingemann Lambertsen 	return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
146795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1));
147795857dfSChen-Yu Tsai }
148795857dfSChen-Yu Tsai 
149795857dfSChen-Yu Tsai /* TODO: re-work other AXP drivers to consolidate ALDO functions. */
axp_set_aldo1(unsigned int mvolt)150795857dfSChen-Yu Tsai int axp_set_aldo1(unsigned int mvolt)
151795857dfSChen-Yu Tsai {
152795857dfSChen-Yu Tsai 	return axp_set_aldo(1, mvolt);
153795857dfSChen-Yu Tsai }
154795857dfSChen-Yu Tsai 
axp_set_aldo2(unsigned int mvolt)155795857dfSChen-Yu Tsai int axp_set_aldo2(unsigned int mvolt)
156795857dfSChen-Yu Tsai {
157795857dfSChen-Yu Tsai 	return axp_set_aldo(2, mvolt);
158795857dfSChen-Yu Tsai }
159795857dfSChen-Yu Tsai 
axp_set_aldo3(unsigned int mvolt)160795857dfSChen-Yu Tsai int axp_set_aldo3(unsigned int mvolt)
161795857dfSChen-Yu Tsai {
162795857dfSChen-Yu Tsai 	return axp_set_aldo(3, mvolt);
163795857dfSChen-Yu Tsai }
164795857dfSChen-Yu Tsai 
axp_set_dldo(int dldo_num,unsigned int mvolt)165795857dfSChen-Yu Tsai int axp_set_dldo(int dldo_num, unsigned int mvolt)
166795857dfSChen-Yu Tsai {
167795857dfSChen-Yu Tsai 	u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
168795857dfSChen-Yu Tsai 	int ret;
169795857dfSChen-Yu Tsai 
170795857dfSChen-Yu Tsai 	if (dldo_num < 1 || dldo_num > 2)
171795857dfSChen-Yu Tsai 		return -EINVAL;
172795857dfSChen-Yu Tsai 
173795857dfSChen-Yu Tsai 	if (mvolt == 0)
174795857dfSChen-Yu Tsai 		return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
175795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
176795857dfSChen-Yu Tsai 
177795857dfSChen-Yu Tsai 	if (dldo_num == 1 && mvolt > 3300)
178795857dfSChen-Yu Tsai 		cfg += 1 + axp809_mvolt_to_cfg(mvolt, 3400, 4200, 200);
179795857dfSChen-Yu Tsai 	ret = pmic_bus_write(AXP809_DLDO1_CTRL + (dldo_num - 1), cfg);
180795857dfSChen-Yu Tsai 	if (ret)
181795857dfSChen-Yu Tsai 		return ret;
182795857dfSChen-Yu Tsai 
183795857dfSChen-Yu Tsai 	return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
184795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
185795857dfSChen-Yu Tsai }
186795857dfSChen-Yu Tsai 
axp_set_eldo(int eldo_num,unsigned int mvolt)187795857dfSChen-Yu Tsai int axp_set_eldo(int eldo_num, unsigned int mvolt)
188795857dfSChen-Yu Tsai {
189795857dfSChen-Yu Tsai 	int ret;
190795857dfSChen-Yu Tsai 	u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
191795857dfSChen-Yu Tsai 
192795857dfSChen-Yu Tsai 	if (eldo_num < 1 || eldo_num > 3)
193795857dfSChen-Yu Tsai 		return -EINVAL;
194795857dfSChen-Yu Tsai 
195795857dfSChen-Yu Tsai 	if (mvolt == 0)
196795857dfSChen-Yu Tsai 		return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
197795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
198795857dfSChen-Yu Tsai 
199795857dfSChen-Yu Tsai 	ret = pmic_bus_write(AXP809_ELDO1_CTRL + (eldo_num - 1), cfg);
200795857dfSChen-Yu Tsai 	if (ret)
201795857dfSChen-Yu Tsai 		return ret;
202795857dfSChen-Yu Tsai 
203795857dfSChen-Yu Tsai 	return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
204795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
205795857dfSChen-Yu Tsai }
206795857dfSChen-Yu Tsai 
axp_set_sw(bool on)207795857dfSChen-Yu Tsai int axp_set_sw(bool on)
208795857dfSChen-Yu Tsai {
209795857dfSChen-Yu Tsai 	if (on)
210795857dfSChen-Yu Tsai 		return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
211795857dfSChen-Yu Tsai 					AXP809_OUTPUT_CTRL2_SWOUT_EN);
212795857dfSChen-Yu Tsai 
213795857dfSChen-Yu Tsai 	return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
214795857dfSChen-Yu Tsai 				AXP809_OUTPUT_CTRL2_SWOUT_EN);
215795857dfSChen-Yu Tsai }
216795857dfSChen-Yu Tsai 
axp_init(void)217795857dfSChen-Yu Tsai int axp_init(void)
218795857dfSChen-Yu Tsai {
219a4ca3799SMasahiro Yamada 	return pmic_bus_init();
220795857dfSChen-Yu Tsai }
221795857dfSChen-Yu Tsai 
do_poweroff(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])222795857dfSChen-Yu Tsai int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
223795857dfSChen-Yu Tsai {
224795857dfSChen-Yu Tsai 	pmic_bus_write(AXP809_SHUTDOWN, AXP809_SHUTDOWN_POWEROFF);
225795857dfSChen-Yu Tsai 
226795857dfSChen-Yu Tsai 	/* infinite loop during shutdown */
227795857dfSChen-Yu Tsai 	while (1) {}
228795857dfSChen-Yu Tsai 
229795857dfSChen-Yu Tsai 	/* not reached */
230795857dfSChen-Yu Tsai 	return 0;
231795857dfSChen-Yu Tsai }
232