1 /* $OpenBSD: axppmic.c,v 1.21 2024/10/06 03:46:48 jsg Exp $ */
2 /*
3 * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22 #include <sys/sensors.h>
23
24 #include <dev/i2c/i2cvar.h>
25 #include <dev/fdt/rsbvar.h>
26
27 #include <dev/ofw/openfirm.h>
28 #include <dev/ofw/ofw_regulator.h>
29 #include <dev/ofw/fdt.h>
30
31 extern void (*powerdownfn)(void);
32
33 #define AXP209_SDR 0x32
34 #define AXP209_SDR_SHUTDOWN (1 << 7)
35 #define AXP209_ADC_EN1 0x82
36 #define AXP209_ADC_EN1_ACIN (3 << 4)
37 #define AXP209_ADC_EN1_VBUS (3 << 2)
38
39 #define AXP803_IRQ1_EN 0x40
40 #define AXP803_IRQ2_EN 0x41
41 #define AXP803_IRQ3_EN 0x42
42 #define AXP803_IRQ4_EN 0x43
43 #define AXP803_IRQ5_EN 0x44
44 #define AXP803_IRQ5_EN_PEK_SHORT (1 << 4)
45 #define AXP803_IRQ6_EN 0x45
46 #define AXP803_IRQ1_STAT 0x48
47 #define AXP803_IRQ2_STAT 0x49
48 #define AXP803_IRQ3_STAT 0x4a
49 #define AXP803_IRQ4_STAT 0x4b
50 #define AXP803_IRQ5_STAT 0x4c
51 #define AXP803_IRQ5_STAT_PEK_SHORT (1 << 4)
52 #define AXP803_IRQ6_STAT 0x4d
53 #define AXP803_BAT_CAP_WARN 0xe6
54 #define AXP803_BAT_CAP_WARN_LV1 0xf0
55 #define AXP803_BAT_CAP_WARN_LV1BASE 5
56 #define AXP803_BAT_CAP_WARN_LV2 0x0f
57
58 #define AXP806_REG_ADDR_EXT 0xff
59 #define AXP806_REG_ADDR_EXT_MASTER_MODE (0 << 4)
60 #define AXP806_REG_ADDR_EXT_SLAVE_MODE (1 << 4)
61
62 /* Regulators for AXP209, AXP221, AXP806 and AXP809. */
63
64 struct axppmic_regdata {
65 const char *name;
66 uint8_t ereg, emask, eval, dval;
67 uint8_t vreg, vmask;
68 uint32_t base, delta, nsteps;
69 uint32_t base2, delta2, nsteps2;
70 };
71
72 const struct axppmic_regdata axp209_regdata[] = {
73 { "dcdc2", 0x12, (1 << 4), (1 << 4), (0 << 4),
74 0x23, 0x3f, 700000, 25000, 64 },
75 { "dcdc3", 0x12, (1 << 1), (1 << 1), (0 << 1),
76 0x27, 0x7f, 700000, 25000, 113 },
77 /* LDO1 can't be controlled */
78 { "ldo2", 0x12, (1 << 2), (1 << 2), (0 << 2),
79 0x28, 0xf0, 1800000, (100000 >> 4), (16 << 4) },
80 { "ldo3", 0x12, (1 << 6), (1 << 6), (0 << 6),
81 0x29, 0x7f, 700000, 25000, 113 },
82 /* LDO4 voltage levels are complicated */
83 { "ldo5", 0x90, 0x07, 0x03, 0x07,
84 0x91, 0xf0, 1800000, (100000 >> 4), (16 << 4) },
85 { NULL }
86 };
87
88 const struct axppmic_regdata axp221_regdata[] = {
89 { "dcdc1", 0x10, (1 << 1), (1 << 1), (0 << 1),
90 0x21, 0x1f, 1600000, 100000, 19 },
91 { "dcdc2", 0x10, (1 << 2), (1 << 2), (0 << 2),
92 0x22, 0x3f, 600000, 20000, 48 },
93 { "dcdc3", 0x10, (1 << 3), (1 << 3), (0 << 3),
94 0x23, 0x3f, 600000, 20000, 64 },
95 { "dcdc4", 0x10, (1 << 4), (1 << 4), (0 << 4),
96 0x24, 0x3f, 600000, 20000, 48 },
97 { "dcdc5", 0x10, (1 << 5), (1 << 5), (0 << 5),
98 0x25, 0x1f, 1000000, 50000, 32 },
99 { "dc1sw", 0x12, (1 << 7), (1 << 7), (0 << 7) },
100 { "dc5ldo", 0x10, (1 << 0), (1 << 0), (0 << 0),
101 0x1c, 0x07, 700000, 100000, 8 },
102 { "aldo1", 0x10, (1 << 6), (1 << 6), (0 << 6),
103 0x28, 0x1f, 700000, 100000, 27 },
104 { "aldo2", 0x10, (1 << 7), (1 << 7), (0 << 7),
105 0x29, 0x1f, 700000, 100000, 27 },
106 { "aldo3", 0x13, (1 << 7), (1 << 7), (0 << 7),
107 0x2a, 0x1f, 700000, 100000, 27 },
108 { "dldo1", 0x12, (1 << 3), (1 << 3), (0 << 3),
109 0x15, 0x1f, 700000, 100000, 27 },
110 { "dldo2", 0x12, (1 << 4), (1 << 4), (0 << 4),
111 0x16, 0x1f, 700000, 100000, 27 },
112 { "dldo3", 0x12, (1 << 5), (1 << 5), (0 << 5),
113 0x17, 0x1f, 700000, 100000, 27 },
114 { "dldo4", 0x12, (1 << 6), (1 << 6), (0 << 6),
115 0x18, 0x1f, 700000, 100000, 27 },
116 { "eldo1", 0x12, (1 << 0), (1 << 0), (0 << 0),
117 0x19, 0x1f, 700000, 100000, 27 },
118 { "eldo2", 0x12, (1 << 1), (1 << 1), (0 << 1),
119 0x1a, 0x1f, 700000, 100000, 27 },
120 { "eldo3", 0x12, (1 << 2), (1 << 2), (0 << 2),
121 0x1b, 0x1f, 700000, 100000, 27 },
122 { "ldo_io0", 0x90, 0x07, 0x03, 0x04,
123 0x91, 0x1f, 700000, 100000, 27 },
124 { "ldo_io1", 0x92, 0x07, 0x03, 0x04,
125 0x93, 0x1f, 700000, 100000, 27 },
126 { NULL }
127 };
128
129 const struct axppmic_regdata axp313a_regdata[] = {
130 /* dcdc1: 1.6-3.4V (100mV step) not supported */
131 { "dcdc1", 0x10, (1 << 0), (1 << 0), (0 << 0),
132 0x13, 0x7f, 500000, 10000, 71, 122000, 20000, 17 },
133 { "dcdc2", 0x10, (1 << 1), (1 << 1), (0 << 1),
134 0x14, 0x7f, 500000, 10000, 71, 122000, 20000, 17 },
135 { "dcdc3", 0x10, (1 << 2), (1 << 2), (0 << 2),
136 0x15, 0x7f, 500000, 10000, 71, 122000, 20000, 32 },
137 { "aldo1", 0x10, (1 << 3), (1 << 3), (0 << 3),
138 0x16, 0x1f, 500000, 100000, 31 },
139 { "dldo1", 0x10, (1 << 4), (1 << 4), (0 << 4),
140 0x17, 0x1f, 500000, 100000, 31 },
141 { NULL }
142 };
143
144 const struct axppmic_regdata axp803_regdata[] = {
145 { "dcdc1", 0x10, (1 << 0), (1 << 0), (0 << 0),
146 0x20, 0x1f, 1600000, 100000, 19 },
147 { "dcdc2", 0x10, (1 << 1), (1 << 1), (0 << 1),
148 0x21, 0x7f, 500000, 10000, 71, 1220000, 20000, 5 },
149 { "dcdc3", 0x10, (1 << 2), (1 << 2), (0 << 2),
150 0x22, 0x7f, 500000, 10000, 71, 1220000, 20000, 5 },
151 { "dcdc4", 0x10, (1 << 3), (1 << 3), (0 << 3),
152 0x23, 0x7f, 500000, 10000, 71, 1220000, 20000, 5 },
153 { "dcdc5", 0x10, (1 << 4), (1 << 4), (0 << 4),
154 0x24, 0x7f, 800000, 10000, 33, 1140000, 20000, 36 },
155 { "dcdc6", 0x10, (1 << 5), (1 << 5), (0 << 5),
156 0x25, 0x7f, 600000, 10000, 51, 1120000, 20000, 21 },
157 { "dc1sw", 0x12, (1 << 7), (1 << 7), (0 << 7) },
158 { "aldo1", 0x13, (1 << 5), (1 << 5), (0 << 5),
159 0x28, 0x1f, 700000, 100000, 27 },
160 { "aldo2", 0x13, (1 << 6), (1 << 6), (0 << 6),
161 0x29, 0x1f, 700000, 100000, 27 },
162 { "aldo3", 0x13, (1 << 7), (1 << 7), (0 << 7),
163 0x2a, 0x1f, 700000, 100000, 27 },
164 { "dldo1", 0x12, (1 << 3), (1 << 3), (0 << 3),
165 0x15, 0x1f, 700000, 100000, 27 },
166 { "dldo2", 0x12, (1 << 4), (1 << 4), (0 << 4),
167 0x16, 0x1f, 700000, 100000, 27, 3400000, 200000, 5 },
168 { "dldo3", 0x12, (1 << 5), (1 << 5), (0 << 5),
169 0x17, 0x1f, 700000, 100000, 27 },
170 { "dldo4", 0x12, (1 << 6), (1 << 6), (0 << 6),
171 0x18, 0x1f, 700000, 100000, 27 },
172 { "eldo1", 0x12, (1 << 0), (1 << 0), (0 << 0),
173 0x19, 0x1f, 700000, 50000, 25 },
174 { "eldo2", 0x12, (1 << 1), (1 << 1), (0 << 1),
175 0x1a, 0x1f, 700000, 50000, 25 },
176 { "eldo3", 0x12, (1 << 2), (1 << 2), (0 << 2),
177 0x1b, 0x1f, 700000, 50000, 25 },
178 { "fldo1", 0x13, (1 << 2), (1 << 2), (0 << 2),
179 0x1c, 0x0f, 700000, 50000, 16 },
180 { "fldo2", 0x13, (1 << 3), (1 << 3), (0 << 3),
181 0x1d, 0x0f, 700000, 50000, 16 },
182 { "ldo-io0", 0x90, 0x07, 0x03, 0x04,
183 0x91, 0x1f, 700000, 100000, 27 },
184 { "ldo-io1", 0x92, 0x07, 0x03, 0x04,
185 0x93, 0x1f, 700000, 100000, 27 },
186 { NULL }
187 };
188
189 const struct axppmic_regdata axp806_regdata[] = {
190 { "dcdca", 0x10, (1 << 0), (1 << 0), (0 << 0),
191 0x12, 0x7f, 600000, 10000, 51, 1120000, 20000, 21 },
192 { "dcdcb", 0x10, (1 << 1), (1 << 1), (0 << 1),
193 0x13, 0x1f, 1000000, 50000, 32 },
194 { "dcdcc", 0x10, (1 << 2), (1 << 2), (0 << 2),
195 0x14, 0x7f, 600000, 10000, 51, 1120000, 20000, 21 },
196 { "dcdcd", 0x10, (1 << 3), (1 << 3), (0 << 3),
197 0x15, 0x3f, 600000, 20000, 46, 1600000, 100000, 18 },
198 { "dcdce", 0x10, (1 << 4), (1 << 4), (0 << 4),
199 0x16, 0x1f, 1100000, 100000, 24 },
200 { "aldo1", 0x10, (1 << 5), (1 << 5), (0 << 5),
201 0x17, 0x1f, 700000, 100000, 27 },
202 { "aldo2", 0x10, (1 << 6), (1 << 6), (0 << 6),
203 0x18, 0x1f, 700000, 100000, 27 },
204 { "aldo3", 0x10, (1 << 7), (1 << 7), (0 << 7),
205 0x19, 0x1f, 700000, 100000, 27 },
206 { "bldo1", 0x11, (1 << 0), (1 << 0), (0 << 0),
207 0x20, 0x0f, 700000, 100000, 13 },
208 { "bldo2", 0x11, (1 << 1), (1 << 1), (0 << 1),
209 0x21, 0x0f, 700000, 100000, 13 },
210 { "bldo3", 0x11, (1 << 2), (1 << 2), (0 << 2),
211 0x22, 0x0f, 700000, 100000, 13 },
212 { "bldo4", 0x11, (1 << 3), (1 << 3), (0 << 3),
213 0x23, 0x0f, 700000, 100000, 13 },
214 { "cldo1", 0x11, (1 << 4), (1 << 4), (0 << 4),
215 0x24, 0x1f, 700000, 100000 , 27},
216 { "cldo2", 0x11, (1 << 5), (1 << 5), (0 << 5),
217 0x25, 0x1f, 700000, 100000, 28, 3600000, 200000, 4 },
218 { "cldo3", 0x11, (1 << 6), (1 << 6), (0 << 6),
219 0x26, 0x1f, 700000, 100000, 27 },
220 { "sw", 0x11, (1 << 7), (1 << 7), (0 << 7) },
221 { NULL }
222 };
223
224 const struct axppmic_regdata axp809_regdata[] = {
225 { "dcdc1", 0x10, (1 << 1), (1 << 1), (0 << 1),
226 0x21, 0x1f, 1600000, 100000, 19 },
227 { "dcdc2", 0x10, (1 << 2), (1 << 2), (0 << 2),
228 0x22, 0x3f, 600000, 20000, 48 },
229 { "dcdc3", 0x10, (1 << 3), (1 << 3), (0 << 3),
230 0x23, 0x3f, 600000, 20000, 64 },
231 { "dcdc4", 0x10, (1 << 4), (1 << 4), (0 << 4),
232 0x24, 0x3f, 600000, 20000, 48, 1800000, 100000, 9 },
233 { "dcdc5", 0x10, (1 << 5), (1 << 5), (0 << 5),
234 0x25, 0x1f, 1000000, 50000, 32 },
235 { "dc5ldo", 0x10, (1 << 0), (1 << 0), (0 << 0),
236 0x1c, 0x07, 700000, 100000, 8 },
237 { "aldo1", 0x10, (1 << 6), (1 << 6), (0 << 6),
238 0x28, 0x1f, 700000, 100000, 27 },
239 { "aldo2", 0x10, (1 << 7), (1 << 7), (0 << 7),
240 0x29, 0x1f, 700000, 100000, 27 },
241 { "aldo3", 0x12, (1 << 5), (1 << 5), (0 << 5),
242 0x2a, 0x1f, 700000, 100000, 27 },
243 { "dldo1", 0x12, (1 << 3), (1 << 3), (0 << 3),
244 0x15, 0x1f, 700000, 100000, 27, 3400000, 200000, 5 },
245 { "dldo2", 0x12, (1 << 4), (1 << 4), (0 << 4),
246 0x16, 0x1f, 700000, 100000, 27 },
247 { "eldo1", 0x12, (1 << 0), (1 << 0), (0 << 0),
248 0x19, 0x1f, 700000, 100000, 27 },
249 { "eldo2", 0x12, (1 << 1), (1 << 1), (0 << 1),
250 0x1a, 0x1f, 700000, 100000, 27 },
251 { "eldo3", 0x12, (1 << 2), (1 << 2), (0 << 2),
252 0x1b, 0x1f, 700000, 100000, 27 },
253 { "ldo_io0", 0x90, 0x07, 0x03, 0x04,
254 0x91, 0x1f, 700000, 100000, 27 },
255 { "ldo_io1", 0x92, 0x07, 0x03, 0x04,
256 0x93, 0x1f, 700000, 100000, 27 },
257 { NULL }
258 };
259
260 const struct axppmic_regdata axp15060_regdata[] = {
261 { "dcdc1", 0x10, (1 << 0), (1 << 0), (0 << 0),
262 0x13, 0x1f, 15000000, 100000, 20 },
263 { "dcdc2", 0x10, (1 << 1), (1 << 1), (0 << 1),
264 0x14, 0x7f, 500000, 10000, 71, 1220000, 20000, 17 },
265 { "dcdc3", 0x10, (1 << 2), (1 << 2), (0 << 2),
266 0x15, 0x7f, 500000, 10000, 71, 1220000, 20000, 17 },
267 { "dcdc4", 0x10, (1 << 3), (1 << 3), (0 << 3),
268 0x16, 0x7f, 500000, 10000, 71, 1220000, 20000, 17 },
269 { "dcdc5", 0x10, (1 << 4), (1 << 4), (0 << 4),
270 0x17, 0x7f, 800000, 10000, 33, 1140000, 20000, 36 },
271 { "dcdc6", 0x10, (1 << 5), (1 << 5), (0 << 5),
272 0x18, 0x1f, 500000, 100000, 30 },
273 { "aldo1", 0x11, (1 << 0), (1 << 0), (0 << 0),
274 0x19, 0x1f, 700000, 100000, 27 },
275 { "aldo2", 0x11, (1 << 1), (1 << 1), (0 << 1),
276 0x20, 0x1f, 700000, 100000, 27 },
277 { "aldo3", 0x11, (1 << 2), (1 << 2), (0 << 2),
278 0x21, 0x1f, 700000, 100000, 27 },
279 { "aldo4", 0x11, (1 << 3), (1 << 3), (0 << 3),
280 0x22, 0x1f, 700000, 100000, 27 },
281 { "aldo5", 0x11, (1 << 4), (1 << 4), (0 << 4),
282 0x23, 0x1f, 700000, 100000, 27 },
283 { "bldo1", 0x11, (1 << 5), (1 << 5), (0 << 5),
284 0x24, 0x1f, 700000, 100000, 27 },
285 { "bldo2", 0x11, (1 << 6), (1 << 6), (0 << 6),
286 0x25, 0x1f, 700000, 100000, 27 },
287 { "bldo3", 0x11, (1 << 7), (1 << 7), (0 << 7),
288 0x26, 0x1f, 700000, 100000, 27 },
289 { "bldo4", 0x12, (1 << 0), (1 << 0), (0 << 0),
290 0x27, 0x1f, 700000, 100000, 27 },
291 { "bldo5", 0x12, (1 << 1), (1 << 1), (0 << 1),
292 0x28, 0x1f, 700000, 100000, 27 },
293 { "cldo1", 0x12, (1 << 2), (1 << 2), (0 << 2),
294 0x29, 0x1f, 700000, 100000, 27 },
295 { "cldo2", 0x12, (1 << 3), (1 << 3), (0 << 3),
296 0x2a, 0x1f, 700000, 100000, 27 },
297 { "cldo3", 0x12, (1 << 4), (1 << 4), (0 << 4),
298 0x2b, 0x1f, 700000, 100000, 27 },
299 { "cldo4", 0x12, (1 << 5), (1 << 5), (0 << 5),
300 0x2d, 0x3f, 700000, 100000, 36 },
301 { "cpusldo", 0x12, (1 << 6), (1 << 6), (0 << 6),
302 0x2e, 0x0f, 700000, 50000, 15 },
303 { "sw", 0x12, (1 << 7), (1 << 7), (0 << 7) },
304 { NULL }
305 };
306
307 /* Sensors for AXP209 and AXP221/AXP809. */
308
309 #define AXPPMIC_NSENSORS 12
310
311 struct axppmic_sensdata {
312 const char *name;
313 enum sensor_type type;
314 uint8_t reg;
315 uint64_t base, delta;
316 };
317
318 const struct axppmic_sensdata axp209_sensdata[] = {
319 { "ACIN", SENSOR_INDICATOR, 0x00, (1 << 7), (1 << 6) },
320 { "VBUS", SENSOR_INDICATOR, 0x00, (1 << 5), (1 << 4) },
321 { "ACIN", SENSOR_VOLTS_DC, 0x56, 0, 1700 },
322 { "ACIN", SENSOR_AMPS, 0x58, 0, 625 },
323 { "VBUS", SENSOR_VOLTS_DC, 0x5a, 0, 1700 },
324 { "VBUS", SENSOR_AMPS, 0x5c, 0, 375 },
325 { "", SENSOR_TEMP, 0x5e, 128450000, 100000 },
326 { "APS", SENSOR_VOLTS_DC, 0x7e, 0, 1400 },
327 { NULL }
328 };
329
330 const struct axppmic_sensdata axp221_sensdata[] = {
331 { "ACIN", SENSOR_INDICATOR, 0x00, (1 << 7), (1 << 6) },
332 { "VBUS", SENSOR_INDICATOR, 0x00, (1 << 5), (1 << 4) },
333 { "", SENSOR_TEMP, 0x56, 5450000, 105861 },
334 { NULL }
335 };
336
337 const struct axppmic_sensdata axp803_sensdata[] = {
338 { "ACIN", SENSOR_INDICATOR, 0x00, (1 << 7), (1 << 6) },
339 { "VBUS", SENSOR_INDICATOR, 0x00, (1 << 5), (1 << 4) },
340 { "", SENSOR_TEMP, 0x56, 5450000, 106250 },
341 { NULL }
342 };
343
344 const struct axppmic_sensdata axp803_battery_sensdata[] = {
345 { "ACIN", SENSOR_INDICATOR, 0x00, (1 << 7), (1 << 6) },
346 { "VBUS", SENSOR_INDICATOR, 0x00, (1 << 5), (1 << 4) },
347 { "", SENSOR_TEMP, 0x56, 5450000, 106250 },
348 { "battery present", SENSOR_INDICATOR, 0x01, (1 << 5), (1 << 4) },
349 { "battery charging", SENSOR_INDICATOR, 0x01, (1 << 6), (1 << 6) },
350 { "battery percent", SENSOR_PERCENT, 0xb9, 0x7f, (1 << 7) },
351 { "battery voltage", SENSOR_VOLTS_DC, 0x78, 0x00, 1100 },
352 { "battery charging current", SENSOR_AMPS, 0x7a, 0x00, 1000 },
353 { "battery discharging current", SENSOR_AMPS, 0x7c, 0x00, 1000 },
354 { "battery maximum capacity", SENSOR_AMPHOUR, 0xe0, 0x00, 1456 },
355 { "battery current capacity", SENSOR_AMPHOUR, 0xe2, 0x00, 1456 },
356 { NULL }
357 };
358
359 struct axppmic_device {
360 const char *name;
361 const char *chip;
362 const struct axppmic_regdata *regdata;
363 const struct axppmic_sensdata *sensdata;
364 };
365
366 const struct axppmic_device axppmic_devices[] = {
367 { "x-powers,axp152", "AXP152" },
368 { "x-powers,axp209", "AXP209", axp209_regdata, axp209_sensdata },
369 { "x-powers,axp221", "AXP221", axp221_regdata, axp221_sensdata },
370 { "x-powers,axp223", "AXP223", axp221_regdata, axp221_sensdata },
371 { "x-powers,axp305", "AXP305", axp806_regdata },
372 { "x-powers,axp313a", "AXP313A", axp313a_regdata },
373 { "x-powers,axp803", "AXP803", axp803_regdata, axp803_sensdata },
374 { "x-powers,axp805", "AXP805", axp806_regdata },
375 { "x-powers,axp806", "AXP806", axp806_regdata },
376 { "x-powers,axp809", "AXP809", axp809_regdata, axp221_sensdata },
377 { "x-powers,axp15060", "AXP15060", axp15060_regdata },
378 };
379
380 const struct axppmic_device *
axppmic_lookup(const char * name)381 axppmic_lookup(const char *name)
382 {
383 int i;
384
385 for (i = 0; i < nitems(axppmic_devices); i++) {
386 if (strcmp(name, axppmic_devices[i].name) == 0)
387 return &axppmic_devices[i];
388 }
389
390 return NULL;
391 }
392
393 struct axppmic_softc {
394 struct device sc_dev;
395 void *sc_cookie;
396 uint16_t sc_addr;
397 const char *sc_name;
398
399 uint8_t (*sc_read)(struct axppmic_softc *, uint8_t);
400 void (*sc_write)(struct axppmic_softc *, uint8_t, uint8_t);
401 const struct axppmic_regdata *sc_regdata;
402 const struct axppmic_sensdata *sc_sensdata;
403
404 struct ksensor sc_sensor[AXPPMIC_NSENSORS];
405 struct ksensordev sc_sensordev;
406
407 uint8_t sc_warn;
408 uint8_t sc_crit;
409 };
410
411 static inline uint8_t
axppmic_read_reg(struct axppmic_softc * sc,uint8_t reg)412 axppmic_read_reg(struct axppmic_softc *sc, uint8_t reg)
413 {
414 return sc->sc_read(sc, reg);
415 }
416
417 static inline void
axppmic_write_reg(struct axppmic_softc * sc,uint8_t reg,uint8_t value)418 axppmic_write_reg(struct axppmic_softc *sc, uint8_t reg, uint8_t value)
419 {
420 sc->sc_write(sc, reg, value);
421 }
422
423 void axppmic_attach_common(struct axppmic_softc *, const char *, int);
424 int axppmic_activate(struct device *, int);
425
426 /* I2C interface */
427
428 int axppmic_i2c_match(struct device *, void *, void *);
429 void axppmic_i2c_attach(struct device *, struct device *, void *);
430
431 const struct cfattach axppmic_ca = {
432 sizeof(struct axppmic_softc), axppmic_i2c_match, axppmic_i2c_attach,
433 NULL, axppmic_activate
434 };
435
436 struct cfdriver axppmic_cd = {
437 NULL, "axppmic", DV_DULL
438 };
439
440 uint8_t axppmic_i2c_read(struct axppmic_softc *, uint8_t);
441 void axppmic_i2c_write(struct axppmic_softc *, uint8_t, uint8_t);
442
443 int
axppmic_i2c_match(struct device * parent,void * match,void * aux)444 axppmic_i2c_match(struct device *parent, void *match, void *aux)
445 {
446 struct i2c_attach_args *ia = aux;
447
448 if (axppmic_lookup(ia->ia_name))
449 return 1;
450 return 0;
451 }
452
453 void
axppmic_i2c_attach(struct device * parent,struct device * self,void * aux)454 axppmic_i2c_attach(struct device *parent, struct device *self, void *aux)
455 {
456 struct axppmic_softc *sc = (struct axppmic_softc *)self;
457 struct i2c_attach_args *ia = aux;
458 int node = *(int *)ia->ia_cookie;
459
460 sc->sc_cookie = ia->ia_tag;
461 sc->sc_addr = ia->ia_addr;
462 sc->sc_read = axppmic_i2c_read;
463 sc->sc_write = axppmic_i2c_write;
464
465 axppmic_attach_common(sc, ia->ia_name, node);
466 }
467
468 uint8_t
axppmic_i2c_read(struct axppmic_softc * sc,uint8_t reg)469 axppmic_i2c_read(struct axppmic_softc *sc, uint8_t reg)
470 {
471 i2c_tag_t tag = sc->sc_cookie;
472 int flags = cold ? I2C_F_POLL : 0;
473 int error;
474 uint8_t value;
475
476 iic_acquire_bus(tag, flags);
477 error = iic_smbus_read_byte(tag, sc->sc_addr, reg, &value, flags);
478 iic_release_bus(tag, flags);
479 if (error) {
480 printf("%s: SMBus read byte from 0x%02x failed\n",
481 sc->sc_dev.dv_xname, reg);
482 return 0xff;
483 }
484
485 return value;
486 }
487
488 void
axppmic_i2c_write(struct axppmic_softc * sc,uint8_t reg,uint8_t value)489 axppmic_i2c_write(struct axppmic_softc *sc, uint8_t reg, uint8_t value)
490 {
491 i2c_tag_t tag = sc->sc_cookie;
492 int flags = cold ? I2C_F_POLL : 0;
493 int error;
494
495 iic_acquire_bus(tag, flags);
496 error = iic_smbus_write_byte(tag, sc->sc_addr, reg, value, flags);
497 iic_release_bus(tag, flags);
498 if (error)
499 printf("%s: SMBus write byte to 0x%02x failed\n",
500 sc->sc_dev.dv_xname, reg);
501 }
502
503 /* RSB interface */
504
505 #include "sxirsb.h"
506
507 #if NSXIRSB > 0
508
509 int axppmic_rsb_match(struct device *, void *, void *);
510 void axppmic_rsb_attach(struct device *, struct device *, void *);
511
512 const struct cfattach axppmic_rsb_ca = {
513 sizeof(struct axppmic_softc), axppmic_rsb_match, axppmic_rsb_attach,
514 NULL, axppmic_activate
515 };
516
517 uint8_t axppmic_rsb_read(struct axppmic_softc *, uint8_t);
518 void axppmic_rsb_write(struct axppmic_softc *, uint8_t, uint8_t);
519
520 int
axppmic_rsb_match(struct device * parent,void * match,void * aux)521 axppmic_rsb_match(struct device *parent, void *match, void *aux)
522 {
523 struct rsb_attach_args *ra = aux;
524
525 if (axppmic_lookup(ra->ra_name))
526 return 1;
527 return 0;
528 }
529
530 void
axppmic_rsb_attach(struct device * parent,struct device * self,void * aux)531 axppmic_rsb_attach(struct device *parent, struct device *self, void *aux)
532 {
533 struct axppmic_softc *sc = (struct axppmic_softc *)self;
534 struct rsb_attach_args *ra = aux;
535
536 sc->sc_cookie = ra->ra_cookie;
537 sc->sc_addr = ra->ra_rta;
538 sc->sc_read = axppmic_rsb_read;
539 sc->sc_write = axppmic_rsb_write;
540
541 axppmic_attach_common(sc, ra->ra_name, ra->ra_node);
542 }
543
544 uint8_t
axppmic_rsb_read(struct axppmic_softc * sc,uint8_t reg)545 axppmic_rsb_read(struct axppmic_softc *sc, uint8_t reg)
546 {
547 return rsb_read_1(sc->sc_cookie, sc->sc_addr, reg);
548 }
549
550 void
axppmic_rsb_write(struct axppmic_softc * sc,uint8_t reg,uint8_t value)551 axppmic_rsb_write(struct axppmic_softc *sc, uint8_t reg, uint8_t value)
552 {
553 rsb_write_1(sc->sc_cookie, sc->sc_addr, reg, value);
554 }
555
556 #endif
557
558 /* Common code */
559
560 void axppmic_attach_node(struct axppmic_softc *, int);
561 void axppmic_attach_regulators(struct axppmic_softc *, int);
562 void axppmic_attach_sensors(struct axppmic_softc *);
563
564 struct axppmic_softc *axppmic_sc;
565 void axp209_powerdown(void);
566
567 void
axppmic_attach_common(struct axppmic_softc * sc,const char * name,int node)568 axppmic_attach_common(struct axppmic_softc *sc, const char *name, int node)
569 {
570 const struct axppmic_device *device;
571 int child;
572
573 device = axppmic_lookup(name);
574 printf(": %s\n", device->chip);
575
576 sc->sc_name = device->name;
577 sc->sc_regdata = device->regdata;
578 sc->sc_sensdata = device->sensdata;
579
580 /* Switch AXP806 into master or slave mode. */
581 if (strcmp(name, "x-powers,axp305") == 0 ||
582 strcmp(name, "x-powers,axp805") == 0 ||
583 strcmp(name, "x-powers,axp806") == 0) {
584 if (OF_getproplen(node, "x-powers,master-mode") == 0 ||
585 OF_getproplen(node, "x-powers,self-working-mode") == 0) {
586 axppmic_write_reg(sc, AXP806_REG_ADDR_EXT,
587 AXP806_REG_ADDR_EXT_MASTER_MODE);
588 } else {
589 axppmic_write_reg(sc, AXP806_REG_ADDR_EXT,
590 AXP806_REG_ADDR_EXT_SLAVE_MODE);
591 }
592 }
593
594 /* Enable data collection on AXP209. */
595 if (strcmp(name, "x-powers,axp209") == 0) {
596 uint8_t reg;
597
598 /* Turn on sampling of ACIN and VBUS voltage and current. */
599 reg = axppmic_read_reg(sc, AXP209_ADC_EN1);
600 reg |= AXP209_ADC_EN1_ACIN;
601 reg |= AXP209_ADC_EN1_VBUS;
602 axppmic_write_reg(sc, AXP209_ADC_EN1, reg);
603 }
604
605 /* Read battery warning levels on AXP803. */
606 if (strcmp(name, "x-powers,axp803") == 0) {
607 uint8_t value;
608
609 value = axppmic_read_reg(sc, AXP803_BAT_CAP_WARN);
610 sc->sc_warn = ((value & AXP803_BAT_CAP_WARN_LV1) >> 4);
611 sc->sc_warn += AXP803_BAT_CAP_WARN_LV1BASE;
612 sc->sc_crit = (value & AXP803_BAT_CAP_WARN_LV2);
613 }
614
615 for (child = OF_child(node); child; child = OF_peer(child))
616 axppmic_attach_node(sc, child);
617
618 if (sc->sc_regdata)
619 axppmic_attach_regulators(sc, node);
620
621 if (sc->sc_sensdata)
622 axppmic_attach_sensors(sc);
623
624 /* Disable all interrupts on AXP803. */
625 if (strcmp(name, "x-powers,axp803") == 0) {
626 axppmic_write_reg(sc, AXP803_IRQ1_EN, 0);
627 axppmic_write_reg(sc, AXP803_IRQ2_EN, 0);
628 axppmic_write_reg(sc, AXP803_IRQ3_EN, 0);
629 axppmic_write_reg(sc, AXP803_IRQ4_EN, 0);
630 axppmic_write_reg(sc, AXP803_IRQ5_EN, 0);
631 axppmic_write_reg(sc, AXP803_IRQ6_EN, 0);
632 }
633
634 #ifdef __armv7__
635 if (strcmp(name, "x-powers,axp152") == 0 ||
636 strcmp(name, "x-powers,axp209") == 0) {
637 axppmic_sc = sc;
638 powerdownfn = axp209_powerdown;
639 }
640 #endif
641
642 #ifdef SUSPEND
643 /* AXP803 can wake us up. */
644 if (strcmp(name, "x-powers,axp803") == 0)
645 device_register_wakeup(&sc->sc_dev);
646 #endif
647 }
648
649 void
axppmic_attach_node(struct axppmic_softc * sc,int node)650 axppmic_attach_node(struct axppmic_softc *sc, int node)
651 {
652 char status[32];
653
654 if (OF_getprop(node, "status", status, sizeof(status)) > 0 &&
655 strcmp(status, "disabled") == 0)
656 return;
657
658 if (OF_is_compatible(node, "x-powers,axp803-battery-power-supply"))
659 sc->sc_sensdata = axp803_battery_sensdata;
660 }
661
662 int
axppmic_activate(struct device * self,int act)663 axppmic_activate(struct device *self, int act)
664 {
665 struct axppmic_softc *sc = (struct axppmic_softc *)self;
666
667 switch (act) {
668 case DVACT_SUSPEND:
669 if (strcmp(sc->sc_name, "x-powers,axp803") == 0) {
670 /* Enable interrupt for short power button press. */
671 axppmic_write_reg(sc, AXP803_IRQ5_STAT,
672 AXP803_IRQ5_STAT_PEK_SHORT);
673 axppmic_write_reg(sc, AXP803_IRQ5_EN,
674 AXP803_IRQ5_EN_PEK_SHORT);
675 }
676 break;
677 case DVACT_RESUME:
678 if (strcmp(sc->sc_name, "x-powers,axp803") == 0) {
679 /* Disable interrupt for short power button press. */
680 axppmic_write_reg(sc, AXP803_IRQ5_EN, 0);
681 }
682 break;
683 }
684
685 return 0;
686 }
687
688 /* Regulators */
689
690 struct axppmic_regulator {
691 struct axppmic_softc *ar_sc;
692
693 uint8_t ar_ereg, ar_emask;
694 uint8_t ar_eval, ar_dval;
695
696 uint8_t ar_vreg, ar_vmask;
697 uint32_t ar_base, ar_delta, ar_nsteps;
698 uint32_t ar_base2, ar_delta2, ar_nsteps2;
699
700 struct regulator_device ar_rd;
701 };
702
703 void axppmic_attach_regulator(struct axppmic_softc *, int);
704 uint32_t axppmic_get_voltage(void *);
705 int axppmic_set_voltage(void *, uint32_t);
706 int axppmic_enable(void *, int);
707
708 void
axppmic_attach_regulators(struct axppmic_softc * sc,int node)709 axppmic_attach_regulators(struct axppmic_softc *sc, int node)
710 {
711 node = OF_getnodebyname(node, "regulators");
712 if (node == 0)
713 return;
714
715 for (node = OF_child(node); node; node = OF_peer(node))
716 axppmic_attach_regulator(sc, node);
717 }
718
719 void
axppmic_attach_regulator(struct axppmic_softc * sc,int node)720 axppmic_attach_regulator(struct axppmic_softc *sc, int node)
721 {
722 struct axppmic_regulator *ar;
723 char name[32];
724 int i;
725
726 name[0] = 0;
727 OF_getprop(node, "name", name, sizeof(name));
728 name[sizeof(name) - 1] = 0;
729 for (i = 0; sc->sc_regdata[i].name; i++) {
730 if (strcmp(sc->sc_regdata[i].name, name) == 0)
731 break;
732 }
733 if (sc->sc_regdata[i].name == NULL)
734 return;
735
736 ar = malloc(sizeof(*ar), M_DEVBUF, M_WAITOK | M_ZERO);
737 ar->ar_sc = sc;
738
739 ar->ar_ereg = sc->sc_regdata[i].ereg;
740 ar->ar_emask = sc->sc_regdata[i].emask;
741 ar->ar_eval = sc->sc_regdata[i].eval;
742 ar->ar_dval = sc->sc_regdata[i].dval;
743 ar->ar_vreg = sc->sc_regdata[i].vreg;
744 ar->ar_vmask = sc->sc_regdata[i].vmask;
745 ar->ar_base = sc->sc_regdata[i].base;
746 ar->ar_delta = sc->sc_regdata[i].delta;
747 ar->ar_nsteps = sc->sc_regdata[i].nsteps;
748 ar->ar_base2 = sc->sc_regdata[i].base2;
749 ar->ar_delta2 = sc->sc_regdata[i].delta2;
750 ar->ar_nsteps2 = sc->sc_regdata[i].nsteps2;
751
752 ar->ar_rd.rd_node = node;
753 ar->ar_rd.rd_cookie = ar;
754 ar->ar_rd.rd_get_voltage = axppmic_get_voltage;
755 ar->ar_rd.rd_set_voltage = axppmic_set_voltage;
756 ar->ar_rd.rd_enable = axppmic_enable;
757 regulator_register(&ar->ar_rd);
758 }
759
760 uint32_t
axppmic_get_voltage(void * cookie)761 axppmic_get_voltage(void *cookie)
762 {
763 struct axppmic_regulator *ar = cookie;
764 uint32_t voltage;
765 uint8_t value;
766
767 value = axppmic_read_reg(ar->ar_sc, ar->ar_vreg);
768 value &= ar->ar_vmask;
769 if (ar->ar_base2 > 0 && value >= ar->ar_nsteps) {
770 voltage =
771 ar->ar_base2 + (value - ar->ar_nsteps) * ar->ar_delta2;
772 } else {
773 voltage = ar->ar_base + value * ar->ar_delta;
774 }
775 return voltage;
776 }
777
778 int
axppmic_set_voltage(void * cookie,uint32_t voltage)779 axppmic_set_voltage(void *cookie, uint32_t voltage)
780 {
781 struct axppmic_regulator *ar = cookie;
782 uint32_t value, reg;
783
784 if (voltage < ar->ar_base)
785 return EINVAL;
786 if (ar->ar_base2 > 0 && voltage >= ar->ar_base2) {
787 value = (voltage - ar->ar_base2) / ar->ar_delta2;
788 if (value >= ar->ar_nsteps2)
789 return EINVAL;
790 value += ar->ar_nsteps;
791 } else {
792 value = (voltage - ar->ar_base) / ar->ar_delta;
793 if (value >= ar->ar_nsteps)
794 return EINVAL;
795 }
796 if (value > ar->ar_vmask)
797 return EINVAL;
798
799 reg = axppmic_read_reg(ar->ar_sc, ar->ar_vreg);
800 axppmic_write_reg(ar->ar_sc, ar->ar_vreg,
801 (reg & ~ar->ar_vmask) | (value & ar->ar_vmask));
802 return 0;
803 }
804
805 int
axppmic_enable(void * cookie,int on)806 axppmic_enable(void *cookie, int on)
807 {
808 struct axppmic_regulator *ar = cookie;
809 uint8_t reg;
810
811 reg = axppmic_read_reg(ar->ar_sc, ar->ar_ereg);
812 reg &= ~ar->ar_emask;
813 if (on)
814 reg |= ar->ar_eval;
815 else
816 reg |= ar->ar_dval;
817 axppmic_write_reg(ar->ar_sc, ar->ar_ereg, reg);
818 return 0;
819 }
820
821 /* Sensors */
822
823 void axppmic_update_sensors(void *);
824 void axppmic_update_indicator(struct axppmic_softc *, int);
825 void axppmic_update_percent(struct axppmic_softc *, int);
826 void axppmic_update_amphour(struct axppmic_softc *, int);
827 void axppmic_update_sensor(struct axppmic_softc *, int);
828
829 void
axppmic_attach_sensors(struct axppmic_softc * sc)830 axppmic_attach_sensors(struct axppmic_softc *sc)
831 {
832 int i;
833
834 for (i = 0; sc->sc_sensdata[i].name; i++) {
835 KASSERT(i < AXPPMIC_NSENSORS);
836
837 sc->sc_sensor[i].type = sc->sc_sensdata[i].type;
838 strlcpy(sc->sc_sensor[i].desc, sc->sc_sensdata[i].name,
839 sizeof(sc->sc_sensor[i].desc));
840 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
841 }
842
843 axppmic_update_sensors(sc);
844 if (sensor_task_register(sc, axppmic_update_sensors, 5) == NULL) {
845 printf(", unable to register update task\n");
846 return;
847 }
848
849 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
850 sizeof(sc->sc_sensordev.xname));
851 sensordev_install(&sc->sc_sensordev);
852 }
853
854 void
axppmic_update_sensors(void * arg)855 axppmic_update_sensors(void *arg)
856 {
857 struct axppmic_softc *sc = arg;
858 int i;
859
860 for (i = 0; sc->sc_sensdata[i].name; i++) {
861 switch (sc->sc_sensdata[i].type) {
862 case SENSOR_INDICATOR:
863 axppmic_update_indicator(sc, i);
864 break;
865 case SENSOR_PERCENT:
866 axppmic_update_percent(sc, i);
867 break;
868 case SENSOR_AMPHOUR:
869 axppmic_update_amphour(sc, i);
870 break;
871 default:
872 axppmic_update_sensor(sc, i);
873 break;
874 }
875 }
876 }
877
878 void
axppmic_update_indicator(struct axppmic_softc * sc,int i)879 axppmic_update_indicator(struct axppmic_softc *sc, int i)
880 {
881 uint8_t reg = sc->sc_sensdata[i].reg;
882 uint8_t mask = sc->sc_sensdata[i].base;
883 uint8_t mask_ok = sc->sc_sensdata[i].delta;
884 uint8_t value;
885
886 value = axppmic_read_reg(sc, reg);
887 sc->sc_sensor[i].value = (value & mask) ? 1 : 0;
888 if (value & mask) {
889 sc->sc_sensor[i].status =
890 (value & mask_ok) ? SENSOR_S_OK : SENSOR_S_WARN;
891 } else {
892 sc->sc_sensor[i].status = SENSOR_S_UNSPEC;
893 }
894 }
895
896 void
axppmic_update_percent(struct axppmic_softc * sc,int i)897 axppmic_update_percent(struct axppmic_softc *sc, int i)
898 {
899 uint8_t reg = sc->sc_sensdata[i].reg;
900 uint8_t mask = sc->sc_sensdata[i].base;
901 uint8_t mask_ok = sc->sc_sensdata[i].delta;
902 uint8_t value;
903
904 value = axppmic_read_reg(sc, reg);
905 sc->sc_sensor[i].value = (value & mask) * 1000;
906
907 if (value & mask_ok) {
908 if ((value & mask) <= sc->sc_crit)
909 sc->sc_sensor[i].status = SENSOR_S_CRIT;
910 else if ((value & mask) <= sc->sc_warn)
911 sc->sc_sensor[i].status = SENSOR_S_WARN;
912 else
913 sc->sc_sensor[i].status = SENSOR_S_OK;
914 } else {
915 sc->sc_sensor[i].status = SENSOR_S_UNSPEC;
916 }
917 }
918
919 void
axppmic_update_amphour(struct axppmic_softc * sc,int i)920 axppmic_update_amphour(struct axppmic_softc *sc, int i)
921 {
922 uint8_t reg = sc->sc_sensdata[i].reg;
923 uint64_t base = sc->sc_sensdata[i].base;
924 uint64_t delta = sc->sc_sensdata[i].delta;
925 uint16_t value;
926
927 value = axppmic_read_reg(sc, reg);
928 sc->sc_sensor[i].status = (value & 0x80) ? SENSOR_S_OK : SENSOR_S_WARN;
929 value = ((value & 0x7f) << 8) | axppmic_read_reg(sc, reg + 1);
930 sc->sc_sensor[i].value = base + value * delta;
931 }
932
933 void
axppmic_update_sensor(struct axppmic_softc * sc,int i)934 axppmic_update_sensor(struct axppmic_softc *sc, int i)
935 {
936 uint8_t reg = sc->sc_sensdata[i].reg;
937 uint64_t base = sc->sc_sensdata[i].base;
938 uint64_t delta = sc->sc_sensdata[i].delta;
939 uint16_t value;
940
941 value = axppmic_read_reg(sc, reg);
942 value = (value << 4) | axppmic_read_reg(sc, reg + 1);
943 sc->sc_sensor[i].value = base + value * delta;
944 }
945
946 void
axp209_powerdown(void)947 axp209_powerdown(void)
948 {
949 axppmic_write_reg(axppmic_sc, AXP209_SDR, AXP209_SDR_SHUTDOWN);
950 }
951