blob: 4667579c9158a99aa0b7caf5c5c217223107e1fd [file] [log] [blame]
Oliver Schinagld3a558d2013-07-26 12:56:58 +02001/*
Hans de Goede1dd334b2014-11-29 23:54:25 +01002 * 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>
Oliver Schinagld3a558d2013-07-26 12:56:58 +02008 * (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>
Hans de Goede1dd334b2014-11-29 23:54:25 +010016#include <asm/arch/rsb.h>
Oliver Schinagld3a558d2013-07-26 12:56:58 +020017#include <axp221.h>
18
Hans de Goede1dd334b2014-11-29 23:54:25 +010019/*
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 */
23static 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
42static 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
51static 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
Oliver Schinagld3a558d2013-07-26 12:56:58 +020060static 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
70static int axp221_setbits(u8 reg, u8 bits)
71{
72 int ret;
73 u8 val;
74
Hans de Goede1dd334b2014-11-29 23:54:25 +010075 ret = pmic_bus_read(reg, &val);
Oliver Schinagld3a558d2013-07-26 12:56:58 +020076 if (ret)
77 return ret;
78
79 val |= bits;
Hans de Goede1dd334b2014-11-29 23:54:25 +010080 return pmic_bus_write(reg, val);
Oliver Schinagld3a558d2013-07-26 12:56:58 +020081}
82
83int axp221_set_dcdc1(unsigned int mvolt)
84{
85 int ret;
86 u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
87
Hans de Goede1dd334b2014-11-29 23:54:25 +010088 ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +020089 if (ret)
90 return ret;
91
92 return axp221_setbits(AXP221_OUTPUT_CTRL2,
93 AXP221_OUTPUT_CTRL2_DCDC1_EN);
94}
95
96int axp221_set_dcdc2(unsigned int mvolt)
97{
98 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
99
Hans de Goede1dd334b2014-11-29 23:54:25 +0100100 return pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200101}
102
103int axp221_set_dcdc3(unsigned int mvolt)
104{
105 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
106
Hans de Goede1dd334b2014-11-29 23:54:25 +0100107 return pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200108}
109
110int axp221_set_dcdc4(unsigned int mvolt)
111{
112 u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
113
Hans de Goede1dd334b2014-11-29 23:54:25 +0100114 return pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200115}
116
117int axp221_set_dcdc5(unsigned int mvolt)
118{
119 u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
120
Hans de Goede1dd334b2014-11-29 23:54:25 +0100121 return pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200122}
123
124int axp221_set_dldo1(unsigned int mvolt)
125{
126 int ret;
127 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
128
Hans de Goede1dd334b2014-11-29 23:54:25 +0100129 ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200130 if (ret)
131 return ret;
132
133 return axp221_setbits(AXP221_OUTPUT_CTRL2,
134 AXP221_OUTPUT_CTRL2_DLDO1_EN);
135}
136
137int axp221_set_dldo2(unsigned int mvolt)
138{
139 int ret;
140 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
141
Hans de Goede1dd334b2014-11-29 23:54:25 +0100142 ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200143 if (ret)
144 return ret;
145
146 return axp221_setbits(AXP221_OUTPUT_CTRL2,
147 AXP221_OUTPUT_CTRL2_DLDO2_EN);
148}
149
150int axp221_set_dldo3(unsigned int mvolt)
151{
152 int ret;
153 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
154
Hans de Goede1dd334b2014-11-29 23:54:25 +0100155 ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200156 if (ret)
157 return ret;
158
159 return axp221_setbits(AXP221_OUTPUT_CTRL2,
160 AXP221_OUTPUT_CTRL2_DLDO3_EN);
161}
162
163int axp221_set_dldo4(unsigned int mvolt)
164{
165 int ret;
166 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
167
Hans de Goede1dd334b2014-11-29 23:54:25 +0100168 ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200169 if (ret)
170 return ret;
171
172 return axp221_setbits(AXP221_OUTPUT_CTRL2,
173 AXP221_OUTPUT_CTRL2_DLDO4_EN);
174}
175
176int axp221_set_aldo1(unsigned int mvolt)
177{
178 int ret;
179 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
180
Hans de Goede1dd334b2014-11-29 23:54:25 +0100181 ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200182 if (ret)
183 return ret;
184
185 return axp221_setbits(AXP221_OUTPUT_CTRL1,
186 AXP221_OUTPUT_CTRL1_ALDO1_EN);
187}
188
189int axp221_set_aldo2(unsigned int mvolt)
190{
191 int ret;
192 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
193
Hans de Goede1dd334b2014-11-29 23:54:25 +0100194 ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200195 if (ret)
196 return ret;
197
198 return axp221_setbits(AXP221_OUTPUT_CTRL1,
199 AXP221_OUTPUT_CTRL1_ALDO2_EN);
200}
201
202int axp221_set_aldo3(unsigned int mvolt)
203{
204 int ret;
205 u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
206
Hans de Goede1dd334b2014-11-29 23:54:25 +0100207 ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200208 if (ret)
209 return ret;
210
211 return axp221_setbits(AXP221_OUTPUT_CTRL3,
212 AXP221_OUTPUT_CTRL3_ALDO3_EN);
213}
214
215int axp221_init(void)
216{
217 u8 axp_chip_id;
218 int ret;
219
Hans de Goede1dd334b2014-11-29 23:54:25 +0100220 ret = pmic_bus_init();
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200221 if (ret)
222 return ret;
223
Hans de Goede1dd334b2014-11-29 23:54:25 +0100224 ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
Oliver Schinagld3a558d2013-07-26 12:56:58 +0200225 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}
Hans de Goede65142e92014-11-25 16:37:52 +0100233
234int 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
Hans de Goede1dd334b2014-11-29 23:54:25 +0100243 ret = pmic_bus_write(AXP221_PAGE, 1);
Hans de Goede65142e92014-11-25 16:37:52 +0100244 if (ret)
245 return ret;
246
247 for (i = 0; i < 16; i++) {
Hans de Goede1dd334b2014-11-29 23:54:25 +0100248 ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
Hans de Goede65142e92014-11-25 16:37:52 +0100249 if (ret)
250 return ret;
251 }
252
Hans de Goede1dd334b2014-11-29 23:54:25 +0100253 pmic_bus_write(AXP221_PAGE, 0);
Hans de Goede65142e92014-11-25 16:37:52 +0100254
255 for (i = 0; i < 4; i++)
256 sid[i] = be32_to_cpu(sid[i]);
257
258 return 0;
259}