summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2024-07-25 20:21:41 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2024-07-25 20:21:41 +0000
commit2b752ee2d59dd27f31430d2289df5e8bffe825e1 (patch)
treea0fc0548b3944c89baab667381d11ba56a15fdcd /sys
parent17077cb78293de34a6883faf467e5e6c44dc0ae9 (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.c56
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