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

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
Loading
Loading
Loading
Loading
+35 −42
Original line number Diff line number Diff line
@@ -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;
}