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