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)