apm(4/arm64) merely provides an all zero/unknown stub for those values, e.g. apm(8) output is useless.
Hardware sensors however provide the information: $ sysctl hw.sensors hw.sensors.rktemp0.temp0=32.22 degC (CPU) hw.sensors.rktemp0.temp1=33.89 degC (GPU) hw.sensors.cwfg0.volt0=3.76 VDC (battery voltage) hw.sensors.cwfg0.raw0=259 (battery remaining minutes) hw.sensors.cwfg0.percent0=58.00% (battery percent) Diff below simply copies them over using apm_setinfohook() (I've looked at sys/arch/loongson/dev/kb3310.c which does the same): $ apm Battery state: high, 58% remaining, 259 minutes life estimate A/C adapter state: not known Performance adjustment mode: auto (408 MHz) Feedback? OK? Index: dev/fdt/cwfg.c =================================================================== RCS file: /cvs/src/sys/dev/fdt/cwfg.c,v retrieving revision 1.1 diff -u -p -r1.1 cwfg.c --- dev/fdt/cwfg.c 10 Jun 2020 17:51:21 -0000 1.1 +++ dev/fdt/cwfg.c 20 Mar 2021 23:43:13 -0000 @@ -32,12 +32,15 @@ #include <sys/malloc.h> #include <sys/sensors.h> +#include <machine/apmvar.h> #include <machine/fdt.h> #include <dev/ofw/openfirm.h> #include <dev/i2c/i2cvar.h> +#include "apm.h" + #define VERSION_REG 0x00 #define VCELL_HI_REG 0x02 #define VCELL_HI_MASK 0x3f @@ -119,6 +122,18 @@ struct cfdriver cwfg_cd = { NULL, "cwfg", DV_DULL }; +int cwfg_apminfo(struct apm_power_info *info); +#if NAPM > 0 +struct apm_power_info cwfg_power; + +int +cwfg_apminfo(struct apm_power_info *info) +{ + bcopy(&cwfg_power, info, sizeof(*info)); + return 0; +} +#endif + int cwfg_match(struct device *parent, void *match, void *aux) { @@ -202,6 +217,12 @@ cwfg_attach(struct device *parent, struc sensor_task_register(sc, cwfg_update_sensors, 5); +#if NAPM > 0 + /* make sure we have the apm state initialized before apm attaches */ + cwfg_update_sensors(sc); + apm_setinfohook(cwfg_apminfo); +#endif + printf("\n"); } @@ -324,6 +345,7 @@ cwfg_update_sensors(void *arg) uint32_t vcell, rtt, tmp; uint8_t val; int error, n; + u_char bat_percent; if ((error = cwfg_lock(sc)) != 0) return; @@ -348,6 +370,7 @@ cwfg_update_sensors(void *arg) if ((error = cwfg_read(sc, SOC_HI_REG, &val)) != 0) goto done; if (val != 0xff) { + bat_percent = val; sc->sc_sensor[CWFG_SENSOR_SOC].value = val * 1000; sc->sc_sensor[CWFG_SENSOR_SOC].flags &= ~SENSOR_FINVALID; } @@ -363,6 +386,14 @@ cwfg_update_sensors(void *arg) sc->sc_sensor[CWFG_SENSOR_RTT].value = rtt; sc->sc_sensor[CWFG_SENSOR_RTT].flags &= ~SENSOR_FINVALID; } + +#if NAPM > 0 + cwfg_power.battery_state = bat_percent > sc->sc_alert_level ? + APM_BATT_HIGH : APM_BATT_LOW; + cwfg_power.ac_state = APM_AC_UNKNOWN; + cwfg_power.battery_life = bat_percent; + cwfg_power.minutes_left = sc->sc_sensor[CWFG_SENSOR_RTT].value; +#endif done: cwfg_unlock(sc);