mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
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:
parent
a00bb94c7b
commit
9dfee1487c
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user