Author: manu
Date: Fri Aug 16 21:40:39 2019
New Revision: 351149
URL: https://svnweb.freebsd.org/changeset/base/351149

Log:
  MFC r343952, r344003, r344219, r344343, r344456
  
  r343952 by ganbold:
  Enable necessary bits when activating interrupts. This allows
  reading some events from the interrupt status registers. These events
  are reported to devd via system "PMU" and subsystem "Battery", "AC"
  and "USB" such as plugged/unplugged, absent, charged and charging.
  
  Reviewed by:  manu
  Differential Revision:        https://reviews.freebsd.org/D19116
  
  r344003 by ganbold:
  Add sensors support for AXP803/AXP813. Sensor values such as
  battery charging, charge state, voltage, charging current, discharging 
current,
  battery capacity etc. can be obtained via sysctl.
  
  Reviewed by:  manu
  Differential Revision:        https://reviews.freebsd.org/D19145
  
  r344219 by ganbold:
  Add sysctl for setting battery charging current.
  The charging current can be set using steps
  from 0: 200mA to 13: 2800mA (200mA/step).
  While there, fix battery charging current related
  sensor descriptions.
  
  Reviewed by:  manu
  Differential Revision:        https://reviews.freebsd.org/D19212
  
  r344343 by ganbold:
  Clarify notifications when battery capacity ratio
  reaches warning and shutdown thresholds.
  
  r344456 by ganbold:
  Add base to the warning threshold.

Modified:
  stable/12/sys/arm/allwinner/axp81x.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/arm/allwinner/axp81x.c
==============================================================================
--- stable/12/sys/arm/allwinner/axp81x.c        Fri Aug 16 21:36:13 2019        
(r351148)
+++ stable/12/sys/arm/allwinner/axp81x.c        Fri Aug 16 21:40:39 2019        
(r351149)
@@ -65,9 +65,13 @@ MALLOC_DEFINE(M_AXP8XX_REG, "AXP8xx regulator", "AXP8x
 #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_CHARING   (1 << 2)        /* Charging Direction */
 #define         AXP_POWERSRC_SHORTED   (1 << 1)
 #define         AXP_POWERSRC_STARTUP   (1 << 0)
+#define        AXP_POWERMODE           0x01
+#define         AXP_POWERMODE_BAT_CHARGING     (1 << 6)
+#define         AXP_POWERMODE_BAT_PRESENT      (1 << 5)
+#define         AXP_POWERMODE_BAT_VALID        (1 << 4)
 #define        AXP_ICTYPE              0x03
 #define        AXP_POWERCTL1           0x10
 #define         AXP_POWERCTL1_DCDC7    (1 << 6)        /* AXP813/818 only */
@@ -116,15 +120,52 @@ MALLOC_DEFINE(M_AXP8XX_REG, "AXP8xx regulator", "AXP8x
 #define         AXP_VOLTCTL_MASK       0x7f
 #define        AXP_POWERBAT            0x32
 #define         AXP_POWERBAT_SHUTDOWN  (1 << 7)
+#define        AXP_CHARGERCTL1         0x33
+#define         AXP_CHARGERCTL1_MIN    0
+#define         AXP_CHARGERCTL1_MAX    13
+#define         AXP_CHARGERCTL1_CMASK  0xf
 #define        AXP_IRQEN1              0x40
+#define         AXP_IRQEN1_ACIN_HI     (1 << 6)
+#define         AXP_IRQEN1_ACIN_LO     (1 << 5)
+#define         AXP_IRQEN1_VBUS_HI     (1 << 3)
+#define         AXP_IRQEN1_VBUS_LO     (1 << 2)
 #define        AXP_IRQEN2              0x41
+#define         AXP_IRQEN2_BAT_IN      (1 << 7)
+#define         AXP_IRQEN2_BAT_NO      (1 << 6)
+#define         AXP_IRQEN2_BATCHGC     (1 << 3)
+#define         AXP_IRQEN2_BATCHGD     (1 << 2)
 #define        AXP_IRQEN3              0x42
 #define        AXP_IRQEN4              0x43
+#define         AXP_IRQEN4_BATLVL_LO1  (1 << 1)
+#define         AXP_IRQEN4_BATLVL_LO0  (1 << 0)
 #define        AXP_IRQEN5              0x44
 #define         AXP_IRQEN5_POKSIRQ     (1 << 4)
+#define         AXP_IRQEN5_POKLIRQ     (1 << 3)
 #define        AXP_IRQEN6              0x45
+#define        AXP_IRQSTAT1            0x48
+#define         AXP_IRQSTAT1_ACIN_HI   (1 << 6)
+#define         AXP_IRQSTAT1_ACIN_LO   (1 << 5)
+#define         AXP_IRQSTAT1_VBUS_HI   (1 << 3)
+#define         AXP_IRQSTAT1_VBUS_LO   (1 << 2)
+#define        AXP_IRQSTAT2            0x49
+#define         AXP_IRQSTAT2_BAT_IN    (1 << 7)
+#define         AXP_IRQSTAT2_BAT_NO    (1 << 6)
+#define         AXP_IRQSTAT2_BATCHGC   (1 << 3)
+#define         AXP_IRQSTAT2_BATCHGD   (1 << 2)
+#define        AXP_IRQSTAT3            0x4a
+#define        AXP_IRQSTAT4            0x4b
+#define         AXP_IRQSTAT4_BATLVL_LO1        (1 << 1)
+#define         AXP_IRQSTAT4_BATLVL_LO0        (1 << 0)
 #define        AXP_IRQSTAT5            0x4c
 #define         AXP_IRQSTAT5_POKSIRQ   (1 << 4)
+#define         AXP_IRQEN5_POKLIRQ     (1 << 3)
+#define        AXP_IRQSTAT6            0x4d
+#define        AXP_BATSENSE_HI         0x78
+#define        AXP_BATSENSE_LO         0x79
+#define        AXP_BATCHG_HI           0x7a
+#define        AXP_BATCHG_LO           0x7b
+#define        AXP_BATDISCHG_HI        0x7c
+#define        AXP_BATDISCHG_LO        0x7d
 #define        AXP_GPIO0_CTRL          0x90
 #define        AXP_GPIO0LDO_CTRL       0x91
 #define        AXP_GPIO1_CTRL          0x92
@@ -138,7 +179,31 @@ MALLOC_DEFINE(M_AXP8XX_REG, "AXP8xx regulator", "AXP8x
 #define         AXP_GPIO_FUNC_LDO_OFF  4
 #define        AXP_GPIO_SIGBIT         0x94
 #define        AXP_GPIO_PD             0x97
+#define        AXP_FUEL_GAUGECTL       0xb8
+#define         AXP_FUEL_GAUGECTL_EN   (1 << 7)
 
+#define        AXP_BAT_CAP             0xb9
+#define         AXP_BAT_CAP_VALID      (1 << 7)
+#define         AXP_BAT_CAP_PERCENT    0x7f
+
+#define        AXP_BAT_MAX_CAP_HI      0xe0
+#define         AXP_BAT_MAX_CAP_VALID  (1 << 7)
+#define        AXP_BAT_MAX_CAP_LO      0xe1
+
+#define        AXP_BAT_COULOMB_HI      0xe2
+#define         AXP_BAT_COULOMB_VALID  (1 << 7)
+#define        AXP_BAT_COULOMB_LO      0xe3
+
+#define        AXP_BAT_CAP_WARN        0xe6
+#define         AXP_BAT_CAP_WARN_LV1           0xf0    /* Bits 4, 5, 6, 7 */
+#define         AXP_BAP_CAP_WARN_LV1BASE       5       /* 5-20%, 1% per step */
+#define         AXP_BAT_CAP_WARN_LV2           0xf     /* Bits 0, 1, 2, 3 */
+
+/* Sensor conversion macros */
+#define        AXP_SENSOR_BAT_H(hi)            ((hi) << 4)
+#define        AXP_SENSOR_BAT_L(lo)            ((lo) & 0xf)
+#define        AXP_SENSOR_COULOMB(hi, lo)      (((hi & ~(1 << 7)) << 8) | (lo))
+
 static const struct {
        const char *name;
        uint8_t ctrl_reg;
@@ -483,6 +548,123 @@ static struct axp8xx_regdef axp8xx_common_regdefs[] = 
        },
 };
 
+enum axp8xx_sensor {
+       AXP_SENSOR_ACIN_PRESENT,
+       AXP_SENSOR_VBUS_PRESENT,
+       AXP_SENSOR_BATT_PRESENT,
+       AXP_SENSOR_BATT_CHARGING,
+       AXP_SENSOR_BATT_CHARGE_STATE,
+       AXP_SENSOR_BATT_VOLTAGE,
+       AXP_SENSOR_BATT_CHARGE_CURRENT,
+       AXP_SENSOR_BATT_DISCHARGE_CURRENT,
+       AXP_SENSOR_BATT_CAPACITY_PERCENT,
+       AXP_SENSOR_BATT_MAXIMUM_CAPACITY,
+       AXP_SENSOR_BATT_CURRENT_CAPACITY,
+};
+
+enum battery_capacity_state {
+       BATT_CAPACITY_NORMAL = 1,       /* normal cap in battery */
+       BATT_CAPACITY_WARNING,          /* warning cap in battery */
+       BATT_CAPACITY_CRITICAL,         /* critical cap in battery */
+       BATT_CAPACITY_HIGH,             /* high cap in battery */
+       BATT_CAPACITY_MAX,              /* maximum cap in battery */
+       BATT_CAPACITY_LOW               /* low cap in battery */
+};
+
+struct axp8xx_sensors {
+       int             id;
+       const char      *name;
+       const char      *desc;
+       const char      *format;
+};
+
+static const struct axp8xx_sensors axp8xx_common_sensors[] = {
+       {
+               .id = AXP_SENSOR_ACIN_PRESENT,
+               .name = "acin",
+               .format = "I",
+               .desc = "ACIN Present",
+       },
+       {
+               .id = AXP_SENSOR_VBUS_PRESENT,
+               .name = "vbus",
+               .format = "I",
+               .desc = "VBUS Present",
+       },
+       {
+               .id = AXP_SENSOR_BATT_PRESENT,
+               .name = "bat",
+               .format = "I",
+               .desc = "Battery Present",
+       },
+       {
+               .id = AXP_SENSOR_BATT_CHARGING,
+               .name = "batcharging",
+               .format = "I",
+               .desc = "Battery Charging",
+       },
+       {
+               .id = AXP_SENSOR_BATT_CHARGE_STATE,
+               .name = "batchargestate",
+               .format = "I",
+               .desc = "Battery Charge State",
+       },
+       {
+               .id = AXP_SENSOR_BATT_VOLTAGE,
+               .name = "batvolt",
+               .format = "I",
+               .desc = "Battery Voltage",
+       },
+       {
+               .id = AXP_SENSOR_BATT_CHARGE_CURRENT,
+               .name = "batchargecurrent",
+               .format = "I",
+               .desc = "Average Battery Charging Current",
+       },
+       {
+               .id = AXP_SENSOR_BATT_DISCHARGE_CURRENT,
+               .name = "batdischargecurrent",
+               .format = "I",
+               .desc = "Average Battery Discharging Current",
+       },
+       {
+               .id = AXP_SENSOR_BATT_CAPACITY_PERCENT,
+               .name = "batcapacitypercent",
+               .format = "I",
+               .desc = "Battery Capacity Percentage",
+       },
+       {
+               .id = AXP_SENSOR_BATT_MAXIMUM_CAPACITY,
+               .name = "batmaxcapacity",
+               .format = "I",
+               .desc = "Battery Maximum Capacity",
+       },
+       {
+               .id = AXP_SENSOR_BATT_CURRENT_CAPACITY,
+               .name = "batcurrentcapacity",
+               .format = "I",
+               .desc = "Battery Current Capacity",
+       },
+};
+
+struct axp8xx_config {
+       const char              *name;
+       int                     batsense_step;  /* uV */
+       int                     charge_step;    /* uA */
+       int                     discharge_step; /* uA */
+       int                     maxcap_step;    /* uAh */
+       int                     coulomb_step;   /* uAh */
+};
+
+static struct axp8xx_config axp803_config = {
+       .name = "AXP803",
+       .batsense_step = 1100,
+       .charge_step = 1000,
+       .discharge_step = 1000,
+       .maxcap_step = 1456,
+       .coulomb_step = 1456,
+};
+
 struct axp8xx_softc;
 
 struct axp8xx_reg_sc {
@@ -503,9 +685,20 @@ struct axp8xx_softc {
 
        int                     type;
 
+       /* Configs */
+       const struct axp8xx_config      *config;
+
+       /* Sensors */
+       const struct axp8xx_sensors     *sensors;
+       int                             nsensors;
+
        /* Regulators */
        struct axp8xx_reg_sc    **regs;
        int                     nregs;
+
+       /* Warning, shutdown thresholds */
+       int                     warn_thres;
+       int                     shut_thres;
 };
 
 #define        AXP_LOCK(sc)    mtx_lock(&(sc)->mtx)
@@ -701,6 +894,137 @@ axp8xx_shutdown(void *devp, int howto)
        axp8xx_write(dev, AXP_POWERBAT, AXP_POWERBAT_SHUTDOWN);
 }
 
+static int
+axp8xx_sysctl_chargecurrent(SYSCTL_HANDLER_ARGS)
+{
+       device_t dev = arg1;
+       uint8_t data;
+       int val, error;
+
+       error = axp8xx_read(dev, AXP_CHARGERCTL1, &data, 1);
+       if (error != 0)
+               return (error);
+
+       if (bootverbose)
+               device_printf(dev, "Raw CHARGECTL1 val: 0x%0x\n", data);
+       val = (data & AXP_CHARGERCTL1_CMASK);
+       error = sysctl_handle_int(oidp, &val, 0, req);
+       if (error || !req->newptr) /* error || read request */
+               return (error);
+
+       if ((val < AXP_CHARGERCTL1_MIN) || (val > AXP_CHARGERCTL1_MAX))
+               return (EINVAL);
+
+       val |= (data & (AXP_CHARGERCTL1_CMASK << 4));
+       axp8xx_write(dev, AXP_CHARGERCTL1, val);
+
+       return (0);
+}
+
+static int
+axp8xx_sysctl(SYSCTL_HANDLER_ARGS)
+{
+       struct axp8xx_softc *sc;
+       device_t dev = arg1;
+       enum axp8xx_sensor sensor = arg2;
+       const struct axp8xx_config *c;
+       uint8_t data;
+       int val, i, found, batt_val;
+       uint8_t lo, hi;
+
+       sc = device_get_softc(dev);
+       c = sc->config;
+
+       for (found = 0, i = 0; i < sc->nsensors; i++) {
+               if (sc->sensors[i].id == sensor) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found == 0)
+               return (ENOENT);
+
+       switch (sensor) {
+       case AXP_SENSOR_ACIN_PRESENT:
+               if (axp8xx_read(dev, AXP_POWERSRC, &data, 1) == 0)
+                       val = !!(data & AXP_POWERSRC_ACIN);
+               break;
+       case AXP_SENSOR_VBUS_PRESENT:
+               if (axp8xx_read(dev, AXP_POWERSRC, &data, 1) == 0)
+                       val = !!(data & AXP_POWERSRC_VBUS);
+               break;
+       case AXP_SENSOR_BATT_PRESENT:
+               if (axp8xx_read(dev, AXP_POWERMODE, &data, 1) == 0) {
+                       if (data & AXP_POWERMODE_BAT_VALID)
+                               val = !!(data & AXP_POWERMODE_BAT_PRESENT);
+               }
+               break;
+       case AXP_SENSOR_BATT_CHARGING:
+               if (axp8xx_read(dev, AXP_POWERMODE, &data, 1) == 0)
+                       val = !!(data & AXP_POWERMODE_BAT_CHARGING);
+               break;
+       case AXP_SENSOR_BATT_CHARGE_STATE:
+               if (axp8xx_read(dev, AXP_BAT_CAP, &data, 1) == 0 &&
+                   (data & AXP_BAT_CAP_VALID) != 0) {
+                       batt_val = (data & AXP_BAT_CAP_PERCENT);
+                       if (batt_val <= sc->shut_thres)
+                               val = BATT_CAPACITY_CRITICAL;
+                       else if (batt_val <= sc->warn_thres)
+                               val = BATT_CAPACITY_WARNING;
+                       else
+                               val = BATT_CAPACITY_NORMAL;
+               }
+               break;
+       case AXP_SENSOR_BATT_CAPACITY_PERCENT:
+               if (axp8xx_read(dev, AXP_BAT_CAP, &data, 1) == 0 &&
+                   (data & AXP_BAT_CAP_VALID) != 0)
+                       val = (data & AXP_BAT_CAP_PERCENT);
+               break;
+       case AXP_SENSOR_BATT_VOLTAGE:
+               if (axp8xx_read(dev, AXP_BATSENSE_HI, &hi, 1) == 0 &&
+                   axp8xx_read(dev, AXP_BATSENSE_LO, &lo, 1) == 0) {
+                       val = (AXP_SENSOR_BAT_H(hi) | AXP_SENSOR_BAT_L(lo));
+                       val *= c->batsense_step;
+               }
+               break;
+       case AXP_SENSOR_BATT_CHARGE_CURRENT:
+               if (axp8xx_read(dev, AXP_POWERSRC, &data, 1) == 0 &&
+                   (data & AXP_POWERSRC_CHARING) != 0 &&
+                   axp8xx_read(dev, AXP_BATCHG_HI, &hi, 1) == 0 &&
+                   axp8xx_read(dev, AXP_BATCHG_LO, &lo, 1) == 0) {
+                       val = (AXP_SENSOR_BAT_H(hi) | AXP_SENSOR_BAT_L(lo));
+                       val *= c->charge_step;
+               }
+               break;
+       case AXP_SENSOR_BATT_DISCHARGE_CURRENT:
+               if (axp8xx_read(dev, AXP_POWERSRC, &data, 1) == 0 &&
+                   (data & AXP_POWERSRC_CHARING) == 0 &&
+                   axp8xx_read(dev, AXP_BATDISCHG_HI, &hi, 1) == 0 &&
+                   axp8xx_read(dev, AXP_BATDISCHG_LO, &lo, 1) == 0) {
+                       val = (AXP_SENSOR_BAT_H(hi) | AXP_SENSOR_BAT_L(lo));
+                       val *= c->discharge_step;
+               }
+               break;
+       case AXP_SENSOR_BATT_MAXIMUM_CAPACITY:
+               if (axp8xx_read(dev, AXP_BAT_MAX_CAP_HI, &hi, 1) == 0 &&
+                   axp8xx_read(dev, AXP_BAT_MAX_CAP_LO, &lo, 1) == 0) {
+                       val = AXP_SENSOR_COULOMB(hi, lo);
+                       val *= c->maxcap_step;
+               }
+               break;
+       case AXP_SENSOR_BATT_CURRENT_CAPACITY:
+               if (axp8xx_read(dev, AXP_BAT_COULOMB_HI, &hi, 1) == 0 &&
+                   axp8xx_read(dev, AXP_BAT_COULOMB_LO, &lo, 1) == 0) {
+                       val = AXP_SENSOR_COULOMB(hi, lo);
+                       val *= c->coulomb_step;
+               }
+               break;
+       }
+
+       return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
+}
+
 static void
 axp8xx_intr(void *arg)
 {
@@ -710,6 +1034,68 @@ axp8xx_intr(void *arg)
 
        dev = arg;
 
+       error = axp8xx_read(dev, AXP_IRQSTAT1, &val, 1);
+       if (error != 0)
+               return;
+
+       if (val) {
+               if (bootverbose)
+                       device_printf(dev, "AXP_IRQSTAT1 val: %x\n", val);
+               if (val & AXP_IRQSTAT1_ACIN_HI)
+                       devctl_notify("PMU", "AC", "plugged", NULL);
+               if (val & AXP_IRQSTAT1_ACIN_LO)
+                       devctl_notify("PMU", "AC", "unplugged", NULL);
+               if (val & AXP_IRQSTAT1_VBUS_HI)
+                       devctl_notify("PMU", "USB", "plugged", NULL);
+               if (val & AXP_IRQSTAT1_VBUS_LO)
+                       devctl_notify("PMU", "USB", "unplugged", NULL);
+               /* Acknowledge */
+               axp8xx_write(dev, AXP_IRQSTAT1, val);
+       }
+
+       error = axp8xx_read(dev, AXP_IRQSTAT2, &val, 1);
+       if (error != 0)
+               return;
+
+       if (val) {
+               if (bootverbose)
+                       device_printf(dev, "AXP_IRQSTAT2 val: %x\n", val);
+               if (val & AXP_IRQSTAT2_BATCHGD)
+                       devctl_notify("PMU", "Battery", "charged", NULL);
+               if (val & AXP_IRQSTAT2_BATCHGC)
+                       devctl_notify("PMU", "Battery", "charging", NULL);
+               if (val & AXP_IRQSTAT2_BAT_NO)
+                       devctl_notify("PMU", "Battery", "absent", NULL);
+               if (val & AXP_IRQSTAT2_BAT_IN)
+                       devctl_notify("PMU", "Battery", "plugged", NULL);
+               /* Acknowledge */
+               axp8xx_write(dev, AXP_IRQSTAT2, val);
+       }
+
+       error = axp8xx_read(dev, AXP_IRQSTAT3, &val, 1);
+       if (error != 0)
+               return;
+
+       if (val) {
+               /* Acknowledge */
+               axp8xx_write(dev, AXP_IRQSTAT3, val);
+       }
+
+       error = axp8xx_read(dev, AXP_IRQSTAT4, &val, 1);
+       if (error != 0)
+               return;
+
+       if (val) {
+               if (bootverbose)
+                       device_printf(dev, "AXP_IRQSTAT4 val: %x\n", val);
+               if (val & AXP_IRQSTAT4_BATLVL_LO0)
+                       devctl_notify("PMU", "Battery", "shutdown threshold", 
NULL);
+               if (val & AXP_IRQSTAT4_BATLVL_LO1)
+                       devctl_notify("PMU", "Battery", "warning threshold", 
NULL);
+               /* Acknowledge */
+               axp8xx_write(dev, AXP_IRQSTAT4, val);
+       }
+
        error = axp8xx_read(dev, AXP_IRQSTAT5, &val, 1);
        if (error != 0)
                return;
@@ -723,6 +1109,15 @@ axp8xx_intr(void *arg)
                /* Acknowledge */
                axp8xx_write(dev, AXP_IRQSTAT5, val);
        }
+
+       error = axp8xx_read(dev, AXP_IRQSTAT6, &val, 1);
+       if (error != 0)
+               return;
+
+       if (val) {
+               /* Acknowledge */
+               axp8xx_write(dev, AXP_IRQSTAT6, val);
+       }
 }
 
 static device_t
@@ -1031,7 +1426,7 @@ axp8xx_attach(device_t dev)
 {
        struct axp8xx_softc *sc;
        struct axp8xx_reg_sc *reg;
-       uint8_t chip_id;
+       uint8_t chip_id, val;
        phandle_t rnode, child;
        int error, i;
 
@@ -1061,6 +1456,10 @@ axp8xx_attach(device_t dev)
                sc->nregs += nitems(axp813_regdefs);
                break;
        }
+       sc->config = &axp803_config;
+       sc->sensors = axp8xx_common_sensors;
+       sc->nsensors = nitems(axp8xx_common_sensors);
+
        sc->regs = malloc(sizeof(struct axp8xx_reg_sc *) * sc->nregs,
            M_AXP8XX_REG, M_WAITOK | M_ZERO);
 
@@ -1105,12 +1504,60 @@ axp8xx_attach(device_t dev)
                }
        }
 
-       /* Enable IRQ on short power key press */
-       axp8xx_write(dev, AXP_IRQEN1, 0);
-       axp8xx_write(dev, AXP_IRQEN2, 0);
+       /* Add sensors */
+       for (i = 0; i < sc->nsensors; i++) {
+               SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+                   SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+                   OID_AUTO, sc->sensors[i].name,
+                   CTLTYPE_INT | CTLFLAG_RD,
+                   dev, sc->sensors[i].id, axp8xx_sysctl,
+                   sc->sensors[i].format,
+                   sc->sensors[i].desc);
+       }
+       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+           OID_AUTO, "batchargecurrentstep",
+           CTLTYPE_INT | CTLFLAG_RW,
+           dev, 0, axp8xx_sysctl_chargecurrent,
+           "I", "Battery Charging Current Step, "
+           "0: 200mA, 1: 400mA, 2: 600mA, 3: 800mA, "
+           "4: 1000mA, 5: 1200mA, 6: 1400mA, 7: 1600mA, "
+           "8: 1800mA, 9: 2000mA, 10: 2200mA, 11: 2400mA, "
+           "12: 2600mA, 13: 2800mA");
+
+       /* Get thresholds */
+       if (axp8xx_read(dev, AXP_BAT_CAP_WARN, &val, 1) == 0) {
+               sc->warn_thres = (val & AXP_BAT_CAP_WARN_LV1) >> 4;
+               sc->warn_thres += AXP_BAP_CAP_WARN_LV1BASE;
+               sc->shut_thres = (val & AXP_BAT_CAP_WARN_LV2);
+               if (bootverbose) {
+                       device_printf(dev,
+                           "Raw reg val: 0x%02x\n", val);
+                       device_printf(dev,
+                           "Warning threshold: 0x%02x\n", sc->warn_thres);
+                       device_printf(dev,
+                           "Shutdown threshold: 0x%02x\n", sc->shut_thres);
+               }
+       }
+
+       /* Enable interrupts */
+       axp8xx_write(dev, AXP_IRQEN1,
+           AXP_IRQEN1_VBUS_LO |
+           AXP_IRQEN1_VBUS_HI |
+           AXP_IRQEN1_ACIN_LO |
+           AXP_IRQEN1_ACIN_HI);
+       axp8xx_write(dev, AXP_IRQEN2,
+           AXP_IRQEN2_BATCHGD |
+           AXP_IRQEN2_BATCHGC |
+           AXP_IRQEN2_BAT_NO |
+           AXP_IRQEN2_BAT_IN);
        axp8xx_write(dev, AXP_IRQEN3, 0);
-       axp8xx_write(dev, AXP_IRQEN4, 0);
-       axp8xx_write(dev, AXP_IRQEN5, AXP_IRQEN5_POKSIRQ);
+       axp8xx_write(dev, AXP_IRQEN4,
+           AXP_IRQEN4_BATLVL_LO0 |
+           AXP_IRQEN4_BATLVL_LO1);
+       axp8xx_write(dev, AXP_IRQEN5,
+           AXP_IRQEN5_POKSIRQ |
+           AXP_IRQEN5_POKLIRQ);
        axp8xx_write(dev, AXP_IRQEN6, 0);
 
        /* Install interrupt handler */
_______________________________________________
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