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