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