1295634Sandrew/*-
2300777Smanu * Copyright (c) 2015-2016 Emmanuel Vadot <manu@freebsd.org>
3300777Smanu * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
4295634Sandrew * All rights reserved.
5295634Sandrew *
6295634Sandrew * Redistribution and use in source and binary forms, with or without
7295634Sandrew * modification, are permitted provided that the following conditions
8295634Sandrew * are met:
9295634Sandrew * 1. Redistributions of source code must retain the above copyright
10295634Sandrew *    notice, this list of conditions and the following disclaimer.
11295634Sandrew * 2. Redistributions in binary form must reproduce the above copyright
12295634Sandrew *    notice, this list of conditions and the following disclaimer in the
13295634Sandrew *    documentation and/or other materials provided with the distribution.
14295634Sandrew *
15295634Sandrew * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16295634Sandrew * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17295634Sandrew * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18295634Sandrew * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19295634Sandrew * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20295634Sandrew * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21295634Sandrew * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22295634Sandrew * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23295634Sandrew * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24295634Sandrew * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25295634Sandrew * SUCH DAMAGE.
26295634Sandrew */
27295634Sandrew
28295634Sandrew#include <sys/cdefs.h>
29295634Sandrew__FBSDID("$FreeBSD: stable/11/sys/arm/allwinner/axp209.c 323467 2017-09-11 22:21:15Z ian $");
30309758Smanu
31295634Sandrew/*
32309758Smanu* X-Power AXP209/AXP211 PMU for Allwinner SoCs
33295634Sandrew*/
34309758Smanu
35295634Sandrew#include <sys/param.h>
36295634Sandrew#include <sys/systm.h>
37295634Sandrew#include <sys/eventhandler.h>
38295634Sandrew#include <sys/kernel.h>
39295634Sandrew#include <sys/module.h>
40295634Sandrew#include <sys/clock.h>
41295634Sandrew#include <sys/time.h>
42295634Sandrew#include <sys/bus.h>
43295634Sandrew#include <sys/proc.h>
44300777Smanu#include <sys/gpio.h>
45295634Sandrew#include <sys/reboot.h>
46295634Sandrew#include <sys/resource.h>
47295634Sandrew#include <sys/rman.h>
48295658Sandrew#include <sys/sysctl.h>
49295634Sandrew
50295634Sandrew#include <dev/iicbus/iiconf.h>
51295634Sandrew
52300777Smanu#include <dev/gpio/gpiobusvar.h>
53300777Smanu
54295634Sandrew#include <dev/ofw/ofw_bus.h>
55295634Sandrew#include <dev/ofw/ofw_bus_subr.h>
56295634Sandrew
57307885Smanu#include <dev/extres/regulator/regulator.h>
58307885Smanu
59300777Smanu#include <arm/allwinner/axp209reg.h>
60300777Smanu
61300777Smanu#include "gpio_if.h"
62307885Smanu#include "regdev_if.h"
63295634Sandrew
64309758SmanuMALLOC_DEFINE(M_AXP2XX_REG, "Axp2XX regulator", "Axp2XX power regulator");
65307885Smanu
66309758Smanustruct axp2xx_regdef {
67307885Smanu	intptr_t		id;
68307885Smanu	char			*name;
69307885Smanu	uint8_t			enable_reg;
70307885Smanu	uint8_t			enable_mask;
71307885Smanu	uint8_t			voltage_reg;
72307885Smanu	uint8_t			voltage_mask;
73307885Smanu	uint8_t			voltage_shift;
74307885Smanu	int			voltage_min;
75307885Smanu	int			voltage_max;
76307885Smanu	int			voltage_step;
77307885Smanu	int			voltage_nstep;
78307885Smanu};
79307885Smanu
80309758Smanustatic struct axp2xx_regdef axp209_regdefs[] = {
81307885Smanu	{
82307885Smanu		.id = AXP209_REG_ID_DCDC2,
83307885Smanu		.name = "dcdc2",
84307885Smanu		.enable_reg = AXP209_POWERCTL,
85307885Smanu		.enable_mask = AXP209_POWERCTL_DCDC2,
86307885Smanu		.voltage_reg = AXP209_REG_DCDC2_VOLTAGE,
87307885Smanu		.voltage_mask = 0x3f,
88307885Smanu		.voltage_min = 700,
89307885Smanu		.voltage_max = 2275,
90307885Smanu		.voltage_step = 25,
91307885Smanu		.voltage_nstep = 64,
92307885Smanu	},
93307885Smanu	{
94307885Smanu		.id = AXP209_REG_ID_DCDC3,
95307885Smanu		.name = "dcdc3",
96307885Smanu		.enable_reg = AXP209_POWERCTL,
97307885Smanu		.enable_mask = AXP209_POWERCTL_DCDC3,
98307885Smanu		.voltage_reg = AXP209_REG_DCDC3_VOLTAGE,
99307885Smanu		.voltage_mask = 0x7f,
100307885Smanu		.voltage_min = 700,
101307885Smanu		.voltage_max = 3500,
102307885Smanu		.voltage_step = 25,
103307885Smanu		.voltage_nstep = 128,
104307885Smanu	},
105307885Smanu	{
106307885Smanu		.id = AXP209_REG_ID_LDO2,
107307885Smanu		.name = "ldo2",
108307885Smanu		.enable_reg = AXP209_POWERCTL,
109307885Smanu		.enable_mask = AXP209_POWERCTL_LDO2,
110307885Smanu		.voltage_reg = AXP209_REG_LDO24_VOLTAGE,
111307885Smanu		.voltage_mask = 0xf0,
112307885Smanu		.voltage_shift = 4,
113307885Smanu		.voltage_min = 1800,
114307885Smanu		.voltage_max = 3300,
115307885Smanu		.voltage_step = 100,
116307885Smanu		.voltage_nstep = 16,
117307885Smanu	},
118307885Smanu	{
119307885Smanu		.id = AXP209_REG_ID_LDO3,
120307885Smanu		.name = "ldo3",
121307885Smanu		.enable_reg = AXP209_POWERCTL,
122307885Smanu		.enable_mask = AXP209_POWERCTL_LDO3,
123307885Smanu		.voltage_reg = AXP209_REG_LDO3_VOLTAGE,
124307885Smanu		.voltage_mask = 0x7f,
125307885Smanu		.voltage_min = 700,
126307885Smanu		.voltage_max = 2275,
127307885Smanu		.voltage_step = 25,
128307885Smanu		.voltage_nstep = 128,
129307885Smanu	},
130307885Smanu};
131307885Smanu
132309758Smanustatic struct axp2xx_regdef axp221_regdefs[] = {
133309758Smanu	{
134309758Smanu		.id = AXP221_REG_ID_DLDO1,
135309758Smanu		.name = "dldo1",
136309758Smanu		.enable_reg = AXP221_POWERCTL_2,
137309758Smanu		.enable_mask = AXP221_POWERCTL2_DLDO1,
138309758Smanu		.voltage_reg = AXP221_REG_DLDO1_VOLTAGE,
139309758Smanu		.voltage_mask = 0x1f,
140309758Smanu		.voltage_min = 700,
141309758Smanu		.voltage_max = 3300,
142309758Smanu		.voltage_step = 100,
143309758Smanu		.voltage_nstep = 26,
144309758Smanu	},
145309758Smanu	{
146309758Smanu		.id = AXP221_REG_ID_DLDO2,
147309758Smanu		.name = "dldo2",
148309758Smanu		.enable_reg = AXP221_POWERCTL_2,
149309758Smanu		.enable_mask = AXP221_POWERCTL2_DLDO2,
150309758Smanu		.voltage_reg = AXP221_REG_DLDO2_VOLTAGE,
151309758Smanu		.voltage_mask = 0x1f,
152309758Smanu		.voltage_min = 700,
153309758Smanu		.voltage_max = 3300,
154309758Smanu		.voltage_step = 100,
155309758Smanu		.voltage_nstep = 26,
156309758Smanu	},
157309758Smanu	{
158309758Smanu		.id = AXP221_REG_ID_DLDO3,
159309758Smanu		.name = "dldo3",
160309758Smanu		.enable_reg = AXP221_POWERCTL_2,
161309758Smanu		.enable_mask = AXP221_POWERCTL2_DLDO3,
162309758Smanu		.voltage_reg = AXP221_REG_DLDO3_VOLTAGE,
163309758Smanu		.voltage_mask = 0x1f,
164309758Smanu		.voltage_min = 700,
165309758Smanu		.voltage_max = 3300,
166309758Smanu		.voltage_step = 100,
167309758Smanu		.voltage_nstep = 26,
168309758Smanu	},
169309758Smanu	{
170309758Smanu		.id = AXP221_REG_ID_DLDO4,
171309758Smanu		.name = "dldo4",
172309758Smanu		.enable_reg = AXP221_POWERCTL_2,
173309758Smanu		.enable_mask = AXP221_POWERCTL2_DLDO4,
174309758Smanu		.voltage_reg = AXP221_REG_DLDO4_VOLTAGE,
175309758Smanu		.voltage_mask = 0x1f,
176309758Smanu		.voltage_min = 700,
177309758Smanu		.voltage_max = 3300,
178309758Smanu		.voltage_step = 100,
179309758Smanu		.voltage_nstep = 26,
180309758Smanu	},
181309758Smanu	{
182309758Smanu		.id = AXP221_REG_ID_ELDO1,
183309758Smanu		.name = "eldo1",
184309758Smanu		.enable_reg = AXP221_POWERCTL_2,
185309758Smanu		.enable_mask = AXP221_POWERCTL2_ELDO1,
186309758Smanu		.voltage_reg = AXP221_REG_ELDO1_VOLTAGE,
187309758Smanu		.voltage_mask = 0x1f,
188309758Smanu		.voltage_min = 700,
189309758Smanu		.voltage_max = 3300,
190309758Smanu		.voltage_step = 100,
191309758Smanu		.voltage_nstep = 26,
192309758Smanu	},
193309758Smanu	{
194309758Smanu		.id = AXP221_REG_ID_ELDO2,
195309758Smanu		.name = "eldo2",
196309758Smanu		.enable_reg = AXP221_POWERCTL_2,
197309758Smanu		.enable_mask = AXP221_POWERCTL2_ELDO2,
198309758Smanu		.voltage_reg = AXP221_REG_ELDO2_VOLTAGE,
199309758Smanu		.voltage_mask = 0x1f,
200309758Smanu		.voltage_min = 700,
201309758Smanu		.voltage_max = 3300,
202309758Smanu		.voltage_step = 100,
203309758Smanu		.voltage_nstep = 26,
204309758Smanu	},
205309758Smanu	{
206309758Smanu		.id = AXP221_REG_ID_ELDO3,
207309758Smanu		.name = "eldo3",
208309758Smanu		.enable_reg = AXP221_POWERCTL_2,
209309758Smanu		.enable_mask = AXP221_POWERCTL2_ELDO3,
210309758Smanu		.voltage_reg = AXP221_REG_ELDO3_VOLTAGE,
211309758Smanu		.voltage_mask = 0x1f,
212309758Smanu		.voltage_min = 700,
213309758Smanu		.voltage_max = 3300,
214309758Smanu		.voltage_step = 100,
215309758Smanu		.voltage_nstep = 26,
216309758Smanu	},
217309758Smanu	{
218309758Smanu		.id = AXP221_REG_ID_DC5LDO,
219309758Smanu		.name = "dc5ldo",
220309758Smanu		.enable_reg = AXP221_POWERCTL_1,
221309758Smanu		.enable_mask = AXP221_POWERCTL1_DC5LDO,
222309758Smanu		.voltage_reg = AXP221_REG_DC5LDO_VOLTAGE,
223309758Smanu		.voltage_mask = 0x3,
224309758Smanu		.voltage_min = 700,
225309758Smanu		.voltage_max = 1400,
226309758Smanu		.voltage_step = 100,
227309758Smanu		.voltage_nstep = 7,
228309758Smanu	},
229309758Smanu	{
230309758Smanu		.id = AXP221_REG_ID_DCDC1,
231309758Smanu		.name = "dcdc1",
232309758Smanu		.enable_reg = AXP221_POWERCTL_1,
233309758Smanu		.enable_mask = AXP221_POWERCTL1_DCDC1,
234309758Smanu		.voltage_reg = AXP221_REG_DCDC1_VOLTAGE,
235309758Smanu		.voltage_mask = 0x1f,
236309758Smanu		.voltage_min = 1600,
237309758Smanu		.voltage_max = 3400,
238309758Smanu		.voltage_step = 100,
239309758Smanu		.voltage_nstep = 18,
240309758Smanu	},
241309758Smanu	{
242309758Smanu		.id = AXP221_REG_ID_DCDC2,
243309758Smanu		.name = "dcdc2",
244309758Smanu		.enable_reg = AXP221_POWERCTL_1,
245309758Smanu		.enable_mask = AXP221_POWERCTL1_DCDC2,
246309758Smanu		.voltage_reg = AXP221_REG_DCDC2_VOLTAGE,
247309758Smanu		.voltage_mask = 0x3f,
248309758Smanu		.voltage_min = 600,
249309758Smanu		.voltage_max = 1540,
250309758Smanu		.voltage_step = 20,
251309758Smanu		.voltage_nstep = 47,
252309758Smanu	},
253309758Smanu	{
254309758Smanu		.id = AXP221_REG_ID_DCDC3,
255309758Smanu		.name = "dcdc3",
256309758Smanu		.enable_reg = AXP221_POWERCTL_1,
257309758Smanu		.enable_mask = AXP221_POWERCTL1_DCDC3,
258309758Smanu		.voltage_reg = AXP221_REG_DCDC3_VOLTAGE,
259309758Smanu		.voltage_mask = 0x3f,
260309758Smanu		.voltage_min = 600,
261309758Smanu		.voltage_max = 1860,
262309758Smanu		.voltage_step = 20,
263309758Smanu		.voltage_nstep = 63,
264309758Smanu	},
265309758Smanu	{
266309758Smanu		.id = AXP221_REG_ID_DCDC4,
267309758Smanu		.name = "dcdc4",
268309758Smanu		.enable_reg = AXP221_POWERCTL_1,
269309758Smanu		.enable_mask = AXP221_POWERCTL1_DCDC4,
270309758Smanu		.voltage_reg = AXP221_REG_DCDC4_VOLTAGE,
271309758Smanu		.voltage_mask = 0x3f,
272309758Smanu		.voltage_min = 600,
273309758Smanu		.voltage_max = 1540,
274309758Smanu		.voltage_step = 20,
275309758Smanu		.voltage_nstep = 47,
276309758Smanu	},
277309758Smanu	{
278309758Smanu		.id = AXP221_REG_ID_DCDC5,
279309758Smanu		.name = "dcdc5",
280309758Smanu		.enable_reg = AXP221_POWERCTL_1,
281309758Smanu		.enable_mask = AXP221_POWERCTL1_DCDC5,
282309758Smanu		.voltage_reg = AXP221_REG_DCDC5_VOLTAGE,
283309758Smanu		.voltage_mask = 0x1f,
284309758Smanu		.voltage_min = 1000,
285309758Smanu		.voltage_max = 2550,
286309758Smanu		.voltage_step = 50,
287309758Smanu		.voltage_nstep = 31,
288309758Smanu	},
289309758Smanu	{
290309758Smanu		.id = AXP221_REG_ID_ALDO1,
291309758Smanu		.name = "aldo1",
292309758Smanu		.enable_reg = AXP221_POWERCTL_1,
293309758Smanu		.enable_mask = AXP221_POWERCTL1_ALDO1,
294309758Smanu		.voltage_reg = AXP221_REG_ALDO1_VOLTAGE,
295309758Smanu		.voltage_mask = 0x1f,
296309758Smanu		.voltage_min = 700,
297309758Smanu		.voltage_max = 3300,
298309758Smanu		.voltage_step = 100,
299309758Smanu		.voltage_nstep = 26,
300309758Smanu	},
301309758Smanu	{
302309758Smanu		.id = AXP221_REG_ID_ALDO2,
303309758Smanu		.name = "aldo2",
304309758Smanu		.enable_reg = AXP221_POWERCTL_1,
305309758Smanu		.enable_mask = AXP221_POWERCTL1_ALDO2,
306309758Smanu		.voltage_reg = AXP221_REG_ALDO2_VOLTAGE,
307309758Smanu		.voltage_mask = 0x1f,
308309758Smanu		.voltage_min = 700,
309309758Smanu		.voltage_max = 3300,
310309758Smanu		.voltage_step = 100,
311309758Smanu		.voltage_nstep = 26,
312309758Smanu	},
313309758Smanu	{
314309758Smanu		.id = AXP221_REG_ID_ALDO3,
315309758Smanu		.name = "aldo3",
316309758Smanu		.enable_reg = AXP221_POWERCTL_3,
317309758Smanu		.enable_mask = AXP221_POWERCTL3_ALDO3,
318309758Smanu		.voltage_reg = AXP221_REG_ALDO3_VOLTAGE,
319309758Smanu		.voltage_mask = 0x1f,
320309758Smanu		.voltage_min = 700,
321309758Smanu		.voltage_max = 3300,
322309758Smanu		.voltage_step = 100,
323309758Smanu		.voltage_nstep = 26,
324309758Smanu	},
325309758Smanu	{
326309758Smanu		.id = AXP221_REG_ID_DC1SW,
327309758Smanu		.name = "dc1sw",
328309758Smanu		.enable_reg = AXP221_POWERCTL_2,
329309758Smanu		.enable_mask = AXP221_POWERCTL2_DC1SW,
330309758Smanu	},
331309758Smanu};
332309758Smanu
333309758Smanustruct axp2xx_reg_sc {
334307885Smanu	struct regnode		*regnode;
335307885Smanu	device_t		base_dev;
336309758Smanu	struct axp2xx_regdef	*def;
337307885Smanu	phandle_t		xref;
338307885Smanu	struct regnode_std_param *param;
339307885Smanu};
340307885Smanu
341309758Smanustruct axp2xx_pins {
342309758Smanu	const char	*name;
343309758Smanu	uint8_t		ctrl_reg;
344309758Smanu	uint8_t		status_reg;
345309758Smanu	uint8_t		status_mask;
346309758Smanu	uint8_t		status_shift;
347309758Smanu};
348309758Smanu
349309758Smanu/* GPIO3 is different, don't expose it for now */
350309758Smanustatic const struct axp2xx_pins axp209_pins[] = {
351309758Smanu	{
352309758Smanu		.name = "GPIO0",
353309758Smanu		.ctrl_reg = AXP2XX_GPIO0_CTRL,
354309758Smanu		.status_reg = AXP2XX_GPIO_STATUS,
355309758Smanu		.status_mask = 0x10,
356309758Smanu		.status_shift = 4,
357309758Smanu	},
358309758Smanu	{
359309758Smanu		.name = "GPIO1",
360309758Smanu		.ctrl_reg = AXP2XX_GPIO1_CTRL,
361309758Smanu		.status_reg = AXP2XX_GPIO_STATUS,
362309758Smanu		.status_mask = 0x20,
363309758Smanu		.status_shift = 5,
364309758Smanu	},
365309758Smanu	{
366309758Smanu		.name = "GPIO2",
367309758Smanu		.ctrl_reg = AXP209_GPIO2_CTRL,
368309758Smanu		.status_reg = AXP2XX_GPIO_STATUS,
369309758Smanu		.status_mask = 0x40,
370309758Smanu		.status_shift = 6,
371309758Smanu	},
372309758Smanu};
373309758Smanu
374309758Smanustatic const struct axp2xx_pins axp221_pins[] = {
375309758Smanu	{
376309758Smanu		.name = "GPIO0",
377309758Smanu		.ctrl_reg = AXP2XX_GPIO0_CTRL,
378309758Smanu		.status_reg = AXP2XX_GPIO_STATUS,
379309758Smanu		.status_mask = 0x1,
380309758Smanu		.status_shift = 0x0,
381309758Smanu	},
382309758Smanu	{
383309758Smanu		.name = "GPIO1",
384309758Smanu		.ctrl_reg = AXP2XX_GPIO0_CTRL,
385309758Smanu		.status_reg = AXP2XX_GPIO_STATUS,
386309758Smanu		.status_mask = 0x2,
387309758Smanu		.status_shift = 0x1,
388309758Smanu	},
389309758Smanu};
390309758Smanu
391309758Smanustruct axp2xx_sensors {
392309758Smanu	int		id;
393309758Smanu	const char	*name;
394309758Smanu	const char	*desc;
395309758Smanu	const char	*format;
396309758Smanu	uint8_t		enable_reg;
397309758Smanu	uint8_t		enable_mask;
398309758Smanu	uint8_t		value_reg;
399309758Smanu	uint8_t		value_size;
400309758Smanu	uint8_t		h_value_mask;
401309758Smanu	uint8_t		h_value_shift;
402309758Smanu	uint8_t		l_value_mask;
403309758Smanu	uint8_t		l_value_shift;
404309758Smanu	int		value_step;
405309758Smanu	int		value_convert;
406309758Smanu};
407309758Smanu
408309758Smanustatic const struct axp2xx_sensors axp209_sensors[] = {
409309758Smanu	{
410309758Smanu		.id = AXP209_ACVOLT,
411309758Smanu		.name = "acvolt",
412309758Smanu		.desc = "AC Voltage (microvolt)",
413309758Smanu		.format = "I",
414309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
415309758Smanu		.enable_mask = AXP209_ADC1_ACVOLT,
416309758Smanu		.value_reg = AXP209_ACIN_VOLTAGE,
417309758Smanu		.value_size = 2,
418309758Smanu		.h_value_mask = 0xff,
419309758Smanu		.h_value_shift = 4,
420309758Smanu		.l_value_mask = 0xf,
421309758Smanu		.l_value_shift = 0,
422309758Smanu		.value_step = AXP209_VOLT_STEP,
423309758Smanu	},
424309758Smanu	{
425309758Smanu		.id = AXP209_ACCURRENT,
426309758Smanu		.name = "accurrent",
427309758Smanu		.desc = "AC Current (microAmpere)",
428309758Smanu		.format = "I",
429309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
430309758Smanu		.enable_mask = AXP209_ADC1_ACCURRENT,
431309758Smanu		.value_reg = AXP209_ACIN_CURRENT,
432309758Smanu		.value_size = 2,
433309758Smanu		.h_value_mask = 0xff,
434309758Smanu		.h_value_shift = 4,
435309758Smanu		.l_value_mask = 0xf,
436309758Smanu		.l_value_shift = 0,
437309758Smanu		.value_step = AXP209_ACCURRENT_STEP,
438309758Smanu	},
439309758Smanu	{
440309758Smanu		.id = AXP209_VBUSVOLT,
441309758Smanu		.name = "vbusvolt",
442309758Smanu		.desc = "VBUS Voltage (microVolt)",
443309758Smanu		.format = "I",
444309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
445309758Smanu		.enable_mask = AXP209_ADC1_VBUSVOLT,
446309758Smanu		.value_reg = AXP209_VBUS_VOLTAGE,
447309758Smanu		.value_size = 2,
448309758Smanu		.h_value_mask = 0xff,
449309758Smanu		.h_value_shift = 4,
450309758Smanu		.l_value_mask = 0xf,
451309758Smanu		.l_value_shift = 0,
452309758Smanu		.value_step = AXP209_VOLT_STEP,
453309758Smanu	},
454309758Smanu	{
455309758Smanu		.id = AXP209_VBUSCURRENT,
456309758Smanu		.name = "vbuscurrent",
457309758Smanu		.desc = "VBUS Current (microAmpere)",
458309758Smanu		.format = "I",
459309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
460309758Smanu		.enable_mask = AXP209_ADC1_VBUSCURRENT,
461309758Smanu		.value_reg = AXP209_VBUS_CURRENT,
462309758Smanu		.value_size = 2,
463309758Smanu		.h_value_mask = 0xff,
464309758Smanu		.h_value_shift = 4,
465309758Smanu		.l_value_mask = 0xf,
466309758Smanu		.l_value_shift = 0,
467309758Smanu		.value_step = AXP209_VBUSCURRENT_STEP,
468309758Smanu	},
469309758Smanu	{
470309758Smanu		.id = AXP2XX_BATVOLT,
471309758Smanu		.name = "batvolt",
472309758Smanu		.desc = "Battery Voltage (microVolt)",
473309758Smanu		.format = "I",
474309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
475309758Smanu		.enable_mask = AXP2XX_ADC1_BATVOLT,
476309758Smanu		.value_reg = AXP2XX_BAT_VOLTAGE,
477309758Smanu		.value_size = 2,
478309758Smanu		.h_value_mask = 0xff,
479309758Smanu		.h_value_shift = 4,
480309758Smanu		.l_value_mask = 0xf,
481309758Smanu		.l_value_shift = 0,
482309758Smanu		.value_step = AXP2XX_BATVOLT_STEP,
483309758Smanu	},
484309758Smanu	{
485309758Smanu		.id = AXP2XX_BATCHARGECURRENT,
486309758Smanu		.name = "batchargecurrent",
487309758Smanu		.desc = "Battery Charging Current (microAmpere)",
488309758Smanu		.format = "I",
489309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
490309758Smanu		.enable_mask = AXP2XX_ADC1_BATCURRENT,
491309758Smanu		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
492309758Smanu		.value_size = 2,
493309758Smanu		.h_value_mask = 0xff,
494309758Smanu		.h_value_shift = 5,
495309758Smanu		.l_value_mask = 0x1f,
496309758Smanu		.l_value_shift = 0,
497309758Smanu		.value_step = AXP2XX_BATCURRENT_STEP,
498309758Smanu	},
499309758Smanu	{
500309758Smanu		.id = AXP2XX_BATDISCHARGECURRENT,
501309758Smanu		.name = "batdischargecurrent",
502309758Smanu		.desc = "Battery Discharging Current (microAmpere)",
503309758Smanu		.format = "I",
504309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
505309758Smanu		.enable_mask = AXP2XX_ADC1_BATCURRENT,
506309758Smanu		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
507309758Smanu		.value_size = 2,
508309758Smanu		.h_value_mask = 0xff,
509309758Smanu		.h_value_shift = 5,
510309758Smanu		.l_value_mask = 0x1f,
511309758Smanu		.l_value_shift = 0,
512309758Smanu		.value_step = AXP2XX_BATCURRENT_STEP,
513309758Smanu	},
514309758Smanu	{
515309758Smanu		.id = AXP2XX_TEMP,
516309758Smanu		.name = "temp",
517309758Smanu		.desc = "Internal Temperature",
518309758Smanu		.format = "IK",
519309758Smanu		.enable_reg = AXP209_ADC_ENABLE2,
520309758Smanu		.enable_mask = AXP209_ADC2_TEMP,
521309758Smanu		.value_reg = AXP209_TEMPMON,
522309758Smanu		.value_size = 2,
523309758Smanu		.h_value_mask = 0xff,
524309758Smanu		.h_value_shift = 4,
525309758Smanu		.l_value_mask = 0xf,
526309758Smanu		.l_value_shift = 0,
527309758Smanu		.value_step = 1,
528309758Smanu		.value_convert = -(AXP209_TEMPMON_MIN - AXP209_0C_TO_K),
529309758Smanu	},
530309758Smanu};
531309758Smanu
532309758Smanustatic const struct axp2xx_sensors axp221_sensors[] = {
533309758Smanu	{
534309758Smanu		.id = AXP2XX_BATVOLT,
535309758Smanu		.name = "batvolt",
536309758Smanu		.desc = "Battery Voltage (microVolt)",
537309758Smanu		.format = "I",
538309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
539309758Smanu		.enable_mask = AXP2XX_ADC1_BATVOLT,
540309758Smanu		.value_reg = AXP2XX_BAT_VOLTAGE,
541309758Smanu		.value_size = 2,
542309758Smanu		.h_value_mask = 0xff,
543309758Smanu		.h_value_shift = 4,
544309758Smanu		.l_value_mask = 0xf,
545309758Smanu		.l_value_shift = 0,
546309758Smanu		.value_step = AXP2XX_BATVOLT_STEP,
547309758Smanu	},
548309758Smanu	{
549309758Smanu		.id = AXP2XX_BATCHARGECURRENT,
550309758Smanu		.name = "batchargecurrent",
551309758Smanu		.desc = "Battery Charging Current (microAmpere)",
552309758Smanu		.format = "I",
553309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
554309758Smanu		.enable_mask = AXP2XX_ADC1_BATCURRENT,
555309758Smanu		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
556309758Smanu		.value_size = 2,
557309758Smanu		.h_value_mask = 0xff,
558309758Smanu		.h_value_shift = 5,
559309758Smanu		.l_value_mask = 0x1f,
560309758Smanu		.l_value_shift = 0,
561309758Smanu		.value_step = AXP2XX_BATCURRENT_STEP,
562309758Smanu	},
563309758Smanu	{
564309758Smanu		.id = AXP2XX_BATDISCHARGECURRENT,
565309758Smanu		.name = "batdischargecurrent",
566309758Smanu		.desc = "Battery Discharging Current (microAmpere)",
567309758Smanu		.format = "I",
568309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
569309758Smanu		.enable_mask = AXP2XX_ADC1_BATCURRENT,
570309758Smanu		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
571309758Smanu		.value_size = 2,
572309758Smanu		.h_value_mask = 0xff,
573309758Smanu		.h_value_shift = 5,
574309758Smanu		.l_value_mask = 0x1f,
575309758Smanu		.l_value_shift = 0,
576309758Smanu		.value_step = AXP2XX_BATCURRENT_STEP,
577309758Smanu	},
578309758Smanu	{
579309758Smanu		.id = AXP2XX_TEMP,
580309758Smanu		.name = "temp",
581309758Smanu		.desc = "Internal Temperature",
582309758Smanu		.format = "IK",
583309758Smanu		.enable_reg = AXP2XX_ADC_ENABLE1,
584309758Smanu		.enable_mask = AXP221_ADC1_TEMP,
585309758Smanu		.value_reg = AXP221_TEMPMON,
586309758Smanu		.value_size = 2,
587309758Smanu		.h_value_mask = 0xff,
588309758Smanu		.h_value_shift = 4,
589309758Smanu		.l_value_mask = 0xf,
590309758Smanu		.l_value_shift = 0,
591309758Smanu		.value_step = 1,
592309758Smanu		.value_convert = -(AXP221_TEMPMON_MIN - AXP209_0C_TO_K),
593309758Smanu	},
594309758Smanu};
595309758Smanu
596309758Smanuenum AXP2XX_TYPE {
597309758Smanu	AXP209 = 1,
598309758Smanu	AXP221,
599309758Smanu};
600309758Smanu
601309758Smanustruct axp2xx_softc {
602300777Smanu	device_t		dev;
603300777Smanu	struct resource *	res[1];
604300777Smanu	void *			intrcookie;
605300777Smanu	struct intr_config_hook	intr_hook;
606300777Smanu	struct mtx		mtx;
607309758Smanu	uint8_t			type;
608307885Smanu
609309758Smanu	/* GPIO */
610309758Smanu	device_t		gpiodev;
611309758Smanu	int			npins;
612309758Smanu	const struct axp2xx_pins	*pins;
613309758Smanu
614309758Smanu	/* Sensors */
615309758Smanu	const struct axp2xx_sensors	*sensors;
616309758Smanu	int				nsensors;
617309758Smanu
618307885Smanu	/* Regulators */
619309758Smanu	struct axp2xx_reg_sc	**regs;
620307885Smanu	int			nregs;
621309758Smanu	struct axp2xx_regdef	*regdefs;
622295634Sandrew};
623295634Sandrew
624309758Smanustatic struct ofw_compat_data compat_data[] = {
625309758Smanu	{ "x-powers,axp209",		AXP209 },
626309758Smanu	{ "x-powers,axp221",		AXP221 },
627309758Smanu	{ NULL,				0 }
628295658Sandrew};
629295658Sandrew
630300777Smanustatic struct resource_spec axp_res_spec[] = {
631300777Smanu	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
632300777Smanu	{ -1,			0,	0 }
633300777Smanu};
634300777Smanu
635300777Smanu#define	AXP_LOCK(sc)	mtx_lock(&(sc)->mtx)
636300777Smanu#define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
637300777Smanu
638295634Sandrewstatic int
639309758Smanuaxp2xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
640295634Sandrew{
641295634Sandrew
642323467Sian	return (iicdev_readfrom(dev, reg, data, size, IIC_INTRWAIT));
643295634Sandrew}
644295634Sandrew
645295634Sandrewstatic int
646309758Smanuaxp2xx_write(device_t dev, uint8_t reg, uint8_t data)
647295634Sandrew{
648295634Sandrew
649323467Sian	return (iicdev_writeto(dev, reg, &data, sizeof(data), IIC_INTRWAIT));
650295634Sandrew}
651295634Sandrew
652295658Sandrewstatic int
653309758Smanuaxp2xx_regnode_init(struct regnode *regnode)
654307885Smanu{
655307885Smanu	return (0);
656307885Smanu}
657307885Smanu
658307885Smanustatic int
659309758Smanuaxp2xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
660307885Smanu{
661309758Smanu	struct axp2xx_reg_sc *sc;
662307885Smanu	uint8_t val;
663307885Smanu
664307885Smanu	sc = regnode_get_softc(regnode);
665307885Smanu
666309758Smanu	axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
667307885Smanu	if (enable)
668307885Smanu		val |= sc->def->enable_mask;
669307885Smanu	else
670307885Smanu		val &= ~sc->def->enable_mask;
671309758Smanu	axp2xx_write(sc->base_dev, sc->def->enable_reg, val);
672307885Smanu
673307885Smanu	*udelay = 0;
674307885Smanu
675307885Smanu	return (0);
676307885Smanu}
677307885Smanu
678307885Smanustatic void
679309758Smanuaxp2xx_regnode_reg_to_voltage(struct axp2xx_reg_sc *sc, uint8_t val, int *uv)
680307885Smanu{
681307885Smanu	if (val < sc->def->voltage_nstep)
682307885Smanu		*uv = sc->def->voltage_min + val * sc->def->voltage_step;
683307885Smanu	else
684307885Smanu		*uv = sc->def->voltage_min +
685307885Smanu		       (sc->def->voltage_nstep * sc->def->voltage_step);
686307885Smanu	*uv *= 1000;
687307885Smanu}
688307885Smanu
689307885Smanustatic int
690309758Smanuaxp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc *sc, int min_uvolt,
691307885Smanu    int max_uvolt, uint8_t *val)
692307885Smanu{
693307885Smanu	uint8_t nval;
694307885Smanu	int nstep, uvolt;
695307885Smanu
696307885Smanu	nval = 0;
697307885Smanu	uvolt = sc->def->voltage_min * 1000;
698307885Smanu
699307885Smanu	for (nstep = 0; nstep < sc->def->voltage_nstep && uvolt < min_uvolt;
700307885Smanu	     nstep++) {
701307885Smanu		++nval;
702307885Smanu		uvolt += (sc->def->voltage_step * 1000);
703307885Smanu	}
704307885Smanu	if (uvolt > max_uvolt)
705307885Smanu		return (EINVAL);
706307885Smanu
707307885Smanu	*val = nval;
708307885Smanu	return (0);
709307885Smanu}
710307885Smanu
711307885Smanustatic int
712309758Smanuaxp2xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
713307885Smanu    int max_uvolt, int *udelay)
714307885Smanu{
715309758Smanu	struct axp2xx_reg_sc *sc;
716307885Smanu	uint8_t val;
717307885Smanu
718307885Smanu	sc = regnode_get_softc(regnode);
719307885Smanu
720307885Smanu	if (!sc->def->voltage_step)
721307885Smanu		return (ENXIO);
722307885Smanu
723309758Smanu	if (axp2xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
724307885Smanu		return (ERANGE);
725307885Smanu
726309758Smanu	axp2xx_write(sc->base_dev, sc->def->voltage_reg, val);
727307885Smanu
728307885Smanu	*udelay = 0;
729307885Smanu
730307885Smanu	return (0);
731307885Smanu}
732307885Smanu
733307885Smanustatic int
734309758Smanuaxp2xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
735307885Smanu{
736309758Smanu	struct axp2xx_reg_sc *sc;
737307885Smanu	uint8_t val;
738307885Smanu
739307885Smanu	sc = regnode_get_softc(regnode);
740307885Smanu
741307885Smanu	if (!sc->def->voltage_step)
742307885Smanu		return (ENXIO);
743307885Smanu
744309758Smanu	axp2xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
745309758Smanu	axp2xx_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
746307885Smanu
747307885Smanu	return (0);
748307885Smanu}
749307885Smanu
750309758Smanustatic regnode_method_t axp2xx_regnode_methods[] = {
751307885Smanu	/* Regulator interface */
752309758Smanu	REGNODEMETHOD(regnode_init,		axp2xx_regnode_init),
753309758Smanu	REGNODEMETHOD(regnode_enable,		axp2xx_regnode_enable),
754309758Smanu	REGNODEMETHOD(regnode_set_voltage,	axp2xx_regnode_set_voltage),
755309758Smanu	REGNODEMETHOD(regnode_get_voltage,	axp2xx_regnode_get_voltage),
756307885Smanu	REGNODEMETHOD_END
757307885Smanu};
758309758SmanuDEFINE_CLASS_1(axp2xx_regnode, axp2xx_regnode_class, axp2xx_regnode_methods,
759309758Smanu    sizeof(struct axp2xx_reg_sc), regnode_class);
760307885Smanu
761307885Smanustatic int
762309758Smanuaxp2xx_sysctl(SYSCTL_HANDLER_ARGS)
763295658Sandrew{
764309758Smanu	struct axp2xx_softc *sc;
765295658Sandrew	device_t dev = arg1;
766309758Smanu	enum axp2xx_sensor sensor = arg2;
767295658Sandrew	uint8_t data[2];
768309758Smanu	int val, error, i, found;
769295658Sandrew
770309758Smanu	sc = device_get_softc(dev);
771295658Sandrew
772309758Smanu	for (found = 0, i = 0; i < sc->nsensors; i++) {
773309758Smanu		if (sc->sensors[i].id == sensor) {
774309758Smanu			found = 1;
775309758Smanu			break;
776309758Smanu		}
777309758Smanu	}
778295658Sandrew
779309758Smanu	if (found == 0)
780309758Smanu		return (ENOENT);
781295658Sandrew
782309758Smanu	error = axp2xx_read(dev, sc->sensors[i].value_reg, data, 2);
783309758Smanu	if (error != 0)
784309758Smanu		return (error);
785300777Smanu
786309758Smanu	val = ((data[0] & sc->sensors[i].h_value_mask) <<
787309758Smanu	    sc->sensors[i].h_value_shift);
788309758Smanu	val |= ((data[1] & sc->sensors[i].l_value_mask) <<
789309758Smanu	    sc->sensors[i].l_value_shift);
790309758Smanu	val *= sc->sensors[i].value_step;
791309758Smanu	val += sc->sensors[i].value_convert;
792300777Smanu
793295658Sandrew	return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
794295658Sandrew}
795295658Sandrew
796295634Sandrewstatic void
797309758Smanuaxp2xx_shutdown(void *devp, int howto)
798295634Sandrew{
799295634Sandrew	device_t dev;
800295634Sandrew
801295634Sandrew	if (!(howto & RB_POWEROFF))
802295634Sandrew		return;
803295634Sandrew	dev = (device_t)devp;
804295634Sandrew
805295634Sandrew	if (bootverbose)
806309758Smanu		device_printf(dev, "Shutdown AXP2xx\n");
807295634Sandrew
808309758Smanu	axp2xx_write(dev, AXP2XX_SHUTBAT, AXP2XX_SHUTBAT_SHUTDOWN);
809295634Sandrew}
810295634Sandrew
811300777Smanustatic void
812309758Smanuaxp2xx_intr(void *arg)
813300777Smanu{
814309758Smanu	struct axp2xx_softc *sc;
815300777Smanu	uint8_t reg;
816300777Smanu
817300777Smanu	sc = arg;
818300777Smanu
819309758Smanu	axp2xx_read(sc->dev, AXP2XX_IRQ1_STATUS, &reg, 1);
820300777Smanu	if (reg) {
821309758Smanu		if (reg & AXP2XX_IRQ1_AC_OVERVOLT)
822300777Smanu			devctl_notify("PMU", "AC", "overvoltage", NULL);
823309758Smanu		if (reg & AXP2XX_IRQ1_VBUS_OVERVOLT)
824300777Smanu			devctl_notify("PMU", "USB", "overvoltage", NULL);
825309758Smanu		if (reg & AXP2XX_IRQ1_VBUS_LOW)
826300777Smanu			devctl_notify("PMU", "USB", "undervoltage", NULL);
827309758Smanu		if (reg & AXP2XX_IRQ1_AC_CONN)
828300777Smanu			devctl_notify("PMU", "AC", "plugged", NULL);
829309758Smanu		if (reg & AXP2XX_IRQ1_AC_DISCONN)
830300777Smanu			devctl_notify("PMU", "AC", "unplugged", NULL);
831309758Smanu		if (reg & AXP2XX_IRQ1_VBUS_CONN)
832300777Smanu			devctl_notify("PMU", "USB", "plugged", NULL);
833309758Smanu		if (reg & AXP2XX_IRQ1_VBUS_DISCONN)
834300777Smanu			devctl_notify("PMU", "USB", "unplugged", NULL);
835309758Smanu		axp2xx_write(sc->dev, AXP2XX_IRQ1_STATUS, AXP2XX_IRQ_ACK);
836300777Smanu	}
837300777Smanu
838309758Smanu	axp2xx_read(sc->dev, AXP2XX_IRQ2_STATUS, &reg, 1);
839300777Smanu	if (reg) {
840309758Smanu		if (reg & AXP2XX_IRQ2_BATT_CHARGED)
841300777Smanu			devctl_notify("PMU", "Battery", "charged", NULL);
842309758Smanu		if (reg & AXP2XX_IRQ2_BATT_CHARGING)
843300777Smanu			devctl_notify("PMU", "Battery", "charging", NULL);
844309758Smanu		if (reg & AXP2XX_IRQ2_BATT_CONN)
845300777Smanu			devctl_notify("PMU", "Battery", "connected", NULL);
846309758Smanu		if (reg & AXP2XX_IRQ2_BATT_DISCONN)
847300777Smanu			devctl_notify("PMU", "Battery", "disconnected", NULL);
848309758Smanu		if (reg & AXP2XX_IRQ2_BATT_TEMP_LOW)
849300777Smanu			devctl_notify("PMU", "Battery", "low temp", NULL);
850309758Smanu		if (reg & AXP2XX_IRQ2_BATT_TEMP_OVER)
851300777Smanu			devctl_notify("PMU", "Battery", "high temp", NULL);
852309758Smanu		axp2xx_write(sc->dev, AXP2XX_IRQ2_STATUS, AXP2XX_IRQ_ACK);
853300777Smanu	}
854300777Smanu
855309758Smanu	axp2xx_read(sc->dev, AXP2XX_IRQ3_STATUS, &reg, 1);
856300777Smanu	if (reg) {
857309758Smanu		if (reg & AXP2XX_IRQ3_PEK_SHORT)
858300777Smanu			shutdown_nice(RB_POWEROFF);
859309758Smanu		axp2xx_write(sc->dev, AXP2XX_IRQ3_STATUS, AXP2XX_IRQ_ACK);
860300777Smanu	}
861300777Smanu
862309758Smanu	axp2xx_read(sc->dev, AXP2XX_IRQ4_STATUS, &reg, 1);
863300777Smanu	if (reg) {
864309758Smanu		axp2xx_write(sc->dev, AXP2XX_IRQ4_STATUS, AXP2XX_IRQ_ACK);
865300777Smanu	}
866300777Smanu
867309758Smanu	axp2xx_read(sc->dev, AXP2XX_IRQ5_STATUS, &reg, 1);
868300777Smanu	if (reg) {
869309758Smanu		axp2xx_write(sc->dev, AXP2XX_IRQ5_STATUS, AXP2XX_IRQ_ACK);
870300777Smanu	}
871300777Smanu}
872300777Smanu
873300777Smanustatic device_t
874309758Smanuaxp2xx_gpio_get_bus(device_t dev)
875300777Smanu{
876309758Smanu	struct axp2xx_softc *sc;
877300777Smanu
878300777Smanu	sc = device_get_softc(dev);
879300777Smanu
880300777Smanu	return (sc->gpiodev);
881300777Smanu}
882300777Smanu
883295634Sandrewstatic int
884309758Smanuaxp2xx_gpio_pin_max(device_t dev, int *maxpin)
885295634Sandrew{
886309758Smanu	struct axp2xx_softc *sc;
887295634Sandrew
888309758Smanu	sc = device_get_softc(dev);
889309758Smanu
890309758Smanu	*maxpin = sc->npins - 1;
891309758Smanu
892300777Smanu	return (0);
893300777Smanu}
894295634Sandrew
895300777Smanustatic int
896309758Smanuaxp2xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
897300777Smanu{
898309758Smanu	struct axp2xx_softc *sc;
899309758Smanu
900309758Smanu	sc = device_get_softc(dev);
901309758Smanu
902309758Smanu	if (pin >= sc->npins)
903300777Smanu		return (EINVAL);
904295634Sandrew
905300777Smanu	snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name);
906295634Sandrew
907300777Smanu	return (0);
908295634Sandrew}
909295634Sandrew
910295634Sandrewstatic int
911309758Smanuaxp2xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
912295634Sandrew{
913309758Smanu	struct axp2xx_softc *sc;
914309758Smanu
915309758Smanu	sc = device_get_softc(dev);
916309758Smanu
917309758Smanu	if (pin >= sc->npins)
918300777Smanu		return (EINVAL);
919300777Smanu
920300777Smanu	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
921300777Smanu
922300777Smanu	return (0);
923300777Smanu}
924300777Smanu
925300777Smanustatic int
926309758Smanuaxp2xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
927300777Smanu{
928309758Smanu	struct axp2xx_softc *sc;
929300777Smanu	uint8_t data, func;
930300777Smanu	int error;
931300777Smanu
932309758Smanu	sc = device_get_softc(dev);
933309758Smanu
934309758Smanu	if (pin >= sc->npins)
935300777Smanu		return (EINVAL);
936300777Smanu
937300777Smanu	AXP_LOCK(sc);
938309758Smanu	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
939300777Smanu	if (error == 0) {
940309758Smanu		func = data & AXP2XX_GPIO_FUNC_MASK;
941309758Smanu		if (func == AXP2XX_GPIO_FUNC_INPUT)
942300777Smanu			*flags = GPIO_PIN_INPUT;
943309758Smanu		else if (func == AXP2XX_GPIO_FUNC_DRVLO ||
944309758Smanu		    func == AXP2XX_GPIO_FUNC_DRVHI)
945300777Smanu			*flags = GPIO_PIN_OUTPUT;
946300777Smanu		else
947300777Smanu			*flags = 0;
948300777Smanu	}
949300777Smanu	AXP_UNLOCK(sc);
950300777Smanu
951300777Smanu	return (error);
952300777Smanu}
953300777Smanu
954300777Smanustatic int
955309758Smanuaxp2xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
956300777Smanu{
957309758Smanu	struct axp2xx_softc *sc;
958300777Smanu	uint8_t data;
959300777Smanu	int error;
960300777Smanu
961309758Smanu	sc = device_get_softc(dev);
962309758Smanu
963309758Smanu	if (pin >= sc->npins)
964300777Smanu		return (EINVAL);
965300777Smanu
966300777Smanu	AXP_LOCK(sc);
967309758Smanu	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
968300777Smanu	if (error == 0) {
969309758Smanu		data &= ~AXP2XX_GPIO_FUNC_MASK;
970300777Smanu		if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
971300777Smanu			if ((flags & GPIO_PIN_OUTPUT) == 0)
972309758Smanu				data |= AXP2XX_GPIO_FUNC_INPUT;
973300777Smanu		}
974309758Smanu		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
975300777Smanu	}
976300777Smanu	AXP_UNLOCK(sc);
977300777Smanu
978300777Smanu	return (error);
979300777Smanu}
980300777Smanu
981300777Smanustatic int
982309758Smanuaxp2xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
983300777Smanu{
984309758Smanu	struct axp2xx_softc *sc;
985300777Smanu	uint8_t data, func;
986300777Smanu	int error;
987300777Smanu
988309758Smanu	sc = device_get_softc(dev);
989309758Smanu
990309758Smanu	if (pin >= sc->npins)
991300777Smanu		return (EINVAL);
992300777Smanu
993300777Smanu	AXP_LOCK(sc);
994309758Smanu	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
995300777Smanu	if (error == 0) {
996309758Smanu		func = data & AXP2XX_GPIO_FUNC_MASK;
997300777Smanu		switch (func) {
998309758Smanu		case AXP2XX_GPIO_FUNC_DRVLO:
999300777Smanu			*val = 0;
1000300777Smanu			break;
1001309758Smanu		case AXP2XX_GPIO_FUNC_DRVHI:
1002300777Smanu			*val = 1;
1003300777Smanu			break;
1004309758Smanu		case AXP2XX_GPIO_FUNC_INPUT:
1005309758Smanu			error = axp2xx_read(dev, sc->pins[pin].status_reg,
1006309758Smanu			    &data, 1);
1007309758Smanu			if (error == 0) {
1008309758Smanu				*val = (data & sc->pins[pin].status_mask);
1009309758Smanu				*val >>= sc->pins[pin].status_shift;
1010309758Smanu			}
1011300777Smanu			break;
1012300777Smanu		default:
1013300777Smanu			error = EIO;
1014300777Smanu			break;
1015300777Smanu		}
1016300777Smanu	}
1017300777Smanu	AXP_UNLOCK(sc);
1018300777Smanu
1019300777Smanu	return (error);
1020300777Smanu}
1021300777Smanu
1022300777Smanustatic int
1023309758Smanuaxp2xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
1024300777Smanu{
1025309758Smanu	struct axp2xx_softc *sc;
1026300777Smanu	uint8_t data, func;
1027300777Smanu	int error;
1028300777Smanu
1029309758Smanu	sc = device_get_softc(dev);
1030309758Smanu
1031309758Smanu	if (pin >= sc->npins)
1032300777Smanu		return (EINVAL);
1033300777Smanu
1034300777Smanu	AXP_LOCK(sc);
1035309758Smanu	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
1036300777Smanu	if (error == 0) {
1037309758Smanu		func = data & AXP2XX_GPIO_FUNC_MASK;
1038300777Smanu		switch (func) {
1039309758Smanu		case AXP2XX_GPIO_FUNC_DRVLO:
1040309758Smanu		case AXP2XX_GPIO_FUNC_DRVHI:
1041300777Smanu			/* GPIO2 can't be set to 1 */
1042300777Smanu			if (pin == 2 && val == 1) {
1043300777Smanu				error = EINVAL;
1044300777Smanu				break;
1045300777Smanu			}
1046309758Smanu			data &= ~AXP2XX_GPIO_FUNC_MASK;
1047300777Smanu			data |= val;
1048300777Smanu			break;
1049300777Smanu		default:
1050300777Smanu			error = EIO;
1051300777Smanu			break;
1052300777Smanu		}
1053300777Smanu	}
1054300777Smanu	if (error == 0)
1055309758Smanu		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
1056300777Smanu	AXP_UNLOCK(sc);
1057300777Smanu
1058300777Smanu	return (error);
1059300777Smanu}
1060300777Smanu
1061300777Smanu
1062300777Smanustatic int
1063309758Smanuaxp2xx_gpio_pin_toggle(device_t dev, uint32_t pin)
1064300777Smanu{
1065309758Smanu	struct axp2xx_softc *sc;
1066300777Smanu	uint8_t data, func;
1067300777Smanu	int error;
1068300777Smanu
1069309758Smanu	sc = device_get_softc(dev);
1070309758Smanu
1071309758Smanu	if (pin >= sc->npins)
1072300777Smanu		return (EINVAL);
1073300777Smanu
1074300777Smanu	AXP_LOCK(sc);
1075309758Smanu	error = axp2xx_read(dev, sc->pins[pin].ctrl_reg, &data, 1);
1076300777Smanu	if (error == 0) {
1077309758Smanu		func = data & AXP2XX_GPIO_FUNC_MASK;
1078300777Smanu		switch (func) {
1079309758Smanu		case AXP2XX_GPIO_FUNC_DRVLO:
1080300777Smanu			/* Pin 2 can't be set to 1*/
1081300777Smanu			if (pin == 2) {
1082300777Smanu				error = EINVAL;
1083300777Smanu				break;
1084300777Smanu			}
1085309758Smanu			data &= ~AXP2XX_GPIO_FUNC_MASK;
1086309758Smanu			data |= AXP2XX_GPIO_FUNC_DRVHI;
1087300777Smanu			break;
1088309758Smanu		case AXP2XX_GPIO_FUNC_DRVHI:
1089309758Smanu			data &= ~AXP2XX_GPIO_FUNC_MASK;
1090309758Smanu			data |= AXP2XX_GPIO_FUNC_DRVLO;
1091300777Smanu			break;
1092300777Smanu		default:
1093300777Smanu			error = EIO;
1094300777Smanu			break;
1095300777Smanu		}
1096300777Smanu	}
1097300777Smanu	if (error == 0)
1098309758Smanu		error = axp2xx_write(dev, sc->pins[pin].ctrl_reg, data);
1099300777Smanu	AXP_UNLOCK(sc);
1100300777Smanu
1101300777Smanu	return (error);
1102300777Smanu}
1103300777Smanu
1104300777Smanustatic int
1105309758Smanuaxp2xx_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
1106300777Smanu    int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
1107300777Smanu{
1108309758Smanu	struct axp2xx_softc *sc;
1109309758Smanu
1110309758Smanu	sc = device_get_softc(bus);
1111309758Smanu
1112309758Smanu	if (gpios[0] >= sc->npins)
1113300777Smanu		return (EINVAL);
1114300777Smanu
1115300777Smanu	*pin = gpios[0];
1116300777Smanu	*flags = gpios[1];
1117300777Smanu
1118300777Smanu	return (0);
1119300777Smanu}
1120300777Smanu
1121300777Smanustatic phandle_t
1122309758Smanuaxp2xx_get_node(device_t dev, device_t bus)
1123300777Smanu{
1124300777Smanu	return (ofw_bus_get_node(dev));
1125300777Smanu}
1126300777Smanu
1127309758Smanustatic struct axp2xx_reg_sc *
1128309758Smanuaxp2xx_reg_attach(device_t dev, phandle_t node,
1129309758Smanu    struct axp2xx_regdef *def)
1130307885Smanu{
1131309758Smanu	struct axp2xx_reg_sc *reg_sc;
1132307885Smanu	struct regnode_init_def initdef;
1133307885Smanu	struct regnode *regnode;
1134307885Smanu
1135307885Smanu	memset(&initdef, 0, sizeof(initdef));
1136307885Smanu	if (regulator_parse_ofw_stdparam(dev, node, &initdef) != 0) {
1137307885Smanu		device_printf(dev, "cannot create regulator\n");
1138307885Smanu		return (NULL);
1139307885Smanu	}
1140307885Smanu	if (initdef.std_param.min_uvolt == 0)
1141307885Smanu		initdef.std_param.min_uvolt = def->voltage_min * 1000;
1142307885Smanu	if (initdef.std_param.max_uvolt == 0)
1143307885Smanu		initdef.std_param.max_uvolt = def->voltage_max * 1000;
1144307885Smanu	initdef.id = def->id;
1145307885Smanu	initdef.ofw_node = node;
1146309758Smanu	regnode = regnode_create(dev, &axp2xx_regnode_class, &initdef);
1147307885Smanu	if (regnode == NULL) {
1148307885Smanu		device_printf(dev, "cannot create regulator\n");
1149307885Smanu		return (NULL);
1150307885Smanu	}
1151307885Smanu
1152307885Smanu	reg_sc = regnode_get_softc(regnode);
1153307885Smanu	reg_sc->regnode = regnode;
1154307885Smanu	reg_sc->base_dev = dev;
1155307885Smanu	reg_sc->def = def;
1156307885Smanu	reg_sc->xref = OF_xref_from_node(node);
1157307885Smanu	reg_sc->param = regnode_get_stdparam(regnode);
1158307885Smanu
1159307885Smanu	regnode_register(regnode);
1160307885Smanu
1161307885Smanu	return (reg_sc);
1162307885Smanu}
1163307885Smanu
1164307885Smanustatic int
1165309758Smanuaxp2xx_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
1166307885Smanu    intptr_t *num)
1167307885Smanu{
1168309758Smanu	struct axp2xx_softc *sc;
1169307885Smanu	int i;
1170307885Smanu
1171307885Smanu	sc = device_get_softc(dev);
1172307885Smanu	for (i = 0; i < sc->nregs; i++) {
1173307885Smanu		if (sc->regs[i] == NULL)
1174307885Smanu			continue;
1175307885Smanu		if (sc->regs[i]->xref == xref) {
1176307885Smanu			*num = sc->regs[i]->def->id;
1177307885Smanu			return (0);
1178307885Smanu		}
1179307885Smanu	}
1180307885Smanu
1181307885Smanu	return (ENXIO);
1182307885Smanu}
1183307885Smanu
1184300777Smanustatic void
1185309758Smanuaxp2xx_start(void *pdev)
1186300777Smanu{
1187300777Smanu	device_t dev;
1188309758Smanu	struct axp2xx_softc *sc;
1189295654Sandrew	const char *pwr_name[] = {"Battery", "AC", "USB", "AC and USB"};
1190309758Smanu	int i;
1191309758Smanu	uint8_t reg, data;
1192295634Sandrew	uint8_t pwr_src;
1193295634Sandrew
1194300777Smanu	dev = pdev;
1195300777Smanu
1196295634Sandrew	sc = device_get_softc(dev);
1197300777Smanu	sc->dev = dev;
1198295634Sandrew
1199295654Sandrew	if (bootverbose) {
1200295654Sandrew		/*
1201295654Sandrew		 * Read the Power State register.
1202295654Sandrew		 * Shift the AC presence into bit 0.
1203295654Sandrew		 * Shift the Battery presence into bit 1.
1204295654Sandrew		 */
1205309758Smanu		axp2xx_read(dev, AXP2XX_PSR, &data, 1);
1206309758Smanu		pwr_src = ((data & AXP2XX_PSR_ACIN) >> AXP2XX_PSR_ACIN_SHIFT) |
1207309758Smanu		    ((data & AXP2XX_PSR_VBUS) >> (AXP2XX_PSR_VBUS_SHIFT - 1));
1208295634Sandrew
1209309758Smanu		device_printf(dev, "Powered by %s\n",
1210295634Sandrew		    pwr_name[pwr_src]);
1211295654Sandrew	}
1212295634Sandrew
1213300777Smanu	/* Only enable interrupts that we are interested in */
1214309758Smanu	axp2xx_write(dev, AXP2XX_IRQ1_ENABLE,
1215309758Smanu	    AXP2XX_IRQ1_AC_OVERVOLT |
1216309758Smanu	    AXP2XX_IRQ1_AC_DISCONN |
1217309758Smanu	    AXP2XX_IRQ1_AC_CONN |
1218309758Smanu	    AXP2XX_IRQ1_VBUS_OVERVOLT |
1219309758Smanu	    AXP2XX_IRQ1_VBUS_DISCONN |
1220309758Smanu	    AXP2XX_IRQ1_VBUS_CONN);
1221309758Smanu	axp2xx_write(dev, AXP2XX_IRQ2_ENABLE,
1222309758Smanu	    AXP2XX_IRQ2_BATT_CONN |
1223309758Smanu	    AXP2XX_IRQ2_BATT_DISCONN |
1224309758Smanu	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_ON |
1225309758Smanu	    AXP2XX_IRQ2_BATT_CHARGE_ACCT_OFF |
1226309758Smanu	    AXP2XX_IRQ2_BATT_CHARGING |
1227309758Smanu	    AXP2XX_IRQ2_BATT_CHARGED |
1228309758Smanu	    AXP2XX_IRQ2_BATT_TEMP_OVER |
1229309758Smanu	    AXP2XX_IRQ2_BATT_TEMP_LOW);
1230309758Smanu	axp2xx_write(dev, AXP2XX_IRQ3_ENABLE,
1231309758Smanu	    AXP2XX_IRQ3_PEK_SHORT | AXP2XX_IRQ3_PEK_LONG);
1232309758Smanu	axp2xx_write(dev, AXP2XX_IRQ4_ENABLE, AXP2XX_IRQ4_APS_LOW_2);
1233309758Smanu	axp2xx_write(dev, AXP2XX_IRQ5_ENABLE, 0x0);
1234300777Smanu
1235309758Smanu	EVENTHANDLER_REGISTER(shutdown_final, axp2xx_shutdown, dev,
1236295634Sandrew	    SHUTDOWN_PRI_LAST);
1237295634Sandrew
1238300777Smanu	/* Enable ADC sensors */
1239309758Smanu	for (i = 0; i < sc->nsensors; i++) {
1240309758Smanu		if (axp2xx_read(dev, sc->sensors[i].enable_reg, &reg, 1) == -1) {
1241309758Smanu			device_printf(dev, "Cannot enable sensor '%s'\n",
1242309758Smanu			    sc->sensors[i].name);
1243309758Smanu			continue;
1244309758Smanu		}
1245309758Smanu		reg |= sc->sensors[i].enable_mask;
1246309758Smanu		if (axp2xx_write(dev, sc->sensors[i].enable_reg, reg) == -1) {
1247309758Smanu			device_printf(dev, "Cannot enable sensor '%s'\n",
1248309758Smanu			    sc->sensors[i].name);
1249309758Smanu			continue;
1250309758Smanu		}
1251300777Smanu		SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
1252300777Smanu		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
1253309758Smanu		    OID_AUTO, sc->sensors[i].name,
1254300777Smanu		    CTLTYPE_INT | CTLFLAG_RD,
1255309758Smanu		    dev, sc->sensors[i].id, axp2xx_sysctl,
1256309758Smanu		    sc->sensors[i].format,
1257309758Smanu		    sc->sensors[i].desc);
1258300777Smanu	}
1259300777Smanu
1260300777Smanu	if ((bus_setup_intr(dev, sc->res[0], INTR_TYPE_MISC | INTR_MPSAFE,
1261309758Smanu	      NULL, axp2xx_intr, sc, &sc->intrcookie)))
1262300777Smanu		device_printf(dev, "unable to register interrupt handler\n");
1263300777Smanu
1264300777Smanu	config_intrhook_disestablish(&sc->intr_hook);
1265300777Smanu}
1266300777Smanu
1267300777Smanustatic int
1268309758Smanuaxp2xx_probe(device_t dev)
1269300777Smanu{
1270300777Smanu
1271300777Smanu	if (!ofw_bus_status_okay(dev))
1272300777Smanu		return (ENXIO);
1273300777Smanu
1274309758Smanu	switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
1275309758Smanu	{
1276309758Smanu	case AXP209:
1277309758Smanu		device_set_desc(dev, "X-Powers AXP209 Power Management Unit");
1278309758Smanu		break;
1279309758Smanu	case AXP221:
1280309758Smanu		device_set_desc(dev, "X-Powers AXP221 Power Management Unit");
1281309758Smanu		break;
1282309758Smanu	default:
1283300777Smanu		return (ENXIO);
1284309758Smanu	}
1285300777Smanu
1286300777Smanu	return (BUS_PROBE_DEFAULT);
1287300777Smanu}
1288300777Smanu
1289300777Smanustatic int
1290309758Smanuaxp2xx_attach(device_t dev)
1291300777Smanu{
1292309758Smanu	struct axp2xx_softc *sc;
1293309758Smanu	struct axp2xx_reg_sc *reg;
1294309758Smanu	struct axp2xx_regdef *regdefs;
1295307885Smanu	phandle_t rnode, child;
1296307885Smanu	int i;
1297300777Smanu
1298300777Smanu	sc = device_get_softc(dev);
1299300777Smanu	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
1300300777Smanu
1301300777Smanu	if (bus_alloc_resources(dev, axp_res_spec, sc->res) != 0) {
1302300777Smanu		device_printf(dev, "can't allocate device resources\n");
1303300777Smanu		return (ENXIO);
1304300777Smanu	}
1305300777Smanu
1306309758Smanu	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
1307309758Smanu	switch (sc->type) {
1308309758Smanu	case AXP209:
1309309758Smanu		sc->pins = axp209_pins;
1310309758Smanu		sc->npins = nitems(axp209_pins);
1311309758Smanu		sc->gpiodev = gpiobus_attach_bus(dev);
1312309758Smanu
1313309758Smanu		sc->sensors = axp209_sensors;
1314309758Smanu		sc->nsensors = nitems(axp209_sensors);
1315309758Smanu
1316309758Smanu		regdefs = axp209_regdefs;
1317309758Smanu		sc->nregs = nitems(axp209_regdefs);
1318309758Smanu		break;
1319309758Smanu	case AXP221:
1320309758Smanu		sc->pins = axp221_pins;
1321309758Smanu		sc->npins = nitems(axp221_pins);
1322309758Smanu		sc->gpiodev = gpiobus_attach_bus(dev);
1323309758Smanu
1324309758Smanu		sc->sensors = axp221_sensors;
1325309758Smanu		sc->nsensors = nitems(axp221_sensors);
1326309758Smanu
1327309758Smanu		regdefs = axp221_regdefs;
1328309758Smanu		sc->nregs = nitems(axp221_regdefs);
1329309758Smanu		break;
1330309758Smanu	}
1331309758Smanu
1332309758Smanu	sc->regs = malloc(sizeof(struct axp2xx_reg_sc *) * sc->nregs,
1333309758Smanu	    M_AXP2XX_REG, M_WAITOK | M_ZERO);
1334309758Smanu
1335309758Smanu	sc->intr_hook.ich_func = axp2xx_start;
1336300777Smanu	sc->intr_hook.ich_arg = dev;
1337300777Smanu
1338300777Smanu	if (config_intrhook_establish(&sc->intr_hook) != 0)
1339300777Smanu		return (ENOMEM);
1340300777Smanu
1341307885Smanu	/* Attach known regulators that exist in the DT */
1342307885Smanu	rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators");
1343307885Smanu	if (rnode > 0) {
1344307885Smanu		for (i = 0; i < sc->nregs; i++) {
1345307885Smanu			child = ofw_bus_find_child(rnode,
1346309758Smanu			    regdefs[i].name);
1347307885Smanu			if (child == 0)
1348307885Smanu				continue;
1349309758Smanu			reg = axp2xx_reg_attach(dev, child, &regdefs[i]);
1350307885Smanu			if (reg == NULL) {
1351307885Smanu				device_printf(dev,
1352307885Smanu				    "cannot attach regulator %s\n",
1353309758Smanu				    regdefs[i].name);
1354307885Smanu				continue;
1355307885Smanu			}
1356307885Smanu			sc->regs[i] = reg;
1357309758Smanu			if (bootverbose)
1358309758Smanu				device_printf(dev, "Regulator %s attached\n",
1359309758Smanu				    regdefs[i].name);
1360307885Smanu		}
1361307885Smanu	}
1362307885Smanu
1363295634Sandrew	return (0);
1364295634Sandrew}
1365295634Sandrew
1366309758Smanustatic device_method_t axp2xx_methods[] = {
1367309758Smanu	DEVMETHOD(device_probe,		axp2xx_probe),
1368309758Smanu	DEVMETHOD(device_attach,	axp2xx_attach),
1369300777Smanu
1370300777Smanu	/* GPIO interface */
1371309758Smanu	DEVMETHOD(gpio_get_bus,		axp2xx_gpio_get_bus),
1372309758Smanu	DEVMETHOD(gpio_pin_max,		axp2xx_gpio_pin_max),
1373309758Smanu	DEVMETHOD(gpio_pin_getname,	axp2xx_gpio_pin_getname),
1374309758Smanu	DEVMETHOD(gpio_pin_getcaps,	axp2xx_gpio_pin_getcaps),
1375309758Smanu	DEVMETHOD(gpio_pin_getflags,	axp2xx_gpio_pin_getflags),
1376309758Smanu	DEVMETHOD(gpio_pin_setflags,	axp2xx_gpio_pin_setflags),
1377309758Smanu	DEVMETHOD(gpio_pin_get,		axp2xx_gpio_pin_get),
1378309758Smanu	DEVMETHOD(gpio_pin_set,		axp2xx_gpio_pin_set),
1379309758Smanu	DEVMETHOD(gpio_pin_toggle,	axp2xx_gpio_pin_toggle),
1380309758Smanu	DEVMETHOD(gpio_map_gpios,	axp2xx_gpio_map_gpios),
1381300777Smanu
1382307885Smanu	/* Regdev interface */
1383309758Smanu	DEVMETHOD(regdev_map,		axp2xx_regdev_map),
1384307885Smanu
1385300777Smanu	/* OFW bus interface */
1386309758Smanu	DEVMETHOD(ofw_bus_get_node,	axp2xx_get_node),
1387300777Smanu
1388300777Smanu	DEVMETHOD_END
1389295634Sandrew};
1390295634Sandrew
1391309758Smanustatic driver_t axp2xx_driver = {
1392309758Smanu	"axp2xx_pmu",
1393309758Smanu	axp2xx_methods,
1394309758Smanu	sizeof(struct axp2xx_softc),
1395295634Sandrew};
1396295634Sandrew
1397309758Smanustatic devclass_t axp2xx_devclass;
1398300777Smanuextern devclass_t ofwgpiobus_devclass, gpioc_devclass;
1399300777Smanuextern driver_t ofw_gpiobus_driver, gpioc_driver;
1400295634Sandrew
1401309758SmanuEARLY_DRIVER_MODULE(axp2xx, iicbus, axp2xx_driver, axp2xx_devclass,
1402304214Smanu  0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
1403309758SmanuEARLY_DRIVER_MODULE(ofw_gpiobus, axp2xx_pmu, ofw_gpiobus_driver,
1404304214Smanu    ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
1405309758SmanuDRIVER_MODULE(gpioc, axp2xx_pmu, gpioc_driver, gpioc_devclass,
1406304214Smanu    0, 0);
1407309758SmanuMODULE_VERSION(axp2xx, 1);
1408323467SianMODULE_DEPEND(axp2xx, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
1409