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