]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/power/axp221.c
dm: blk: Use uclass_find_first/next_device() in blk_first/next_device()
[people/ms/u-boot.git] / drivers / power / axp221.c
CommitLineData
5c7f10fd 1/*
bdcdf846
HG
2 * AXP221 and AXP223 driver
3 *
4 * IMPORTANT when making changes to this file check that the registers
5 * used are the same for the axp221 and axp223.
6 *
7 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
5c7f10fd
OS
8 * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
9 *
10 * SPDX-License-Identifier: GPL-2.0+
11 */
12
13#include <common.h>
fe4b71b2 14#include <command.h>
5c7f10fd 15#include <errno.h>
1d624a4f 16#include <asm/arch/pmic_bus.h>
6944aff1 17#include <axp_pmic.h>
5c7f10fd
OS
18
19static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
20{
21 if (mvolt < min)
22 mvolt = min;
23 else if (mvolt > max)
24 mvolt = max;
25
26 return (mvolt - min) / div;
27}
28
6944aff1 29int axp_set_dcdc1(unsigned int mvolt)
5c7f10fd
OS
30{
31 int ret;
32 u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
33
50e0d5e6 34 if (mvolt == 0)
1d624a4f
HG
35 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
36 AXP221_OUTPUT_CTRL1_DCDC1_EN);
50e0d5e6 37
bdcdf846 38 ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
5c7f10fd
OS
39 if (ret)
40 return ret;
41
1d624a4f
HG
42 ret = pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
43 AXP221_OUTPUT_CTRL2_DCDC1SW_EN);
50e0d5e6
HG
44 if (ret)
45 return ret;
46
1d624a4f
HG
47 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
48 AXP221_OUTPUT_CTRL1_DCDC1_EN);
5c7f10fd
OS
49}
50
6944aff1 51int axp_set_dcdc2(unsigned int mvolt)
5c7f10fd 52{
50e0d5e6 53 int ret;
5c7f10fd
OS
54 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
55
50e0d5e6 56 if (mvolt == 0)
1d624a4f
HG
57 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
58 AXP221_OUTPUT_CTRL1_DCDC2_EN);
50e0d5e6
HG
59
60 ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
61 if (ret)
62 return ret;
63
1d624a4f
HG
64 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
65 AXP221_OUTPUT_CTRL1_DCDC2_EN);
5c7f10fd
OS
66}
67
6944aff1 68int axp_set_dcdc3(unsigned int mvolt)
5c7f10fd 69{
50e0d5e6 70 int ret;
5c7f10fd
OS
71 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
72
50e0d5e6 73 if (mvolt == 0)
1d624a4f
HG
74 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
75 AXP221_OUTPUT_CTRL1_DCDC3_EN);
50e0d5e6
HG
76
77 ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
78 if (ret)
79 return ret;
80
1d624a4f
HG
81 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
82 AXP221_OUTPUT_CTRL1_DCDC3_EN);
5c7f10fd
OS
83}
84
6944aff1 85int axp_set_dcdc4(unsigned int mvolt)
5c7f10fd 86{
50e0d5e6 87 int ret;
5c7f10fd
OS
88 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
89
50e0d5e6 90 if (mvolt == 0)
1d624a4f
HG
91 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
92 AXP221_OUTPUT_CTRL1_DCDC4_EN);
50e0d5e6
HG
93
94 ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
95 if (ret)
96 return ret;
97
1d624a4f
HG
98 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
99 AXP221_OUTPUT_CTRL1_DCDC4_EN);
5c7f10fd
OS
100}
101
6944aff1 102int axp_set_dcdc5(unsigned int mvolt)
5c7f10fd 103{
50e0d5e6 104 int ret;
5c7f10fd
OS
105 u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
106
50e0d5e6 107 if (mvolt == 0)
1d624a4f
HG
108 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
109 AXP221_OUTPUT_CTRL1_DCDC5_EN);
50e0d5e6
HG
110
111 ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
112 if (ret)
113 return ret;
114
1d624a4f
HG
115 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
116 AXP221_OUTPUT_CTRL1_DCDC5_EN);
5c7f10fd
OS
117}
118
6944aff1 119int axp_set_aldo1(unsigned int mvolt)
5c7f10fd
OS
120{
121 int ret;
122 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
123
50e0d5e6 124 if (mvolt == 0)
1d624a4f
HG
125 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
126 AXP221_OUTPUT_CTRL1_ALDO1_EN);
50e0d5e6 127
bdcdf846 128 ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
5c7f10fd
OS
129 if (ret)
130 return ret;
131
1d624a4f
HG
132 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
133 AXP221_OUTPUT_CTRL1_ALDO1_EN);
5c7f10fd
OS
134}
135
6944aff1 136int axp_set_aldo2(unsigned int mvolt)
5c7f10fd
OS
137{
138 int ret;
139 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
140
50e0d5e6 141 if (mvolt == 0)
1d624a4f
HG
142 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1,
143 AXP221_OUTPUT_CTRL1_ALDO2_EN);
50e0d5e6 144
bdcdf846 145 ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
5c7f10fd
OS
146 if (ret)
147 return ret;
148
1d624a4f
HG
149 return pmic_bus_setbits(AXP221_OUTPUT_CTRL1,
150 AXP221_OUTPUT_CTRL1_ALDO2_EN);
5c7f10fd
OS
151}
152
6944aff1 153int axp_set_aldo3(unsigned int mvolt)
5c7f10fd
OS
154{
155 int ret;
156 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
157
50e0d5e6 158 if (mvolt == 0)
1d624a4f
HG
159 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL3,
160 AXP221_OUTPUT_CTRL3_ALDO3_EN);
50e0d5e6 161
bdcdf846 162 ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
5c7f10fd
OS
163 if (ret)
164 return ret;
165
1d624a4f
HG
166 return pmic_bus_setbits(AXP221_OUTPUT_CTRL3,
167 AXP221_OUTPUT_CTRL3_ALDO3_EN);
5c7f10fd
OS
168}
169
3517a27d
CYT
170int axp_set_dldo(int dldo_num, unsigned int mvolt)
171{
172 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
173 int ret;
174
175 if (dldo_num < 1 || dldo_num > 4)
176 return -EINVAL;
177
178 if (mvolt == 0)
179 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
180 AXP221_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
181
182 ret = pmic_bus_write(AXP221_DLDO1_CTRL + (dldo_num - 1), cfg);
183 if (ret)
184 return ret;
185
186 return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
187 AXP221_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1));
188}
189
6944aff1 190int axp_set_eldo(int eldo_num, unsigned int mvolt)
6906df1a
SS
191{
192 int ret;
193 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
aa23f539
CYT
194
195 if (eldo_num < 1 || eldo_num > 3)
6906df1a 196 return -EINVAL;
6906df1a
SS
197
198 if (mvolt == 0)
aa23f539
CYT
199 return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2,
200 AXP221_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
6906df1a 201
aa23f539 202 ret = pmic_bus_write(AXP221_ELDO1_CTRL + (eldo_num - 1), cfg);
6906df1a
SS
203 if (ret)
204 return ret;
205
aa23f539
CYT
206 return pmic_bus_setbits(AXP221_OUTPUT_CTRL2,
207 AXP221_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1));
6906df1a
SS
208}
209
6944aff1 210int axp_init(void)
5c7f10fd
OS
211{
212 u8 axp_chip_id;
213 int ret;
214
bdcdf846 215 ret = pmic_bus_init();
5c7f10fd
OS
216 if (ret)
217 return ret;
218
bdcdf846 219 ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
5c7f10fd
OS
220 if (ret)
221 return ret;
222
223 if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17))
224 return -ENODEV;
225
253e62bf
HG
226 /*
227 * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting
228 * from android these are sometimes on.
229 */
230 ret = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT);
231 if (ret)
232 return ret;
233
234 ret = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT);
235 if (ret)
236 return ret;
237
5c7f10fd
OS
238 return 0;
239}
f3fba566 240
6944aff1 241int axp_get_sid(unsigned int *sid)
f3fba566
HG
242{
243 u8 *dest = (u8 *)sid;
244 int i, ret;
245
6944aff1 246 ret = pmic_bus_init();
f3fba566
HG
247 if (ret)
248 return ret;
249
bdcdf846 250 ret = pmic_bus_write(AXP221_PAGE, 1);
f3fba566
HG
251 if (ret)
252 return ret;
253
254 for (i = 0; i < 16; i++) {
bdcdf846 255 ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
f3fba566
HG
256 if (ret)
257 return ret;
258 }
259
bdcdf846 260 pmic_bus_write(AXP221_PAGE, 0);
f3fba566
HG
261
262 for (i = 0; i < 4; i++)
263 sid[i] = be32_to_cpu(sid[i]);
264
265 return 0;
266}
fe4b71b2
HG
267
268int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
269{
270 pmic_bus_write(AXP221_SHUTDOWN, AXP221_SHUTDOWN_POWEROFF);
271
272 /* infinite loop during shutdown */
273 while (1) {}
274
275 /* not reached */
276 return 0;
277}