From d49c6f029c3aeb62bcea97004159377efb72692c Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sun, 12 Oct 2014 19:12:48 +0000 Subject: [PATCH] Add an AC line monitor so power_profile can work Summary: Add a polling loop (1Hz) to monitor the battery and AC status, to notify devd like ACPI does for power monitoring. This allows /etc/rc.d/power_profile to work on PowerPC laptops Test Plan: Tested on a Titanium PowerBook, configuring economy_cpu_freq and performance_cpu_freq, disabling powerd. Reviewers: #powerpc, nwhitehorn Reviewed By: nwhitehorn Subscribers: rpaulo Differential Revision: https://reviews.freebsd.org/D937 --- etc/devd/apple.conf | 8 ++++++- sys/powerpc/powermac/pmu.c | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/etc/devd/apple.conf b/etc/devd/apple.conf index 8518890a5d6d..7f066cdf5ad7 100644 --- a/etc/devd/apple.conf +++ b/etc/devd/apple.conf @@ -71,4 +71,10 @@ notify 0 { action "camcontrol eject cd0"; }; - +# Equivalent to the ACPI/ACAD notify +notify 10 { + match "system" "PMU"; + match "subsystem" "POWER"; + match "type" "ACLINE"; + action "/etc/rc.d/power_profile $notify"; +} diff --git a/sys/powerpc/powermac/pmu.c b/sys/powerpc/powermac/pmu.c index 913845e59bc8..bb3147952d59 100644 --- a/sys/powerpc/powermac/pmu.c +++ b/sys/powerpc/powermac/pmu.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -183,6 +184,9 @@ static int pmu_send(void *cookie, int cmd, int length, uint8_t *in_msg, static uint8_t pmu_read_reg(struct pmu_softc *sc, u_int offset); static void pmu_write_reg(struct pmu_softc *sc, u_int offset, uint8_t value); static int pmu_intr_state(struct pmu_softc *); +static void pmu_battquery_proc(void); +static void pmu_battery_notify(struct pmu_battstate *batt, + struct pmu_battstate *old); /* these values shows that number of data returned after 'send' cmd is sent */ static signed char pm_send_cmd_type[] = { @@ -256,6 +260,13 @@ static signed char pm_receive_cmd_type[] = { -1, -1, -1, -1, -1, -1, -1, -1, }; +static struct proc *pmubattproc; +static struct kproc_desc pmu_batt_kp = { + "pmu_batt", + pmu_battquery_proc, + &pmubattproc +}; + /* We only have one of each device, so globals are safe */ static device_t pmu = NULL; static device_t pmu_extint = NULL; @@ -420,6 +431,8 @@ pmu_attach(device_t dev) struct sysctl_oid *oid, *battroot; char battnum[2]; + /* Only start the battery monitor if we have a battery. */ + kproc_start(&pmu_batt_kp); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "acline", CTLTYPE_INT | CTLFLAG_RD, sc, 0, pmu_acline_state, "I", "AC Line Status"); @@ -914,6 +927,39 @@ pmu_query_battery(struct pmu_softc *sc, int batt, struct pmu_battstate *info) return (0); } +static void +pmu_battery_notify(struct pmu_battstate *batt, struct pmu_battstate *old) +{ + char notify_buf[16]; + int acline; + + acline = (batt->state & PMU_PWR_AC_PRESENT) ? 1 : 0; + if (acline != (old->state & PMU_PWR_AC_PRESENT)) { + snprintf(notify_buf, sizeof(notify_buf), + "notify=0x%02x", acline); + devctl_notify("PMU", "POWER", "ACLINE", notify_buf); + } +} + +static void +pmu_battquery_proc() +{ + struct pmu_softc *sc; + struct pmu_battstate batt; + struct pmu_battstate cur_batt; + int error; + + sc = device_get_softc(pmu); + + error = pmu_query_battery(sc, 0, &cur_batt); + while (1) { + error = pmu_query_battery(sc, 0, &batt); + pmu_battery_notify(&batt, &cur_batt); + cur_batt = batt; + pause("pmu_batt", hz); + } +} + static int pmu_acline_state(SYSCTL_HANDLER_ARGS) {