Commit f3f94ce5 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6

* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
  i2c-algo-bit: Read block data bugfix
  i2c-pxa: Fix adapter number
  i2c-gpio: Fix adapter number
parents 5d9adefc 939bc494
...@@ -357,13 +357,29 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) ...@@ -357,13 +357,29 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
return wrcount; return wrcount;
} }
static int acknak(struct i2c_adapter *i2c_adap, int is_ack)
{
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
/* assert: sda is high */
if (is_ack) /* send ack */
setsda(adap, 0);
udelay((adap->udelay + 1) / 2);
if (sclhi(adap) < 0) { /* timeout */
dev_err(&i2c_adap->dev, "readbytes: ack/nak timeout\n");
return -ETIMEDOUT;
}
scllo(adap);
return 0;
}
static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
{ {
int inval; int inval;
int rdcount=0; /* counts bytes read */ int rdcount=0; /* counts bytes read */
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
unsigned char *temp = msg->buf; unsigned char *temp = msg->buf;
int count = msg->len; int count = msg->len;
const unsigned flags = msg->flags;
while (count > 0) { while (count > 0) {
inval = i2c_inb(i2c_adap); inval = i2c_inb(i2c_adap);
...@@ -377,28 +393,12 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) ...@@ -377,28 +393,12 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
temp++; temp++;
count--; count--;
if (msg->flags & I2C_M_NO_RD_ACK) {
bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x\n",
inval);
continue;
}
/* assert: sda is high */
if (count) /* send ack */
setsda(adap, 0);
udelay((adap->udelay + 1) / 2);
bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x %s\n", inval,
count ? "A" : "NA");
if (sclhi(adap)<0) { /* timeout */
dev_err(&i2c_adap->dev, "readbytes: timeout at ack\n");
return -ETIMEDOUT;
};
scllo(adap);
/* Some SMBus transactions require that we receive the /* Some SMBus transactions require that we receive the
transaction length as the first read byte. */ transaction length as the first read byte. */
if (rdcount == 1 && (msg->flags & I2C_M_RECV_LEN)) { if (rdcount == 1 && (flags & I2C_M_RECV_LEN)) {
if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) { if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {
if (!(flags & I2C_M_NO_RD_ACK))
acknak(i2c_adap, 0);
dev_err(&i2c_adap->dev, "readbytes: invalid " dev_err(&i2c_adap->dev, "readbytes: invalid "
"block length (%d)\n", inval); "block length (%d)\n", inval);
return -EREMOTEIO; return -EREMOTEIO;
...@@ -409,6 +409,18 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) ...@@ -409,6 +409,18 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
count += inval; count += inval;
msg->len += inval; msg->len += inval;
} }
bit_dbg(2, &i2c_adap->dev, "readbytes: 0x%02x %s\n",
inval,
(flags & I2C_M_NO_RD_ACK)
? "(no ack/nak)"
: (count ? "A" : "NA"));
if (!(flags & I2C_M_NO_RD_ACK)) {
inval = acknak(i2c_adap, count);
if (inval < 0)
return inval;
}
} }
return rdcount; return rdcount;
} }
......
...@@ -147,7 +147,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev) ...@@ -147,7 +147,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev)
* The reason to do so is to avoid sysfs names that only make * The reason to do so is to avoid sysfs names that only make
* sense when there are multiple adapters. * sense when there are multiple adapters.
*/ */
adap->nr = pdev->id >= 0 ? pdev->id : 0; adap->nr = (pdev->id != -1) ? pdev->id : 0;
ret = i2c_bit_add_numbered_bus(adap); ret = i2c_bit_add_numbered_bus(adap);
if (ret) if (ret)
goto err_add_bus; goto err_add_bus;
......
...@@ -926,7 +926,7 @@ static int i2c_pxa_probe(struct platform_device *dev) ...@@ -926,7 +926,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
* The reason to do so is to avoid sysfs names that only make * The reason to do so is to avoid sysfs names that only make
* sense when there are multiple adapters. * sense when there are multiple adapters.
*/ */
i2c->adap.nr = dev->id >= 0 ? dev->id : 0; i2c->adap.nr = dev->id != -1 ? dev->id : 0;
ret = i2c_add_numbered_adapter(&i2c->adap); ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) { if (ret < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment