diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2024-07-25 20:21:41 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2024-07-25 20:21:41 +0000 |
commit | 2b752ee2d59dd27f31430d2289df5e8bffe825e1 (patch) | |
tree | a0fc0548b3944c89baab667381d11ba56a15fdcd /sys | |
parent | 17077cb78293de34a6883faf467e5e6c44dc0ae9 (diff) |
Explicitly request for battery status updates as the firmware doesn't seem
to send us regular updates itself. Estamate the remaining battery (charge)
time by using the reported rate.
ok phessler@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/fdt/qcpas.c | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/sys/dev/fdt/qcpas.c b/sys/dev/fdt/qcpas.c index 36ea06517b7..c943a7db853 100644 --- a/sys/dev/fdt/qcpas.c +++ b/sys/dev/fdt/qcpas.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qcpas.c,v 1.2 2023/07/01 15:50:18 drahn Exp $ */ +/* $OpenBSD: qcpas.c,v 1.3 2024/07/25 20:21:40 kettenis Exp $ */ /* * Copyright (c) 2023 Patrick Wildt <patrick@blueri.se> * @@ -795,13 +795,6 @@ qcpas_glink_recv_open(struct qcpas_softc *sc, uint32_t rcid, uint32_t namelen) return; } - /* Assume we can leave HW dangling if proto init fails */ - err = proto->init(NULL); - if (err) { - free(name, M_TEMP, namelen); - return; - } - ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO); ch->ch_sc = sc; ch->ch_proto = proto; @@ -811,6 +804,15 @@ qcpas_glink_recv_open(struct qcpas_softc *sc, uint32_t rcid, uint32_t namelen) TAILQ_INIT(&ch->ch_r_intents); TAILQ_INSERT_TAIL(&sc->sc_glink_channels, ch, ch_q); + /* Assume we can leave HW dangling if proto init fails */ + err = proto->init(ch); + if (err) { + TAILQ_REMOVE(&sc->sc_glink_channels, ch, ch_q); + free(ch, M_TEMP, sizeof(*ch)); + free(name, M_TEMP, namelen); + return; + } + msg.cmd = GLINK_CMD_OPEN_ACK; msg.param1 = ch->ch_rcid; msg.param2 = 0; @@ -1108,7 +1110,7 @@ struct battmgr_bat_status { #define BATTMGR_BAT_STATE_CHARGING (1 << 1) #define BATTMGR_BAT_STATE_CRITICAL_LOW (1 << 2) uint32_t capacity; - uint32_t rate; + int32_t rate; uint32_t battery_voltage; uint32_t power_state; #define BATTMGR_PWR_STATE_AC_ON (1 << 0) @@ -1151,7 +1153,7 @@ qcpas_pmic_rtr_battmgr_req_status(void *cookie) #if NAPM > 0 struct apm_power_info qcpas_pmic_rtr_apm_power_info; -uint32_t qcpas_pmic_rtr_last_full_capacity; +void *qcpas_pmic_rtr_apm_cookie; #endif int @@ -1166,6 +1168,7 @@ qcpas_pmic_rtr_init(void *cookie) info->battery_life = 0; info->minutes_left = -1; + qcpas_pmic_rtr_apm_cookie = cookie; apm_setinfohook(qcpas_pmic_rtr_apminfo); #endif return 0; @@ -1174,6 +1177,9 @@ qcpas_pmic_rtr_init(void *cookie) int qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len) { +#if NAPM > 0 + static uint32_t last_full_capacity; +#endif struct pmic_glink_hdr hdr; uint32_t notification; extern int hw_power; @@ -1221,8 +1227,7 @@ qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len) bat = malloc(sizeof(*bat), M_TEMP, M_WAITOK); memcpy((void *)bat, buf + sizeof(hdr), sizeof(*bat)); #if NAPM > 0 - qcpas_pmic_rtr_last_full_capacity = - bat->last_full_capacity; + last_full_capacity = bat->last_full_capacity; #endif free(bat, M_TEMP, sizeof(*bat)); break; @@ -1231,6 +1236,7 @@ qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len) struct battmgr_bat_status *bat; #if NAPM > 0 struct apm_power_info *info; + uint32_t delta; #endif if (len - sizeof(hdr) != sizeof(*bat)) { printf("%s: invalid battgmr bat status\n", @@ -1239,15 +1245,17 @@ qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len) } #if NAPM > 0 /* Needs BAT_INFO fist */ - if (!qcpas_pmic_rtr_last_full_capacity) + if (last_full_capacity == 0) { + wakeup(&qcpas_pmic_rtr_apm_power_info); return 0; + } #endif bat = malloc(sizeof(*bat), M_TEMP, M_WAITOK); memcpy((void *)bat, buf + sizeof(hdr), sizeof(*bat)); #if NAPM > 0 info = &qcpas_pmic_rtr_apm_power_info; info->battery_life = ((bat->capacity * 100) / - qcpas_pmic_rtr_last_full_capacity); + last_full_capacity); if (info->battery_life > 50) info->battery_state = APM_BATT_HIGH; else if (info->battery_life > 25) @@ -1259,6 +1267,16 @@ qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len) else if (bat->battery_state & BATTMGR_BAT_STATE_CRITICAL_LOW) info->battery_state = APM_BATT_CRITICAL; + if (bat->rate < 0) + delta = bat->capacity; + else + delta = last_full_capacity - bat->capacity; + if (bat->rate == 0) + info->minutes_left = -1; + else + info->minutes_left = + (60 * delta) / abs(bat->rate); + if (bat->power_state & BATTMGR_PWR_STATE_AC_ON) { info->ac_state = APM_AC_ON; hw_power = 1; @@ -1266,6 +1284,7 @@ qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len) info->ac_state = APM_AC_OFF; hw_power = 0; } + wakeup(&qcpas_pmic_rtr_apm_power_info); #endif free(bat, M_TEMP, sizeof(*bat)); break; @@ -1289,8 +1308,15 @@ qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len) int qcpas_pmic_rtr_apminfo(struct apm_power_info *info) { - memcpy(info, &qcpas_pmic_rtr_apm_power_info, sizeof(*info)); + int error; + qcpas_pmic_rtr_battmgr_req_status(qcpas_pmic_rtr_apm_cookie); + error = tsleep_nsec(&qcpas_pmic_rtr_apm_power_info, PWAIT | PCATCH, + "qcapm", SEC_TO_NSEC(5)); + if (error) + return error; + + memcpy(info, &qcpas_pmic_rtr_apm_power_info, sizeof(*info)); return 0; } #endif |