]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 20 Dec 2016 23:19:55 +0000 (15:19 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 20 Dec 2016 23:19:55 +0000 (15:19 -0800)
Pull i2c fixes from Wolfram Sang.

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: mux: mlxcpld: fix i2c mux selection caching
  i2c: designware: fix wrong Tx/Rx FIFO for ACPI
  i2c: xgene: Fix missing code of DTB support
  i2c: mux: pca954x: fix i2c mux selection caching
  i2c: octeon: thunderx: Limit register access retries

drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-octeon-core.c
drivers/i2c/busses/i2c-octeon-core.h
drivers/i2c/busses/i2c-xgene-slimpro.c
drivers/i2c/muxes/i2c-mux-mlxcpld.c
drivers/i2c/muxes/i2c-mux-pca954x.c

index 08153ea4d848097ef5659f40c6bb71964cbc99e2..6ce4313231257f8251b62e02f5aaa390a4619edf 100644 (file)
@@ -150,6 +150,29 @@ static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare)
        return 0;
 }
 
+static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)
+{
+       u32 param, tx_fifo_depth, rx_fifo_depth;
+
+       /*
+        * Try to detect the FIFO depth if not set by interface driver,
+        * the depth could be from 2 to 256 from HW spec.
+        */
+       param = i2c_dw_read_comp_param(dev);
+       tx_fifo_depth = ((param >> 16) & 0xff) + 1;
+       rx_fifo_depth = ((param >> 8)  & 0xff) + 1;
+       if (!dev->tx_fifo_depth) {
+               dev->tx_fifo_depth = tx_fifo_depth;
+               dev->rx_fifo_depth = rx_fifo_depth;
+               dev->adapter.nr = id;
+       } else if (tx_fifo_depth >= 2) {
+               dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
+                               tx_fifo_depth);
+               dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
+                               rx_fifo_depth);
+       }
+}
+
 static int dw_i2c_plat_probe(struct platform_device *pdev)
 {
        struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -245,13 +268,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
                                1000000);
        }
 
-       if (!dev->tx_fifo_depth) {
-               u32 param1 = i2c_dw_read_comp_param(dev);
-
-               dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
-               dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
-               dev->adapter.nr = pdev->id;
-       }
+       dw_i2c_set_fifo_size(dev, pdev->id);
 
        adap = &dev->adapter;
        adap->owner = THIS_MODULE;
index 3d10f1a802be4b8df5488535fda6e32f5d2b2fca..1d87757990568c40b9cebe4df7dda54fe21918f7 100644 (file)
@@ -342,7 +342,9 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
                if (result)
                        return result;
 
-               data[i] = octeon_i2c_data_read(i2c);
+               data[i] = octeon_i2c_data_read(i2c, &result);
+               if (result)
+                       return result;
                if (recv_len && i == 0) {
                        if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
                                return -EPROTO;
index 87151ea74acd475a37726fd43fa927f486ddc76e..e160f838c25461f111f89871eac87beebca61a09 100644 (file)
@@ -141,11 +141,14 @@ static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)
  */
 static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
 {
+       int tries = 1000;
        u64 tmp;
 
        __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c));
        do {
                tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+               if (--tries < 0)
+                       return;
        } while ((tmp & SW_TWSI_V) != 0);
 }
 
@@ -163,24 +166,32 @@ static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8
  *
  * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
  */
-static inline u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg)
+static inline int octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg,
+                                     int *error)
 {
+       int tries = 1000;
        u64 tmp;
 
        __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c));
        do {
                tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+               if (--tries < 0) {
+                       /* signal that the returned data is invalid */
+                       if (error)
+                               *error = -EIO;
+                       return 0;
+               }
        } while ((tmp & SW_TWSI_V) != 0);
 
        return tmp & 0xFF;
 }
 
 #define octeon_i2c_ctl_read(i2c)                                       \
-       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL)
-#define octeon_i2c_data_read(i2c)                                      \
-       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA)
+       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL, NULL)
+#define octeon_i2c_data_read(i2c, error)                               \
+       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA, error)
 #define octeon_i2c_stat_read(i2c)                                      \
-       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT)
+       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT, NULL)
 
 /**
  * octeon_i2c_read_int - read the TWSI_INT register
index 05cf192ef1acae340397d9ff67f942bca6d08d3e..0ab1e55558bcd7a520afd8dcf07ae3d8cb77e1c0 100644 (file)
@@ -415,6 +415,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
        adapter->algo = &xgene_slimpro_i2c_algorithm;
        adapter->class = I2C_CLASS_HWMON;
        adapter->dev.parent = &pdev->dev;
+       adapter->dev.of_node = pdev->dev.of_node;
        i2c_set_adapdata(adapter, ctx);
        rc = i2c_add_adapter(adapter);
        if (rc) {
index 3ab654bbfab56f4fe299800e2372fbee86b1385d..b7ca249ec9c38b884ed48fbb8387dcc6729f1cc6 100644 (file)
@@ -95,6 +95,7 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap,
                                 struct i2c_client *client, u8 val)
 {
        struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
+       int ret = -ENODEV;
 
        if (adap->algo->master_xfer) {
                struct i2c_msg msg;
@@ -104,17 +105,21 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap,
                msg.flags = 0;
                msg.len = 2;
                msg.buf = msgbuf;
-               return __i2c_transfer(adap, &msg, 1);
+               ret = __i2c_transfer(adap, &msg, 1);
+
+               if (ret >= 0 && ret != 1)
+                       ret = -EREMOTEIO;
        } else if (adap->algo->smbus_xfer) {
                union i2c_smbus_data data;
 
                data.byte = val;
-               return adap->algo->smbus_xfer(adap, client->addr,
-                                             client->flags, I2C_SMBUS_WRITE,
-                                             pdata->sel_reg_addr,
-                                             I2C_SMBUS_BYTE_DATA, &data);
-       } else
-               return -ENODEV;
+               ret = adap->algo->smbus_xfer(adap, client->addr,
+                                            client->flags, I2C_SMBUS_WRITE,
+                                            pdata->sel_reg_addr,
+                                            I2C_SMBUS_BYTE_DATA, &data);
+       }
+
+       return ret;
 }
 
 static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
@@ -127,10 +132,7 @@ static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
        /* Only select the channel if its different from the last channel */
        if (data->last_chan != regval) {
                err = mlxcpld_mux_reg_write(muxc->parent, client, regval);
-               if (err)
-                       data->last_chan = 0;
-               else
-                       data->last_chan = regval;
+               data->last_chan = err < 0 ? 0 : regval;
        }
 
        return err;
index 9a348ee4dc14deb9eb1686fd1a20dc672b73a5df..dd18b9ccb1f40b4f6ddf5904e1f6d529931801df 100644 (file)
@@ -167,6 +167,9 @@ static int pca954x_reg_write(struct i2c_adapter *adap,
                buf[0] = val;
                msg.buf = buf;
                ret = __i2c_transfer(adap, &msg, 1);
+
+               if (ret >= 0 && ret != 1)
+                       ret = -EREMOTEIO;
        } else {
                union i2c_smbus_data data;
                ret = adap->algo->smbus_xfer(adap, client->addr,
@@ -195,7 +198,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
        /* Only select the channel if its different from the last channel */
        if (data->last_chan != regval) {
                ret = pca954x_reg_write(muxc->parent, client, regval);
-               data->last_chan = ret ? 0 : regval;
+               data->last_chan = ret < 0 ? 0 : regval;
        }
 
        return ret;