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