]>
Commit | Line | Data |
---|---|---|
813c7372 | 1 | /* |
2 | * AXP818 driver based on AXP221 driver | |
3 | * | |
4 | * | |
5 | * (C) Copyright 2015 Vishnu Patekar <[email protected]> | |
6 | * | |
7 | * Based on axp221.c | |
8 | * (C) Copyright 2014 Hans de Goede <[email protected]> | |
9 | * (C) Copyright 2013 Oliver Schinagl <[email protected]> | |
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 | ||
20 | static u8 axp818_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 | ||
30 | int axp_set_dcdc1(unsigned int mvolt) | |
31 | { | |
32 | int ret; | |
33 | u8 cfg = axp818_mvolt_to_cfg(mvolt, 1600, 3400, 100); | |
34 | ||
35 | if (mvolt == 0) | |
36 | return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1, | |
37 | AXP818_OUTPUT_CTRL1_DCDC1_EN); | |
38 | ||
39 | ret = pmic_bus_write(AXP818_DCDC1_CTRL, cfg); | |
40 | if (ret) | |
41 | return ret; | |
42 | ||
43 | return pmic_bus_setbits(AXP818_OUTPUT_CTRL1, | |
44 | AXP818_OUTPUT_CTRL1_DCDC1_EN); | |
45 | } | |
46 | ||
47 | int axp_set_dcdc2(unsigned int mvolt) | |
48 | { | |
49 | int ret; | |
50 | u8 cfg; | |
51 | ||
52 | if (mvolt >= 1220) | |
53 | cfg = 70 + axp818_mvolt_to_cfg(mvolt, 1220, 1300, 20); | |
54 | else | |
55 | cfg = axp818_mvolt_to_cfg(mvolt, 500, 1200, 10); | |
56 | ||
57 | if (mvolt == 0) | |
58 | return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1, | |
59 | AXP818_OUTPUT_CTRL1_DCDC2_EN); | |
60 | ||
61 | ret = pmic_bus_write(AXP818_DCDC2_CTRL, cfg); | |
62 | if (ret) | |
63 | return ret; | |
64 | ||
65 | return pmic_bus_setbits(AXP818_OUTPUT_CTRL1, | |
66 | AXP818_OUTPUT_CTRL1_DCDC2_EN); | |
67 | } | |
68 | ||
69 | int axp_set_dcdc3(unsigned int mvolt) | |
70 | { | |
71 | int ret; | |
72 | u8 cfg; | |
73 | ||
74 | if (mvolt >= 1220) | |
75 | cfg = 70 + axp818_mvolt_to_cfg(mvolt, 1220, 1300, 20); | |
76 | else | |
77 | cfg = axp818_mvolt_to_cfg(mvolt, 500, 1200, 10); | |
78 | ||
79 | if (mvolt == 0) | |
80 | return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1, | |
81 | AXP818_OUTPUT_CTRL1_DCDC3_EN); | |
82 | ||
83 | ret = pmic_bus_write(AXP818_DCDC3_CTRL, cfg); | |
84 | if (ret) | |
85 | return ret; | |
86 | ||
87 | return pmic_bus_setbits(AXP818_OUTPUT_CTRL1, | |
88 | AXP818_OUTPUT_CTRL1_DCDC3_EN); | |
89 | } | |
90 | ||
91 | int axp_set_dcdc5(unsigned int mvolt) | |
92 | { | |
93 | int ret; | |
94 | u8 cfg; | |
95 | ||
96 | if (mvolt >= 1140) | |
97 | cfg = 32 + axp818_mvolt_to_cfg(mvolt, 1140, 1840, 20); | |
98 | else | |
99 | cfg = axp818_mvolt_to_cfg(mvolt, 800, 1120, 10); | |
100 | ||
101 | if (mvolt == 0) | |
102 | return pmic_bus_clrbits(AXP818_OUTPUT_CTRL1, | |
103 | AXP818_OUTPUT_CTRL1_DCDC5_EN); | |
104 | ||
105 | ret = pmic_bus_write(AXP818_DCDC5_CTRL, cfg); | |
106 | if (ret) | |
107 | return ret; | |
108 | ||
109 | return pmic_bus_setbits(AXP818_OUTPUT_CTRL1, | |
110 | AXP818_OUTPUT_CTRL1_DCDC5_EN); | |
111 | } | |
112 | ||
f3c5045a CYT |
113 | int axp_set_aldo(int aldo_num, unsigned int mvolt) |
114 | { | |
115 | int ret; | |
116 | u8 cfg; | |
117 | ||
118 | if (aldo_num < 1 || aldo_num > 3) | |
119 | return -EINVAL; | |
120 | ||
121 | if (mvolt == 0) | |
122 | return pmic_bus_clrbits(AXP818_OUTPUT_CTRL3, | |
123 | AXP818_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1)); | |
124 | ||
125 | cfg = axp818_mvolt_to_cfg(mvolt, 700, 3300, 100); | |
126 | ret = pmic_bus_write(AXP818_ALDO1_CTRL + (aldo_num - 1), cfg); | |
127 | if (ret) | |
128 | return ret; | |
129 | ||
130 | return pmic_bus_setbits(AXP818_OUTPUT_CTRL3, | |
131 | AXP818_OUTPUT_CTRL3_ALDO1_EN << (aldo_num - 1)); | |
132 | } | |
133 | ||
134 | /* TODO: re-work other AXP drivers to consolidate ALDO functions. */ | |
135 | int axp_set_aldo1(unsigned int mvolt) | |
136 | { | |
137 | return axp_set_aldo(1, mvolt); | |
138 | } | |
139 | ||
140 | int axp_set_aldo2(unsigned int mvolt) | |
141 | { | |
142 | return axp_set_aldo(2, mvolt); | |
143 | } | |
144 | ||
145 | int axp_set_aldo3(unsigned int mvolt) | |
146 | { | |
147 | return axp_set_aldo(3, mvolt); | |
148 | } | |
149 | ||
0509efb7 CYT |
150 | int axp_set_dldo(int dldo_num, unsigned int mvolt) |
151 | { | |
152 | int ret; | |
153 | u8 cfg; | |
154 | ||
155 | if (dldo_num < 1 || dldo_num > 4) | |
156 | return -EINVAL; | |
157 | ||
158 | if (mvolt == 0) | |
159 | return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2, | |
160 | AXP818_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1)); | |
161 | ||
162 | cfg = axp818_mvolt_to_cfg(mvolt, 700, 3300, 100); | |
163 | if (dldo_num == 2 && mvolt > 3300) | |
164 | cfg += 1 + axp818_mvolt_to_cfg(mvolt, 3400, 4200, 200); | |
165 | ret = pmic_bus_write(AXP818_ELDO1_CTRL + (dldo_num - 1), cfg); | |
166 | if (ret) | |
167 | return ret; | |
168 | ||
169 | return pmic_bus_setbits(AXP818_OUTPUT_CTRL2, | |
170 | AXP818_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1)); | |
171 | } | |
172 | ||
173 | int axp_set_eldo(int eldo_num, unsigned int mvolt) | |
174 | { | |
175 | int ret; | |
176 | u8 cfg; | |
177 | ||
178 | if (eldo_num < 1 || eldo_num > 3) | |
179 | return -EINVAL; | |
180 | ||
181 | if (mvolt == 0) | |
182 | return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2, | |
183 | AXP818_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1)); | |
184 | ||
185 | cfg = axp818_mvolt_to_cfg(mvolt, 700, 1900, 50); | |
186 | ret = pmic_bus_write(AXP818_ELDO1_CTRL + (eldo_num - 1), cfg); | |
187 | if (ret) | |
188 | return ret; | |
189 | ||
190 | return pmic_bus_setbits(AXP818_OUTPUT_CTRL2, | |
191 | AXP818_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1)); | |
192 | } | |
193 | ||
38491d9c CYT |
194 | int axp_set_fldo(int fldo_num, unsigned int mvolt) |
195 | { | |
196 | int ret; | |
197 | u8 cfg; | |
198 | ||
199 | if (fldo_num < 1 || fldo_num > 3) | |
200 | return -EINVAL; | |
201 | ||
202 | if (mvolt == 0) | |
203 | return pmic_bus_clrbits(AXP818_OUTPUT_CTRL3, | |
204 | AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1)); | |
205 | ||
206 | if (fldo_num < 3) { | |
207 | cfg = axp818_mvolt_to_cfg(mvolt, 700, 1450, 50); | |
208 | ret = pmic_bus_write(AXP818_FLDO1_CTRL + (fldo_num - 1), cfg); | |
209 | } else { | |
210 | /* | |
211 | * Special case for FLDO3, which is DCDC5 / 2 or FLDOIN / 2 | |
212 | * Since FLDOIN is unknown, test against DCDC5. | |
213 | */ | |
214 | if (mvolt * 2 == CONFIG_AXP_DCDC5_VOLT) | |
215 | ret = pmic_bus_clrbits(AXP818_FLDO2_3_CTRL, | |
216 | AXP818_FLDO2_3_CTRL_FLDO3_VOL); | |
217 | else | |
218 | ret = pmic_bus_setbits(AXP818_FLDO2_3_CTRL, | |
219 | AXP818_FLDO2_3_CTRL_FLDO3_VOL); | |
220 | } | |
221 | if (ret) | |
222 | return ret; | |
223 | ||
224 | return pmic_bus_setbits(AXP818_OUTPUT_CTRL3, | |
225 | AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1)); | |
226 | } | |
227 | ||
15278ccb CYT |
228 | int axp_set_sw(bool on) |
229 | { | |
230 | if (on) | |
231 | return pmic_bus_setbits(AXP818_OUTPUT_CTRL2, | |
232 | AXP818_OUTPUT_CTRL2_SW_EN); | |
233 | ||
234 | return pmic_bus_clrbits(AXP818_OUTPUT_CTRL2, | |
235 | AXP818_OUTPUT_CTRL2_SW_EN); | |
236 | } | |
237 | ||
813c7372 | 238 | int axp_init(void) |
239 | { | |
240 | u8 axp_chip_id; | |
241 | int ret; | |
242 | ||
243 | ret = pmic_bus_init(); | |
244 | if (ret) | |
245 | return ret; | |
246 | ||
247 | ret = pmic_bus_read(AXP818_CHIP_ID, &axp_chip_id); | |
248 | if (ret) | |
249 | return ret; | |
250 | ||
251 | if (!(axp_chip_id == 0x51)) | |
252 | return -ENODEV; | |
253 | else | |
254 | return ret; | |
255 | ||
256 | return 0; | |
257 | } |