Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 91887
b: refs/heads/master
c: 4dd39bb
h: refs/heads/master
i:
  91885: 2341503
  91883: f5ccd9a
  91879: 6960711
  91871: 843aa71
v: v3
  • Loading branch information
Sonic Zhang authored and Jean Delvare committed Apr 22, 2008
1 parent 260fdaa commit c972cea
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 72 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: 4c03f68fc4ab902353336b6b0c6933617821cf70
refs/heads/master: 4dd39bb12f5b9f0d9a98f29071dc1c51e9306954
185 changes: 114 additions & 71 deletions trunk/drivers/i2c/busses/i2c-bfin-twi.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@
#define POLL_TIMEOUT (2 * HZ)

/* SMBus mode*/
#define TWI_I2C_MODE_STANDARD 0x01
#define TWI_I2C_MODE_STANDARDSUB 0x02
#define TWI_I2C_MODE_COMBINED 0x04
#define TWI_I2C_MODE_STANDARD 1
#define TWI_I2C_MODE_STANDARDSUB 2
#define TWI_I2C_MODE_COMBINED 3
#define TWI_I2C_MODE_REPEAT 4

struct bfin_twi_iface {
int irq;
Expand All @@ -58,6 +59,9 @@ struct bfin_twi_iface {
struct timer_list timeout_timer;
struct i2c_adapter adap;
struct completion complete;
struct i2c_msg *pmsg;
int msg_num;
int cur_msg;
};

static struct bfin_twi_iface twi_iface;
Expand All @@ -76,12 +80,16 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
/* start receive immediately after complete sending in
* combine mode.
*/
else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
else if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
| MDIR | RSTART);
} else if (iface->manual_stop)
else if (iface->manual_stop)
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
| STOP);
else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
iface->cur_msg+1 < iface->msg_num)
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
| RSTART);
SSYNC();
/* Clear status */
bfin_write_TWI_INT_STAT(XMTSERV);
Expand All @@ -108,6 +116,11 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
| STOP);
SSYNC();
} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
iface->cur_msg+1 < iface->msg_num) {
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
| RSTART);
SSYNC();
}
/* Clear interrupt source */
bfin_write_TWI_INT_STAT(RCVSERV);
Expand All @@ -119,7 +132,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
bfin_write_TWI_MASTER_STAT(0x3e);
bfin_write_TWI_MASTER_CTL(0);
SSYNC();
iface->result = -1;
iface->result = -EIO;
/* if both err and complete int stats are set, return proper
* results.
*/
Expand Down Expand Up @@ -170,6 +183,42 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
MEN | MDIR);
SSYNC();
} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
iface->cur_msg+1 < iface->msg_num) {
iface->cur_msg++;
iface->transPtr = iface->pmsg[iface->cur_msg].buf;
iface->writeNum = iface->readNum =
iface->pmsg[iface->cur_msg].len;
/* Set Transmit device address */
bfin_write_TWI_MASTER_ADDR(
iface->pmsg[iface->cur_msg].addr);
if (iface->pmsg[iface->cur_msg].flags & I2C_M_RD)
iface->read_write = I2C_SMBUS_READ;
else {
iface->read_write = I2C_SMBUS_WRITE;
/* Transmit first data */
if (iface->writeNum > 0) {
bfin_write_TWI_XMT_DATA8(
*(iface->transPtr++));
iface->writeNum--;
SSYNC();
}
}

if (iface->pmsg[iface->cur_msg].len <= 255)
bfin_write_TWI_MASTER_CTL(
iface->pmsg[iface->cur_msg].len << 6);
else {
bfin_write_TWI_MASTER_CTL(0xff << 6);
iface->manual_stop = 1;
}
/* remove restart bit and enable master receive */
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() &
~RSTART);
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
MEN | ((iface->read_write == I2C_SMBUS_READ) ?
MDIR : 0));
SSYNC();
} else {
iface->result = 1;
bfin_write_TWI_INT_MASK(0);
Expand Down Expand Up @@ -221,7 +270,6 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
{
struct bfin_twi_iface *iface = adap->algo_data;
struct i2c_msg *pmsg;
int i, ret;
int rc = 0;

if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
Expand All @@ -231,81 +279,76 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
yield();
}

ret = 0;
for (i = 0; rc >= 0 && i < num; i++) {
pmsg = &msgs[i];
if (pmsg->flags & I2C_M_TEN) {
dev_err(&(adap->dev), "i2c-bfin-twi: 10 bits addr "
"not supported !\n");
rc = -EINVAL;
break;
}
iface->pmsg = msgs;
iface->msg_num = num;
iface->cur_msg = 0;

iface->cur_mode = TWI_I2C_MODE_STANDARD;
iface->manual_stop = 0;
iface->transPtr = pmsg->buf;
iface->writeNum = iface->readNum = pmsg->len;
iface->result = 0;
iface->timeout_count = 10;
/* Set Transmit device address */
bfin_write_TWI_MASTER_ADDR(pmsg->addr);

/* FIFO Initiation. Data in FIFO should be
* discarded before start a new operation.
*/
bfin_write_TWI_FIFO_CTL(0x3);
SSYNC();
bfin_write_TWI_FIFO_CTL(0);
SSYNC();
pmsg = &msgs[0];
if (pmsg->flags & I2C_M_TEN) {
dev_err(&adap->dev, "10 bits addr not supported!\n");
return -EINVAL;
}

if (pmsg->flags & I2C_M_RD)
iface->read_write = I2C_SMBUS_READ;
else {
iface->read_write = I2C_SMBUS_WRITE;
/* Transmit first data */
if (iface->writeNum > 0) {
bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
iface->writeNum--;
SSYNC();
}
iface->cur_mode = TWI_I2C_MODE_REPEAT;
iface->manual_stop = 0;
iface->transPtr = pmsg->buf;
iface->writeNum = iface->readNum = pmsg->len;
iface->result = 0;
iface->timeout_count = 10;
/* Set Transmit device address */
bfin_write_TWI_MASTER_ADDR(pmsg->addr);

/* FIFO Initiation. Data in FIFO should be
* discarded before start a new operation.
*/
bfin_write_TWI_FIFO_CTL(0x3);
SSYNC();
bfin_write_TWI_FIFO_CTL(0);
SSYNC();

if (pmsg->flags & I2C_M_RD)
iface->read_write = I2C_SMBUS_READ;
else {
iface->read_write = I2C_SMBUS_WRITE;
/* Transmit first data */
if (iface->writeNum > 0) {
bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
iface->writeNum--;
SSYNC();
}
}

/* clear int stat */
bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
/* clear int stat */
bfin_write_TWI_INT_STAT(MERR | MCOMP | XMTSERV | RCVSERV);

/* Interrupt mask . Enable XMT, RCV interrupt */
bfin_write_TWI_INT_MASK(MCOMP | MERR |
((iface->read_write == I2C_SMBUS_READ)?
RCVSERV : XMTSERV));
SSYNC();
/* Interrupt mask . Enable XMT, RCV interrupt */
bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV);
SSYNC();

if (pmsg->len > 0 && pmsg->len <= 255)
bfin_write_TWI_MASTER_CTL(pmsg->len << 6);
else if (pmsg->len > 255) {
bfin_write_TWI_MASTER_CTL(0xff << 6);
iface->manual_stop = 1;
} else
break;
if (pmsg->len <= 255)
bfin_write_TWI_MASTER_CTL(pmsg->len << 6);
else {
bfin_write_TWI_MASTER_CTL(0xff << 6);
iface->manual_stop = 1;
}

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

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

wait_for_completion(&iface->complete);
wait_for_completion(&iface->complete);

rc = iface->result;
if (rc == 1)
ret++;
else if (rc == -1)
break;
}
rc = iface->result;

return ret;
if (rc == 1)
return num;
else
return rc;
}

/*
Expand Down

0 comments on commit c972cea

Please sign in to comment.