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; }