Module Name: src Committed By: rkujawa Date: Sun Aug 4 00:24:28 UTC 2013
Modified Files: src/sys/dev/i2c: tps65217pmic.c tps65217pmicreg.h Log Message: Monitor for power source changes and report with appropriate information in dmesg, a pmf event and sysmon_pswitch event. To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/sys/dev/i2c/tps65217pmic.c \ src/sys/dev/i2c/tps65217pmicreg.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/i2c/tps65217pmic.c diff -u src/sys/dev/i2c/tps65217pmic.c:1.5 src/sys/dev/i2c/tps65217pmic.c:1.6 --- src/sys/dev/i2c/tps65217pmic.c:1.5 Thu May 16 21:25:27 2013 +++ src/sys/dev/i2c/tps65217pmic.c Sun Aug 4 00:24:28 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: tps65217pmic.c,v 1.5 2013/05/16 21:25:27 rkujawa Exp $ */ +/* $NetBSD: tps65217pmic.c,v 1.6 2013/08/04 00:24:28 rkujawa Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tps65217pmic.c,v 1.5 2013/05/16 21:25:27 rkujawa Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tps65217pmic.c,v 1.6 2013/08/04 00:24:28 rkujawa Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -51,6 +51,9 @@ __KERNEL_RCSID(0, "$NetBSD: tps65217pmic #include <dev/i2c/tps65217pmicreg.h> #define NTPS_REG 7 +#define SNUM_REGS NTPS_REG-1 +#define SNUM_USBSTATUS NTPS_REG +#define SNUM_ACSTATUS NTPS_REG+1 struct tps65217pmic_softc { device_t sc_dev; @@ -61,10 +64,22 @@ struct tps65217pmic_softc { uint8_t sc_version; uint8_t sc_revision; - /* envsys(4) stuff */ - struct sysmon_envsys *sc_sme; - envsys_data_t sc_sensor[NTPS_REG]; kmutex_t sc_lock; + + bool sc_acstatus; + bool sc_usbstatus; + bool sc_acenabled; + bool sc_usbenabled; + + callout_t sc_powerpollco; + + /* sysmon(4) stuff */ + struct sysmon_envsys *sc_sme; + envsys_data_t sc_regsensor[NTPS_REG]; + envsys_data_t sc_acsensor; + envsys_data_t sc_usbsensor; + + struct sysmon_pswitch sc_smpsw; }; /* Voltage regulators */ @@ -117,7 +132,7 @@ static void tps65217pmic_attach(device_t static uint8_t tps65217pmic_reg_read(struct tps65217pmic_softc *, uint8_t); -static void tps65217pmic_refresh(struct tps65217pmic_softc *); +static void tps65217pmic_reg_refresh(struct tps65217pmic_softc *); static uint16_t tps65217pmic_ppath_max_usb_current(uint8_t); static uint16_t tps65217pmic_ppath_max_ac_current(uint8_t); @@ -133,6 +148,9 @@ static void tps65217pmic_version(struct static void tps65217pmic_envsys_register(struct tps65217pmic_softc *); static void tps65217pmic_envsys_refresh(struct sysmon_envsys *, envsys_data_t *); +static void tps65217pmic_power_monitor_init(struct tps65217pmic_softc *); +static void tps65217pmic_power_monitor(void *); + CFATTACH_DECL_NEW(tps65217pmic, sizeof (struct tps65217pmic_softc), tps65217pmic_match, tps65217pmic_attach, NULL, NULL); @@ -301,16 +319,94 @@ tps65217pmic_attach(device_t parent, dev mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); - tps65217pmic_refresh(sc); + sc->sc_smpsw.smpsw_name = device_xname(self); + sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_ACADAPTER; + sysmon_pswitch_register(&sc->sc_smpsw); + + tps65217pmic_reg_refresh(sc); tps65217pmic_print_ppath(sc); tps65217pmic_print_ldos(sc); + tps65217pmic_power_monitor_init(sc); + tps65217pmic_envsys_register(sc); } static void -tps65217pmic_refresh(struct tps65217pmic_softc *sc) +tps65217pmic_power_monitor_init(struct tps65217pmic_softc *sc) +{ + uint8_t intr, intrmask, status, ppath; + + intrmask = TPS65217PMIC_INT_USBM | TPS65217PMIC_INT_ACM | + TPS65217PMIC_INT_PBM; + + status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS); + ppath = tps65217pmic_reg_read(sc, TPS65217PMIC_PPATH); + /* acknowledge and disregard whatever interrupt was generated earlier */ + intr = tps65217pmic_reg_read(sc, TPS65217PMIC_INT); + + sc->sc_usbstatus = status & TPS65217PMIC_STATUS_USBPWR; + sc->sc_acstatus = status & TPS65217PMIC_STATUS_ACPWR; + sc->sc_usbenabled = ppath & TPS65217PMIC_PPATH_USB_EN; + sc->sc_acenabled = ppath & TPS65217PMIC_PPATH_AC_EN; + + if (intr & intrmask) + aprint_normal_dev(sc->sc_dev, + "WARNING: hardware interrupt enabled but not supported"); + + /* set up callout to poll for power source changes */ + callout_init(&sc->sc_powerpollco, 0); + callout_setfunc(&sc->sc_powerpollco, tps65217pmic_power_monitor, sc); + + callout_schedule(&sc->sc_powerpollco, hz); +} + +static void +tps65217pmic_power_monitor(void *aux) +{ + struct tps65217pmic_softc *sc; + uint8_t status; + bool usbstatus, acstatus; + + sc = aux; + + mutex_enter(&sc->sc_lock); + + status = tps65217pmic_reg_read(sc, TPS65217PMIC_STATUS); + usbstatus = status & TPS65217PMIC_STATUS_USBPWR; + acstatus = status & TPS65217PMIC_STATUS_ACPWR; + + if (usbstatus != sc->sc_usbstatus) { + sc->sc_usbstatus = usbstatus; + pmf_event_inject(NULL, PMFE_POWER_CHANGED); + if (usbstatus) + aprint_normal_dev(sc->sc_dev, + "USB power source connected\n"); + else + aprint_normal_dev(sc->sc_dev, + "USB power source disconnected\n"); + } + + if (acstatus != sc->sc_acstatus) { + sc->sc_acstatus = acstatus; + pmf_event_inject(NULL, PMFE_POWER_CHANGED); + if (acstatus) { + sysmon_pswitch_event(&sc->sc_smpsw, + PSWITCH_EVENT_PRESSED); + } else { + sysmon_pswitch_event(&sc->sc_smpsw, + PSWITCH_EVENT_RELEASED); + } + } + + mutex_exit(&sc->sc_lock); + + callout_schedule(&sc->sc_powerpollco, hz); +} + +static void +tps65217pmic_reg_refresh(struct tps65217pmic_softc *sc) { int i; struct tps_reg_param *c_reg; @@ -518,19 +614,35 @@ tps65217pmic_envsys_register(struct tps6 sc->sc_sme = sysmon_envsys_create(); - /* iterate over all regulators and register them as sensors */ - for(i = 0; i < NTPS_REG; i++) { + /* iterate over all regulators and attach them as sensors */ + for(i = 0; i <= SNUM_REGS; i++) { /* set name */ - strlcpy(sc->sc_sensor[i].desc, tps_regulators[i].name, - sizeof(sc->sc_sensor[i].desc)); - sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC; - sc->sc_sensor[i].state = ENVSYS_SINVALID; + strlcpy(sc->sc_regsensor[i].desc, tps_regulators[i].name, + sizeof(sc->sc_regsensor[i].desc)); + sc->sc_regsensor[i].units = ENVSYS_SVOLTS_DC; + sc->sc_regsensor[i].state = ENVSYS_SINVALID; - if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i])) + if (sysmon_envsys_sensor_attach(sc->sc_sme, + &sc->sc_regsensor[i])) aprint_error_dev(sc->sc_dev, - "error attaching sensor %d\n", i); + "error attaching regulator sensor %d\n", i); } + /* attach power source indicators */ + strcpy(sc->sc_usbsensor.desc, "USB power source"); /* SNUM_USBSTATUS */ + sc->sc_usbsensor.units = ENVSYS_INDICATOR; + sc->sc_usbsensor.state = ENVSYS_SINVALID; + if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_usbsensor)) + aprint_error_dev(sc->sc_dev, + "error attaching USB power source sensor\n"); + strcpy(sc->sc_acsensor.desc, "AC power source"); /* SNUM_ACSTATUS */ + sc->sc_acsensor.units = ENVSYS_INDICATOR; + sc->sc_acsensor.state = ENVSYS_SINVALID; + if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_acsensor)) + aprint_error_dev(sc->sc_dev, + "error attaching AC power source sensor\n"); + + /* register everything in sysmon */ sc->sc_sme->sme_name = device_xname(sc->sc_dev); sc->sc_sme->sme_cookie = sc; sc->sc_sme->sme_refresh = tps65217pmic_envsys_refresh; @@ -548,11 +660,20 @@ tps65217pmic_envsys_refresh(struct sysmo mutex_enter(&sc->sc_lock); - tps65217pmic_refresh(sc); + tps65217pmic_reg_refresh(sc); - /* TODO: handle special cases like LS, XADJ... */ - edata->value_cur = tps_regulators[edata->sensor].current_voltage * 1000; - edata->state = ENVSYS_SVALID; + if (edata->sensor <= SNUM_REGS) { + /* TODO: handle special cases like LS, XADJ... */ + edata->value_cur = tps_regulators[edata->sensor].current_voltage * 1000; + edata->state = ENVSYS_SVALID; + } else if (edata->sensor == SNUM_USBSTATUS) { + edata->value_cur = sc->sc_usbstatus && sc->sc_usbenabled; + edata->state = ENVSYS_SVALID; + } else if (edata->sensor == SNUM_ACSTATUS) { + edata->value_cur = sc->sc_acstatus && sc->sc_acenabled; + edata->state = ENVSYS_SVALID; + } else + aprint_error_dev(sc->sc_dev, "unknown sensor number\n"); mutex_exit(&sc->sc_lock); } Index: src/sys/dev/i2c/tps65217pmicreg.h diff -u src/sys/dev/i2c/tps65217pmicreg.h:1.5 src/sys/dev/i2c/tps65217pmicreg.h:1.6 --- src/sys/dev/i2c/tps65217pmicreg.h:1.5 Tue May 7 01:16:25 2013 +++ src/sys/dev/i2c/tps65217pmicreg.h Sun Aug 4 00:24:28 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: tps65217pmicreg.h,v 1.5 2013/05/07 01:16:25 jakllsch Exp $ */ +/* $NetBSD: tps65217pmicreg.h,v 1.6 2013/08/04 00:24:28 rkujawa Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -59,6 +59,14 @@ #define TPS65217PMIC_PPATH_USB_EN __BIT(4) #define TPS65217PMIC_PPATH_AC_EN __BIT(5) +#define TPS65217PMIC_INT 0x02 +#define TPS65217PMIC_INT_USBI __BIT(0) +#define TPS65217PMIC_INT_ACI __BIT(1) +#define TPS65217PMIC_INT_PBI __BIT(2) +#define TPS65217PMIC_INT_USBM __BIT(4) +#define TPS65217PMIC_INT_ACM __BIT(5) +#define TPS65217PMIC_INT_PBM __BIT(6) + #define TPS65217PMIC_WLEDCTRL1 0x07 #define TPS65217PMIC_WLEDCTRL1_FDIM __BITS(1,0) #define TPS65217PMIC_WLEDCTRL1_FDIM_100Hz 0