Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 193168
b: refs/heads/master
c: dd7319a
h: refs/heads/master
v: v3
  • Loading branch information
Sonic Zhang authored and Ben Dooks committed May 19, 2010
1 parent 0c727a1 commit dd8f204
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 60 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1bc2962e530527de829bf4b1eb99f24dc25d1828
refs/heads/master: dd7319a5289deb4e17beb8851d343e7930b32c3b
125 changes: 66 additions & 59 deletions trunk/drivers/i2c/busses/i2c-bfin-twi.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
#include <asm/portmux.h>
#include <asm/irq.h>

#define POLL_TIMEOUT (2 * HZ)

/* SMBus mode*/
#define TWI_I2C_MODE_STANDARD 1
#define TWI_I2C_MODE_STANDARDSUB 2
Expand All @@ -44,8 +42,6 @@ struct bfin_twi_iface {
int cur_mode;
int manual_stop;
int result;
int timeout_count;
struct timer_list timeout_timer;
struct i2c_adapter adap;
struct completion complete;
struct i2c_msg *pmsg;
Expand Down Expand Up @@ -169,16 +165,13 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
write_INT_MASK(iface, 0);
write_MASTER_CTL(iface, 0);
SSYNC();
/* If it is a quick transfer, only address bug no data,
/* If it is a quick transfer, only address without data,
* not an err, return 1.
* If address is acknowledged return 1.
*/
if (iface->writeNum == 0 && (mast_stat & BUFRDERR))
if ((iface->writeNum == 0 && (mast_stat & BUFRDERR))
|| !(mast_stat & ANAK))
iface->result = 1;
/* If address not acknowledged return -1,
* else return 0.
*/
else if (!(mast_stat & ANAK))
iface->result = 0;
}
complete(&iface->complete);
return;
Expand Down Expand Up @@ -250,9 +243,9 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
write_INT_MASK(iface, 0);
write_MASTER_CTL(iface, 0);
SSYNC();
complete(&iface->complete);
}
}
complete(&iface->complete);
}

/* Interrupt handler */
Expand All @@ -262,36 +255,15 @@ static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id)
unsigned long flags;

spin_lock_irqsave(&iface->lock, flags);
del_timer(&iface->timeout_timer);
bfin_twi_handle_interrupt(iface);
spin_unlock_irqrestore(&iface->lock, flags);
return IRQ_HANDLED;
}

static void bfin_twi_timeout(unsigned long data)
{
struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data;
unsigned long flags;

spin_lock_irqsave(&iface->lock, flags);
bfin_twi_handle_interrupt(iface);
if (iface->result == 0) {
iface->timeout_count--;
if (iface->timeout_count > 0) {
iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
add_timer(&iface->timeout_timer);
} else {
iface->result = -1;
complete(&iface->complete);
}
}
spin_unlock_irqrestore(&iface->lock, flags);
}

/*
* Generic i2c master transfer entrypoint
* One i2c master transfer
*/
static int bfin_twi_master_xfer(struct i2c_adapter *adap,
static int bfin_twi_do_master_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
struct bfin_twi_iface *iface = adap->algo_data;
Expand Down Expand Up @@ -319,7 +291,6 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
iface->transPtr = pmsg->buf;
iface->writeNum = iface->readNum = pmsg->len;
iface->result = 0;
iface->timeout_count = 10;
init_completion(&(iface->complete));
/* Set Transmit device address */
write_MASTER_ADDR(iface, pmsg->addr);
Expand Down Expand Up @@ -358,30 +329,49 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
iface->manual_stop = 1;
}

iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
add_timer(&iface->timeout_timer);

/* Master enable */
write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
SSYNC();

wait_for_completion(&iface->complete);

rc = iface->result;
while (!iface->result) {
if (!wait_for_completion_timeout(&iface->complete,
adap->timeout)) {
iface->result = -1;
dev_err(&adap->dev, "master transfer timeout\n");
}
}

if (rc == 1)
return num;
if (iface->result == 1)
rc = iface->cur_msg + 1;
else
return rc;
rc = iface->result;

return rc;
}

/*
* SMBus type transfer entrypoint
* Generic i2c master transfer entrypoint
*/
static int bfin_twi_master_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
int i, ret = 0;

int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
for (i = 0; i < adap->retries; i++) {
ret = bfin_twi_do_master_xfer(adap, msgs, num);
if (ret > 0)
break;
}

return ret;
}

/*
* One I2C SMBus transfer
*/
int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data)
{
Expand Down Expand Up @@ -469,7 +459,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
iface->manual_stop = 0;
iface->read_write = read_write;
iface->command = command;
iface->timeout_count = 10;
init_completion(&(iface->complete));

/* FIFO Initiation. Data in FIFO should be discarded before
Expand All @@ -486,9 +475,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
write_MASTER_ADDR(iface, addr);
SSYNC();

iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
add_timer(&iface->timeout_timer);

switch (iface->cur_mode) {
case TWI_I2C_MODE_STANDARDSUB:
write_XMT_DATA8(iface, iface->command);
Expand Down Expand Up @@ -550,10 +536,8 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
else if (iface->readNum > 255) {
write_MASTER_CTL(iface, 0xff << 6);
iface->manual_stop = 1;
} else {
del_timer(&iface->timeout_timer);
} else
break;
}
}
}
write_INT_MASK(iface, MCOMP | MERR |
Expand All @@ -569,13 +553,38 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
}
SSYNC();

wait_for_completion(&iface->complete);
while (!iface->result) {
if (!wait_for_completion_timeout(&iface->complete,
adap->timeout)) {
iface->result = -1;
dev_err(&adap->dev, "smbus transfer timeout\n");
}
}

rc = (iface->result >= 0) ? 0 : -1;

return rc;
}

/*
* Generic I2C SMBus transfer entrypoint
*/
int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data)
{
int i, ret = 0;

for (i = 0; i < adap->retries; i++) {
ret = bfin_twi_do_smbus_xfer(adap, addr, flags,
read_write, command, size, data);
if (ret == 0)
break;
}

return ret;
}

/*
* Return what the adapter supports
*/
Expand Down Expand Up @@ -667,17 +676,15 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
goto out_error_no_irq;
}

init_timer(&(iface->timeout_timer));
iface->timeout_timer.function = bfin_twi_timeout;
iface->timeout_timer.data = (unsigned long)iface;

p_adap = &iface->adap;
p_adap->nr = pdev->id;
strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name));
p_adap->algo = &bfin_twi_algorithm;
p_adap->algo_data = iface;
p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
p_adap->dev.parent = &pdev->dev;
p_adap->timeout = 5 * HZ;
p_adap->retries = 3;

rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi");
if (rc) {
Expand Down

0 comments on commit dd8f204

Please sign in to comment.