Module Name: src
Committed By: jmcneill
Date: Thu Jan 1 15:18:45 UTC 2015
Modified Files:
src/sys/arch/arm/rockchip: rockchip_i2c.c
Log Message:
drop clk rate to 100kHz, explicit register initialization, shift slave addr
left 1, add some more debugging, now this works
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/rockchip/rockchip_i2c.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/rockchip/rockchip_i2c.c
diff -u src/sys/arch/arm/rockchip/rockchip_i2c.c:1.3 src/sys/arch/arm/rockchip/rockchip_i2c.c:1.4
--- src/sys/arch/arm/rockchip/rockchip_i2c.c:1.3 Tue Dec 30 18:57:36 2014
+++ src/sys/arch/arm/rockchip/rockchip_i2c.c Thu Jan 1 15:18:45 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: rockchip_i2c.c,v 1.3 2014/12/30 18:57:36 jmcneill Exp $ */
+/* $NetBSD: rockchip_i2c.c,v 1.4 2015/01/01 15:18:45 jmcneill Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -30,7 +30,7 @@
#include "opt_rkiic.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rockchip_i2c.c,v 1.3 2014/12/30 18:57:36 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rockchip_i2c.c,v 1.4 2015/01/01 15:18:45 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -48,7 +48,7 @@ __KERNEL_RCSID(0, "$NetBSD: rockchip_i2c
#include <dev/i2c/i2cvar.h>
-#define RKIIC_CLOCK_RATE 400000
+#define RKIIC_CLOCK_RATE 100000
struct rkiic_softc {
device_t sc_dev;
@@ -129,6 +129,14 @@ rkiic_attach(device_t parent, device_t s
}
}
+ if (rkiic_set_rate(sc, RKIIC_CLOCK_RATE) != 0) {
+ aprint_error_dev(sc->sc_dev, "couldn't set clock rate\n");
+ return;
+ }
+
+ I2C_WRITE(sc, I2C_CON_REG, 0);
+ I2C_WRITE(sc, I2C_IEN_REG, 0);
+
sc->sc_ic.ic_cookie = sc;
sc->sc_ic.ic_acquire_bus = rkiic_acquire_bus;
sc->sc_ic.ic_release_bus = rkiic_release_bus;
@@ -151,6 +159,10 @@ rkiic_intr(void *priv)
I2C_WRITE(sc, I2C_IPD_REG, ipd);
+#ifdef RKIIC_INTR
+ device_printf(sc->sc_dev, "%s: ipd %#x\n", __func__, ipd);
+#endif
+
mutex_enter(&sc->sc_lock);
sc->sc_intr_ipd |= ipd;
cv_broadcast(&sc->sc_cv);
@@ -183,12 +195,12 @@ rkiic_exec(void *priv, i2c_op_t op, i2c_
{
struct rkiic_softc *sc = priv;
uint32_t con, ien;
- u_int mode;
+ u_int mode, sraddr;
int error;
KASSERT(mutex_owned(&sc->sc_lock));
- if (sc->sc_ih == NULL) {
+ if (sc->sc_ih == NULL || cold) {
flags |= I2C_F_POLL;
}
@@ -199,30 +211,27 @@ rkiic_exec(void *priv, i2c_op_t op, i2c_
if (error)
return error;
- I2C_WRITE(sc, I2C_MRXADDR_REG, I2C_MRXADDR_ADDLVLD |
- __SHIFTIN(addr, I2C_MRXADDR_SADDR));
-
if (cmdlen == 1) {
- const uint8_t reg = *(const uint8_t *)cmdbuf;
if (I2C_OP_READ_P(op)) {
mode = I2C_CON_MODE_TRX;
} else {
mode = I2C_CON_MODE_TX;
}
- I2C_WRITE(sc, I2C_MRXRADDR_REG, I2C_MRXRADDR_SRADDLVLD |
- __SHIFTIN(reg, I2C_MRXRADDR_SRADDR));
+ sraddr = *(const uint8_t *)cmdbuf;
} else {
if (I2C_OP_READ_P(op)) {
mode = I2C_CON_MODE_RX;
} else {
mode = I2C_CON_MODE_TX;
}
- I2C_WRITE(sc, I2C_MRXRADDR_REG, 0);
+ sraddr = 0;
}
sc->sc_intr_ipd = 0;
+ I2C_WRITE(sc, I2C_IPD_REG, I2C_READ(sc, I2C_IPD_REG));
- ien = I2C_INT_START | (I2C_OP_READ_P(op) ? I2C_INT_MBRF : I2C_INT_MBTF);
+ ien = I2C_OP_READ_P(op) ? I2C_INT_MBRF : I2C_INT_MBTF;
+ ien |= I2C_INT_START | I2C_INT_STOP | I2C_INT_NAKRCV;
I2C_WRITE(sc, I2C_IEN_REG, ien);
con = I2C_CON_START | I2C_CON_EN | I2C_CON_ACK |
@@ -236,6 +245,13 @@ rkiic_exec(void *priv, i2c_op_t op, i2c_
#endif
goto done;
}
+ con &= ~I2C_CON_START;
+ I2C_WRITE(sc, I2C_CON_REG, con);
+
+ I2C_WRITE(sc, I2C_MRXADDR_REG, I2C_MRXADDR_ADDLVLD |
+ __SHIFTIN((addr << 1), I2C_MRXADDR_SADDR));
+ I2C_WRITE(sc, I2C_MRXRADDR_REG, I2C_MRXRADDR_SRADDLVLD |
+ __SHIFTIN(sraddr, I2C_MRXRADDR_SRADDR));
if (I2C_OP_READ_P(op)) {
error = rkiic_read(sc, addr, buf, len, flags);
@@ -244,10 +260,22 @@ rkiic_exec(void *priv, i2c_op_t op, i2c_
}
if (I2C_OP_STOP_P(op)) {
- I2C_WRITE(sc, I2C_CON_REG, I2C_CON_STOP);
+ con = I2C_READ(sc, I2C_CON_REG);
+ con |= I2C_CON_STOP;
+ I2C_WRITE(sc, I2C_CON_REG, con);
+ if (rkiic_wait(sc, I2C_INT_STOP, hz, flags) != 0) {
+#ifdef RKIIC_DEBUG
+ device_printf(sc->sc_dev, "timeout waiting for stop\n");
+#endif
+ error = ETIMEDOUT;
+ goto done;
+ }
+ con &= ~I2C_CON_STOP;
+ I2C_WRITE(sc, I2C_CON_REG, con);
}
done:
+ I2C_WRITE(sc, I2C_CON_REG, 0);
I2C_WRITE(sc, I2C_IEN_REG, 0);
return error;
}
@@ -283,6 +311,9 @@ rkiic_wait(struct rkiic_softc *sc, uint3
}
}
+#ifdef RKIIC_DEBUG
+ device_printf(sc->sc_dev, "%s: ipd %#x\n", __func__, sc->sc_intr_ipd);
+#endif
return ETIMEDOUT;
}
@@ -307,6 +338,13 @@ rkiic_read(struct rkiic_softc *sc, i2c_a
return error;
}
+ if (sc->sc_intr_ipd & I2C_INT_NAKRCV) {
+#ifdef RKIIC_DEBUG
+ device_printf(sc->sc_dev, "nak received\n");
+#endif
+ return EIO;
+ }
+
for (off = 0, resid = buflen; off < 8 && resid > 0; off++) {
const uint32_t data = I2C_READ(sc, I2C_RXDATA_REG(off));
for (byte = 0; byte < 4 && resid > 0; byte++, resid--) {
@@ -346,6 +384,13 @@ rkiic_write(struct rkiic_softc *sc, i2c_
return error;
}
+ if (sc->sc_intr_ipd & I2C_INT_NAKRCV) {
+#ifdef RKIIC_DEBUG
+ device_printf(sc->sc_dev, "nak received\n");
+#endif
+ return EIO;
+ }
+
return 0;
}