Author: manu
Date: Sat Mar  3 18:28:19 2018
New Revision: 330347
URL: https://svnweb.freebsd.org/changeset/base/330347

Log:
  axp81x: Add support for AXP803
  
  AXP803 and AXP813/818 are very similar, only two regulators differs.
  AXP803 is the companion chip for A64/R18
  AXP813 is the companion chip for A83T
  AXP818 is the companion chip for H8 (~A83T)
  Add support for all regulators found in both of them.

Modified:
  head/sys/arm/allwinner/axp81x.c

Modified: head/sys/arm/allwinner/axp81x.c
==============================================================================
--- head/sys/arm/allwinner/axp81x.c     Sat Mar  3 18:25:50 2018        
(r330346)
+++ head/sys/arm/allwinner/axp81x.c     Sat Mar  3 18:28:19 2018        
(r330347)
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Emmanuel Vadot <m...@freebsd.org>
  * Copyright (c) 2016 Jared McNeill <jmcne...@invisible.ca>
  * All rights reserved.
  *
@@ -27,7 +28,7 @@
  */
 
 /*
- * X-Powers AXP813/818 PMU for Allwinner SoCs
+ * X-Powers AXP803/813/818 PMU for Allwinner SoCs
  */
 
 #include <sys/cdefs.h>
@@ -58,14 +59,59 @@ __FBSDID("$FreeBSD$");
 #include "iicbus_if.h"
 #include "regdev_if.h"
 
-MALLOC_DEFINE(M_AXP81X_REG, "AXP81x regulator", "AXP81x power regulator");
+MALLOC_DEFINE(M_AXP8XX_REG, "AXP8xx regulator", "AXP8xx power regulator");
 
+#define        AXP_POWERSRC            0x00
+#define         AXP_POWERSRC_ACIN      (1 << 7)
+#define         AXP_POWERSRC_VBUS      (1 << 5)
+#define         AXP_POWERSRC_VBAT      (1 << 3)
+#define         AXP_POWERSRC_CHARING   (1 << 2)
+#define         AXP_POWERSRC_SHORTED   (1 << 1)
+#define         AXP_POWERSRC_STARTUP   (1 << 0)
 #define        AXP_ICTYPE              0x03
 #define        AXP_POWERCTL1           0x10
+#define         AXP_POWERCTL1_DCDC7    (1 << 6)        /* AXP813/818 only */
+#define         AXP_POWERCTL1_DCDC6    (1 << 5)
+#define         AXP_POWERCTL1_DCDC5    (1 << 4)
+#define         AXP_POWERCTL1_DCDC4    (1 << 3)
+#define         AXP_POWERCTL1_DCDC3    (1 << 2)
 #define         AXP_POWERCTL1_DCDC2    (1 << 1)
+#define         AXP_POWERCTL1_DCDC1    (1 << 0)
 #define        AXP_POWERCTL2           0x12
-#define         AXP_POWERCTL2_DC1SW    (1 << 7)
+#define         AXP_POWERCTL2_DC1SW    (1 << 7)        /* AXP803 only */
+#define         AXP_POWERCTL2_DLDO4    (1 << 6)
+#define         AXP_POWERCTL2_DLDO3    (1 << 5)
+#define         AXP_POWERCTL2_DLDO2    (1 << 4)
+#define         AXP_POWERCTL2_DLDO1    (1 << 3)
+#define         AXP_POWERCTL2_ELDO3    (1 << 2)
+#define         AXP_POWERCTL2_ELDO2    (1 << 1)
+#define         AXP_POWERCTL2_ELDO1    (1 << 0)
+#define        AXP_POWERCTL3           0x13
+#define         AXP_POWERCTL3_ALDO3    (1 << 7)
+#define         AXP_POWERCTL3_ALDO2    (1 << 6)
+#define         AXP_POWERCTL3_ALDO1    (1 << 5)
+#define         AXP_POWERCTL3_FLDO3    (1 << 4)        /* AXP813/818 only */
+#define         AXP_POWERCTL3_FLDO2    (1 << 3)
+#define         AXP_POWERCTL3_FLDO1    (1 << 2)
+#define        AXP_VOLTCTL_DLDO1       0x15
+#define        AXP_VOLTCTL_DLDO2       0x16
+#define        AXP_VOLTCTL_DLDO3       0x17
+#define        AXP_VOLTCTL_DLDO4       0x18
+#define        AXP_VOLTCTL_ELDO1       0x19
+#define        AXP_VOLTCTL_ELDO2       0x1A
+#define        AXP_VOLTCTL_ELDO3       0x1B
+#define        AXP_VOLTCTL_FLDO1       0x1C
+#define        AXP_VOLTCTL_FLDO2       0x1D
+#define        AXP_VOLTCTL_DCDC1       0x20
 #define        AXP_VOLTCTL_DCDC2       0x21
+#define        AXP_VOLTCTL_DCDC3       0x22
+#define        AXP_VOLTCTL_DCDC4       0x23
+#define        AXP_VOLTCTL_DCDC5       0x24
+#define        AXP_VOLTCTL_DCDC6       0x25
+#define        AXP_VOLTCTL_DCDC7       0x26
+#define        AXP_VOLTCTL_ALDO1       0x28
+#define        AXP_VOLTCTL_ALDO2       0x29
+#define        AXP_VOLTCTL_ALDO3       0x2A
 #define         AXP_VOLTCTL_STATUS     (1 << 7)
 #define         AXP_VOLTCTL_MASK       0x7f
 #define        AXP_POWERBAT            0x32
@@ -92,23 +138,29 @@ MALLOC_DEFINE(M_AXP81X_REG, "AXP81x regulator", "AXP81
 static const struct {
        const char *name;
        uint8_t ctrl_reg;
-} axp81x_pins[] = {
+} axp8xx_pins[] = {
        { "GPIO0", AXP_GPIO0_CTRL },
        { "GPIO1", AXP_GPIO1_CTRL },
 };
 
+enum AXP8XX_TYPE {
+       AXP803 = 1,
+       AXP813,
+};
+
 static struct ofw_compat_data compat_data[] = {
-       { "x-powers,axp813",                    1 },
-       { "x-powers,axp818",                    1 },
+       { "x-powers,axp803",                    AXP803 },
+       { "x-powers,axp813",                    AXP813 },
+       { "x-powers,axp818",                    AXP813 },
        { NULL,                                 0 }
 };
 
-static struct resource_spec axp81x_spec[] = {
+static struct resource_spec axp8xx_spec[] = {
        { SYS_RES_IRQ,          0,      RF_ACTIVE },
        { -1, 0 }
 };
 
-struct axp81x_regdef {
+struct axp8xx_regdef {
        intptr_t                id;
        char                    *name;
        char                    *supply_name;
@@ -123,20 +175,69 @@ struct axp81x_regdef {
        int                     voltage_nstep2;
 };
 
-enum axp81x_reg_id {
-       AXP81X_REG_ID_DC1SW,
-       AXP81X_REG_ID_DCDC2,
+enum axp8xx_reg_id {
+       AXP8XX_REG_ID_DCDC1 = 100,
+       AXP8XX_REG_ID_DCDC2,
+       AXP8XX_REG_ID_DCDC3,
+       AXP8XX_REG_ID_DCDC4,
+       AXP8XX_REG_ID_DCDC5,
+       AXP8XX_REG_ID_DCDC6,
+       AXP813_REG_ID_DCDC7,
+       AXP803_REG_ID_DC1SW,
+       AXP8XX_REG_ID_DLDO1,
+       AXP8XX_REG_ID_DLDO2,
+       AXP8XX_REG_ID_DLDO3,
+       AXP8XX_REG_ID_DLDO4,
+       AXP8XX_REG_ID_ELDO1,
+       AXP8XX_REG_ID_ELDO2,
+       AXP8XX_REG_ID_ELDO3,
+       AXP8XX_REG_ID_ALDO1,
+       AXP8XX_REG_ID_ALDO2,
+       AXP8XX_REG_ID_ALDO3,
+       AXP8XX_REG_ID_FLDO1,
+       AXP8XX_REG_ID_FLDO2,
+       AXP813_REG_ID_FLDO3,
 };
 
-static struct axp81x_regdef axp81x_regdefs[] = {
+static struct axp8xx_regdef axp803_regdefs[] = {
        {
-               .id = AXP81X_REG_ID_DC1SW,
+               .id = AXP803_REG_ID_DC1SW,
                .name = "dc1sw",
                .enable_reg = AXP_POWERCTL2,
                .enable_mask = AXP_POWERCTL2_DC1SW,
        },
+};
+
+static struct axp8xx_regdef axp813_regdefs[] = {
        {
-               .id = AXP81X_REG_ID_DCDC2,
+               .id = AXP813_REG_ID_DCDC7,
+               .name = "dcdc7",
+               .enable_reg = AXP_POWERCTL1,
+               .enable_mask = AXP_POWERCTL1_DCDC7,
+               .voltage_reg = AXP_VOLTCTL_DCDC7,
+               .voltage_min = 600,
+               .voltage_max = 1520,
+               .voltage_step1 = 10,
+               .voltage_nstep1 = 50,
+               .voltage_step2 = 20,
+               .voltage_nstep2 = 21,
+       },
+};
+
+static struct axp8xx_regdef axp8xx_common_regdefs[] = {
+       {
+               .id = AXP8XX_REG_ID_DCDC1,
+               .name = "dcdc1",
+               .enable_reg = AXP_POWERCTL1,
+               .enable_mask = AXP_POWERCTL1_DCDC1,
+               .voltage_reg = AXP_VOLTCTL_DCDC1,
+               .voltage_min = 1600,
+               .voltage_max = 3400,
+               .voltage_step1 = 100,
+               .voltage_nstep1 = 18,
+       },
+       {
+               .id = AXP8XX_REG_ID_DCDC2,
                .name = "dcdc2",
                .enable_reg = AXP_POWERCTL1,
                .enable_mask = AXP_POWERCTL1_DCDC2,
@@ -148,19 +249,197 @@ static struct axp81x_regdef axp81x_regdefs[] = {
                .voltage_step2 = 20,
                .voltage_nstep2 = 5,
        },
+       {
+               .id = AXP8XX_REG_ID_DCDC3,
+               .name = "dcdc3",
+               .enable_reg = AXP_POWERCTL1,
+               .enable_mask = AXP_POWERCTL1_DCDC3,
+               .voltage_reg = AXP_VOLTCTL_DCDC3,
+               .voltage_min = 500,
+               .voltage_max = 1300,
+               .voltage_step1 = 10,
+               .voltage_nstep1 = 70,
+               .voltage_step2 = 20,
+               .voltage_nstep2 = 5,
+       },
+       {
+               .id = AXP8XX_REG_ID_DCDC4,
+               .name = "dcdc4",
+               .enable_reg = AXP_POWERCTL1,
+               .enable_mask = AXP_POWERCTL1_DCDC4,
+               .voltage_reg = AXP_VOLTCTL_DCDC4,
+               .voltage_min = 500,
+               .voltage_max = 1300,
+               .voltage_step1 = 10,
+               .voltage_nstep1 = 70,
+               .voltage_step2 = 20,
+               .voltage_nstep2 = 5,
+       },
+       {
+               .id = AXP8XX_REG_ID_DCDC5,
+               .name = "dcdc5",
+               .enable_reg = AXP_POWERCTL1,
+               .enable_mask = AXP_POWERCTL1_DCDC5,
+               .voltage_reg = AXP_VOLTCTL_DCDC5,
+               .voltage_min = 800,
+               .voltage_max = 1840,
+               .voltage_step1 = 10,
+               .voltage_nstep1 = 42,
+               .voltage_step2 = 20,
+               .voltage_nstep2 = 36,
+       },
+       {
+               .id = AXP8XX_REG_ID_DCDC6,
+               .name = "dcdc6",
+               .enable_reg = AXP_POWERCTL1,
+               .enable_mask = AXP_POWERCTL1_DCDC6,
+               .voltage_reg = AXP_VOLTCTL_DCDC6,
+               .voltage_min = 600,
+               .voltage_max = 1520,
+               .voltage_step1 = 10,
+               .voltage_nstep1 = 50,
+               .voltage_step2 = 20,
+               .voltage_nstep2 = 21,
+       },
+       {
+               .id = AXP8XX_REG_ID_DLDO1,
+               .name = "dldo1",
+               .enable_reg = AXP_POWERCTL2,
+               .enable_mask = AXP_POWERCTL2_DLDO1,
+               .voltage_reg = AXP_VOLTCTL_DLDO1,
+               .voltage_min = 700,
+               .voltage_max = 3300,
+               .voltage_step1 = 100,
+               .voltage_nstep1 = 26,
+       },
+       {
+               .id = AXP8XX_REG_ID_DLDO2,
+               .name = "dldo2",
+               .enable_reg = AXP_POWERCTL2,
+               .enable_mask = AXP_POWERCTL2_DLDO2,
+               .voltage_reg = AXP_VOLTCTL_DLDO2,
+               .voltage_min = 700,
+               .voltage_max = 4200,
+               .voltage_step1 = 100,
+               .voltage_nstep1 = 27,
+               .voltage_step2 = 200,
+               .voltage_nstep2 = 4,
+       },
+       {
+               .id = AXP8XX_REG_ID_DLDO3,
+               .name = "dldo3",
+               .enable_reg = AXP_POWERCTL2,
+               .enable_mask = AXP_POWERCTL2_DLDO3,
+               .voltage_reg = AXP_VOLTCTL_DLDO3,
+               .voltage_min = 700,
+               .voltage_max = 3300,
+               .voltage_step1 = 100,
+               .voltage_nstep1 = 26,
+       },
+       {
+               .id = AXP8XX_REG_ID_DLDO4,
+               .name = "dldo4",
+               .enable_reg = AXP_POWERCTL2,
+               .enable_mask = AXP_POWERCTL2_DLDO4,
+               .voltage_reg = AXP_VOLTCTL_DLDO4,
+               .voltage_min = 700,
+               .voltage_max = 3300,
+               .voltage_step1 = 100,
+               .voltage_nstep1 = 26,
+       },
+       {
+               .id = AXP8XX_REG_ID_ALDO1,
+               .name = "aldo1",
+               .enable_reg = AXP_POWERCTL3,
+               .enable_mask = AXP_POWERCTL3_ALDO1,
+               .voltage_min = 700,
+               .voltage_max = 3300,
+               .voltage_step1 = 100,
+               .voltage_nstep1 = 26,
+       },
+       {
+               .id = AXP8XX_REG_ID_ALDO2,
+               .name = "aldo2",
+               .enable_reg = AXP_POWERCTL3,
+               .enable_mask = AXP_POWERCTL3_ALDO2,
+               .voltage_min = 700,
+               .voltage_max = 3300,
+               .voltage_step1 = 100,
+               .voltage_nstep1 = 26,
+       },
+       {
+               .id = AXP8XX_REG_ID_ALDO3,
+               .name = "aldo3",
+               .enable_reg = AXP_POWERCTL3,
+               .enable_mask = AXP_POWERCTL3_ALDO3,
+               .voltage_min = 700,
+               .voltage_max = 3300,
+               .voltage_step1 = 100,
+               .voltage_nstep1 = 26,
+       },
+       {
+               .id = AXP8XX_REG_ID_ELDO1,
+               .name = "eldo1",
+               .enable_reg = AXP_POWERCTL2,
+               .enable_mask = AXP_POWERCTL2_ELDO1,
+               .voltage_min = 700,
+               .voltage_max = 1900,
+               .voltage_step1 = 50,
+               .voltage_nstep1 = 24,
+       },
+       {
+               .id = AXP8XX_REG_ID_ELDO2,
+               .name = "eldo2",
+               .enable_reg = AXP_POWERCTL2,
+               .enable_mask = AXP_POWERCTL2_ELDO2,
+               .voltage_min = 700,
+               .voltage_max = 1900,
+               .voltage_step1 = 50,
+               .voltage_nstep1 = 24,
+       },
+       {
+               .id = AXP8XX_REG_ID_ELDO3,
+               .name = "eldo3",
+               .enable_reg = AXP_POWERCTL2,
+               .enable_mask = AXP_POWERCTL2_ELDO3,
+               .voltage_min = 700,
+               .voltage_max = 1900,
+               .voltage_step1 = 50,
+               .voltage_nstep1 = 24,
+       },
+       {
+               .id = AXP8XX_REG_ID_FLDO1,
+               .name = "fldo1",
+               .enable_reg = AXP_POWERCTL3,
+               .enable_mask = AXP_POWERCTL3_FLDO1,
+               .voltage_min = 700,
+               .voltage_max = 1450,
+               .voltage_step1 = 50,
+               .voltage_nstep1 = 15,
+       },
+       {
+               .id = AXP8XX_REG_ID_FLDO2,
+               .name = "fldo2",
+               .enable_reg = AXP_POWERCTL3,
+               .enable_mask = AXP_POWERCTL3_FLDO2,
+               .voltage_min = 700,
+               .voltage_max = 1450,
+               .voltage_step1 = 50,
+               .voltage_nstep1 = 15,
+       },
 };
 
-struct axp81x_softc;
+struct axp8xx_softc;
 
-struct axp81x_reg_sc {
+struct axp8xx_reg_sc {
        struct regnode          *regnode;
        device_t                base_dev;
-       struct axp81x_regdef    *def;
+       struct axp8xx_regdef    *def;
        phandle_t               xref;
        struct regnode_std_param *param;
 };
 
-struct axp81x_softc {
+struct axp8xx_softc {
        struct resource         *res;
        uint16_t                addr;
        void                    *ih;
@@ -168,8 +447,10 @@ struct axp81x_softc {
        struct mtx              mtx;
        int                     busy;
 
+       int                     type;
+
        /* Regulators */
-       struct axp81x_reg_sc    **regs;
+       struct axp8xx_reg_sc    **regs;
        int                     nregs;
 };
 
@@ -177,9 +458,9 @@ struct axp81x_softc {
 #define        AXP_UNLOCK(sc)  mtx_unlock(&(sc)->mtx)
 
 static int
-axp81x_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
+axp8xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
 {
-       struct axp81x_softc *sc;
+       struct axp8xx_softc *sc;
        struct iic_msg msg[2];
 
        sc = device_get_softc(dev);
@@ -198,9 +479,9 @@ axp81x_read(device_t dev, uint8_t reg, uint8_t *data, 
 }
 
 static int
-axp81x_write(device_t dev, uint8_t reg, uint8_t val)
+axp8xx_write(device_t dev, uint8_t reg, uint8_t val)
 {
-       struct axp81x_softc *sc;
+       struct axp8xx_softc *sc;
        struct iic_msg msg[2];
 
        sc = device_get_softc(dev);
@@ -219,25 +500,31 @@ axp81x_write(device_t dev, uint8_t reg, uint8_t val)
 }
 
 static int
-axp81x_regnode_init(struct regnode *regnode)
+axp8xx_regnode_init(struct regnode *regnode)
 {
        return (0);
 }
 
 static int
-axp81x_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
+axp8xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
 {
-       struct axp81x_reg_sc *sc;
+       struct axp8xx_reg_sc *sc;
        uint8_t val;
 
        sc = regnode_get_softc(regnode);
 
-       axp81x_read(sc->base_dev, sc->def->enable_reg, &val, 1);
+       if (bootverbose)
+               device_printf(sc->base_dev, "%sable %s (%s)\n",
+                   enable ? "En" : "Dis",
+                   regnode_get_name(regnode),
+                   sc->def->name);
+
+       axp8xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
        if (enable)
                val |= sc->def->enable_mask;
        else
                val &= ~sc->def->enable_mask;
-       axp81x_write(sc->base_dev, sc->def->enable_reg, val);
+       axp8xx_write(sc->base_dev, sc->def->enable_reg, val);
 
        *udelay = 0;
 
@@ -245,7 +532,7 @@ axp81x_regnode_enable(struct regnode *regnode, bool en
 }
 
 static void
-axp81x_regnode_reg_to_voltage(struct axp81x_reg_sc *sc, uint8_t val, int *uv)
+axp8xx_regnode_reg_to_voltage(struct axp8xx_reg_sc *sc, uint8_t val, int *uv)
 {
        if (val < sc->def->voltage_nstep1)
                *uv = sc->def->voltage_min + val * sc->def->voltage_step1;
@@ -257,7 +544,7 @@ axp81x_regnode_reg_to_voltage(struct axp81x_reg_sc *sc
 }
 
 static int
-axp81x_regnode_voltage_to_reg(struct axp81x_reg_sc *sc, int min_uvolt,
+axp8xx_regnode_voltage_to_reg(struct axp8xx_reg_sc *sc, int min_uvolt,
     int max_uvolt, uint8_t *val)
 {
        uint8_t nval;
@@ -284,21 +571,27 @@ axp81x_regnode_voltage_to_reg(struct axp81x_reg_sc *sc
 }
 
 static int
-axp81x_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
+axp8xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
     int max_uvolt, int *udelay)
 {
-       struct axp81x_reg_sc *sc;
+       struct axp8xx_reg_sc *sc;
        uint8_t val;
 
        sc = regnode_get_softc(regnode);
 
-       if (!sc->def->voltage_step1 || !sc->def->voltage_step2)
+       if (bootverbose)
+               device_printf(sc->base_dev, "Setting %s (%s) to %d<->%d\n",
+                   regnode_get_name(regnode),
+                   sc->def->name,
+                   min_uvolt, max_uvolt);
+
+       if (sc->def->voltage_step1 == 0)
                return (ENXIO);
 
-       if (axp81x_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
+       if (axp8xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
                return (ERANGE);
 
-       axp81x_write(sc->base_dev, sc->def->voltage_reg, val);
+       axp8xx_write(sc->base_dev, sc->def->voltage_reg, val);
 
        *udelay = 0;
 
@@ -306,9 +599,9 @@ axp81x_regnode_set_voltage(struct regnode *regnode, in
 }
 
 static int
-axp81x_regnode_get_voltage(struct regnode *regnode, int *uvolt)
+axp8xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
 {
-       struct axp81x_reg_sc *sc;
+       struct axp8xx_reg_sc *sc;
        uint8_t val;
 
        sc = regnode_get_softc(regnode);
@@ -316,25 +609,25 @@ axp81x_regnode_get_voltage(struct regnode *regnode, in
        if (!sc->def->voltage_step1 || !sc->def->voltage_step2)
                return (ENXIO);
 
-       axp81x_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
-       axp81x_regnode_reg_to_voltage(sc, val & AXP_VOLTCTL_MASK, uvolt);
+       axp8xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
+       axp8xx_regnode_reg_to_voltage(sc, val & AXP_VOLTCTL_MASK, uvolt);
 
        return (0);
 }
 
-static regnode_method_t axp81x_regnode_methods[] = {
+static regnode_method_t axp8xx_regnode_methods[] = {
        /* Regulator interface */
-       REGNODEMETHOD(regnode_init,             axp81x_regnode_init),
-       REGNODEMETHOD(regnode_enable,           axp81x_regnode_enable),
-       REGNODEMETHOD(regnode_set_voltage,      axp81x_regnode_set_voltage),
-       REGNODEMETHOD(regnode_get_voltage,      axp81x_regnode_get_voltage),
+       REGNODEMETHOD(regnode_init,             axp8xx_regnode_init),
+       REGNODEMETHOD(regnode_enable,           axp8xx_regnode_enable),
+       REGNODEMETHOD(regnode_set_voltage,      axp8xx_regnode_set_voltage),
+       REGNODEMETHOD(regnode_get_voltage,      axp8xx_regnode_get_voltage),
        REGNODEMETHOD_END
 };
-DEFINE_CLASS_1(axp81x_regnode, axp81x_regnode_class, axp81x_regnode_methods,
-    sizeof(struct axp81x_reg_sc), regnode_class);
+DEFINE_CLASS_1(axp8xx_regnode, axp8xx_regnode_class, axp8xx_regnode_methods,
+    sizeof(struct axp8xx_reg_sc), regnode_class);
 
 static void
-axp81x_shutdown(void *devp, int howto)
+axp8xx_shutdown(void *devp, int howto)
 {
        device_t dev;
 
@@ -344,13 +637,13 @@ axp81x_shutdown(void *devp, int howto)
        dev = devp;
 
        if (bootverbose)
-               device_printf(dev, "Shutdown AXP81x\n");
+               device_printf(dev, "Shutdown Axp8xx\n");
 
-       axp81x_write(dev, AXP_POWERBAT, AXP_POWERBAT_SHUTDOWN);
+       axp8xx_write(dev, AXP_POWERBAT, AXP_POWERBAT_SHUTDOWN);
 }
 
 static void
-axp81x_intr(void *arg)
+axp8xx_intr(void *arg)
 {
        device_t dev;
        uint8_t val;
@@ -358,7 +651,7 @@ axp81x_intr(void *arg)
 
        dev = arg;
 
-       error = axp81x_read(dev, AXP_IRQSTAT5, &val, 1);
+       error = axp8xx_read(dev, AXP_IRQSTAT5, &val, 1);
        if (error != 0)
                return;
 
@@ -369,14 +662,14 @@ axp81x_intr(void *arg)
                        shutdown_nice(RB_POWEROFF);
                }
                /* Acknowledge */
-               axp81x_write(dev, AXP_IRQSTAT5, val);
+               axp8xx_write(dev, AXP_IRQSTAT5, val);
        }
 }
 
 static device_t
-axp81x_gpio_get_bus(device_t dev)
+axp8xx_gpio_get_bus(device_t dev)
 {
-       struct axp81x_softc *sc;
+       struct axp8xx_softc *sc;
 
        sc = device_get_softc(dev);
 
@@ -384,28 +677,28 @@ axp81x_gpio_get_bus(device_t dev)
 }
 
 static int
-axp81x_gpio_pin_max(device_t dev, int *maxpin)
+axp8xx_gpio_pin_max(device_t dev, int *maxpin)
 {
-       *maxpin = nitems(axp81x_pins) - 1;
+       *maxpin = nitems(axp8xx_pins) - 1;
 
        return (0);
 }
 
 static int
-axp81x_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+axp8xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
 {
-       if (pin >= nitems(axp81x_pins))
+       if (pin >= nitems(axp8xx_pins))
                return (EINVAL);
 
-       snprintf(name, GPIOMAXNAME, "%s", axp81x_pins[pin].name);
+       snprintf(name, GPIOMAXNAME, "%s", axp8xx_pins[pin].name);
 
        return (0);
 }
 
 static int
-axp81x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+axp8xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 {
-       if (pin >= nitems(axp81x_pins))
+       if (pin >= nitems(axp8xx_pins))
                return (EINVAL);
 
        *caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
@@ -414,19 +707,19 @@ axp81x_gpio_pin_getcaps(device_t dev, uint32_t pin, ui
 }
 
 static int
-axp81x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+axp8xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
 {
-       struct axp81x_softc *sc;
+       struct axp8xx_softc *sc;
        uint8_t data, func;
        int error;
 
-       if (pin >= nitems(axp81x_pins))
+       if (pin >= nitems(axp8xx_pins))
                return (EINVAL);
 
        sc = device_get_softc(dev);
 
        AXP_LOCK(sc);
-       error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+       error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
        if (error == 0) {
                func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
                if (func == AXP_GPIO_FUNC_INPUT)
@@ -443,26 +736,26 @@ axp81x_gpio_pin_getflags(device_t dev, uint32_t pin, u
 }
 
 static int
-axp81x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+axp8xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
 {
-       struct axp81x_softc *sc;
+       struct axp8xx_softc *sc;
        uint8_t data;
        int error;
 
-       if (pin >= nitems(axp81x_pins))
+       if (pin >= nitems(axp8xx_pins))
                return (EINVAL);
 
        sc = device_get_softc(dev);
 
        AXP_LOCK(sc);
-       error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+       error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
        if (error == 0) {
                data &= ~AXP_GPIO_FUNC;
                if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
                        if ((flags & GPIO_PIN_OUTPUT) == 0)
                                data |= AXP_GPIO_FUNC_INPUT;
                }
-               error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
+               error = axp8xx_write(dev, axp8xx_pins[pin].ctrl_reg, data);
        }
        AXP_UNLOCK(sc);
 
@@ -470,19 +763,19 @@ axp81x_gpio_pin_setflags(device_t dev, uint32_t pin, u
 }
 
 static int
-axp81x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+axp8xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
 {
-       struct axp81x_softc *sc;
+       struct axp8xx_softc *sc;
        uint8_t data, func;
        int error;
 
-       if (pin >= nitems(axp81x_pins))
+       if (pin >= nitems(axp8xx_pins))
                return (EINVAL);
 
        sc = device_get_softc(dev);
 
        AXP_LOCK(sc);
-       error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+       error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
        if (error == 0) {
                func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
                switch (func) {
@@ -493,7 +786,7 @@ axp81x_gpio_pin_get(device_t dev, uint32_t pin, unsign
                        *val = 1;
                        break;
                case AXP_GPIO_FUNC_INPUT:
-                       error = axp81x_read(dev, AXP_GPIO_SIGBIT, &data, 1);
+                       error = axp8xx_read(dev, AXP_GPIO_SIGBIT, &data, 1);
                        if (error == 0)
                                *val = (data & (1 << pin)) ? 1 : 0;
                        break;
@@ -508,19 +801,19 @@ axp81x_gpio_pin_get(device_t dev, uint32_t pin, unsign
 }
 
 static int
-axp81x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
+axp8xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
 {
-       struct axp81x_softc *sc;
+       struct axp8xx_softc *sc;
        uint8_t data, func;
        int error;
 
-       if (pin >= nitems(axp81x_pins))
+       if (pin >= nitems(axp8xx_pins))
                return (EINVAL);
 
        sc = device_get_softc(dev);
 
        AXP_LOCK(sc);
-       error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+       error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
        if (error == 0) {
                func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
                switch (func) {
@@ -535,7 +828,7 @@ axp81x_gpio_pin_set(device_t dev, uint32_t pin, unsign
                }
        }
        if (error == 0)
-               error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
+               error = axp8xx_write(dev, axp8xx_pins[pin].ctrl_reg, data);
        AXP_UNLOCK(sc);
 
        return (error);
@@ -543,19 +836,19 @@ axp81x_gpio_pin_set(device_t dev, uint32_t pin, unsign
 
 
 static int
-axp81x_gpio_pin_toggle(device_t dev, uint32_t pin)
+axp8xx_gpio_pin_toggle(device_t dev, uint32_t pin)
 {
-       struct axp81x_softc *sc;
+       struct axp8xx_softc *sc;
        uint8_t data, func;
        int error;
 
-       if (pin >= nitems(axp81x_pins))
+       if (pin >= nitems(axp8xx_pins))
                return (EINVAL);
 
        sc = device_get_softc(dev);
 
        AXP_LOCK(sc);
-       error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+       error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
        if (error == 0) {
                func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
                switch (func) {
@@ -573,17 +866,17 @@ axp81x_gpio_pin_toggle(device_t dev, uint32_t pin)
                }
        }
        if (error == 0)
-               error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
+               error = axp8xx_write(dev, axp8xx_pins[pin].ctrl_reg, data);
        AXP_UNLOCK(sc);
 
        return (error);
 }
 
 static int
-axp81x_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
+axp8xx_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
 {
-       if (gpios[0] >= nitems(axp81x_pins))
+       if (gpios[0] >= nitems(axp8xx_pins))
                return (EINVAL);
 
        *pin = gpios[0];
@@ -593,16 +886,16 @@ axp81x_gpio_map_gpios(device_t bus, phandle_t dev, pha
 }
 
 static phandle_t
-axp81x_get_node(device_t dev, device_t bus)
+axp8xx_get_node(device_t dev, device_t bus)
 {
        return (ofw_bus_get_node(dev));
 }
 
-static struct axp81x_reg_sc *
-axp81x_reg_attach(device_t dev, phandle_t node,
-    struct axp81x_regdef *def)
+static struct axp8xx_reg_sc *
+axp8xx_reg_attach(device_t dev, phandle_t node,
+    struct axp8xx_regdef *def)
 {
-       struct axp81x_reg_sc *reg_sc;
+       struct axp8xx_reg_sc *reg_sc;
        struct regnode_init_def initdef;
        struct regnode *regnode;
 
@@ -614,7 +907,7 @@ axp81x_reg_attach(device_t dev, phandle_t node,
                initdef.std_param.max_uvolt = def->voltage_max * 1000;
        initdef.id = def->id;
        initdef.ofw_node = node;
-       regnode = regnode_create(dev, &axp81x_regnode_class, &initdef);
+       regnode = regnode_create(dev, &axp8xx_regnode_class, &initdef);
        if (regnode == NULL) {
                device_printf(dev, "cannot create regulator\n");
                return (NULL);
@@ -633,10 +926,10 @@ axp81x_reg_attach(device_t dev, phandle_t node,
 }
 
 static int
-axp81x_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
+axp8xx_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
     intptr_t *num)
 {
-       struct axp81x_softc *sc;
+       struct axp8xx_softc *sc;
        int i;
 
        sc = device_get_softc(dev);
@@ -653,24 +946,31 @@ axp81x_regdev_map(device_t dev, phandle_t xref, int nc
 }
 
 static int
-axp81x_probe(device_t dev)
+axp8xx_probe(device_t dev)
 {
        if (!ofw_bus_status_okay(dev))
                return (ENXIO);
 
-       if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+       switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+       {
+       case AXP803:
+               device_set_desc(dev, "X-Powers AXP803 Power Management Unit");
+               break;
+       case AXP813:
+               device_set_desc(dev, "X-Powers AXP813 Power Management Unit");
+               break;
+       default:
                return (ENXIO);
+       }
 
-       device_set_desc(dev, "X-Powers AXP81x Power Management Unit");
-
        return (BUS_PROBE_DEFAULT);
 }
 
 static int
-axp81x_attach(device_t dev)
+axp8xx_attach(device_t dev)
 {
-       struct axp81x_softc *sc;
-       struct axp81x_reg_sc *reg;
+       struct axp8xx_softc *sc;
+       struct axp8xx_reg_sc *reg;
        uint8_t chip_id;
        phandle_t rnode, child;
        int error, i;
@@ -680,34 +980,65 @@ axp81x_attach(device_t dev)
        sc->addr = iicbus_get_addr(dev);
        mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
 
-       error = bus_alloc_resources(dev, axp81x_spec, &sc->res);
+       error = bus_alloc_resources(dev, axp8xx_spec, &sc->res);
        if (error != 0) {
                device_printf(dev, "cannot allocate resources for device\n");
                return (error);
        }
 
        if (bootverbose) {
-               axp81x_read(dev, AXP_ICTYPE, &chip_id, 1);
+               axp8xx_read(dev, AXP_ICTYPE, &chip_id, 1);
                device_printf(dev, "chip ID 0x%02x\n", chip_id);
        }
 
-       sc->nregs = nitems(axp81x_regdefs);
-       sc->regs = malloc(sizeof(struct axp81x_reg_sc *) * sc->nregs,
-           M_AXP81X_REG, M_WAITOK | M_ZERO);
+       sc->nregs = nitems(axp8xx_common_regdefs);
+       sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+       switch (sc->type) {
+       case AXP803:
+               sc->nregs += nitems(axp803_regdefs);
+               break;
+       case AXP813:
+               sc->nregs += nitems(axp813_regdefs);
+               break;
+       }
+       sc->regs = malloc(sizeof(struct axp8xx_reg_sc *) * sc->nregs,
+           M_AXP8XX_REG, M_WAITOK | M_ZERO);
 
        /* Attach known regulators that exist in the DT */
        rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators");
        if (rnode > 0) {
                for (i = 0; i < sc->nregs; i++) {
+                       char *regname;
+                       struct axp8xx_regdef *regdef;
+
+                       if (i <= nitems(axp8xx_common_regdefs)) {
+                               regname = axp8xx_common_regdefs[i].name;
+                               regdef = &axp8xx_common_regdefs[i];
+                       } else {
+                               int off;
+
+                               off = i - nitems(axp8xx_common_regdefs);
+                               switch (sc->type) {
+                               case AXP803:
+                                       regname = axp803_regdefs[off].name;
+                                       regdef = &axp803_regdefs[off];
+                                       break;
+                               case AXP813:
+                                       regname = axp813_regdefs[off].name;
+                                       regdef = &axp813_regdefs[off];
+                                       break;
+                               }
+                       }
                        child = ofw_bus_find_child(rnode,
-                           axp81x_regdefs[i].name);
+                           regname);
                        if (child == 0)
                                continue;
-                       reg = axp81x_reg_attach(dev, child, &axp81x_regdefs[i]);
+                       reg = axp8xx_reg_attach(dev, child,
+                           regdef);
                        if (reg == NULL) {
                                device_printf(dev,
                                    "cannot attach regulator %s\n",
-                                   axp81x_regdefs[i].name);
+                                   regname);
                                return (ENXIO);
                        }
                        sc->regs[i] = reg;
@@ -715,22 +1046,22 @@ axp81x_attach(device_t dev)
        }
 
        /* Enable IRQ on short power key press */
-       axp81x_write(dev, AXP_IRQEN1, 0);
-       axp81x_write(dev, AXP_IRQEN2, 0);
-       axp81x_write(dev, AXP_IRQEN3, 0);
-       axp81x_write(dev, AXP_IRQEN4, 0);
-       axp81x_write(dev, AXP_IRQEN5, AXP_IRQEN5_POKSIRQ);
-       axp81x_write(dev, AXP_IRQEN6, 0);
+       axp8xx_write(dev, AXP_IRQEN1, 0);
+       axp8xx_write(dev, AXP_IRQEN2, 0);
+       axp8xx_write(dev, AXP_IRQEN3, 0);
+       axp8xx_write(dev, AXP_IRQEN4, 0);
+       axp8xx_write(dev, AXP_IRQEN5, AXP_IRQEN5_POKSIRQ);
+       axp8xx_write(dev, AXP_IRQEN6, 0);
 
        /* Install interrupt handler */
        error = bus_setup_intr(dev, sc->res, INTR_TYPE_MISC | INTR_MPSAFE,
-           NULL, axp81x_intr, dev, &sc->ih);
+           NULL, axp8xx_intr, dev, &sc->ih);
        if (error != 0) {
                device_printf(dev, "cannot setup interrupt handler\n");
                return (error);
        }
 
-       EVENTHANDLER_REGISTER(shutdown_final, axp81x_shutdown, dev,
+       EVENTHANDLER_REGISTER(shutdown_final, axp8xx_shutdown, dev,
            SHUTDOWN_PRI_LAST);
 
        sc->gpiodev = gpiobus_attach_bus(dev);
@@ -738,46 +1069,46 @@ axp81x_attach(device_t dev)

*** 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