Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/mips/ingenic support interrupt-driven transfers



details:   https://anonhg.NetBSD.org/src/rev/0444b2b15cb9
branches:  trunk
changeset: 337615:0444b2b15cb9
user:      macallan <macallan%NetBSD.org@localhost>
date:      Tue Apr 21 06:12:41 2015 +0000

description:
support interrupt-driven transfers

diffstat:

 sys/arch/mips/ingenic/jziic.c |  333 +++++++++++++++++++++++++++++++++++++----
 1 files changed, 294 insertions(+), 39 deletions(-)

diffs (truncated from 483 to 300 lines):

diff -r c8eda682aa6d -r 0444b2b15cb9 sys/arch/mips/ingenic/jziic.c
--- a/sys/arch/mips/ingenic/jziic.c     Tue Apr 21 05:27:30 2015 +0000
+++ b/sys/arch/mips/ingenic/jziic.c     Tue Apr 21 06:12:41 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: jziic.c,v 1.1 2015/04/04 12:28:52 macallan Exp $ */
+/*     $NetBSD: jziic.c,v 1.2 2015/04/21 06:12:41 macallan Exp $ */
 
 /*-
  * Copyright (c) 2015 Michael Lorenz
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: jziic.c,v 1.1 2015/04/04 12:28:52 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: jziic.c,v 1.2 2015/04/21 06:12:41 macallan Exp $");
 
 /*
  * a preliminary driver for JZ4780's on-chip SMBus controllers
@@ -39,10 +39,12 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/kernel.h>
 #include <sys/device.h>
 #include <sys/mutex.h>
 #include <sys/bus.h>
 #include <sys/mutex.h>
+#include <sys/condvar.h>
 
 #include <mips/ingenic/ingenic_var.h>
 #include <mips/ingenic/ingenic_regs.h>
@@ -53,34 +55,54 @@
 
 #ifdef JZIIC_DEBUG
 #define DPRINTF aprint_error
+#define STATIC /* */
 #else
 #define DPRINTF while (0) printf
+#define STATIC static
 #endif
-static int jziic_match(device_t, struct cfdata *, void *);
-static void jziic_attach(device_t, device_t, void *);
+
+STATIC int jziic_match(device_t, struct cfdata *, void *);
+STATIC void jziic_attach(device_t, device_t, void *);
 
 struct jziic_softc {
        device_t                sc_dev;
        bus_space_tag_t         sc_memt;
        bus_space_handle_t      sc_memh;
        struct i2c_controller   sc_i2c;
-       kmutex_t                sc_buslock;
+       kmutex_t                sc_buslock, sc_cvlock;
        uint32_t                sc_pclk;
+       /* stuff used for interrupt-driven transfers */
+       const uint8_t           *sc_cmd;
+       uint8_t                 *sc_buf;
+       uint32_t                sc_cmdlen, sc_buflen;
+       uint32_t                sc_cmdptr, sc_bufptr, sc_rds;
+       uint32_t                sc_abort;
+       kcondvar_t              sc_ping;
+       uint8_t                 sc_txbuf[256];
+       boolean_t               sc_reading;
 };
 
 CFATTACH_DECL_NEW(jziic, sizeof(struct jziic_softc),
     jziic_match, jziic_attach, NULL, NULL);
 
-static int jziic_enable(struct jziic_softc *);
-static void jziic_disable(struct jziic_softc *);
-static int jziic_i2c_acquire_bus(void *, int);
-static void jziic_i2c_release_bus(void *, int);
-static int jziic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
+STATIC int jziic_enable(struct jziic_softc *);
+STATIC void jziic_disable(struct jziic_softc *);
+STATIC int jziic_wait(struct jziic_softc *);
+STATIC void jziic_set_speed(struct jziic_softc *);
+STATIC int jziic_i2c_acquire_bus(void *, int);
+STATIC void jziic_i2c_release_bus(void *, int);
+STATIC int jziic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
                    void *, size_t, int);
+STATIC int jziic_i2c_exec_poll(struct jziic_softc *, i2c_op_t, i2c_addr_t,
+    const void *, size_t, void *, size_t, int);
+STATIC int jziic_i2c_exec_intr(struct jziic_softc *, i2c_op_t, i2c_addr_t,
+    const void *, size_t, void *, size_t, int);
+
+STATIC int jziic_intr(void *);
 
 
 /* ARGSUSED */
-static int
+STATIC int
 jziic_match(device_t parent, struct cfdata *match, void *aux)
 {
        struct apbus_attach_args *aa = aux;
@@ -92,13 +114,14 @@
 }
 
 /* ARGSUSED */
-static void
+STATIC void
 jziic_attach(device_t parent, device_t self, void *aux)
 {
        struct jziic_softc *sc = device_private(self);
        struct apbus_attach_args *aa = aux;
        struct i2cbus_attach_args iba;
        int error;
+       void *ih;
 #ifdef JZIIC_DEBUG
        int i;
        uint8_t in[1] = {0}, out[16];
@@ -116,19 +139,19 @@
        }
 
        mutex_init(&sc->sc_buslock, MUTEX_DEFAULT, IPL_NONE);
+       mutex_init(&sc->sc_cvlock, MUTEX_DEFAULT, IPL_NONE);
+       cv_init(&sc->sc_ping, device_xname(self));
 
        aprint_naive(": SMBus controller\n");
        aprint_normal(": SMBus controller\n");
 
-#if notyet
-       ih = evbmips_intr_establish(aa->aa_irq, ohci_intr, sc);
+       ih = evbmips_intr_establish(aa->aa_irq, jziic_intr, sc);
 
        if (ih == NULL) {
                aprint_error_dev(self, "failed to establish interrupt %d\n",
                     aa->aa_irq);
                goto fail;
        }
-#endif
 
 #ifdef JZIIC_DEBUG
        if (jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP, 0x51, in, 1, out, 9, 0)
@@ -168,16 +191,14 @@
 
        return;
 
-#if notyet
 fail:
        if (ih) {
                evbmips_intr_disestablish(ih);
        }
        bus_space_unmap(sc->sc_memt, sc->sc_memh, 0x100);
-#endif
 }
 
-static int
+STATIC int
 jziic_enable(struct jziic_softc *sc)
 {
        int bail = 100000;
@@ -194,7 +215,7 @@
        return (reg != 0);
 }
 
-static void
+STATIC void
 jziic_disable(struct jziic_softc *sc)
 {
        int bail = 100000;
@@ -210,7 +231,7 @@
        DPRINTF("bail: %d\n", bail);
 }
 
-static int
+STATIC int
 jziic_i2c_acquire_bus(void *cookie, int flags)
 {
        struct jziic_softc *sc = cookie;
@@ -219,7 +240,7 @@
        return 0;
 }
 
-static void
+STATIC void
 jziic_i2c_release_bus(void *cookie, int flags)
 {
        struct jziic_softc *sc = cookie;
@@ -227,7 +248,7 @@
        mutex_exit(&sc->sc_buslock);
 }
 
-static int
+STATIC int
 jziic_wait(struct jziic_softc *sc)
 {
        uint32_t reg;
@@ -241,25 +262,10 @@
        return ((reg & JZ_MSTACT) == 0);
 }
 
-int
-jziic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *vcmd,
-    size_t cmdlen, void *vbuf, size_t buflen, int flags)
+STATIC void
+jziic_set_speed(struct jziic_softc *sc)
 {
-       struct jziic_softc *sc = cookie;
        int ticks, hcnt, lcnt, hold, setup;
-       int i, bail = 10000, ret = 0;
-       uint32_t abort;
-       uint8_t *rx, data;
-       const uint8_t *tx;
-
-       tx = vcmd;
-       rx = vbuf;
-
-       DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen);
-
-       jziic_disable(sc);
-
-       /* set speed and such */
 
        /* PCLK ticks per SMBus cycle */
        ticks = sc->sc_pclk / 100; /* assuming 100kHz for now */
@@ -277,6 +283,63 @@
        bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON,
            JZ_SLVDIS | JZ_STPHLD | JZ_REST | JZ_SPD_100KB | JZ_MD);
        (void)bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT);
+}
+
+STATIC int
+jziic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *vcmd,
+    size_t cmdlen, void *vbuf, size_t buflen, int flags)
+{
+       struct jziic_softc *sc = cookie;
+
+       if (cold || (flags & I2C_F_POLL)) {
+               return jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf,
+                   buflen, flags);
+       } else {
+#ifdef JZIIC_DEBUG
+               uint8_t *b = vbuf;
+               int i, ret;
+
+               memset(vbuf, 0, buflen);
+               jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf,
+                   buflen, flags);
+               for (i = 0; i < buflen; i++) {
+                       printf(" %02x", b[i]);
+               }
+               printf("\n");
+               ret = jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf,
+                   buflen, flags);
+               for (i = 0; i < buflen; i++) {
+                       printf(" %02x", b[i]);
+               }
+               printf("\n");
+               return ret;
+#else
+               return jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf,
+                   buflen, flags);
+#endif
+       }
+}
+
+STATIC int
+jziic_i2c_exec_poll(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr,
+    const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags)
+{
+       int i, bail = 10000, ret = 0;
+       uint32_t abort;
+       uint8_t *rx, data;
+       const uint8_t *tx;
+
+       tx = vcmd;
+       rx = vbuf;
+
+       DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen);
+
+       jziic_disable(sc);
+
+       /* we're polling, so disable interrupts */
+       bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
+
+       jziic_set_speed(sc);
        jziic_wait(sc);
        /* try to talk... */
 
@@ -284,6 +347,7 @@
                ret = -1;
                goto bork;
        }
+       bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
 
        bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTAR, addr);
        jziic_wait(sc);
@@ -378,3 +442,194 @@
        jziic_disable(sc);
        return ret;
 }
+
+STATIC int
+jziic_i2c_exec_intr(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr,
+    const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags)
+{
+       int i, ret = 0, bail;
+
+       DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen);



Home | Main Index | Thread Index | Old Index