]> git.sur5r.net Git - u-boot/blob - drivers/power/axp221.c
sunxi: axp221: Add axp223 support
[u-boot] / drivers / power / axp221.c
1 /*
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>
8  * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
9  *
10  * SPDX-License-Identifier:     GPL-2.0+
11  */
12
13 #include <common.h>
14 #include <errno.h>
15 #include <asm/arch/p2wi.h>
16 #include <asm/arch/rsb.h>
17 #include <axp221.h>
18
19 /*
20  * The axp221 uses the p2wi bus, the axp223 is identical (for all registers
21  * used sofar) but uses the rsb bus. These functions abstract this.
22  */
23 static int pmic_bus_init(void)
24 {
25 #ifdef CONFIG_MACH_SUN6I
26         p2wi_init();
27         return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
28                                         AXP221_INIT_DATA);
29 #else
30         int ret;
31
32         rsb_init();
33
34         ret = rsb_set_device_mode(AXP223_DEVICE_MODE_DATA);
35         if (ret)
36                 return ret;
37
38         return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
39 #endif
40 }
41
42 static int pmic_bus_read(const u8 addr, u8 *data)
43 {
44 #ifdef CONFIG_MACH_SUN6I
45         return p2wi_read(addr, data);
46 #else
47         return rsb_read(AXP223_RUNTIME_ADDR, addr, data);
48 #endif
49 }
50
51 static int pmic_bus_write(const u8 addr, u8 data)
52 {
53 #ifdef CONFIG_MACH_SUN6I
54         return p2wi_write(addr, data);
55 #else
56         return rsb_write(AXP223_RUNTIME_ADDR, addr, data);
57 #endif
58 }
59
60 static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
61 {
62         if (mvolt < min)
63                 mvolt = min;
64         else if (mvolt > max)
65                 mvolt = max;
66
67         return (mvolt - min) / div;
68 }
69
70 static int axp221_setbits(u8 reg, u8 bits)
71 {
72         int ret;
73         u8 val;
74
75         ret = pmic_bus_read(reg, &val);
76         if (ret)
77                 return ret;
78
79         val |= bits;
80         return pmic_bus_write(reg, val);
81 }
82
83 int axp221_set_dcdc1(unsigned int mvolt)
84 {
85         int ret;
86         u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
87
88         ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
89         if (ret)
90                 return ret;
91
92         return axp221_setbits(AXP221_OUTPUT_CTRL2,
93                               AXP221_OUTPUT_CTRL2_DCDC1_EN);
94 }
95
96 int axp221_set_dcdc2(unsigned int mvolt)
97 {
98         u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
99
100         return pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
101 }
102
103 int axp221_set_dcdc3(unsigned int mvolt)
104 {
105         u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
106
107         return pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
108 }
109
110 int axp221_set_dcdc4(unsigned int mvolt)
111 {
112         u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
113
114         return pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
115 }
116
117 int axp221_set_dcdc5(unsigned int mvolt)
118 {
119         u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
120
121         return pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
122 }
123
124 int axp221_set_dldo1(unsigned int mvolt)
125 {
126         int ret;
127         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
128
129         ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
130         if (ret)
131                 return ret;
132
133         return axp221_setbits(AXP221_OUTPUT_CTRL2,
134                               AXP221_OUTPUT_CTRL2_DLDO1_EN);
135 }
136
137 int axp221_set_dldo2(unsigned int mvolt)
138 {
139         int ret;
140         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
141
142         ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
143         if (ret)
144                 return ret;
145
146         return axp221_setbits(AXP221_OUTPUT_CTRL2,
147                               AXP221_OUTPUT_CTRL2_DLDO2_EN);
148 }
149
150 int axp221_set_dldo3(unsigned int mvolt)
151 {
152         int ret;
153         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
154
155         ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
156         if (ret)
157                 return ret;
158
159         return axp221_setbits(AXP221_OUTPUT_CTRL2,
160                               AXP221_OUTPUT_CTRL2_DLDO3_EN);
161 }
162
163 int axp221_set_dldo4(unsigned int mvolt)
164 {
165         int ret;
166         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
167
168         ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
169         if (ret)
170                 return ret;
171
172         return axp221_setbits(AXP221_OUTPUT_CTRL2,
173                               AXP221_OUTPUT_CTRL2_DLDO4_EN);
174 }
175
176 int axp221_set_aldo1(unsigned int mvolt)
177 {
178         int ret;
179         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
180
181         ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
182         if (ret)
183                 return ret;
184
185         return axp221_setbits(AXP221_OUTPUT_CTRL1,
186                               AXP221_OUTPUT_CTRL1_ALDO1_EN);
187 }
188
189 int axp221_set_aldo2(unsigned int mvolt)
190 {
191         int ret;
192         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
193
194         ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
195         if (ret)
196                 return ret;
197
198         return axp221_setbits(AXP221_OUTPUT_CTRL1,
199                               AXP221_OUTPUT_CTRL1_ALDO2_EN);
200 }
201
202 int axp221_set_aldo3(unsigned int mvolt)
203 {
204         int ret;
205         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
206
207         ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
208         if (ret)
209                 return ret;
210
211         return axp221_setbits(AXP221_OUTPUT_CTRL3,
212                               AXP221_OUTPUT_CTRL3_ALDO3_EN);
213 }
214
215 int axp221_init(void)
216 {
217         u8 axp_chip_id;
218         int ret;
219
220         ret = pmic_bus_init();
221         if (ret)
222                 return ret;
223
224         ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
225         if (ret)
226                 return ret;
227
228         if (!(axp_chip_id == 0x6 || axp_chip_id == 0x7 || axp_chip_id == 0x17))
229                 return -ENODEV;
230
231         return 0;
232 }
233
234 int axp221_get_sid(unsigned int *sid)
235 {
236         u8 *dest = (u8 *)sid;
237         int i, ret;
238
239         ret = axp221_init();
240         if (ret)
241                 return ret;
242
243         ret = pmic_bus_write(AXP221_PAGE, 1);
244         if (ret)
245                 return ret;
246
247         for (i = 0; i < 16; i++) {
248                 ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
249                 if (ret)
250                         return ret;
251         }
252
253         pmic_bus_write(AXP221_PAGE, 0);
254
255         for (i = 0; i < 4; i++)
256                 sid[i] = be32_to_cpu(sid[i]);
257
258         return 0;
259 }