Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/khorben-n900]: src/sys Beginning to handle interrupts from the TPS65950 ...
details: https://anonhg.NetBSD.org/src/rev/c8ea6de5fea1
branches: khorben-n900
changeset: 786703:c8ea6de5fea1
user: khorben <khorben%NetBSD.org@localhost>
date: Sat May 11 18:22:47 2013 +0000
description:
Beginning to handle interrupts from the TPS65950 companion chip.
diffstat:
sys/arch/evbarm/conf/N900 | 4 +-
sys/dev/i2c/tps65950.c | 109 ++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/i2c/tps65950reg.h | 24 +++++++++-
3 files changed, 131 insertions(+), 6 deletions(-)
diffs (216 lines):
diff -r 5e4bafa443fa -r c8ea6de5fea1 sys/arch/evbarm/conf/N900
--- a/sys/arch/evbarm/conf/N900 Sat May 11 18:01:04 2013 +0000
+++ b/sys/arch/evbarm/conf/N900 Sat May 11 18:22:47 2013 +0000
@@ -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 @@
# 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
diff -r 5e4bafa443fa -r c8ea6de5fea1 sys/dev/i2c/tps65950.c
--- a/sys/dev/i2c/tps65950.c Sat May 11 18:01:04 2013 +0000
+++ b/sys/dev/i2c/tps65950.c Sat May 11 18:22:47 2013 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
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 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 @@
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 @@
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)
{
diff -r 5e4bafa443fa -r c8ea6de5fea1 sys/dev/i2c/tps65950reg.h
--- a/sys/dev/i2c/tps65950reg.h Sat May 11 18:01:04 2013 +0000
+++ b/sys/dev/i2c/tps65950reg.h Sat May 11 18:22:47 2013 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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)
Home |
Main Index |
Thread Index |
Old Index