i2c: algo: bit: allow getsda to be NULL
authorHeiner Kallweit <hkallweit1@gmail.com>
Wed, 18 Jan 2023 21:54:03 +0000 (22:54 +0100)
committerWolfram Sang <wsa@kernel.org>
Mon, 23 Jan 2023 22:15:49 +0000 (23:15 +0100)
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>
drivers/i2c/algos/i2c-algo-bit.c

index fc90293..eddf25b 100644 (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;
 }