Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sandpoint/sandpoint Rewrote most of the code to mak...
details: https://anonhg.NetBSD.org/src/rev/f2821e85eb89
branches: trunk
changeset: 754786:f2821e85eb89
user: phx <phx%NetBSD.org@localhost>
date: Wed May 12 17:20:24 2010 +0000
description:
Rewrote most of the code to make the 8245 I2C module finally work.
Tested with a RICOH RS5C372 RTC on a Synology DS-101g+ and Kurobox.
Reviewed by <nisimura>.
diffstat:
sys/arch/sandpoint/sandpoint/eumbvar.h | 4 +-
sys/arch/sandpoint/sandpoint/iic_eumb.c | 266 +++++++++++++++++++------------
2 files changed, 162 insertions(+), 108 deletions(-)
diffs (truncated from 398 to 300 lines):
diff -r eb71e0a3eca2 -r f2821e85eb89 sys/arch/sandpoint/sandpoint/eumbvar.h
--- a/sys/arch/sandpoint/sandpoint/eumbvar.h Wed May 12 17:03:11 2010 +0000
+++ b/sys/arch/sandpoint/sandpoint/eumbvar.h Wed May 12 17:20:24 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: eumbvar.h,v 1.4 2008/04/28 20:23:34 martin Exp $ */
+/* $NetBSD: eumbvar.h,v 1.5 2010/05/12 17:20:24 phx Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -38,5 +38,3 @@
};
int eumbcnattach(bus_space_tag_t, int, int, int, int, int);
-void iic_bootstrap_init(void);
-int iic_bootstrap_read(int, int, uint8_t *, size_t);
diff -r eb71e0a3eca2 -r f2821e85eb89 sys/arch/sandpoint/sandpoint/iic_eumb.c
--- a/sys/arch/sandpoint/sandpoint/iic_eumb.c Wed May 12 17:03:11 2010 +0000
+++ b/sys/arch/sandpoint/sandpoint/iic_eumb.c Wed May 12 17:20:24 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: iic_eumb.c,v 1.7 2009/03/18 10:22:35 cegger Exp $ */
+/* $NetBSD: iic_eumb.c,v 1.8 2010/05/12 17:20:24 phx Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: iic_eumb.c,v 1.7 2009/03/18 10:22:35 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: iic_eumb.c,v 1.8 2010/05/12 17:20:24 phx Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -45,31 +45,31 @@
#include <sandpoint/sandpoint/eumbvar.h>
-void iic_bootstrap_init(void);
-int iic_bootstrap_read(int, int, uint8_t *, size_t);
-
-static int iic_eumb_match(struct device *, struct cfdata *, void *);
-static void iic_eumb_attach(struct device *, struct device *, void *);
-
struct iic_eumb_softc {
struct device sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
struct i2c_controller sc_i2c;
kmutex_t sc_buslock;
+ bool sc_start;
};
+static int iic_eumb_match(struct device *, struct cfdata *, void *);
+static void iic_eumb_attach(struct device *, struct device *, void *);
+
CFATTACH_DECL(iic_eumb, sizeof(struct iic_eumb_softc),
iic_eumb_match, iic_eumb_attach, NULL, NULL);
-static int motoi2c_acquire_bus(void *, int);
+static int motoi2c_acquire_bus(void *, int);
static void motoi2c_release_bus(void *, int);
-static int motoi2c_send_start(void *, int);
-static int motoi2c_send_stop(void *, int);
-static int motoi2c_initiate_xfer(void *, uint16_t, int);
-static int motoi2c_read_byte(void *, uint8_t *, int);
-static int motoi2c_write_byte(void *, uint8_t, int);
-static void waitxferdone(int);
+static int motoi2c_send_start(void *, int);
+static int motoi2c_send_stop(void *, int);
+static int motoi2c_initiate_xfer(void *, uint16_t, int);
+static int motoi2c_read_byte(void *, uint8_t *, int);
+static int motoi2c_write_byte(void *, uint8_t, int);
+static int motoi2c_waitxferdone(struct iic_eumb_softc *);
+
+struct iic_eumb_softc *iic_eumb;
static struct i2c_controller motoi2c = {
.ic_acquire_bus = motoi2c_acquire_bus,
@@ -103,9 +103,11 @@
#define SR_RXAK 0x01 /* 1 to indicate receive has completed */
#define I2CDR 0x0010 /* data */
-#define CSR_READ(r) in8rb(0xfc003000 + (r))
-#define CSR_WRITE(r,v) out8rb(0xfc003000 + (r), (v))
-#define CSR_WRITE4(r,v) out32rb(0xfc003000 + (r), (v))
+#define I2C_READ(r) bus_space_read_4(sc->sc_iot, sc->sc_ioh, (r))
+#define I2C_WRITE(r,v) bus_space_write_4(sc->sc_iot, sc->sc_ioh, (r), (v))
+#define I2C_SETCLR(r, s, c) \
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, (r), \
+ (bus_space_read_4(sc->sc_iot, sc->sc_ioh, (r)) | (s)) & ~(c))
static int found;
@@ -119,74 +121,48 @@
static void
iic_eumb_attach(struct device *parent, struct device *self, void *aux)
{
- struct iic_eumb_softc *sc = (void *)self;
- struct eumb_attach_args *eaa = aux;
+ struct iic_eumb_softc *sc;
+ struct eumb_attach_args *eaa;
struct i2cbus_attach_args iba;
bus_space_handle_t ioh;
+ sc = (struct iic_eumb_softc *)self;
+ eaa = aux;
found = 1;
printf("\n");
bus_space_map(eaa->eumb_bt, 0x3000, 0x20, 0, &ioh);
mutex_init(&sc->sc_buslock, MUTEX_DEFAULT, IPL_NONE);
+
+ iic_eumb = sc;
sc->sc_i2c = motoi2c;
sc->sc_i2c.ic_cookie = sc;
sc->sc_iot = eaa->eumb_bt;
sc->sc_ioh = ioh;
+ sc->sc_start = false;
+ memset(&iba, 0, sizeof(iba));
iba.iba_tag = &sc->sc_i2c;
- iic_bootstrap_init();
-#if 0
- /* not yet */
+ I2C_WRITE(I2CCR, 0); /* reset before changing anything */
+ I2C_WRITE(I2CFDR, 0x1031); /* DFFSR=0x10, divider 3072 (0x31) */
+ I2C_WRITE(I2CADR, 0x7f << 1); /* our slave address is 0x7f */
+ I2C_WRITE(I2CSR, 0); /* clear status flags */
+ I2C_WRITE(I2CCR, CR_MEN); /* enable the I2C module */
+
config_found_ia(&sc->sc_dev, "i2cbus", &iba, iicbus_print);
- /* we never attempt to use I2C interrupt */
- intr_establish(16 + 16, IST_LEVEL, IPL_BIO, iic_intr, sc);
+#if 0
+ /* we do not use the I2C interrupt yet */
+ intr_establish(16 + 16, IST_LEVEL, IPL_BIO, motoic2_intr, sc);
#endif
}
-void
-iic_bootstrap_init(void)
-{
-
- CSR_WRITE(I2CCR, 0);
- CSR_WRITE4(I2CFDR, 0x1031); /* XXX magic XXX */
- CSR_WRITE(I2CADR, 0);
- CSR_WRITE(I2CSR, 0);
- CSR_WRITE(I2CCR, CR_MEN);
-}
-
-int
-iic_bootstrap_read(int i2caddr, int offset, uint8_t *rvp, size_t len)
-{
- i2c_addr_t addr;
- uint8_t cmdbuf[1];
-
- if (motoi2c_acquire_bus(&motoi2c, I2C_F_POLL) != 0)
- return -1;
- while (len) {
- addr = i2caddr + (offset >> 8);
- cmdbuf[0] = offset & 0xff;
- if (iic_exec(&motoi2c, I2C_OP_READ_WITH_STOP, addr,
- cmdbuf, 1, rvp, 1, I2C_F_POLL)) {
- motoi2c_release_bus(&motoi2c, I2C_F_POLL);
- return -1;
- }
- len--;
- rvp++;
- offset++;
- }
- motoi2c_release_bus(&motoi2c, I2C_F_POLL);
- return 0;
-}
-
static int
motoi2c_acquire_bus(void *v, int flags)
{
- struct iic_eumb_softc *sc = v;
+ struct iic_eumb_softc *sc;
- if (flags & I2C_F_POLL)
- return 0;
+ sc = v;
mutex_enter(&sc->sc_buslock);
return 0;
}
@@ -194,88 +170,168 @@
static void
motoi2c_release_bus(void *v, int flags)
{
- struct iic_eumb_softc *sc = v;
+ struct iic_eumb_softc *sc;
- if (flags & I2C_F_POLL)
- return;
+ sc = v;
mutex_exit(&sc->sc_buslock);
}
static int
motoi2c_send_start(void *v, int flags)
{
- int loop = 10;
+ struct iic_eumb_softc *sc;
+ int timo;
+
+ sc = v;
+
+ if (!sc->sc_start && (I2C_READ(I2CSR) & SR_MBB) != 0) {
+ /* wait for bus becoming available */
+ timo = 100;
+ do
+ DELAY(10);
+ while (--timo > 0 && (I2C_READ(I2CSR) & SR_MBB) != 0);
- CSR_WRITE(I2CSR, 0);
- CSR_WRITE(I2CCR, CR_MEN);
- do {
- DELAY(1);
- } while (--loop > 0 && (CSR_READ(I2CSR) & SR_MBB));
+ if (timo == 0) {
+#ifdef DEBUG
+ printf("%s: bus is busy\n", __func__);
+#endif
+ return -1;
+ }
+ }
+ else if (sc->sc_start &&
+ (I2C_READ(I2CSR) & (SR_MIF | SR_MAL)) == SR_MIF) {
+ sc->sc_start = false;
+#ifdef DEBUG
+ printf("%s: lost the bus\n", __func__);
+#endif
+ return -1;
+ }
+
+ /* reset interrupt and arbitration-lost flags */
+ I2C_SETCLR(I2CSR, 0, SR_MIF | SR_MAL);
+
+ if (!sc->sc_start) {
+ /* generate start condition */
+ I2C_SETCLR(I2CCR, CR_MSTA | CR_MTX, CR_TXAK | CR_RSTA);
+ sc->sc_start = true;
+ } else /* repeated start, we still own the bus */
+ I2C_SETCLR(I2CCR, CR_RSTA | CR_MTX, CR_TXAK);
+
return 0;
}
static int
motoi2c_send_stop(void *v, int flags)
{
+ struct iic_eumb_softc *sc;
- CSR_WRITE(I2CCR, CR_MEN);
+ sc = v;
+ I2C_SETCLR(I2CCR, 0, CR_MSTA | CR_RSTA | CR_TXAK);
+ sc->sc_start = false;
+ DELAY(100);
return 0;
}
static int
motoi2c_initiate_xfer(void *v, i2c_addr_t addr, int flags)
{
- int rd_req;
+ struct iic_eumb_softc *sc;
+
+ sc = v;
+
+ /* start condition */
+ if (motoi2c_send_start(v, flags) != 0)
+ return -1;
+
+ /* send target address and transfer direction */
+ I2C_WRITE(I2CDR, (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0));
- rd_req = !!(flags & I2C_F_READ);
- CSR_WRITE(I2CCR, CR_MIEN | CR_MEN | CR_MSTA | CR_MTX);
- CSR_WRITE(I2CDR, (addr << 1) | rd_req);
- if (flags & I2C_F_STOP)
- CSR_WRITE(I2CCR, CR_MIEN | CR_MEN | CR_TXAK);
- waitxferdone(SR_MIF);
- return 0;
+ if (motoi2c_waitxferdone(sc) == 0) {
+ if (flags & I2C_F_READ) {
+ /* clear TX mode */
+ I2C_SETCLR(I2CCR, 0, CR_MTX);
+ /*
+ * A dummy read is required to start with
+ * receiving bytes.
+ */
+ (void)I2C_READ(I2CDR);
+ }
+ if (flags & I2C_F_STOP)
+ return motoi2c_send_stop(v, flags);
+ return 0;
+ }
+ return -1;
Home |
Main Index |
Thread Index |
Old Index