Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/xscale Support slave mode for PXA2x0 I2C.



details:   https://anonhg.NetBSD.org/src/rev/ad5ef35b8031
branches:  trunk
changeset: 767988:ad5ef35b8031
user:      kiyohara <kiyohara%NetBSD.org@localhost>
date:      Sat Aug 06 03:42:11 2011 +0000

description:
Support slave mode for PXA2x0 I2C.

diffstat:

 sys/arch/arm/xscale/pxa2x0_i2c.c |  231 +++++++++++++++++++++++++++++++++++---
 sys/arch/arm/xscale/pxa2x0_i2c.h |   19 ++-
 2 files changed, 225 insertions(+), 25 deletions(-)

diffs (truncated from 387 to 300 lines):

diff -r 00086a91e900 -r ad5ef35b8031 sys/arch/arm/xscale/pxa2x0_i2c.c
--- a/sys/arch/arm/xscale/pxa2x0_i2c.c  Fri Aug 05 21:20:27 2011 +0000
+++ b/sys/arch/arm/xscale/pxa2x0_i2c.c  Sat Aug 06 03:42:11 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pxa2x0_i2c.c,v 1.7 2011/06/23 11:26:22 kiyohara Exp $  */
+/*     $NetBSD: pxa2x0_i2c.c,v 1.8 2011/08/06 03:42:11 kiyohara Exp $  */
 /*     $OpenBSD: pxa2x0_i2c.c,v 1.2 2005/05/26 03:52:07 pascoe Exp $   */
 
 /*
@@ -18,12 +18,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pxa2x0_i2c.c,v 1.7 2011/06/23 11:26:22 kiyohara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pxa2x0_i2c.c,v 1.8 2011/08/06 03:42:11 kiyohara Exp $");
 
 #include <sys/param.h>
-#include <sys/systm.h>
+#include <sys/bus.h>
 #include <sys/device.h>
-#include <sys/bus.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
 
 #include <dev/i2c/i2cvar.h>
 
@@ -118,7 +119,7 @@
 
 retry:
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
-       bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
+       bus_space_write_4(iot, ioh, I2C_ISAR, sc->sc_isar);
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE | ISR_IRF);
        delay(1);
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
@@ -162,8 +163,7 @@
 
        rv = bus_space_read_4(iot, ioh, I2C_IDBR);
        *valuep = (u_char)rv;
-       rv = bus_space_read_4(iot, ioh, I2C_ICR);
-       bus_space_write_4(iot, ioh, I2C_ICR, rv & ~(ICR_STOP | ICR_ACKNAK));
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_BEIE | ICR_SADIE);
 
        return 0;
 
@@ -172,9 +172,9 @@
                goto retry;
 
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
-       bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
+       bus_space_write_4(iot, ioh, I2C_ISAR, sc->sc_isar);
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE | ISR_IRF);
-       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_BEIE | ICR_SADIE);
 
        return EIO;
 }
@@ -190,7 +190,7 @@
 
 retry:
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
-       bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
+       bus_space_write_4(iot, ioh, I2C_ISAR, sc->sc_isar);
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
        delay(1);
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
@@ -235,8 +235,7 @@
 
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
 
-       rv = bus_space_read_4(iot, ioh, I2C_ICR);
-       bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_BEIE | ICR_SADIE);
 
        return 0;
 
@@ -245,9 +244,9 @@
                goto retry;
 
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
-       bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
+       bus_space_write_4(iot, ioh, I2C_ISAR, sc->sc_isar);
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
-       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_BEIE | ICR_SADIE);
 
        return EIO;
 }
@@ -266,7 +265,7 @@
 
 retry:
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
-       bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
+       bus_space_write_4(iot, ioh, I2C_ISAR, sc->sc_isar);
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
        delay(1);
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
@@ -290,8 +289,7 @@
 
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
 
-       rv = bus_space_read_4(iot, ioh, I2C_ICR);
-       bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_BEIE | ICR_SADIE);
 
        return 0;
 
@@ -300,9 +298,9 @@
                goto retry;
 
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
-       bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
+       bus_space_write_4(iot, ioh, I2C_ISAR, sc->sc_isar);
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
-       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_BEIE | ICR_SADIE);
 
        return EIO;
 }
@@ -318,7 +316,7 @@
 
 retry:
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
-       bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
+       bus_space_write_4(iot, ioh, I2C_ISAR, sc->sc_isar);
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
        delay(1);
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
@@ -386,6 +384,8 @@
        rv = bus_space_read_4(iot, ioh, I2C_ICR);
        bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
 
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_BEIE | ICR_SADIE);
+
        return 0;
 
 err:
@@ -393,9 +393,9 @@
                goto retry;
 
        bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
-       bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
+       bus_space_write_4(iot, ioh, I2C_ISAR, sc->sc_isar);
        bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
-       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_BEIE | ICR_SADIE);
 
        return EIO;
 }
@@ -529,3 +529,190 @@
        }
        return 0;
 }
+
+
+int
+pxa2x0_i2c_poll(struct pxa2x0_i2c_softc *sc, int len, char *data, int op)
+{
+       bus_space_tag_t iot = sc->sc_iot;
+       bus_space_handle_t ioh = sc->sc_ioh;
+       uint32_t rv;
+       int timeout, tries, n = 0;
+
+       KASSERT(len > 0);
+
+       if (sc->sc_stat == PI2C_STAT_SEND) {
+               if (op != I2C_F_WRITE)
+                       return 0;
+               goto send;
+       } else if (sc->sc_stat == PI2C_STAT_RECEIVE) {
+               if (op != I2C_F_READ)
+                       return 0;
+               goto receive;
+       }
+
+       bus_space_write_4(iot, ioh, I2C_ISAR, sc->sc_isar);
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SADIE);
+
+       /* Poll Slave Address Detected */
+       tries = I2C_RETRY_COUNT;
+       while (1 /*CONSTCOND*/) {
+               rv = bus_space_read_4(iot, ioh, I2C_ISR);
+               if ((rv & (ISR_SAD | ISR_UB)) == (ISR_SAD | ISR_UB))
+                       break;
+               if (--tries <= 0)
+                       return 0;
+               delay(1000);    /* XXXX */
+       }
+       bus_space_write_4(iot, ioh, I2C_ISR, ISR_SAD);  /* Clear SAD */
+
+       rv = bus_space_read_4(iot, ioh, I2C_ISR);
+       if (rv & ISR_RWM) {
+               if (op != I2C_F_WRITE)
+                       return 0;
+               if (rv & ISR_ACKNAK)
+                       return 0;
+
+send:
+               bus_space_write_4(iot, ioh, I2C_IDBR, data[n]);
+
+               /* Initiate the transfer */
+               rv = bus_space_read_4(iot, ioh, I2C_ICR);
+               bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB | ICR_ITEIE);
+
+               while (n < len - 1) {
+                       timeout = 10000;
+                       while (--timeout > 0) {
+                               rv = bus_space_read_4(iot, ioh, I2C_ISR);
+                               rv &= (ISR_ITE | ISR_ACKNAK | ISR_RWM);
+                               if (rv == ISR_ITE)
+                                       break;
+                               delay(1);
+                       }
+                       if (timeout == 0)
+                               goto err;
+                       bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
+
+                       n++;
+                       if (n < len)
+                               bus_space_write_4(iot, ioh, I2C_IDBR, data[n]);
+
+                       rv = bus_space_read_4(iot, ioh, I2C_ICR);
+                       bus_space_write_4(iot, ioh, I2C_ICR,
+                           rv | ICR_TB | ICR_ITEIE);
+               }
+
+               timeout = 10000;
+               while (--timeout > 0) {
+                       rv = bus_space_read_4(iot, ioh, I2C_ISR);
+                       rv &= (ISR_ITE | ISR_ACKNAK | ISR_RWM);
+                       if (rv == (ISR_ITE | ISR_ACKNAK))
+                               break;
+                       delay(1);
+               }
+               if (timeout == 0)
+                       goto err;
+               bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
+
+               n++;
+       } else {
+               if (op != I2C_F_READ)
+                       return 0;
+
+               while (n < len) {
+                       rv = bus_space_read_4(iot, ioh, I2C_ICR);
+                       bus_space_write_4(iot, ioh, I2C_ICR,
+                           rv | ICR_TB | ICR_IRFIE);
+
+receive:
+                       timeout = 10000;
+                       while (--timeout > 0) {
+                               rv = bus_space_read_4(iot, ioh, I2C_ISR);
+                               rv &= (ISR_IRF | ISR_ACKNAK | ISR_RWM);
+                               if (rv == ISR_IRF)
+                                       break;
+                               delay(1);
+                       }
+                       if (timeout == 0)
+                               goto err;
+
+                       data[n++] = bus_space_read_4(iot, ioh, I2C_IDBR);
+
+                       bus_space_write_4(iot, ioh, I2C_ISR, ISR_IRF);
+               }
+
+               /* Release I2C bus and allow next transfer. */
+               rv = bus_space_read_4(iot, ioh, I2C_ICR);
+               bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
+       }
+
+       timeout = 10000;
+       while (--timeout > 0) {
+               rv = bus_space_read_4(iot, ioh, I2C_ISR);
+               rv &= (ISR_UB | ISR_SSD);
+               if (rv == ISR_SSD)
+                       break;
+               delay(1);
+       }
+       if (timeout == 0)
+               goto err;
+       bus_space_write_4(iot, ioh, I2C_ISR, ISR_SSD);
+
+err:
+       bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_BEIE | ICR_SADIE);
+
+       sc->sc_stat = PI2C_STAT_STOP;
+       return n;
+}
+
+int
+pxa2x0_i2c_intr_sub(struct pxa2x0_i2c_softc *sc, int *len, uint8_t *buf)
+{
+       bus_space_tag_t iot = sc->sc_iot;
+       bus_space_handle_t ioh = sc->sc_ioh;
+       int rv;
+       uint16_t isr;
+
+       isr = bus_space_read_4(iot, ioh, I2C_ISR);
+       bus_space_write_4(iot, ioh, I2C_ISR,
+         isr & (ISR_BED|ISR_SAD|ISR_IRF|ISR_ITE|ISR_ALD|ISR_SSD));



Home | Main Index | Thread Index | Old Index