Commit 74f65bbf authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

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
parents 1351522b 649ac63a
...@@ -150,6 +150,29 @@ static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare) ...@@ -150,6 +150,29 @@ static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare)
return 0; 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) static int dw_i2c_plat_probe(struct platform_device *pdev)
{ {
struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev); 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) ...@@ -245,13 +268,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
1000000); 1000000);
} }
if (!dev->tx_fifo_depth) { dw_i2c_set_fifo_size(dev, pdev->id);
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;
}
adap = &dev->adapter; adap = &dev->adapter;
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
......
...@@ -342,7 +342,9 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, ...@@ -342,7 +342,9 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
if (result) if (result)
return 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 (recv_len && i == 0) {
if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
return -EPROTO; return -EPROTO;
......
...@@ -141,11 +141,14 @@ static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr) ...@@ -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) static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
{ {
int tries = 1000;
u64 tmp; u64 tmp;
__raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c)); __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c));
do { do {
tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
if (--tries < 0)
return;
} while ((tmp & SW_TWSI_V) != 0); } 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 ...@@ -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. * 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; u64 tmp;
__raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c)); __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c));
do { do {
tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c)); 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); } while ((tmp & SW_TWSI_V) != 0);
return tmp & 0xFF; return tmp & 0xFF;
} }
#define octeon_i2c_ctl_read(i2c) \ #define octeon_i2c_ctl_read(i2c) \
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL) octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL, NULL)
#define octeon_i2c_data_read(i2c) \ #define octeon_i2c_data_read(i2c, error) \
octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA) octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA, error)
#define octeon_i2c_stat_read(i2c) \ #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 * octeon_i2c_read_int - read the TWSI_INT register
......
...@@ -415,6 +415,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) ...@@ -415,6 +415,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
adapter->algo = &xgene_slimpro_i2c_algorithm; adapter->algo = &xgene_slimpro_i2c_algorithm;
adapter->class = I2C_CLASS_HWMON; adapter->class = I2C_CLASS_HWMON;
adapter->dev.parent = &pdev->dev; adapter->dev.parent = &pdev->dev;
adapter->dev.of_node = pdev->dev.of_node;
i2c_set_adapdata(adapter, ctx); i2c_set_adapdata(adapter, ctx);
rc = i2c_add_adapter(adapter); rc = i2c_add_adapter(adapter);
if (rc) { if (rc) {
......
...@@ -95,6 +95,7 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap, ...@@ -95,6 +95,7 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap,
struct i2c_client *client, u8 val) struct i2c_client *client, u8 val)
{ {
struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev); struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
int ret = -ENODEV;
if (adap->algo->master_xfer) { if (adap->algo->master_xfer) {
struct i2c_msg msg; struct i2c_msg msg;
...@@ -104,17 +105,21 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap, ...@@ -104,17 +105,21 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap,
msg.flags = 0; msg.flags = 0;
msg.len = 2; msg.len = 2;
msg.buf = msgbuf; 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) { } else if (adap->algo->smbus_xfer) {
union i2c_smbus_data data; union i2c_smbus_data data;
data.byte = val; data.byte = val;
return adap->algo->smbus_xfer(adap, client->addr, ret = adap->algo->smbus_xfer(adap, client->addr,
client->flags, I2C_SMBUS_WRITE, client->flags, I2C_SMBUS_WRITE,
pdata->sel_reg_addr, pdata->sel_reg_addr,
I2C_SMBUS_BYTE_DATA, &data); I2C_SMBUS_BYTE_DATA, &data);
} else }
return -ENODEV;
return ret;
} }
static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan) 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) ...@@ -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 */ /* Only select the channel if its different from the last channel */
if (data->last_chan != regval) { if (data->last_chan != regval) {
err = mlxcpld_mux_reg_write(muxc->parent, client, regval); err = mlxcpld_mux_reg_write(muxc->parent, client, regval);
if (err) data->last_chan = err < 0 ? 0 : regval;
data->last_chan = 0;
else
data->last_chan = regval;
} }
return err; return err;
......
...@@ -167,6 +167,9 @@ static int pca954x_reg_write(struct i2c_adapter *adap, ...@@ -167,6 +167,9 @@ static int pca954x_reg_write(struct i2c_adapter *adap,
buf[0] = val; buf[0] = val;
msg.buf = buf; msg.buf = buf;
ret = __i2c_transfer(adap, &msg, 1); ret = __i2c_transfer(adap, &msg, 1);
if (ret >= 0 && ret != 1)
ret = -EREMOTEIO;
} else { } else {
union i2c_smbus_data data; union i2c_smbus_data data;
ret = adap->algo->smbus_xfer(adap, client->addr, ret = adap->algo->smbus_xfer(adap, client->addr,
...@@ -195,7 +198,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) ...@@ -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 */ /* Only select the channel if its different from the last channel */
if (data->last_chan != regval) { if (data->last_chan != regval) {
ret = pca954x_reg_write(muxc->parent, client, regval); ret = pca954x_reg_write(muxc->parent, client, regval);
data->last_chan = ret ? 0 : regval; data->last_chan = ret < 0 ? 0 : regval;
} }
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment