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
axp809_mvolt_to_cfg(int mvolt,int min,int max,int div)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
axp_set_dcdc1(unsigned int mvolt)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
axp_set_dcdc2(unsigned int mvolt)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
axp_set_dcdc3(unsigned int mvolt)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
axp_set_dcdc4(unsigned int mvolt)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
axp_set_dcdc5(unsigned int mvolt)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
axp_set_aldo(int aldo_num,unsigned int mvolt)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);
146*3cc293e2SRask Ingemann Lambertsen return pmic_bus_setbits(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. */
axp_set_aldo1(unsigned int mvolt)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
axp_set_aldo2(unsigned int mvolt)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
axp_set_aldo3(unsigned int mvolt)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
axp_set_dldo(int dldo_num,unsigned int mvolt)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
axp_set_eldo(int eldo_num,unsigned int mvolt)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
axp_set_sw(bool on)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
axp_init(void)218795857dfSChen-Yu Tsai int axp_init(void)
219795857dfSChen-Yu Tsai {
220a4ca3799SMasahiro Yamada return pmic_bus_init();
221795857dfSChen-Yu Tsai }
222795857dfSChen-Yu Tsai
do_poweroff(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])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