- if SDA is set to low during DIR(INPUT) in gpiic_set_bits(),

store the SDA status into softc and enable it once after
  DIR() is changed to OUTPUT in gpiic_set_dir()
- remove "Read in output mode" warning in gpiic_read_bits()
  since it's a vaild operation (to read SCL during SDA output is low)

Tested by kiyohara@ on OPENBLOCKS266.
This commit is contained in:
tsutsui 2008-07-12 02:04:07 +00:00
parent e04577112e
commit ce1887dc69

View File

@ -1,4 +1,4 @@
/* $NetBSD: gpiic_opb.c,v 1.5 2007/12/06 17:00:33 ad Exp $ */
/* $NetBSD: gpiic_opb.c,v 1.6 2008/07/12 02:04:07 tsutsui Exp $ */
/*
* Copyright 2002, 2003 Wasabi Systems, Inc.
@ -55,6 +55,7 @@ struct gpiic_softc {
bus_space_tag_t sc_bust;
bus_space_handle_t sc_bush;
uint8_t sc_txen;
uint8_t sc_tx;
struct i2c_controller sc_i2c;
struct i2c_bitbang_ops sc_bops;
kmutex_t sc_buslock;
@ -105,6 +106,7 @@ gpiic_attach(struct device *parent, struct device *self, void *args)
mutex_init(&sc->sc_buslock, MUTEX_DEFAULT, IPL_NONE);
sc->sc_txen = 0;
sc->sc_tx = IIC_DIRECTCNTL_SCC | IIC_DIRECTCNTL_SDAC;
sc->sc_i2c.ic_cookie = sc;
sc->sc_i2c.ic_acquire_bus = gpiic_acquire_bus;
sc->sc_i2c.ic_release_bus = gpiic_release_bus;
@ -204,8 +206,18 @@ static void
gpiic_set_dir(void *arg, uint32_t bits)
{
struct gpiic_softc *sc = arg;
uint8_t tx, txen;
sc->sc_txen = (uint8_t)bits;
txen = (uint8_t)bits;
if (sc->sc_txen == txen)
return;
sc->sc_txen = txen;
tx = sc->sc_tx;
if (sc->sc_txen == 0)
tx |= IIC_DIRECTCNTL_SDAC;
bus_space_write_1(sc->sc_bust, sc->sc_bush, IIC_DIRECTCNTL, tx);
}
static void
@ -213,10 +225,9 @@ gpiic_set_bits(void *arg, uint32_t bits)
{
struct gpiic_softc *sc = arg;
if (sc->sc_txen == 0 && (bits & IIC_DIRECTCNTL_SDAC) == 0) {
printf("gpiic_set_bits: SDA low with no output enable\n");
sc->sc_tx = (uint8_t)bits;
if (sc->sc_txen == 0)
bits |= IIC_DIRECTCNTL_SDAC;
}
bus_space_write_1(sc->sc_bust, sc->sc_bush, IIC_DIRECTCNTL, bits);
}
@ -227,9 +238,6 @@ gpiic_read_bits(void *arg)
struct gpiic_softc *sc = arg;
uint8_t rv;
if (sc->sc_txen != 0)
printf("gpiic_read_bits: Read in output mode\n");
rv = bus_space_read_1(sc->sc_bust, sc->sc_bush, IIC_DIRECTCNTL) << 2;
rv &= (IIC_DIRECTCNTL_SCC | IIC_DIRECTCNTL_SDAC);