1
0
Fork 0

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
zero-colors
Linus Torvalds 2016-12-20 15:19:55 -08:00
commit 74f65bbf46
6 changed files with 61 additions and 25 deletions

View 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;

View 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;

View 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

View 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) {

View 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;

View 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;