mirror of https://gitee.com/openkylin/linux.git
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
This commit is contained in:
commit
74f65bbf46
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue