Hi,
I'm trying to improve Pinebook experience on OpenBSD. I added a few more
sensors to axppmic 803.
I have two boards I tested this patch on:
- Pinebook: axppmic0 at sxirsb0 addr 0x3a3: AXP803
$ sysctl hw.sensors.axppmic0
hw.sensors.axppmic0.temp0=42.55 degC
hw.sensors.axppmic0.volt0=3.85 VDC (battery voltage)
hw.sensors.axppmic0.current0=0.00 A (battery charging current)
hw.sensors.axppmic0.current1=0.98 A (battery discharging current)
hw.sensors.axppmic0.amphour0=0.00 Ah (battery maximum capacity), WARNING
hw.sensors.axppmic0.amphour1=0.00 Ah (battery current capacity), WARNING
hw.sensors.axppmic0.indicator0=Off (ACIN)
hw.sensors.axppmic0.indicator1=Off (VBUS)
hw.sensors.axppmic0.indicator2=On (battery present), OK
hw.sensors.axppmic0.indicator3=Off (battery charging)
hw.sensors.axppmic0.percent0=74.00% (battery percent), OK
- A64+: axppmic0 at sxirsb0 addr 0x3a3: AXP803
$ sysctl hw.sensors.axppmic0
hw.sensors.axppmic0.temp0=49.14 degC
hw.sensors.axppmic0.volt0=0.00 VDC (battery voltage)
hw.sensors.axppmic0.current0=0.00 A (battery charging current)
hw.sensors.axppmic0.current1=0.00 A (battery discharging current)
hw.sensors.axppmic0.amphour0=0.00 Ah (battery maximum capacity), WARNING
hw.sensors.axppmic0.amphour1=0.00 Ah (battery current capacity), WARNING
hw.sensors.axppmic0.indicator0=On (ACIN), OK
hw.sensors.axppmic0.indicator1=Off (VBUS)
hw.sensors.axppmic0.indicator2=Off (battery present)
hw.sensors.axppmic0.indicator3=Off (battery charging)
hw.sensors.axppmic0.percent0=100.00% (battery percent), WARNING
Unfortunately, I wasn't able to test hw.sensors.axppmic0.amphours.
WARNING is presented when specific bit for given field marks the value as
invalid - this follow existing implementation.
And hw.sensors.axppmic0.percent0 also sets WARN and CRIT when "warn" and
"shut" thresholds are met.
--
Krystian
Index: sys/dev/fdt/axppmic.c
===================================================================
RCS file: /cvs/src/sys/dev/fdt/axppmic.c,v
retrieving revision 1.6
diff -u -p -r1.6 axppmic.c
--- sys/dev/fdt/axppmic.c 10 Feb 2018 22:32:01 -0000 1.6
+++ sys/dev/fdt/axppmic.c 8 Aug 2019 13:46:17 -0000
@@ -36,6 +36,15 @@ extern void (*powerdownfn)(void);
#define AXP209_ADC_EN1_ACIN (3 << 4)
#define AXP209_ADC_EN1_VBUS (3 << 2)
+#define AXP803_BAT_CAP_WARN 0xe6
+#define AXP803_BAT_CAP_WARN_LV1 0xf0
+#define AXP803_BAT_CAP_WARN_LV1BASE 5
+#define AXP803_BAT_CAP_WARN_LV2 0x0f
+#define AXP803_BAT_MAX_CAP 0xe0
+#define AXP803_BAT_CUR_CAP 0xe2
+#define AXP803_BAT_CAP_VALID (1 << 7)
+#define AXP803_BAT_CAP 0xb9
+
#define AXP806_REG_ADDR_EXT 0xff
#define AXP806_REG_ADDR_EXT_MASTER_MODE (0 << 4)
#define AXP806_REG_ADDR_EXT_SLAVE_MODE (1 << 4)
@@ -225,7 +234,7 @@ struct axppmic_regdata axp809_regdata[]
/* Sensors for AXP209 and AXP221/AXP809. */
-#define AXPPMIC_NSENSORS 8
+#define AXPPMIC_NSENSORS 12
struct axppmic_sensdata {
const char *name;
@@ -256,6 +265,14 @@ struct axppmic_sensdata axp221_sensdata[
struct axppmic_sensdata axp803_sensdata[] = {
{ "ACIN", SENSOR_INDICATOR, 0x00, (1 << 7), (1 << 6) },
{ "VBUS", SENSOR_INDICATOR, 0x00, (1 << 5), (1 << 4) },
+ { "battery present", SENSOR_INDICATOR, 0x01, (1 << 5), (1 << 4) },
+ { "battery charging", SENSOR_INDICATOR, 0x01, (1 << 6), (1 << 6) },
+ { "battery percent", SENSOR_PERCENT, AXP803_BAT_CAP, ( 0x7f ), (1 << 7)
},
+ { "battery voltage", SENSOR_VOLTS_DC, 0x78, 0x00, 1100 },
+ { "battery charging current", SENSOR_AMPS, 0x7a, 0x00, 1000 },
+ { "battery discharging current", SENSOR_AMPS, 0x7c, 0x00, 1000 },
+ { "battery maximum capacity", SENSOR_AMPHOUR, AXP803_BAT_MAX_CAP, 0x00,
1456 },
+ { "battery current capacity", SENSOR_AMPHOUR, AXP803_BAT_CUR_CAP, 0x00,
1456 },
{ "", SENSOR_TEMP, 0x56, 5450000, 106250 },
{ NULL }
};
@@ -302,6 +319,8 @@ struct axppmic_softc {
struct ksensor sc_sensor[AXPPMIC_NSENSORS];
struct ksensordev sc_sensordev;
+
+ uint8_t warn_thres, shut_thres;
};
inline uint8_t
@@ -487,6 +506,16 @@ axppmic_attach_common(struct axppmic_sof
axppmic_write_reg(sc, AXP209_ADC_EN1, reg);
}
+ /* Read battery warning level */
+ if(strcmp(name, "x-powers,axp803") == 0) {
+ uint8_t value;
+
+ value = axppmic_read_reg(sc, AXP803_BAT_CAP_WARN);
+ sc->warn_thres = ((value & AXP803_BAT_CAP_WARN_LV1) >> 4);
+ sc->warn_thres += AXP803_BAT_CAP_WARN_LV1BASE;
+ sc->shut_thres = (value & AXP803_BAT_CAP_WARN_LV2);
+ }
+
if (sc->sc_regdata)
axppmic_attach_regulators(sc, node);
@@ -629,6 +658,7 @@ axppmic_enable(void *cookie, int on)
void axppmic_update_sensors(void *);
void axppmic_update_indicator(struct axppmic_softc *, int);
+void axppmic_update_percent(struct axppmic_softc *, int);
void axppmic_update_sensor(struct axppmic_softc *, int);
void
@@ -665,6 +695,8 @@ axppmic_update_sensors(void *arg)
for (i = 0; sc->sc_sensdata[i].name; i++) {
if (sc->sc_sensdata[i].type == SENSOR_INDICATOR)
axppmic_update_indicator(sc, i);
+ else if(sc->sc_sensdata[i].type == SENSOR_PERCENT)
+ axppmic_update_percent(sc, i);
else
axppmic_update_sensor(sc, i);
}
@@ -689,6 +721,34 @@ axppmic_update_indicator(struct axppmic_
}
void
+axppmic_update_percent(struct axppmic_softc *sc, int i)
+{
+ uint8_t reg = sc->sc_sensdata[i].reg;
+ uint8_t mask = sc->sc_sensdata[i].base;
+ uint8_t mask_ok = sc->sc_sensdata[i].delta;
+ uint8_t value;
+ enum sensor_status status = SENSOR_S_OK;
+
+ value = axppmic_read_reg(sc, reg);
+ sc->sc_sensor[i].value = (value & mask) * 1000;
+
+ if (reg == AXP803_BAT_CAP) {
+ if (value <= sc->shut_thres) {
+ status = SENSOR_S_CRIT;
+ } else if (value <= sc->warn_thres) {
+ status = SENSOR_S_WARN;
+ }
+ }
+
+ if (value & mask) {
+ sc->sc_sensor[i].status =
+ (value & mask_ok) ? status : SENSOR_S_WARN;
+ } else {
+ sc->sc_sensor[i].status = SENSOR_S_UNSPEC;
+ }
+}
+
+void
axppmic_update_sensor(struct axppmic_softc *sc, int i)
{
uint8_t reg = sc->sc_sensdata[i].reg;
@@ -697,7 +757,12 @@ axppmic_update_sensor(struct axppmic_sof
uint16_t value;
value = axppmic_read_reg(sc, reg);
- value = (value << 4) | axppmic_read_reg(sc, reg + 1);
+ if (reg == AXP803_BAT_MAX_CAP || reg == AXP803_BAT_CUR_CAP) {
+ sc->sc_sensor[i].status = (value & (AXP803_BAT_CAP_VALID)) ?
SENSOR_S_OK : SENSOR_S_WARN;
+ value = (((value & ~(AXP803_BAT_CAP_VALID)) << 8) |
axppmic_read_reg(sc, reg + 1));
+ } else {
+ value = (value << 4) | axppmic_read_reg(sc, reg + 1);
+ }
sc->sc_sensor[i].value = base + value * delta;
}