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 = &reg;
+
+               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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to