blob: 5b5cb360ec0c230b8bb4ace90ad36b586fd31a10 [file] [log] [blame]
Chen-Yu Tsai795857d2016-05-02 10:28:15 +08001/*
2 * AXP809 driver based on AXP221 driver
3 *
4 *
5 * (C) Copyright 2016 Chen-Yu Tsai <wens@csie.org>
6 *
7 * Based on axp221.c
8 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
9 * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
10 *
11 * SPDX-License-Identifier: GPL-2.0+
12 */
13
14#include <common.h>
15#include <errno.h>
16#include <asm/arch/gpio.h>
17#include <asm/arch/pmic_bus.h>
18#include <axp_pmic.h>
19
20static 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
30int 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
52int 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
69int 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
86int 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
106int 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
123int 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);
Rask Ingemann Lambertsen3cc293e2017-01-18 21:53:40 +0100146 return pmic_bus_setbits(AXP809_OUTPUT_CTRL1,
Chen-Yu Tsai795857d2016-05-02 10:28:15 +0800147 AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1));
148}
149
150/* TODO: re-work other AXP drivers to consolidate ALDO functions. */
151int axp_set_aldo1(unsigned int mvolt)
152{
153 return axp_set_aldo(1, mvolt);
154}
155
156int axp_set_aldo2(unsigned int mvolt)
157{
158 return axp_set_aldo(2, mvolt);
159}
160
161int axp_set_aldo3(unsigned int mvolt)
162{
163 return axp_set_aldo(3, mvolt);
164}
165
166int 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
188int 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
208int 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
218int axp_init(void)
219{
Masahiro Yamadaa4ca3792016-09-06 22:17:39 +0900220 return pmic_bus_init();
Chen-Yu Tsai795857d2016-05-02 10:28:15 +0800221}
222
223int do_poweroff(cmd_tbl_t *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}