xref: /openbsd-src/sys/dev/fdt/axppmic.c (revision 42ac1f71ddfc8f2b1ea1555399aa1e1ffc2faced)
1 /*	$OpenBSD: axppmic.c,v 1.13 2022/01/09 05:42:37 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_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,axp805", "AXP805", axp806_regdata },
297 	{ "x-powers,axp806", "AXP806", axp806_regdata },
298 	{ "x-powers,axp809", "AXP809", axp809_regdata, axp221_sensdata }
299 };
300 
301 const struct axppmic_device *
302 axppmic_lookup(const char *name)
303 {
304 	int i;
305 
306 	for (i = 0; i < nitems(axppmic_devices); i++) {
307 		if (strcmp(name, axppmic_devices[i].name) == 0)
308 			return &axppmic_devices[i];
309 	}
310 
311 	return NULL;
312 }
313 
314 struct axppmic_softc {
315 	struct device	sc_dev;
316 	void		*sc_cookie;
317 	uint16_t 	sc_addr;
318 
319 	uint8_t		(*sc_read)(struct axppmic_softc *, uint8_t);
320 	void		(*sc_write)(struct axppmic_softc *, uint8_t, uint8_t);
321 	struct axppmic_regdata *sc_regdata;
322 	struct axppmic_sensdata *sc_sensdata;
323 
324 	struct ksensor	sc_sensor[AXPPMIC_NSENSORS];
325 	struct ksensordev sc_sensordev;
326 
327 	uint8_t 	sc_warn;
328 	uint8_t		sc_crit;
329 };
330 
331 static inline uint8_t
332 axppmic_read_reg(struct axppmic_softc *sc, uint8_t reg)
333 {
334 	return sc->sc_read(sc, reg);
335 }
336 
337 static inline void
338 axppmic_write_reg(struct axppmic_softc *sc, uint8_t reg, uint8_t value)
339 {
340 	sc->sc_write(sc, reg, value);
341 }
342 
343 void	axppmic_attach_common(struct axppmic_softc *, const char *, int);
344 
345 /* I2C interface */
346 
347 int	axppmic_i2c_match(struct device *, void *, void *);
348 void	axppmic_i2c_attach(struct device *, struct device *, void *);
349 
350 const struct cfattach axppmic_ca = {
351 	sizeof(struct axppmic_softc), axppmic_i2c_match, axppmic_i2c_attach
352 };
353 
354 struct cfdriver axppmic_cd = {
355 	NULL, "axppmic", DV_DULL
356 };
357 
358 uint8_t	axppmic_i2c_read(struct axppmic_softc *, uint8_t);
359 void	axppmic_i2c_write(struct axppmic_softc *, uint8_t, uint8_t);
360 
361 int
362 axppmic_i2c_match(struct device *parent, void *match, void *aux)
363 {
364 	struct i2c_attach_args *ia = aux;
365 
366 	if (axppmic_lookup(ia->ia_name))
367 		return 1;
368 	return 0;
369 }
370 
371 void
372 axppmic_i2c_attach(struct device *parent, struct device *self, void *aux)
373 {
374 	struct axppmic_softc *sc = (struct axppmic_softc *)self;
375 	struct i2c_attach_args *ia = aux;
376 	int node = *(int *)ia->ia_cookie;
377 
378 	sc->sc_cookie = ia->ia_tag;
379 	sc->sc_addr = ia->ia_addr;
380 	sc->sc_read = axppmic_i2c_read;
381 	sc->sc_write = axppmic_i2c_write;
382 
383 	axppmic_attach_common(sc, ia->ia_name, node);
384 }
385 
386 uint8_t
387 axppmic_i2c_read(struct axppmic_softc *sc, uint8_t reg)
388 {
389 	i2c_tag_t tag = sc->sc_cookie;
390 	int flags = cold ? I2C_F_POLL : 0;
391 	int error;
392 	uint8_t value;
393 
394 	iic_acquire_bus(tag, flags);
395 	error = iic_smbus_read_byte(tag, sc->sc_addr, reg, &value, flags);
396 	iic_release_bus(tag, flags);
397 	if (error) {
398 		printf("%s: SMBus read byte from 0x%02x failed\n",
399 		    sc->sc_dev.dv_xname, reg);
400 		return 0xff;
401 	}
402 
403 	return value;
404 }
405 
406 void
407 axppmic_i2c_write(struct axppmic_softc *sc, uint8_t reg, uint8_t value)
408 {
409 	i2c_tag_t tag = sc->sc_cookie;
410 	int flags = cold ? I2C_F_POLL : 0;
411 	int error;
412 
413 	iic_acquire_bus(tag, flags);
414 	error = iic_smbus_write_byte(tag, sc->sc_addr, reg, value, flags);
415 	iic_release_bus(tag, flags);
416 	if (error)
417 		printf("%s: SMBus write byte to 0x%02x failed\n",
418 		    sc->sc_dev.dv_xname, reg);
419 }
420 
421 /* RSB interface */
422 
423 int	axppmic_rsb_match(struct device *, void *, void *);
424 void	axppmic_rsb_attach(struct device *, struct device *, void *);
425 
426 const struct cfattach axppmic_rsb_ca = {
427 	sizeof(struct axppmic_softc), axppmic_rsb_match, axppmic_rsb_attach
428 };
429 
430 struct cfdriver axppmic_rsb_cd = {
431 	NULL, "axppmic", DV_DULL
432 };
433 
434 uint8_t	axppmic_rsb_read(struct axppmic_softc *, uint8_t);
435 void	axppmic_rsb_write(struct axppmic_softc *, uint8_t, uint8_t);
436 
437 int
438 axppmic_rsb_match(struct device *parent, void *match, void *aux)
439 {
440 	struct rsb_attach_args *ra = aux;
441 
442 	if (axppmic_lookup(ra->ra_name))
443 		return 1;
444 	return 0;
445 }
446 
447 void
448 axppmic_rsb_attach(struct device *parent, struct device *self, void *aux)
449 {
450 	struct axppmic_softc *sc = (struct axppmic_softc *)self;
451 	struct rsb_attach_args *ra = aux;
452 
453 	sc->sc_cookie = ra->ra_cookie;
454 	sc->sc_addr = ra->ra_rta;
455 	sc->sc_read = axppmic_rsb_read;
456 	sc->sc_write = axppmic_rsb_write;
457 
458 	axppmic_attach_common(sc, ra->ra_name, ra->ra_node);
459 }
460 
461 uint8_t
462 axppmic_rsb_read(struct axppmic_softc *sc, uint8_t reg)
463 {
464 	return rsb_read_1(sc->sc_cookie, sc->sc_addr, reg);
465 }
466 
467 void
468 axppmic_rsb_write(struct axppmic_softc *sc, uint8_t reg, uint8_t value)
469 {
470 	rsb_write_1(sc->sc_cookie, sc->sc_addr, reg, value);
471 }
472 
473 /* Common code */
474 
475 void	axppmic_attach_node(struct axppmic_softc *, int);
476 void	axppmic_attach_regulators(struct axppmic_softc *, int);
477 void	axppmic_attach_sensors(struct axppmic_softc *);
478 
479 struct axppmic_softc *axppmic_sc;
480 void	axp209_powerdown(void);
481 
482 void
483 axppmic_attach_common(struct axppmic_softc *sc, const char *name, int node)
484 {
485 	const struct axppmic_device *device;
486 	int child;
487 
488 	device = axppmic_lookup(name);
489 	printf(": %s\n", device->chip);
490 
491 	sc->sc_regdata = device->regdata;
492 	sc->sc_sensdata = device->sensdata;
493 
494 	/* Switch AXP806 into master or slave mode. */
495 	if (strcmp(name, "x-powers,axp805") == 0 ||
496 	    strcmp(name, "x-powers,axp806") == 0) {
497 	    if (OF_getproplen(node, "x-powers,master-mode") == 0 ||
498 	        OF_getproplen(node, "x-powers,self-working-mode") == 0) {
499 			axppmic_write_reg(sc, AXP806_REG_ADDR_EXT,
500 			    AXP806_REG_ADDR_EXT_MASTER_MODE);
501 		} else {
502 			axppmic_write_reg(sc, AXP806_REG_ADDR_EXT,
503 			    AXP806_REG_ADDR_EXT_SLAVE_MODE);
504 		}
505 	}
506 
507 	/* Enable data collection on AXP209. */
508 	if (strcmp(name, "x-powers,axp209") == 0) {
509 		uint8_t reg;
510 
511 		/* Turn on sampling of ACIN and VBUS voltage and current. */
512 		reg = axppmic_read_reg(sc, AXP209_ADC_EN1);
513 		reg |= AXP209_ADC_EN1_ACIN;
514 		reg |= AXP209_ADC_EN1_VBUS;
515 		axppmic_write_reg(sc, AXP209_ADC_EN1, reg);
516 	}
517 
518 	/* Read battery warning levels on AXP803. */
519 	if (strcmp(name, "x-powers,axp803") == 0) {
520 		uint8_t value;
521 
522 		value = axppmic_read_reg(sc, AXP803_BAT_CAP_WARN);
523 		sc->sc_warn = ((value & AXP803_BAT_CAP_WARN_LV1) >> 4);
524 		sc->sc_warn += AXP803_BAT_CAP_WARN_LV1BASE;
525 		sc->sc_crit = (value & AXP803_BAT_CAP_WARN_LV2);
526 	}
527 
528 	for (child = OF_child(node); child; child = OF_peer(child))
529 		axppmic_attach_node(sc, child);
530 
531 	if (sc->sc_regdata)
532 		axppmic_attach_regulators(sc, node);
533 
534 	if (sc->sc_sensdata)
535 		axppmic_attach_sensors(sc);
536 
537 #ifdef __armv7__
538 	if (strcmp(name, "x-powers,axp152") == 0 ||
539 	    strcmp(name, "x-powers,axp209") == 0) {
540 		axppmic_sc = sc;
541 		powerdownfn = axp209_powerdown;
542 	}
543 #endif
544 }
545 
546 void
547 axppmic_attach_node(struct axppmic_softc *sc, int node)
548 {
549 	char status[32];
550 
551 	if (OF_getprop(node, "status", status, sizeof(status)) > 0 &&
552 	    strcmp(status, "disabled") == 0)
553 		return;
554 
555 	if (OF_is_compatible(node, "x-powers,axp803-battery-power-supply"))
556 		sc->sc_sensdata = axp803_battery_sensdata;
557 }
558 
559 /* Regulators */
560 
561 struct axppmic_regulator {
562 	struct axppmic_softc *ar_sc;
563 
564 	uint8_t ar_ereg, ar_emask;
565 	uint8_t ar_eval, ar_dval;
566 
567 	uint8_t ar_vreg, ar_vmask;
568 	uint32_t ar_base, ar_delta;
569 	uint32_t ar_base2, ar_delta2;
570 
571 	struct regulator_device ar_rd;
572 };
573 
574 void	axppmic_attach_regulator(struct axppmic_softc *, int);
575 uint32_t axppmic_get_voltage(void *);
576 int	axppmic_set_voltage(void *, uint32_t);
577 int	axppmic_enable(void *, int);
578 
579 void
580 axppmic_attach_regulators(struct axppmic_softc *sc, int node)
581 {
582 	node = OF_getnodebyname(node, "regulators");
583 	if (node == 0)
584 		return;
585 
586 	for (node = OF_child(node); node; node = OF_peer(node))
587 		axppmic_attach_regulator(sc, node);
588 }
589 
590 void
591 axppmic_attach_regulator(struct axppmic_softc *sc, int node)
592 {
593 	struct axppmic_regulator *ar;
594 	char name[32];
595 	int i;
596 
597 	name[0] = 0;
598 	OF_getprop(node, "name", name, sizeof(name));
599 	name[sizeof(name) - 1] = 0;
600 	for (i = 0; sc->sc_regdata[i].name; i++) {
601 		if (strcmp(sc->sc_regdata[i].name, name) == 0)
602 			break;
603 	}
604 	if (sc->sc_regdata[i].name == NULL)
605 		return;
606 
607 	ar = malloc(sizeof(*ar), M_DEVBUF, M_WAITOK | M_ZERO);
608 	ar->ar_sc = sc;
609 
610 	ar->ar_ereg = sc->sc_regdata[i].ereg;
611 	ar->ar_emask = sc->sc_regdata[i].emask;
612 	ar->ar_eval = sc->sc_regdata[i].eval;
613 	ar->ar_dval = sc->sc_regdata[i].dval;
614 	ar->ar_vreg = sc->sc_regdata[i].vreg;
615 	ar->ar_vmask = sc->sc_regdata[i].vmask;
616 	ar->ar_base = sc->sc_regdata[i].base;
617 	ar->ar_delta = sc->sc_regdata[i].delta;
618 
619 	ar->ar_rd.rd_node = node;
620 	ar->ar_rd.rd_cookie = ar;
621 	ar->ar_rd.rd_get_voltage = axppmic_get_voltage;
622 	ar->ar_rd.rd_set_voltage = axppmic_set_voltage;
623 	ar->ar_rd.rd_enable = axppmic_enable;
624 	regulator_register(&ar->ar_rd);
625 }
626 
627 uint32_t
628 axppmic_get_voltage(void *cookie)
629 {
630 	struct axppmic_regulator *ar = cookie;
631 	uint32_t voltage;
632 	uint8_t value;
633 
634 	value = axppmic_read_reg(ar->ar_sc, ar->ar_vreg);
635 	value &= ar->ar_vmask;
636 	voltage = ar->ar_base + value * ar->ar_delta;
637 	if (ar->ar_base2 > 0 && voltage > ar->ar_base2) {
638 		value -= (ar->ar_base2 - ar->ar_base) / ar->ar_delta;
639 		voltage = ar->ar_base2 + value * ar->ar_delta2;
640 	}
641 	return voltage;
642 }
643 
644 int
645 axppmic_set_voltage(void *cookie, uint32_t voltage)
646 {
647 	struct axppmic_regulator *ar = cookie;
648 	uint32_t value, reg;
649 
650 	if (voltage < ar->ar_base)
651 		return EINVAL;
652 	value = (voltage - ar->ar_base) / ar->ar_delta;
653 	if (ar->ar_base2 > 0 && voltage > ar->ar_base2) {
654 		value = (ar->ar_base2 - ar->ar_base) / ar->ar_delta;
655 		value += (voltage - ar->ar_base2) / ar->ar_delta2;
656 	}
657 	if (value > ar->ar_vmask)
658 		return EINVAL;
659 
660 	reg = axppmic_read_reg(ar->ar_sc, ar->ar_vreg);
661 	reg &= ~ar->ar_vmask;
662 	axppmic_write_reg(ar->ar_sc, ar->ar_vreg, reg | value);
663 	return 0;
664 }
665 
666 int
667 axppmic_enable(void *cookie, int on)
668 {
669 	struct axppmic_regulator *ar = cookie;
670 	uint8_t reg;
671 
672 	reg = axppmic_read_reg(ar->ar_sc, ar->ar_ereg);
673 	reg &= ~ar->ar_emask;
674 	if (on)
675 		reg |= ar->ar_eval;
676 	else
677 		reg |= ar->ar_dval;
678 	axppmic_write_reg(ar->ar_sc, ar->ar_ereg, reg);
679 	return 0;
680 }
681 
682 /* Sensors */
683 
684 void	axppmic_update_sensors(void *);
685 void	axppmic_update_indicator(struct axppmic_softc *, int);
686 void	axppmic_update_percent(struct axppmic_softc *, int);
687 void	axppmic_update_amphour(struct axppmic_softc *, int);
688 void	axppmic_update_sensor(struct axppmic_softc *, int);
689 
690 void
691 axppmic_attach_sensors(struct axppmic_softc *sc)
692 {
693 	int i;
694 
695 	for (i = 0; sc->sc_sensdata[i].name; i++) {
696 		KASSERT(i < AXPPMIC_NSENSORS);
697 
698 		sc->sc_sensor[i].type = sc->sc_sensdata[i].type;
699 		strlcpy(sc->sc_sensor[i].desc, sc->sc_sensdata[i].name,
700 		    sizeof(sc->sc_sensor[i].desc));
701 		sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
702 	}
703 
704 	axppmic_update_sensors(sc);
705 	if (sensor_task_register(sc, axppmic_update_sensors, 5) == NULL) {
706 		printf(", unable to register update task\n");
707 		return;
708 	}
709 
710 	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
711 	    sizeof(sc->sc_sensordev.xname));
712 	sensordev_install(&sc->sc_sensordev);
713 }
714 
715 void
716 axppmic_update_sensors(void *arg)
717 {
718 	struct axppmic_softc *sc = arg;
719 	int i;
720 
721 	for (i = 0; sc->sc_sensdata[i].name; i++) {
722 		switch (sc->sc_sensdata[i].type) {
723 		case SENSOR_INDICATOR:
724 			axppmic_update_indicator(sc, i);
725 			break;
726 		case SENSOR_PERCENT:
727 			axppmic_update_percent(sc, i);
728 			break;
729 		case SENSOR_AMPHOUR:
730 			axppmic_update_amphour(sc, i);
731 			break;
732 		default:
733 			axppmic_update_sensor(sc, i);
734 			break;
735 		}
736 	}
737 }
738 
739 void
740 axppmic_update_indicator(struct axppmic_softc *sc, int i)
741 {
742 	uint8_t reg = sc->sc_sensdata[i].reg;
743 	uint8_t mask = sc->sc_sensdata[i].base;
744 	uint8_t mask_ok = sc->sc_sensdata[i].delta;
745 	uint8_t value;
746 
747 	value = axppmic_read_reg(sc, reg);
748 	sc->sc_sensor[i].value = (value & mask) ? 1 : 0;
749 	if (value & mask) {
750 		sc->sc_sensor[i].status =
751 		    (value & mask_ok) ? SENSOR_S_OK : SENSOR_S_WARN;
752 	} else {
753 		sc->sc_sensor[i].status = SENSOR_S_UNSPEC;
754 	}
755 }
756 
757 void
758 axppmic_update_percent(struct axppmic_softc *sc, int i)
759 {
760 	uint8_t reg = sc->sc_sensdata[i].reg;
761 	uint8_t mask = sc->sc_sensdata[i].base;
762 	uint8_t mask_ok = sc->sc_sensdata[i].delta;
763 	uint8_t value;
764 
765 	value = axppmic_read_reg(sc, reg);
766 	sc->sc_sensor[i].value = (value & mask) * 1000;
767 
768 	if (value & mask_ok) {
769 		if ((value & mask) <= sc->sc_crit)
770 			sc->sc_sensor[i].status = SENSOR_S_CRIT;
771 		else if ((value & mask) <= sc->sc_warn)
772 			sc->sc_sensor[i].status = SENSOR_S_WARN;
773 		else
774 			sc->sc_sensor[i].status = SENSOR_S_OK;
775 	} else {
776 		sc->sc_sensor[i].status = SENSOR_S_UNSPEC;
777 	}
778 }
779 
780 void
781 axppmic_update_amphour(struct axppmic_softc *sc, int i)
782 {
783 	uint8_t reg = sc->sc_sensdata[i].reg;
784 	uint64_t base = sc->sc_sensdata[i].base;
785 	uint64_t delta = sc->sc_sensdata[i].delta;
786 	uint16_t value;
787 
788 	value = axppmic_read_reg(sc, reg);
789 	sc->sc_sensor[i].status = (value & 0x80) ? SENSOR_S_OK : SENSOR_S_WARN;
790 	value = ((value & 0x7f) << 8) | axppmic_read_reg(sc, reg + 1);
791 	sc->sc_sensor[i].value = base + value * delta;
792 }
793 
794 void
795 axppmic_update_sensor(struct axppmic_softc *sc, int i)
796 {
797 	uint8_t reg = sc->sc_sensdata[i].reg;
798 	uint64_t base = sc->sc_sensdata[i].base;
799 	uint64_t delta = sc->sc_sensdata[i].delta;
800 	uint16_t value;
801 
802 	value = axppmic_read_reg(sc, reg);
803 	value = (value << 4) | axppmic_read_reg(sc, reg + 1);
804 	sc->sc_sensor[i].value = base + value * delta;
805 }
806 
807 void
808 axp209_powerdown(void)
809 {
810 	axppmic_write_reg(axppmic_sc, AXP209_SDR, AXP209_SDR_SHUTDOWN);
811 }
812