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

Reply via email to