Port-arm archive

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

Re: NSLU2 not reading real-time clock on bootup



don%donhayford.com@localhost wrote:

> Chris Gilbert wrote:
> > Donald T Hayford wrote:
> >> I built a kerrnel to add usb audio.  Source was retrieved June 2, 1800
> >> EDT.  The startup messages on the console and an attempt to set the
> >> clock from the command line indicate that the I2C driver isn't talking
> >> to the clock again.
> >>
> >
> > Random stab in the dark, what happens is you roll back:
> > src/sys/dev/i2c: i2c_bitbang.c
> >
> > As there were some changes made to it recently:
> > http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/dev/i2c/i2c_bitbang.c
> >
> > Thanks,
> > Chris
> It boots correctly when I revert back to v1.10 of i2c_bitbang.c.   Thanks.

Isn't it better to fix MD backend rather than breaking another I2C device?
---

Index: nslu2_iic.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/nslu2/nslu2_iic.c,v
retrieving revision 1.5
diff -u -r1.5 nslu2_iic.c
--- nslu2_iic.c 28 Apr 2008 20:23:17 -0000      1.5
+++ nslu2_iic.c 6 Jun 2008 14:12:12 -0000
@@ -49,9 +49,7 @@
        struct i2c_controller sc_ic;
        struct i2c_bitbang_ops sc_ibo;
        kmutex_t sc_lock;
-#ifdef DIAGNOSTIC
        uint32_t sc_dirout;
-#endif
 };
 
 static int
@@ -120,42 +118,70 @@
 static void
 slugiic_set_dir(void *arg, uint32_t bits)
 {
-#ifdef DIAGNOSTIC
        struct slugiic_softc *sc = arg;
+       uint32_t reg;
+       int s;
+
+       if (sc->sc_dirout == bits)
+               return;
+
+       s = splhigh();
 
        sc->sc_dirout = bits;
-#endif
+
+       if (sc->sc_dirout) {
+               /* SDA is output; enable SDA output if SDA OUTR is low */
+               reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOUTR);
+               if ((reg & GPIO_I2C_SDA_BIT) == 0) {
+                       reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOER);
+                       reg |= GPIO_I2C_SDA_BIT;
+                       GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOER, reg);
+               }
+       } else {
+               /* SDA is input; disable SDA output */
+               reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOER);
+               reg &= ~GPIO_I2C_SDA_BIT;
+               GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOER, reg);
+       }
+
+       splx(s);
 }
 
 static void
 slugiic_set_bits(void *arg, uint32_t bits)
 {
-       uint32_t reg;
-       int s;
-
-#ifdef DIAGNOSTIC
        struct slugiic_softc *sc = arg;
-       if (sc->sc_dirout == 0 && (bits & GPIO_I2C_SDA_BIT) == 0) {
-               printf("slugiic_set_bits: SDA low in input mode!\n");
-               bits |= GPIO_I2C_SDA_BIT;
-       }
-#endif
+       uint32_t oer, outr;
+       int s;
 
        s = splhigh();
 
-       reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOUTR);
-       reg &= ~(GPIO_I2C_SDA_BIT | GPIO_I2C_SCL_BIT);
-       GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOUTR, reg | bits);
-
        /*
-        * Enable output only if the SDA/SCL lines are to be driven low.
-        * Otherwise switch to input and allow the pullup resistors
-        * to hold them high.
+        * Enable SCL output if the SCL line is to be driven low.
+        * Enable SDA output if the SDA line is to be driven low and
+        * SDA direction is output.
+        * Otherwise switch them to input even if directions are output
+        * so that we can emulate open collector output with the pullup
+        * resistors.
+        * If lines are to be set to high, disable OER first then set OUTR.
+        * If lines are to be set to low, set OUTR first then enable OER.
         */
-       reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOER);
-       reg &= ~(GPIO_I2C_SDA_BIT | GPIO_I2C_SCL_BIT);
-       reg |= bits & (GPIO_I2C_SDA_BIT | GPIO_I2C_SCL_BIT);
-       GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOER, reg);
+       oer = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOER);
+       if ((bits & GPIO_I2C_SCL_BIT) != 0)
+               oer &= ~GPIO_I2C_SCL_BIT;
+       if ((bits & GPIO_I2C_SDA_BIT) != 0)
+               oer &= ~GPIO_I2C_SDA_BIT;
+       GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOER, oer);
+
+       outr = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOUTR);
+       outr &= ~(GPIO_I2C_SDA_BIT | GPIO_I2C_SCL_BIT);
+       GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOUTR, outr | bits);
+
+       if ((bits & GPIO_I2C_SCL_BIT) == 0)
+               oer |= GPIO_I2C_SCL_BIT;
+       if ((bits & GPIO_I2C_SDA_BIT) == 0 && sc->sc_dirout)
+               oer |= GPIO_I2C_SDA_BIT;
+       GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOER, oer);
 
        splx(s);
 }
@@ -165,12 +191,6 @@
 {
        uint32_t reg;
 
-#ifdef DIAGNOSTIC
-       struct slugiic_softc *sc = arg;
-       if (sc->sc_dirout)
-               printf("slugiic_read_bits: Read in output mode\n");
-#endif
-
        reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPINR);
        return (reg & (GPIO_I2C_SDA_BIT | GPIO_I2C_SCL_BIT));
 }
@@ -230,9 +250,7 @@
 
        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
 
-#ifdef DIAGNOSTIC
        sc->sc_dirout = 0;
-#endif
 
        /*
         * Defer until ixp425_softc has been initialised

---
Izumi Tsutsui


Home | Main Index | Thread Index | Old Index