Module Name:    src
Committed By:   khorben
Date:           Sat May 11 18:22:47 UTC 2013

Modified Files:
        src/sys/arch/evbarm/conf [khorben-n900]: N900
        src/sys/dev/i2c [khorben-n900]: tps65950.c tps65950reg.h

Log Message:
Beginning to handle interrupts from the TPS65950 companion chip.


To generate a diff of this commit:
cvs rdiff -u -r1.13.2.2 -r1.13.2.3 src/sys/arch/evbarm/conf/N900
cvs rdiff -u -r1.3.10.1 -r1.3.10.2 src/sys/dev/i2c/tps65950.c
cvs rdiff -u -r1.1.2.1 -r1.1.2.2 src/sys/dev/i2c/tps65950reg.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/arch/evbarm/conf/N900
diff -u src/sys/arch/evbarm/conf/N900:1.13.2.2 src/sys/arch/evbarm/conf/N900:1.13.2.3
--- src/sys/arch/evbarm/conf/N900:1.13.2.2	Sat May 11 18:01:04 2013
+++ src/sys/arch/evbarm/conf/N900	Sat May 11 18:22:47 2013
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: N900,v 1.13.2.2 2013/05/11 18:01:04 khorben Exp $
+#	$NetBSD: N900,v 1.13.2.3 2013/05/11 18:22:47 khorben Exp $
 #
 #	N900 -- Nokia N900 Kernel
 #
@@ -248,7 +248,7 @@ iic*		at omapiic?
 # I2C devices
 # Power Management and System Companion Device
 tps65950pm0	at iic0 addr 0x48
-tps65950pm1	at iic0 addr 0x49
+tps65950pm1	at iic0 addr 0x49 intr 7
 tps65950pm2	at iic0 addr 0x4a
 tps65950pm3	at iic0 addr 0x4b
 

Index: src/sys/dev/i2c/tps65950.c
diff -u src/sys/dev/i2c/tps65950.c:1.3.10.1 src/sys/dev/i2c/tps65950.c:1.3.10.2
--- src/sys/dev/i2c/tps65950.c:1.3.10.1	Sat May 11 17:48:22 2013
+++ src/sys/dev/i2c/tps65950.c	Sat May 11 18:22:47 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: tps65950.c,v 1.3.10.1 2013/05/11 17:48:22 khorben Exp $ */
+/* $NetBSD: tps65950.c,v 1.3.10.2 2013/05/11 18:22:47 khorben Exp $ */
 
 /*-
  * Copyright (c) 2012 Jared D. McNeill <[email protected]>
@@ -31,11 +31,12 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tps65950.c,v 1.3.10.1 2013/05/11 17:48:22 khorben Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tps65950.c,v 1.3.10.2 2013/05/11 18:22:47 khorben Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/device.h>
+#include <sys/workqueue.h>
 #include <sys/conf.h>
 #include <sys/bus.h>
 #include <sys/kmem.h>
@@ -60,10 +61,24 @@ struct tps65950_softc {
 	i2c_addr_t	sc_addr;
 
 	struct sysctllog *sc_sysctllog;
+
+	/* PIH */
+	void			*sc_intr;
+	struct workqueue	*sc_workq;
+	struct work		sc_work;
+	bool			sc_queued;
+
+	/* WATCHDOG */
 	struct sysmon_wdog sc_smw;
 	struct todr_chip_handle sc_todr;
 };
 
+
+/* XXX global workqueue to re-enable interrupts once handled */
+static struct workqueue		*tps65950_pih_workqueue;
+static struct work		tps65950_pih_workqueue_work;
+static bool			tps65950_pih_workqueue_available;
+
 static int	tps65950_match(device_t, cfdata_t, void *);
 static void	tps65950_attach(device_t, device_t, void *);
 
@@ -72,6 +87,12 @@ static int	tps65950_write_1(struct tps65
 
 static void	tps65950_sysctl_attach(struct tps65950_softc *);
 
+static int	tps65950_intr(void *);
+static void	tps65950_intr_work(struct work *, void *);
+
+static void	tps65950_pih_attach(struct tps65950_softc *, int);
+static void	tps65950_pih_intr_work(struct work *, void *);
+
 static void	tps65950_rtc_attach(struct tps65950_softc *);
 static int	tps65950_rtc_enable(struct tps65950_softc *, bool);
 static int	tps65950_rtc_gettime(todr_chip_handle_t, struct clock_ymdhms *);
@@ -128,7 +149,10 @@ tps65950_attach(device_t parent, device_
 		iic_release_bus(sc->sc_i2c, 0);
 		idcode = (buf[0] << 0) | (buf[1] << 8) |
 			 (buf[2] << 16) | (buf[3] << 24);
-		aprint_normal(": IDCODE %08X\n", idcode);
+		aprint_normal(": IDCODE %08X", idcode);
+
+		aprint_normal(": PIH\n");
+		tps65950_pih_attach(sc, ia->ia_intr);
 		break;
 	case TPS65950_ADDR_ID3:
 		aprint_normal(": LED\n");
@@ -262,6 +286,85 @@ tps65950_sysctl_attach(struct tps65950_s
 		return;
 }
 
+static int
+tps65950_intr(void *v)
+{
+	struct tps65950_softc *sc = v;
+
+	if (sc->sc_queued == false) {
+		workqueue_enqueue(sc->sc_workq, &sc->sc_work, NULL);
+		sc->sc_queued = true;
+	}
+
+	/* disable the interrupt until it's properly handled */
+	return 0;
+}
+
+static void
+tps65950_intr_work(struct work *work, void *v)
+{
+	struct tps65950_softc *sc = v;
+	uint8_t u8;
+
+	iic_acquire_bus(sc->sc_i2c, 0);
+
+	/* acknowledge the interrupt */
+	tps65950_read_1(sc, TPS65950_PIH_REG_ISR_P1, &u8);
+	tps65950_write_1(sc, TPS65950_PIH_REG_ISR_P1, u8);
+
+	iic_release_bus(sc->sc_i2c, 0);
+
+	/* allow the workqueue to be entered again */
+	sc->sc_queued = false;
+
+	/* restore the main interrupt handler */
+	if (tps65950_pih_workqueue_available) {
+		tps65950_pih_workqueue_available = false;
+		workqueue_enqueue(tps65950_pih_workqueue,
+				&tps65950_pih_workqueue_work, NULL);
+	}
+}
+
+static void
+tps65950_pih_attach(struct tps65950_softc *sc, int intr)
+{
+	int error;
+
+	/* create the workqueues */
+	error = workqueue_create(&sc->sc_workq, device_xname(sc->sc_dev),
+			tps65950_intr_work, sc, PRIO_MAX, IPL_VM, 0);
+	if (error) {
+		aprint_error_dev(sc->sc_dev, "couldn't create workqueue\n");
+		return;
+	}
+	sc->sc_queued = false;
+
+	error = workqueue_create(&tps65950_pih_workqueue,
+			device_xname(sc->sc_dev), tps65950_pih_intr_work, sc,
+			PRIO_MAX, IPL_HIGH, 0);
+	if (error) {
+		aprint_error_dev(sc->sc_dev, "couldn't create workqueue\n");
+		return;
+	}
+	tps65950_pih_workqueue_available = true;
+
+	/* establish the interrupt handler */
+	sc->sc_intr = intr_establish(intr, IPL_VM, IST_LEVEL, tps65950_intr,
+			sc);
+	if (sc->sc_intr == NULL) {
+		aprint_error_dev(sc->sc_dev, "couldn't establish interrupt\n");
+	}
+}
+
+static void
+tps65950_pih_intr_work(struct work *work, void *v)
+{
+	struct tps65950_softc *sc = v;
+
+	tps65950_pih_workqueue_available = true;
+	intr_enable(sc->sc_intr);
+}
+
 static void
 tps65950_rtc_attach(struct tps65950_softc *sc)
 {

Index: src/sys/dev/i2c/tps65950reg.h
diff -u src/sys/dev/i2c/tps65950reg.h:1.1.2.1 src/sys/dev/i2c/tps65950reg.h:1.1.2.2
--- src/sys/dev/i2c/tps65950reg.h:1.1.2.1	Sat May 11 17:48:22 2013
+++ src/sys/dev/i2c/tps65950reg.h	Sat May 11 18:22:47 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: tps65950reg.h,v 1.1.2.1 2013/05/11 17:48:22 khorben Exp $ */
+/* $NetBSD: tps65950reg.h,v 1.1.2.2 2013/05/11 18:22:47 khorben Exp $ */
 
 /*-
  * Copyright (c) 2012 Jared D. McNeill <[email protected]>
@@ -48,6 +48,28 @@
 #define TPS65950_ID2_UNLOCK_TEST_REG	0x97
 #define TPS65950_ID2_UNLOCK_TEST_REG_MAGIC 0x49
 
+/* ID2: PIH */
+#define TPS65950_PIH_BASE		0x80
+#define TPS65950_PIH_REG_ISR_P1		(TPS65950_PIH_BASE + 0x01)
+#define  TPS65950_PIH_REG_ISR_P1_ISR7	__BIT(7)
+#define  TPS65950_PIH_REG_ISR_P1_ISR6	__BIT(6)
+#define  TPS65950_PIH_REG_ISR_P1_ISR5	__BIT(5)
+#define  TPS65950_PIH_REG_ISR_P1_ISR4	__BIT(4)
+#define  TPS65950_PIH_REG_ISR_P1_ISR3	__BIT(3)
+#define  TPS65950_PIH_REG_ISR_P1_ISR2	__BIT(2)
+#define  TPS65950_PIH_REG_ISR_P1_ISR1	__BIT(1)
+#define  TPS65950_PIH_REG_ISR_P1_ISR0	__BIT(0)
+#define TPS65950_PIH_REG_ISR_P2		(TPS65950_PIH_BASE + 0x02)
+#define  TPS65950_PIH_REG_ISR_P2_ISR7	__BIT(7)
+#define  TPS65950_PIH_REG_ISR_P2_ISR6	__BIT(6)
+#define  TPS65950_PIH_REG_ISR_P2_ISR5	__BIT(5)
+#define  TPS65950_PIH_REG_ISR_P2_ISR4	__BIT(4)
+#define  TPS65950_PIH_REG_ISR_P2_ISR3	__BIT(3)
+#define  TPS65950_PIH_REG_ISR_P2_ISR2	__BIT(2)
+#define  TPS65950_PIH_REG_ISR_P2_ISR1	__BIT(1)
+#define  TPS65950_PIH_REG_ISR_P2_ISR0	__BIT(0)
+#define TPS65950_PIH_REG_SIR		(TPS65950_PIH_BASE + 0x03)
+
 /* ID3 */
 #define TPS65950_LED_BASE		0xee
 #define	TPS65950_ID3_REG_LED		(TPS65950_LED_BASE + 0)

Reply via email to