i2c: algo: bit: allow getsda to be NULL

This is in preparation of supporting write-only SDA in i2c-gpio.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
This commit is contained in:
Heiner Kallweit 2023-01-18 22:54:03 +01:00 committed by Wolfram Sang
parent a00bb94c7b
commit 9dfee1487c

View file

@ -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
* 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,
ack ? "A" : "NA");
@ -238,71 +239,55 @@ static int test_bus(struct i2c_adapter *i2c_adap)
return -ENODEV;
}
if (adap->getsda == NULL)
pr_info("%s: SDA is write-only, testing not possible\n", name);
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);
scl = (adap->getscl == NULL) ? 1 : getscl(adap);
sda = adap->getsda ? getsda(adap) : 1;
scl = adap->getscl ? getscl(adap) : 1;
if (!scl || !sda) {
printk(KERN_WARNING
"%s: bus seems to be busy (scl=%d, sda=%d)\n",
name, scl, sda);
pr_warn("%s: bus seems to be busy (scl=%d, sda=%d)\n", name, scl, sda);
goto bailout;
}
sdalo(adap);
sda = getsda(adap);
scl = (adap->getscl == NULL) ? 1 : getscl(adap);
if (sda) {
printk(KERN_WARNING "%s: SDA stuck high!\n", name);
if (adap->getsda && getsda(adap)) {
pr_warn("%s: SDA stuck high!\n", name);
goto bailout;
}
if (!scl) {
printk(KERN_WARNING
"%s: SCL unexpected low while pulling SDA low!\n",
name);
if (adap->getscl && !getscl(adap)) {
pr_warn("%s: SCL unexpected low while pulling SDA low!\n", name);
goto bailout;
}
sdahi(adap);
sda = getsda(adap);
scl = (adap->getscl == NULL) ? 1 : getscl(adap);
if (!sda) {
printk(KERN_WARNING "%s: SDA stuck low!\n", name);
if (adap->getsda && !getsda(adap)) {
pr_warn("%s: SDA stuck low!\n", name);
goto bailout;
}
if (!scl) {
printk(KERN_WARNING
"%s: SCL unexpected low while pulling SDA high!\n",
name);
if (adap->getscl && !getscl(adap)) {
pr_warn("%s: SCL unexpected low while pulling SDA high!\n", name);
goto bailout;
}
scllo(adap);
sda = getsda(adap);
scl = (adap->getscl == NULL) ? 0 : getscl(adap);
if (scl) {
printk(KERN_WARNING "%s: SCL stuck high!\n", name);
if (adap->getscl && getscl(adap)) {
pr_warn("%s: SCL stuck high!\n", name);
goto bailout;
}
if (!sda) {
printk(KERN_WARNING
"%s: SDA unexpected low while pulling SCL low!\n",
name);
if (adap->getsda && !getsda(adap)) {
pr_warn("%s: SDA unexpected low while pulling SCL low!\n", name);
goto bailout;
}
sclhi(adap);
sda = getsda(adap);
scl = (adap->getscl == NULL) ? 1 : getscl(adap);
if (!scl) {
printk(KERN_WARNING "%s: SCL stuck low!\n", name);
if (adap->getscl && !getscl(adap)) {
pr_warn("%s: SCL stuck low!\n", name);
goto bailout;
}
if (!sda) {
printk(KERN_WARNING
"%s: SDA unexpected low while pulling SCL high!\n",
name);
if (adap->getsda && !getsda(adap)) {
pr_warn("%s: SDA unexpected low while pulling SCL high!\n", name);
goto bailout;
}
@ -420,6 +405,10 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
unsigned char *temp = msg->buf;
int count = msg->len;
const unsigned flags = msg->flags;
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
if (!adap->getsda)
return -EOPNOTSUPP;
while (count > 0) {
inval = i2c_inb(i2c_adap);
@ -670,11 +659,15 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap,
if (ret < 0)
return ret;
/* Complain if SCL can't be read */
if (bit_adap->getscl == NULL) {
if (bit_adap->getsda == 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");
if (bit_adap->getsda == NULL || bit_adap->getscl == NULL)
dev_warn(&adap->dev, "Bus may be unreliable\n");
}
return 0;
}