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