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 <jmcne...@invisible.ca>
@@ -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;
 
 }

Reply via email to