1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * AXP809 driver based on AXP221 driver
4 *
5 *
6 * (C) Copyright 2016 Chen-Yu Tsai <wens@csie.org>
7 *
8 * Based on axp221.c
9 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
10 * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
11 */
12
13 #include <common.h>
14 #include <command.h>
15 #include <errno.h>
16 #include <asm/arch/gpio.h>
17 #include <asm/arch/pmic_bus.h>
18 #include <axp_pmic.h>
19
axp809_mvolt_to_cfg(int mvolt,int min,int max,int div)20 static u8 axp809_mvolt_to_cfg(int mvolt, int min, int max, int div)
21 {
22 if (mvolt < min)
23 mvolt = min;
24 else if (mvolt > max)
25 mvolt = max;
26
27 return (mvolt - min) / div;
28 }
29
axp_set_dcdc1(unsigned int mvolt)30 int axp_set_dcdc1(unsigned int mvolt)
31 {
32 int ret;
33 u8 cfg = axp809_mvolt_to_cfg(mvolt, 1600, 3400, 100);
34
35 if (mvolt == 0)
36 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
37 AXP809_OUTPUT_CTRL1_DCDC1_EN);
38
39 ret = pmic_bus_write(AXP809_DCDC1_CTRL, cfg);
40 if (ret)
41 return ret;
42
43 ret = pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
44 AXP809_OUTPUT_CTRL2_DC1SW_EN);
45 if (ret)
46 return ret;
47
48 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
49 AXP809_OUTPUT_CTRL1_DCDC1_EN);
50 }
51
axp_set_dcdc2(unsigned int mvolt)52 int axp_set_dcdc2(unsigned int mvolt)
53 {
54 int ret;
55 u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
56
57 if (mvolt == 0)
58 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
59 AXP809_OUTPUT_CTRL1_DCDC2_EN);
60
61 ret = pmic_bus_write(AXP809_DCDC2_CTRL, cfg);
62 if (ret)
63 return ret;
64
65 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
66 AXP809_OUTPUT_CTRL1_DCDC2_EN);
67 }
68
axp_set_dcdc3(unsigned int mvolt)69 int axp_set_dcdc3(unsigned int mvolt)
70 {
71 int ret;
72 u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1860, 20);
73
74 if (mvolt == 0)
75 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
76 AXP809_OUTPUT_CTRL1_DCDC3_EN);
77
78 ret = pmic_bus_write(AXP809_DCDC3_CTRL, cfg);
79 if (ret)
80 return ret;
81
82 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
83 AXP809_OUTPUT_CTRL1_DCDC3_EN);
84 }
85
axp_set_dcdc4(unsigned int mvolt)86 int axp_set_dcdc4(unsigned int mvolt)
87 {
88 int ret;
89 u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20);
90
91 if (mvolt >= 1540)
92 cfg = 0x30 + axp809_mvolt_to_cfg(mvolt, 1800, 2600, 100);
93
94 if (mvolt == 0)
95 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
96 AXP809_OUTPUT_CTRL1_DCDC4_EN);
97
98 ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg);
99 if (ret)
100 return ret;
101
102 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
103 AXP809_OUTPUT_CTRL1_DCDC4_EN);
104 }
105
axp_set_dcdc5(unsigned int mvolt)106 int axp_set_dcdc5(unsigned int mvolt)
107 {
108 int ret;
109 u8 cfg = axp809_mvolt_to_cfg(mvolt, 1000, 2550, 50);
110
111 if (mvolt == 0)
112 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
113 AXP809_OUTPUT_CTRL1_DCDC5_EN);
114
115 ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg);
116 if (ret)
117 return ret;
118
119 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
120 AXP809_OUTPUT_CTRL1_DCDC5_EN);
121 }
122
axp_set_aldo(int aldo_num,unsigned int mvolt)123 int axp_set_aldo(int aldo_num, unsigned int mvolt)
124 {
125 int ret;
126 u8 cfg;
127
128 if (aldo_num < 1 || aldo_num > 3)
129 return -EINVAL;
130
131 if (mvolt == 0 && aldo_num == 3)
132 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
133 AXP809_OUTPUT_CTRL2_ALDO3_EN);
134 if (mvolt == 0)
135 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1,
136 AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1));
137
138 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
139 ret = pmic_bus_write(AXP809_ALDO1_CTRL + (aldo_num - 1), cfg);
140 if (ret)
141 return ret;
142
143 if (aldo_num == 3)
144 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
145 AXP809_OUTPUT_CTRL2_ALDO3_EN);
146 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
147 AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1));
148 }
149
150 /* TODO: re-work other AXP drivers to consolidate ALDO functions. */
axp_set_aldo1(unsigned int mvolt)151 int axp_set_aldo1(unsigned int mvolt)
152 {
153 return axp_set_aldo(1, mvolt);
154 }
155
axp_set_aldo2(unsigned int mvolt)156 int axp_set_aldo2(unsigned int mvolt)
157 {
158 return axp_set_aldo(2, mvolt);
159 }
160
axp_set_aldo3(unsigned int mvolt)161 int axp_set_aldo3(unsigned int mvolt)
162 {
163 return axp_set_aldo(3, mvolt);
164 }
165
axp_set_dldo(int dldo_num,unsigned int mvolt)166 int axp_set_dldo(int dldo_num, unsigned int mvolt)
167 {
168 u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
169 int ret;
170
171 if (dldo_num < 1 || dldo_num > 2)
172 return -EINVAL;
173
174 if (mvolt == 0)
175 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
176 AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
177
178 if (dldo_num == 1 && mvolt > 3300)
179 cfg += 1 + axp809_mvolt_to_cfg(mvolt, 3400, 4200, 200);
180 ret = pmic_bus_write(AXP809_DLDO1_CTRL + (dldo_num - 1), cfg);
181 if (ret)
182 return ret;
183
184 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
185 AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
186 }
187
axp_set_eldo(int eldo_num,unsigned int mvolt)188 int axp_set_eldo(int eldo_num, unsigned int mvolt)
189 {
190 int ret;
191 u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100);
192
193 if (eldo_num < 1 || eldo_num > 3)
194 return -EINVAL;
195
196 if (mvolt == 0)
197 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
198 AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
199
200 ret = pmic_bus_write(AXP809_ELDO1_CTRL + (eldo_num - 1), cfg);
201 if (ret)
202 return ret;
203
204 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
205 AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
206 }
207
axp_set_sw(bool on)208 int axp_set_sw(bool on)
209 {
210 if (on)
211 return pmic_bus_setbits(AXP809_OUTPUT_CTRL2,
212 AXP809_OUTPUT_CTRL2_SWOUT_EN);
213
214 return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2,
215 AXP809_OUTPUT_CTRL2_SWOUT_EN);
216 }
217
axp_init(void)218 int axp_init(void)
219 {
220 return pmic_bus_init();
221 }
222
do_poweroff(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])223 int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
224 {
225 pmic_bus_write(AXP809_SHUTDOWN, AXP809_SHUTDOWN_POWEROFF);
226
227 /* infinite loop during shutdown */
228 while (1) {}
229
230 /* not reached */
231 return 0;
232 }
233