svn commit: r308309 - head/sys/arm/allwinner

Emmanuel Vadot manu at FreeBSD.org
Fri Nov 4 20:02:53 UTC 2016


Author: manu
Date: Fri Nov  4 20:02:52 2016
New Revision: 308309
URL: https://svnweb.freebsd.org/changeset/base/308309

Log:
  Add support for AXP221 Power Management Unit.
  
  AXP221 is used on board with A31/A31S and is mostly compatible with AXP209.
  Regulators, GPIO and Sensors are supported.
  
  MFC after:	2 weeks

Modified:
  head/sys/arm/allwinner/axp209.c
  head/sys/arm/allwinner/axp209reg.h

Modified: head/sys/arm/allwinner/axp209.c
==============================================================================
--- head/sys/arm/allwinner/axp209.c	Fri Nov  4 19:35:49 2016	(r308308)
+++ head/sys/arm/allwinner/axp209.c	Fri Nov  4 20:02:52 2016	(r308309)
@@ -27,9 +27,11 @@
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
+
 /*
-* X-Power AXP209 PMU for Allwinner SoCs
+* X-Power AXP209/AXP211 PMU for Allwinner SoCs
 */
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/eventhandler.h>
@@ -61,9 +63,9 @@ __FBSDID("$FreeBSD$");
 #include "gpio_if.h"
 #include "regdev_if.h"
 
-MALLOC_DEFINE(M_AXP209_REG, "Axp209 regulator", "Axp209 power regulator");
+MALLOC_DEFINE(M_AXP2XX_REG, "Axp2XX regulator", "Axp2XX power regulator");
 
-struct axp209_regdef {
+struct axp2xx_regdef {
 	intptr_t		id;
 	char			*name;
 	uint8_t			enable_reg;
@@ -77,7 +79,7 @@ struct axp209_regdef {
 	int			voltage_nstep;
 };
 
-static struct axp209_regdef axp209_regdefs[] = {
+static struct axp2xx_regdef axp209_regdefs[] = {
 	{
 		.id = AXP209_REG_ID_DCDC2,
 		.name = "dcdc2",
@@ -129,36 +131,503 @@ static struct axp209_regdef axp209_regde
 	},
 };
 
-struct axp209_reg_sc {
+static struct axp2xx_regdef axp221_regdefs[] = {
+	{
+		.id = AXP221_REG_ID_DLDO1,
+		.name = "dldo1",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DLDO1,
+		.voltage_reg = AXP221_REG_DLDO1_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DLDO2,
+		.name = "dldo2",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DLDO2,
+		.voltage_reg = AXP221_REG_DLDO2_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DLDO3,
+		.name = "dldo3",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DLDO3,
+		.voltage_reg = AXP221_REG_DLDO3_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DLDO4,
+		.name = "dldo4",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DLDO4,
+		.voltage_reg = AXP221_REG_DLDO4_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ELDO1,
+		.name = "eldo1",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_ELDO1,
+		.voltage_reg = AXP221_REG_ELDO1_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ELDO2,
+		.name = "eldo2",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_ELDO2,
+		.voltage_reg = AXP221_REG_ELDO2_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ELDO3,
+		.name = "eldo3",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_ELDO3,
+		.voltage_reg = AXP221_REG_ELDO3_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DC5LDO,
+		.name = "dc5ldo",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DC5LDO,
+		.voltage_reg = AXP221_REG_DC5LDO_VOLTAGE,
+		.voltage_mask = 0x3,
+		.voltage_min = 700,
+		.voltage_max = 1400,
+		.voltage_step = 100,
+		.voltage_nstep = 7,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC1,
+		.name = "dcdc1",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC1,
+		.voltage_reg = AXP221_REG_DCDC1_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 1600,
+		.voltage_max = 3400,
+		.voltage_step = 100,
+		.voltage_nstep = 18,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC2,
+		.name = "dcdc2",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC2,
+		.voltage_reg = AXP221_REG_DCDC2_VOLTAGE,
+		.voltage_mask = 0x3f,
+		.voltage_min = 600,
+		.voltage_max = 1540,
+		.voltage_step = 20,
+		.voltage_nstep = 47,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC3,
+		.name = "dcdc3",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC3,
+		.voltage_reg = AXP221_REG_DCDC3_VOLTAGE,
+		.voltage_mask = 0x3f,
+		.voltage_min = 600,
+		.voltage_max = 1860,
+		.voltage_step = 20,
+		.voltage_nstep = 63,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC4,
+		.name = "dcdc4",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC4,
+		.voltage_reg = AXP221_REG_DCDC4_VOLTAGE,
+		.voltage_mask = 0x3f,
+		.voltage_min = 600,
+		.voltage_max = 1540,
+		.voltage_step = 20,
+		.voltage_nstep = 47,
+	},
+	{
+		.id = AXP221_REG_ID_DCDC5,
+		.name = "dcdc5",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_DCDC5,
+		.voltage_reg = AXP221_REG_DCDC5_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 1000,
+		.voltage_max = 2550,
+		.voltage_step = 50,
+		.voltage_nstep = 31,
+	},
+	{
+		.id = AXP221_REG_ID_ALDO1,
+		.name = "aldo1",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_ALDO1,
+		.voltage_reg = AXP221_REG_ALDO1_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ALDO2,
+		.name = "aldo2",
+		.enable_reg = AXP221_POWERCTL_1,
+		.enable_mask = AXP221_POWERCTL1_ALDO2,
+		.voltage_reg = AXP221_REG_ALDO2_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_ALDO3,
+		.name = "aldo3",
+		.enable_reg = AXP221_POWERCTL_3,
+		.enable_mask = AXP221_POWERCTL3_ALDO3,
+		.voltage_reg = AXP221_REG_ALDO3_VOLTAGE,
+		.voltage_mask = 0x1f,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step = 100,
+		.voltage_nstep = 26,
+	},
+	{
+		.id = AXP221_REG_ID_DC1SW,
+		.name = "dc1sw",
+		.enable_reg = AXP221_POWERCTL_2,
+		.enable_mask = AXP221_POWERCTL2_DC1SW,
+	},
+};
+
+struct axp2xx_reg_sc {
 	struct regnode		*regnode;
 	device_t		base_dev;
-	struct axp209_regdef	*def;
+	struct axp2xx_regdef	*def;
 	phandle_t		xref;
 	struct regnode_std_param *param;
 };
 
-struct axp209_softc {
+struct axp2xx_pins {
+	const char	*name;
+	uint8_t		ctrl_reg;
+	uint8_t		status_reg;
+	uint8_t		status_mask;
+	uint8_t		status_shift;
+};
+
+/* GPIO3 is different, don't expose it for now */
+static const struct axp2xx_pins axp209_pins[] = {
+	{
+		.name = "GPIO0",
+		.ctrl_reg = AXP2XX_GPIO0_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x10,
+		.status_shift = 4,
+	},
+	{
+		.name = "GPIO1",
+		.ctrl_reg = AXP2XX_GPIO1_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x20,
+		.status_shift = 5,
+	},
+	{
+		.name = "GPIO2",
+		.ctrl_reg = AXP209_GPIO2_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x40,
+		.status_shift = 6,
+	},
+};
+
+static const struct axp2xx_pins axp221_pins[] = {
+	{
+		.name = "GPIO0",
+		.ctrl_reg = AXP2XX_GPIO0_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x1,
+		.status_shift = 0x0,
+	},
+	{
+		.name = "GPIO1",
+		.ctrl_reg = AXP2XX_GPIO0_CTRL,
+		.status_reg = AXP2XX_GPIO_STATUS,
+		.status_mask = 0x2,
+		.status_shift = 0x1,
+	},
+};
+
+struct axp2xx_sensors {
+	int		id;
+	const char	*name;
+	const char	*desc;
+	const char	*format;
+	uint8_t		enable_reg;
+	uint8_t		enable_mask;
+	uint8_t		value_reg;
+	uint8_t		value_size;
+	uint8_t		h_value_mask;
+	uint8_t		h_value_shift;
+	uint8_t		l_value_mask;
+	uint8_t		l_value_shift;
+	int		value_step;
+	int		value_convert;
+};
+
+static const struct axp2xx_sensors axp209_sensors[] = {
+	{
+		.id = AXP209_ACVOLT,
+		.name = "acvolt",
+		.desc = "AC Voltage (microvolt)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP209_ADC1_ACVOLT,
+		.value_reg = AXP209_ACIN_VOLTAGE,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP209_VOLT_STEP,
+	},
+	{
+		.id = AXP209_ACCURRENT,
+		.name = "accurrent",
+		.desc = "AC Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP209_ADC1_ACCURRENT,
+		.value_reg = AXP209_ACIN_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP209_ACCURRENT_STEP,
+	},
+	{
+		.id = AXP209_VBUSVOLT,
+		.name = "vbusvolt",
+		.desc = "VBUS Voltage (microVolt)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP209_ADC1_VBUSVOLT,
+		.value_reg = AXP209_VBUS_VOLTAGE,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP209_VOLT_STEP,
+	},
+	{
+		.id = AXP209_VBUSCURRENT,
+		.name = "vbuscurrent",
+		.desc = "VBUS Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP209_ADC1_VBUSCURRENT,
+		.value_reg = AXP209_VBUS_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP209_VBUSCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_BATVOLT,
+		.name = "batvolt",
+		.desc = "Battery Voltage (microVolt)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATVOLT,
+		.value_reg = AXP2XX_BAT_VOLTAGE,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATVOLT_STEP,
+	},
+	{
+		.id = AXP2XX_BATCHARGECURRENT,
+		.name = "batchargecurrent",
+		.desc = "Battery Charging Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATCURRENT,
+		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 5,
+		.l_value_mask = 0x1f,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_BATDISCHARGECURRENT,
+		.name = "batdischargecurrent",
+		.desc = "Battery Discharging Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATCURRENT,
+		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 5,
+		.l_value_mask = 0x1f,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_TEMP,
+		.name = "temp",
+		.desc = "Internal Temperature",
+		.format = "IK",
+		.enable_reg = AXP209_ADC_ENABLE2,
+		.enable_mask = AXP209_ADC2_TEMP,
+		.value_reg = AXP209_TEMPMON,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = 1,
+		.value_convert = -(AXP209_TEMPMON_MIN - AXP209_0C_TO_K),
+	},
+};
+
+static const struct axp2xx_sensors axp221_sensors[] = {
+	{
+		.id = AXP2XX_BATVOLT,
+		.name = "batvolt",
+		.desc = "Battery Voltage (microVolt)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATVOLT,
+		.value_reg = AXP2XX_BAT_VOLTAGE,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATVOLT_STEP,
+	},
+	{
+		.id = AXP2XX_BATCHARGECURRENT,
+		.name = "batchargecurrent",
+		.desc = "Battery Charging Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATCURRENT,
+		.value_reg = AXP2XX_BAT_CHARGE_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 5,
+		.l_value_mask = 0x1f,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_BATDISCHARGECURRENT,
+		.name = "batdischargecurrent",
+		.desc = "Battery Discharging Current (microAmpere)",
+		.format = "I",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP2XX_ADC1_BATCURRENT,
+		.value_reg = AXP2XX_BAT_DISCHARGE_CURRENT,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 5,
+		.l_value_mask = 0x1f,
+		.l_value_shift = 0,
+		.value_step = AXP2XX_BATCURRENT_STEP,
+	},
+	{
+		.id = AXP2XX_TEMP,
+		.name = "temp",
+		.desc = "Internal Temperature",
+		.format = "IK",
+		.enable_reg = AXP2XX_ADC_ENABLE1,
+		.enable_mask = AXP221_ADC1_TEMP,
+		.value_reg = AXP221_TEMPMON,
+		.value_size = 2,
+		.h_value_mask = 0xff,
+		.h_value_shift = 4,
+		.l_value_mask = 0xf,
+		.l_value_shift = 0,
+		.value_step = 1,
+		.value_convert = -(AXP221_TEMPMON_MIN - AXP209_0C_TO_K),
+	},
+};
+
+enum AXP2XX_TYPE {
+	AXP209 = 1,
+	AXP221,
+};
+
+struct axp2xx_softc {
 	device_t		dev;
 	uint32_t		addr;
 	struct resource *	res[1];
 	void *			intrcookie;
 	struct intr_config_hook	intr_hook;
-	device_t		gpiodev;
 	struct mtx		mtx;
+	uint8_t			type;
+
+	/* GPIO */
+	device_t		gpiodev;
+	int			npins;
+	const struct axp2xx_pins	*pins;
+
+	/* Sensors */
+	const struct axp2xx_sensors	*sensors;
+	int				nsensors;
 
 	/* Regulators */
-	struct axp209_reg_sc	**regs;
+	struct axp2xx_reg_sc	**regs;
 	int			nregs;
+	struct axp2xx_regdef	*regdefs;
 };
 
-/* GPIO3 is different, don't expose it for now */
-static const struct {
-	const char *name;
-	uint8_t	ctrl_reg;
-} axp209_pins[] = {
-	{ "GPIO0", AXP209_GPIO0_CTRL },
-	{ "GPIO1", AXP209_GPIO1_CTRL },
-	{ "GPIO2", AXP209_GPIO2_CTRL },
+static struct ofw_compat_data compat_data[] = {
+	{ "x-powers,axp209",		AXP209 },
+	{ "x-powers,axp221",		AXP221 },
+	{ NULL,				0 }
 };
 
 static struct resource_spec axp_res_spec[] = {
@@ -170,9 +639,9 @@ static struct resource_spec axp_res_spec
 #define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
 
 static int
-axp209_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
+axp2xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
 {
-	struct axp209_softc *sc = device_get_softc(dev);
+	struct axp2xx_softc *sc = device_get_softc(dev);
 	struct iic_msg msg[2];
 
 	msg[0].slave = sc->addr;
@@ -189,43 +658,62 @@ axp209_read(device_t dev, uint8_t reg, u
 }
 
 static int
-axp209_write(device_t dev, uint8_t reg, uint8_t data)
+axp2xx_write(device_t dev, uint8_t reg, uint8_t data)
 {
 	uint8_t buffer[2];
-	struct axp209_softc *sc = device_get_softc(dev);
-	struct iic_msg msg;
+	struct axp2xx_softc *sc = device_get_softc(dev);
+	struct iic_msg msg[2];
+	int nmsgs = 0;
 
-	buffer[0] = reg;
-	buffer[1] = data;
+	if (sc->type == AXP209) {
+		buffer[0] = reg;
+		buffer[1] = data;
+
+		msg[0].slave = sc->addr;
+		msg[0].flags = IIC_M_WR;
+		msg[0].len = 2;
+		msg[0].buf = buffer;
 
-	msg.slave = sc->addr;
-	msg.flags = IIC_M_WR;
-	msg.len = 2;
-	msg.buf = buffer;
+		nmsgs = 1;
+	}
+	else if (sc->type == AXP221) {
+		msg[0].slave = sc->addr;
+		msg[0].flags = IIC_M_WR;
+		msg[0].len = 1;
+		msg[0].buf = ®
+
+		msg[1].slave = sc->addr;
+		msg[1].flags = IIC_M_WR;
+		msg[1].len = 1;
+		msg[1].buf = &data;
+		nmsgs = 2;
+	}
+	else
+		return (EINVAL);
 
-	return (iicbus_transfer(dev, &msg, 1));
+	return (iicbus_transfer(dev, msg, nmsgs));
 }
 
 static int
-axp209_regnode_init(struct regnode *regnode)
+axp2xx_regnode_init(struct regnode *regnode)
 {
 	return (0);
 }
 
 static int
-axp209_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
+axp2xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
 {
-	struct axp209_reg_sc *sc;
+	struct axp2xx_reg_sc *sc;
 	uint8_t val;
 
 	sc = regnode_get_softc(regnode);
 
-	axp209_read(sc->base_dev, sc->def->enable_reg, &val, 1);
+	axp2xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
 	if (enable)
 		val |= sc->def->enable_mask;
 	else
 		val &= ~sc->def->enable_mask;
-	axp209_write(sc->base_dev, sc->def->enable_reg, val);
+	axp2xx_write(sc->base_dev, sc->def->enable_reg, val);
 
 	*udelay = 0;
 
@@ -233,7 +721,7 @@ axp209_regnode_enable(struct regnode *re
 }
 
 static void
-axp209_regnode_reg_to_voltage(struct axp209_reg_sc *sc, uint8_t val, int *uv)
+axp2xx_regnode_reg_to_voltage(struct axp2xx_reg_sc *sc, uint8_t val, int *uv)
 {
 	if (val < sc->def->voltage_nstep)
 		*uv = sc->def->voltage_min + val * sc->def->voltage_step;
@@ -244,7 +732,7 @@ axp209_regnode_reg_to_voltage(struct axp
 }
 
 static int
-axp209_regnode_voltage_to_reg(struct axp209_reg_sc *sc, int min_uvolt,
+axp2xx_regnode_voltage_to_reg(struct axp2xx_reg_sc *sc, int min_uvolt,
     int max_uvolt, uint8_t *val)
 {
 	uint8_t nval;
@@ -266,10 +754,10 @@ axp209_regnode_voltage_to_reg(struct axp
 }
 
 static int
-axp209_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
+axp2xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
     int max_uvolt, int *udelay)
 {
-	struct axp209_reg_sc *sc;
+	struct axp2xx_reg_sc *sc;
 	uint8_t val;
 
 	sc = regnode_get_softc(regnode);
@@ -277,10 +765,10 @@ axp209_regnode_set_voltage(struct regnod
 	if (!sc->def->voltage_step)
 		return (ENXIO);
 
-	if (axp209_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
+	if (axp2xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
 		return (ERANGE);
 
-	axp209_write(sc->base_dev, sc->def->voltage_reg, val);
+	axp2xx_write(sc->base_dev, sc->def->voltage_reg, val);
 
 	*udelay = 0;
 
@@ -288,9 +776,9 @@ axp209_regnode_set_voltage(struct regnod
 }
 
 static int
-axp209_regnode_get_voltage(struct regnode *regnode, int *uvolt)
+axp2xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
 {
-	struct axp209_reg_sc *sc;
+	struct axp2xx_reg_sc *sc;
 	uint8_t val;
 
 	sc = regnode_get_softc(regnode);
@@ -298,106 +786,60 @@ axp209_regnode_get_voltage(struct regnod
 	if (!sc->def->voltage_step)
 		return (ENXIO);
 
-	axp209_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
-	axp209_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
+	axp2xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
+	axp2xx_regnode_reg_to_voltage(sc, val & sc->def->voltage_mask, uvolt);
 
 	return (0);
 }
 
-static regnode_method_t axp209_regnode_methods[] = {
+static regnode_method_t axp2xx_regnode_methods[] = {
 	/* Regulator interface */
-	REGNODEMETHOD(regnode_init,		axp209_regnode_init),
-	REGNODEMETHOD(regnode_enable,		axp209_regnode_enable),
-	REGNODEMETHOD(regnode_set_voltage,	axp209_regnode_set_voltage),
-	REGNODEMETHOD(regnode_get_voltage,	axp209_regnode_get_voltage),
+	REGNODEMETHOD(regnode_init,		axp2xx_regnode_init),
+	REGNODEMETHOD(regnode_enable,		axp2xx_regnode_enable),
+	REGNODEMETHOD(regnode_set_voltage,	axp2xx_regnode_set_voltage),
+	REGNODEMETHOD(regnode_get_voltage,	axp2xx_regnode_get_voltage),
 	REGNODEMETHOD_END
 };
-DEFINE_CLASS_1(axp209_regnode, axp209_regnode_class, axp209_regnode_methods,
-    sizeof(struct axp209_reg_sc), regnode_class);
+DEFINE_CLASS_1(axp2xx_regnode, axp2xx_regnode_class, axp2xx_regnode_methods,
+    sizeof(struct axp2xx_reg_sc), regnode_class);
 
 static int
-axp209_sysctl(SYSCTL_HANDLER_ARGS)
+axp2xx_sysctl(SYSCTL_HANDLER_ARGS)
 {
+	struct axp2xx_softc *sc;
 	device_t dev = arg1;
-	enum axp209_sensor sensor = arg2;
+	enum axp2xx_sensor sensor = arg2;
 	uint8_t data[2];
-	int val, error;
-
-	switch (sensor) {
-	case AXP209_TEMP:
-		error = axp209_read(dev, AXP209_TEMPMON, data, 2);
-		if (error != 0)
-			return (error);
-
-		/* Temperature is between -144.7C and 264.8C, step +0.1C */
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) -
-		    AXP209_TEMPMON_MIN + AXP209_0C_TO_K;
-		break;
-	case AXP209_ACVOLT:
-		error = axp209_read(dev, AXP209_ACIN_VOLTAGE, data, 2);
-		if (error != 0)
-			return (error);
+	int val, error, i, found;
 
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_VOLT_STEP;
-		break;
-	case AXP209_ACCURRENT:
-		error = axp209_read(dev, AXP209_ACIN_CURRENT, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_ACCURRENT_STEP;
-		break;
-	case AXP209_VBUSVOLT:
-		error = axp209_read(dev, AXP209_VBUS_VOLTAGE, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_VOLT_STEP;
-		break;
-	case AXP209_VBUSCURRENT:
-		error = axp209_read(dev, AXP209_VBUS_CURRENT, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_VBUSCURRENT_STEP;
-		break;
-	case AXP209_BATVOLT:
-		error = axp209_read(dev, AXP209_BAT_VOLTAGE, data, 2);
-		if (error != 0)
-			return (error);
-
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_BATVOLT_STEP;
-		break;
-	case AXP209_BATCHARGECURRENT:
-		error = axp209_read(dev, AXP209_BAT_CHARGE_CURRENT, data, 2);
-		if (error != 0)
-			return (error);
+	sc = device_get_softc(dev);
 
-		val = (AXP209_SENSOR_H(data[0]) | AXP209_SENSOR_L(data[1])) *
-		    AXP209_BATCURRENT_STEP;
-		break;
-	case AXP209_BATDISCHARGECURRENT:
-		error = axp209_read(dev, AXP209_BAT_DISCHARGE_CURRENT, data, 2);
-		if (error != 0)
-			return (error);
+	for (found = 0, i = 0; i < sc->nsensors; i++) {
+		if (sc->sensors[i].id == sensor) {
+			found = 1;
+			break;
+		}
+	}
 
-		val = (AXP209_SENSOR_BAT_H(data[0]) |
-		    AXP209_SENSOR_BAT_L(data[1])) * AXP209_BATCURRENT_STEP;
-		break;
-	default:
+	if (found == 0)
 		return (ENOENT);
-	}
+
+	error = axp2xx_read(dev, sc->sensors[i].value_reg, data, 2);
+	if (error != 0)
+		return (error);
+
+	val = ((data[0] & sc->sensors[i].h_value_mask) <<
+	    sc->sensors[i].h_value_shift);
+	val |= ((data[1] & sc->sensors[i].l_value_mask) <<
+	    sc->sensors[i].l_value_shift);
+	val *= sc->sensors[i].value_step;
+	val += sc->sensors[i].value_convert;
 
 	return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
 }
 
 static void
-axp209_shutdown(void *devp, int howto)
+axp2xx_shutdown(void *devp, int howto)
 {
 	device_t dev;
 
@@ -406,77 +848,77 @@ axp209_shutdown(void *devp, int howto)
 	dev = (device_t)devp;
 
 	if (bootverbose)
-		device_printf(dev, "Shutdown AXP209\n");
+		device_printf(dev, "Shutdown AXP2xx\n");
 
-	axp209_write(dev, AXP209_SHUTBAT, AXP209_SHUTBAT_SHUTDOWN);
+	axp2xx_write(dev, AXP2XX_SHUTBAT, AXP2XX_SHUTBAT_SHUTDOWN);
 }
 
 static void
-axp_intr(void *arg)
+axp2xx_intr(void *arg)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 	uint8_t reg;
 
 	sc = arg;
 
-	axp209_read(sc->dev, AXP209_IRQ1_STATUS, &reg, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ1_STATUS, &reg, 1);
 	if (reg) {
-		if (reg & AXP209_IRQ1_AC_OVERVOLT)
+		if (reg & AXP2XX_IRQ1_AC_OVERVOLT)
 			devctl_notify("PMU", "AC", "overvoltage", NULL);
-		if (reg & AXP209_IRQ1_VBUS_OVERVOLT)
+		if (reg & AXP2XX_IRQ1_VBUS_OVERVOLT)
 			devctl_notify("PMU", "USB", "overvoltage", NULL);
-		if (reg & AXP209_IRQ1_VBUS_LOW)
+		if (reg & AXP2XX_IRQ1_VBUS_LOW)
 			devctl_notify("PMU", "USB", "undervoltage", NULL);
-		if (reg & AXP209_IRQ1_AC_CONN)
+		if (reg & AXP2XX_IRQ1_AC_CONN)
 			devctl_notify("PMU", "AC", "plugged", NULL);
-		if (reg & AXP209_IRQ1_AC_DISCONN)
+		if (reg & AXP2XX_IRQ1_AC_DISCONN)
 			devctl_notify("PMU", "AC", "unplugged", NULL);
-		if (reg & AXP209_IRQ1_VBUS_CONN)
+		if (reg & AXP2XX_IRQ1_VBUS_CONN)
 			devctl_notify("PMU", "USB", "plugged", NULL);
-		if (reg & AXP209_IRQ1_VBUS_DISCONN)
+		if (reg & AXP2XX_IRQ1_VBUS_DISCONN)
 			devctl_notify("PMU", "USB", "unplugged", NULL);
-		axp209_write(sc->dev, AXP209_IRQ1_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ1_STATUS, AXP2XX_IRQ_ACK);
 	}
 
-	axp209_read(sc->dev, AXP209_IRQ2_STATUS, &reg, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ2_STATUS, &reg, 1);
 	if (reg) {
-		if (reg & AXP209_IRQ2_BATT_CHARGED)
+		if (reg & AXP2XX_IRQ2_BATT_CHARGED)
 			devctl_notify("PMU", "Battery", "charged", NULL);
-		if (reg & AXP209_IRQ2_BATT_CHARGING)
+		if (reg & AXP2XX_IRQ2_BATT_CHARGING)
 			devctl_notify("PMU", "Battery", "charging", NULL);
-		if (reg & AXP209_IRQ2_BATT_CONN)
+		if (reg & AXP2XX_IRQ2_BATT_CONN)
 			devctl_notify("PMU", "Battery", "connected", NULL);
-		if (reg & AXP209_IRQ2_BATT_DISCONN)
+		if (reg & AXP2XX_IRQ2_BATT_DISCONN)
 			devctl_notify("PMU", "Battery", "disconnected", NULL);
-		if (reg & AXP209_IRQ2_BATT_TEMP_LOW)
+		if (reg & AXP2XX_IRQ2_BATT_TEMP_LOW)
 			devctl_notify("PMU", "Battery", "low temp", NULL);
-		if (reg & AXP209_IRQ2_BATT_TEMP_OVER)
+		if (reg & AXP2XX_IRQ2_BATT_TEMP_OVER)
 			devctl_notify("PMU", "Battery", "high temp", NULL);
-		axp209_write(sc->dev, AXP209_IRQ2_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ2_STATUS, AXP2XX_IRQ_ACK);
 	}
 
-	axp209_read(sc->dev, AXP209_IRQ3_STATUS, &reg, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ3_STATUS, &reg, 1);
 	if (reg) {
-		if (reg & AXP209_IRQ3_PEK_SHORT)
+		if (reg & AXP2XX_IRQ3_PEK_SHORT)
 			shutdown_nice(RB_POWEROFF);
-		axp209_write(sc->dev, AXP209_IRQ3_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ3_STATUS, AXP2XX_IRQ_ACK);
 	}
 
-	axp209_read(sc->dev, AXP209_IRQ4_STATUS, &reg, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ4_STATUS, &reg, 1);
 	if (reg) {
-		axp209_write(sc->dev, AXP209_IRQ4_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ4_STATUS, AXP2XX_IRQ_ACK);
 	}
 
-	axp209_read(sc->dev, AXP209_IRQ5_STATUS, &reg, 1);
+	axp2xx_read(sc->dev, AXP2XX_IRQ5_STATUS, &reg, 1);
 	if (reg) {
-		axp209_write(sc->dev, AXP209_IRQ5_STATUS, AXP209_IRQ_ACK);
+		axp2xx_write(sc->dev, AXP2XX_IRQ5_STATUS, AXP2XX_IRQ_ACK);
 	}
 }
 
 static device_t
-axp209_gpio_get_bus(device_t dev)
+axp2xx_gpio_get_bus(device_t dev)
 {
-	struct axp209_softc *sc;
+	struct axp2xx_softc *sc;
 
 	sc = device_get_softc(dev);
 
@@ -484,17 +926,25 @@ axp209_gpio_get_bus(device_t dev)
 }
 
 static int
-axp209_gpio_pin_max(device_t dev, int *maxpin)
+axp2xx_gpio_pin_max(device_t dev, int *maxpin)
 {
-	*maxpin = nitems(axp209_pins) - 1;
+	struct axp2xx_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	*maxpin = sc->npins - 1;
 
 	return (0);
 }
 
 static int
-axp209_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+axp2xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
 {
-	if (pin >= nitems(axp209_pins))
+	struct axp2xx_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	if (pin >= sc->npins)
 		return (EINVAL);
 
 	snprintf(name, GPIOMAXNAME, "%s", axp209_pins[pin].name);
@@ -503,9 +953,13 @@ axp209_gpio_pin_getname(device_t dev, ui
 }
 
 static int
-axp209_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+axp2xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 {
-	if (pin >= nitems(axp209_pins))
+	struct axp2xx_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	if (pin >= sc->npins)
 		return (EINVAL);
 
 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
@@ -514,25 +968,25 @@ axp209_gpio_pin_getcaps(device_t dev, ui
 }
 
 static int
-axp209_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+axp2xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
 {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list