Commit 9dfee148 authored by Heiner Kallweit's avatar Heiner Kallweit Committed by Wolfram Sang

i2c: algo: bit: allow getsda to be NULL

This is in preparation of supporting write-only SDA in i2c-gpio.
Signed-off-by: default avatarHeiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
parent a00bb94c
...@@ -184,8 +184,9 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c) ...@@ -184,8 +184,9 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
/* read ack: SDA should be pulled down by slave, or it may /* read ack: SDA should be pulled down by slave, or it may
* NAK (usually to report problems with the data we wrote). * NAK (usually to report problems with the data we wrote).
* Always report ACK if SDA is write-only.
*/ */
ack = !getsda(adap); /* ack: sda is pulled low -> success */ ack = !adap->getsda || !getsda(adap); /* ack: sda is pulled low -> success */
bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c, bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
ack ? "A" : "NA"); ack ? "A" : "NA");
...@@ -238,71 +239,55 @@ static int test_bus(struct i2c_adapter *i2c_adap) ...@@ -238,71 +239,55 @@ static int test_bus(struct i2c_adapter *i2c_adap)
return -ENODEV; return -ENODEV;
} }
if (adap->getsda == NULL)
pr_info("%s: SDA is write-only, testing not possible\n", name);
if (adap->getscl == NULL) if (adap->getscl == NULL)
pr_info("%s: Testing SDA only, SCL is not readable\n", name); pr_info("%s: SCL is write-only, testing not possible\n", name);
sda = getsda(adap); sda = adap->getsda ? getsda(adap) : 1;
scl = (adap->getscl == NULL) ? 1 : getscl(adap); scl = adap->getscl ? getscl(adap) : 1;
if (!scl || !sda) { if (!scl || !sda) {
printk(KERN_WARNING pr_warn("%s: bus seems to be busy (scl=%d, sda=%d)\n", name, scl, sda);
"%s: bus seems to be busy (scl=%d, sda=%d)\n",
name, scl, sda);
goto bailout; goto bailout;
} }
sdalo(adap); sdalo(adap);
sda = getsda(adap); if (adap->getsda && getsda(adap)) {
scl = (adap->getscl == NULL) ? 1 : getscl(adap); pr_warn("%s: SDA stuck high!\n", name);
if (sda) {
printk(KERN_WARNING "%s: SDA stuck high!\n", name);
goto bailout; goto bailout;
} }
if (!scl) { if (adap->getscl && !getscl(adap)) {
printk(KERN_WARNING pr_warn("%s: SCL unexpected low while pulling SDA low!\n", name);
"%s: SCL unexpected low while pulling SDA low!\n",
name);
goto bailout; goto bailout;
} }
sdahi(adap); sdahi(adap);
sda = getsda(adap); if (adap->getsda && !getsda(adap)) {
scl = (adap->getscl == NULL) ? 1 : getscl(adap); pr_warn("%s: SDA stuck low!\n", name);
if (!sda) {
printk(KERN_WARNING "%s: SDA stuck low!\n", name);
goto bailout; goto bailout;
} }
if (!scl) { if (adap->getscl && !getscl(adap)) {
printk(KERN_WARNING pr_warn("%s: SCL unexpected low while pulling SDA high!\n", name);
"%s: SCL unexpected low while pulling SDA high!\n",
name);
goto bailout; goto bailout;
} }
scllo(adap); scllo(adap);
sda = getsda(adap); if (adap->getscl && getscl(adap)) {
scl = (adap->getscl == NULL) ? 0 : getscl(adap); pr_warn("%s: SCL stuck high!\n", name);
if (scl) {
printk(KERN_WARNING "%s: SCL stuck high!\n", name);
goto bailout; goto bailout;
} }
if (!sda) { if (adap->getsda && !getsda(adap)) {
printk(KERN_WARNING pr_warn("%s: SDA unexpected low while pulling SCL low!\n", name);
"%s: SDA unexpected low while pulling SCL low!\n",
name);
goto bailout; goto bailout;
} }
sclhi(adap); sclhi(adap);
sda = getsda(adap); if (adap->getscl && !getscl(adap)) {
scl = (adap->getscl == NULL) ? 1 : getscl(adap); pr_warn("%s: SCL stuck low!\n", name);
if (!scl) {
printk(KERN_WARNING "%s: SCL stuck low!\n", name);
goto bailout; goto bailout;
} }
if (!sda) { if (adap->getsda && !getsda(adap)) {
printk(KERN_WARNING pr_warn("%s: SDA unexpected low while pulling SCL high!\n", name);
"%s: SDA unexpected low while pulling SCL high!\n",
name);
goto bailout; goto bailout;
} }
...@@ -420,6 +405,10 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) ...@@ -420,6 +405,10 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
unsigned char *temp = msg->buf; unsigned char *temp = msg->buf;
int count = msg->len; int count = msg->len;
const unsigned flags = msg->flags; const unsigned flags = msg->flags;
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
if (!adap->getsda)
return -EOPNOTSUPP;
while (count > 0) { while (count > 0) {
inval = i2c_inb(i2c_adap); inval = i2c_inb(i2c_adap);
...@@ -670,11 +659,15 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap, ...@@ -670,11 +659,15 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap,
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Complain if SCL can't be read */ if (bit_adap->getsda == NULL)
if (bit_adap->getscl == NULL) { dev_warn(&adap->dev, "Not I2C compliant: can't read SDA\n");
if (bit_adap->getscl == NULL)
dev_warn(&adap->dev, "Not I2C compliant: can't read SCL\n"); dev_warn(&adap->dev, "Not I2C compliant: can't read SCL\n");
if (bit_adap->getsda == NULL || bit_adap->getscl == NULL)
dev_warn(&adap->dev, "Bus may be unreliable\n"); dev_warn(&adap->dev, "Bus may be unreliable\n");
}
return 0; return 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