SCCB is a serial communication bus developed by Omnivision. Its 2-wire
mode is very similar to SMBus byte data transactions, but requires the
controller to ignore the ACK bit and to insert a stop condition after
each message.

Add a device SCCB flag and a message stop flag to be passed to
controller drivers.

Signed-off-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/i2c/i2c-core.c |   13 ++++++++++++-
 include/linux/i2c.h    |    2 ++
 2 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index feb7dc3..8cfa660 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1939,6 +1939,12 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter 
*adapter, u16 addr,
        u8 partial_pec = 0;
        int status;
 
+       if (unlikely(flags & I2C_CLIENT_SCCB) && size != I2C_SMBUS_BYTE_DATA) {
+               dev_err(&adapter->dev,
+                       "SCCB devices only support I2C_SMBUS_BYTE_DATA\n");
+               return -EINVAL;
+       }
+
        msgbuf0[0] = command;
        switch (size) {
        case I2C_SMBUS_QUICK:
@@ -1956,6 +1962,11 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter 
*adapter, u16 addr,
                }
                break;
        case I2C_SMBUS_BYTE_DATA:
+               if (unlikely(flags & I2C_CLIENT_SCCB)) {
+                       msg[0].flags |= I2C_M_IGNORE_NAK | I2C_M_STOP;
+                       msg[1].flags |= I2C_M_IGNORE_NAK | I2C_M_STOP;
+               }
+
                if (read_write == I2C_SMBUS_READ)
                        msg[1].len = 1;
                else {
@@ -2105,7 +2116,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, 
unsigned short flags,
        int try;
        s32 res;
 
-       flags &= I2C_M_TEN | I2C_CLIENT_PEC;
+       flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
 
        if (adapter->algo->smbus_xfer) {
                i2c_lock_adapter(adapter);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 195d8b3..bd42914 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -420,6 +420,7 @@ void i2c_lock_adapter(struct i2c_adapter *);
 void i2c_unlock_adapter(struct i2c_adapter *);
 
 /*flags for the client struct: */
+#define I2C_CLIENT_SCCB        0x02            /* Use Omnivision SCCB protocol 
*/
 #define I2C_CLIENT_PEC 0x04            /* Use Packet Error Checking */
 #define I2C_CLIENT_TEN 0x10            /* we have a ten bit chip address */
                                        /* Must equal I2C_M_TEN below */
@@ -540,6 +541,7 @@ struct i2c_msg {
        __u16 flags;
 #define I2C_M_TEN              0x0010  /* this is a ten bit chip address */
 #define I2C_M_RD               0x0001  /* read data, from slave to master */
+#define I2C_M_STOP             0x8000  /* if I2C_FUNC_PROTOCOL_MANGLING */
 #define I2C_M_NOSTART          0x4000  /* if I2C_FUNC_PROTOCOL_MANGLING */
 #define I2C_M_REV_DIR_ADDR     0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */
 #define I2C_M_IGNORE_NAK       0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to