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