IIC bitbang changes - prepare to make the bit delay configurable; debug print changes.

* Right now the delay is hard coded at 10uS. This is a bit long when doing lots
  of periodic i2c transactions. So create a 'udelay' parameter and initialise it
  to 10. This can be tuned later.

* Add a newline after a transaction finishes, so the debugging output isn't so
  horrible.
This commit is contained in:
adrian 2011-12-20 02:49:01 +00:00
parent f90cdf352e
commit 943f0fd2d3

View File

@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
struct iicbb_softc {
device_t iicbus;
int udelay; /* signal toggle delay in usec */
};
static int iicbb_attach(device_t);
@ -123,6 +124,7 @@ iicbb_attach(device_t dev)
sc->iicbus = device_add_child(dev, "iicbus", -1);
if (!sc->iicbus)
return (ENXIO);
sc->udelay = 10; /* 10 uS default */
bus_generic_attach(dev);
return (0);
@ -184,20 +186,18 @@ iicbb_print_child(device_t bus, device_t dev)
return (retval);
}
#define IIC_DELAY 10
#define I2C_SETSDA(dev,val) do { \
#define I2C_SETSDA(sc,dev,val) do { \
IICBB_SETSDA(device_get_parent(dev), val); \
DELAY(IIC_DELAY); \
DELAY(sc->udelay); \
} while (0)
#define I2C_SETSCL(dev,val) do { \
iicbb_setscl(dev, val, 100); \
} while (0)
#define I2C_SET(dev,ctrl,data) do { \
#define I2C_SET(sc,dev,ctrl,data) do { \
I2C_SETSCL(dev, ctrl); \
I2C_SETSDA(dev, data); \
I2C_SETSDA(sc, dev, data); \
} while (0)
#define I2C_GETSDA(dev) (IICBB_GETSDA(device_get_parent(dev)))
@ -216,34 +216,39 @@ static int i2c_debug = 0;
static void
iicbb_setscl(device_t dev, int val, int timeout)
{
struct iicbb_softc *sc = device_get_softc(dev);
int k = 0;
IICBB_SETSCL(device_get_parent(dev), val);
DELAY(IIC_DELAY);
DELAY(sc->udelay);
while (val && !I2C_GETSCL(dev) && k++ < timeout) {
IICBB_SETSCL(device_get_parent(dev), val);
DELAY(IIC_DELAY);
DELAY(sc->udelay);
}
return;
}
static void
iicbb_one(device_t dev, int timeout)
{
I2C_SET(dev,0,1);
I2C_SET(dev,1,1);
I2C_SET(dev,0,1);
struct iicbb_softc *sc = device_get_softc(dev);
I2C_SET(sc,dev,0,1);
I2C_SET(sc,dev,1,1);
I2C_SET(sc,dev,0,1);
return;
}
static void
iicbb_zero(device_t dev, int timeout)
{
I2C_SET(dev,0,0);
I2C_SET(dev,1,0);
I2C_SET(dev,0,0);
struct iicbb_softc *sc = device_get_softc(dev);
I2C_SET(sc,dev,0,0);
I2C_SET(sc,dev,1,0);
I2C_SET(sc,dev,0,0);
return;
}
@ -264,20 +269,21 @@ iicbb_zero(device_t dev, int timeout)
static int
iicbb_ack(device_t dev, int timeout)
{
struct iicbb_softc *sc = device_get_softc(dev);
int noack;
int k = 0;
I2C_SET(dev,0,1);
I2C_SET(dev,1,1);
I2C_SET(sc,dev,0,1);
I2C_SET(sc,dev,1,1);
do {
noack = I2C_GETSDA(dev);
if (!noack)
break;
DELAY(10);
k += 10;
DELAY(1);
k++;
} while (k < timeout);
I2C_SET(dev,0,1);
I2C_SET(sc,dev,0,1);
I2C_DEBUG(printf("%c ",noack?'-':'+'));
return (noack);
@ -302,16 +308,17 @@ iicbb_sendbyte(device_t dev, u_char data, int timeout)
static u_char
iicbb_readbyte(device_t dev, int last, int timeout)
{
struct iicbb_softc *sc = device_get_softc(dev);
int i;
unsigned char data=0;
I2C_SET(dev,0,1);
I2C_SET(sc,dev,0,1);
for (i=7; i>=0; i--)
{
I2C_SET(dev,1,1);
I2C_SET(sc,dev,1,1);
if (I2C_GETSDA(dev))
data |= (1<<i);
I2C_SET(dev,0,1);
I2C_SET(sc,dev,0,1);
}
if (last) {
iicbb_one(dev, timeout);
@ -337,13 +344,14 @@ iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
static int
iicbb_start(device_t dev, u_char slave, int timeout)
{
struct iicbb_softc *sc = device_get_softc(dev);
int error;
I2C_DEBUG(printf("<"));
I2C_SET(dev,1,1);
I2C_SET(dev,1,0);
I2C_SET(dev,0,0);
I2C_SET(sc,dev,1,1);
I2C_SET(sc,dev,1,0);
I2C_SET(sc,dev,0,0);
/* send address */
iicbb_sendbyte(dev, slave, timeout);
@ -364,10 +372,13 @@ iicbb_start(device_t dev, u_char slave, int timeout)
static int
iicbb_stop(device_t dev)
{
I2C_SET(dev,0,0);
I2C_SET(dev,1,0);
I2C_SET(dev,1,1);
struct iicbb_softc *sc = device_get_softc(dev);
I2C_SET(sc,dev,0,0);
I2C_SET(sc,dev,1,0);
I2C_SET(sc,dev,1,1);
I2C_DEBUG(printf(">"));
I2C_DEBUG(printf("\n"));
return (0);
}