Skip to content

Commit

Permalink
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Linus Torvalds committed Dec 20, 2016
2 parents 1351522 + 649ac63 commit 74f65bb
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 25 deletions.
31 changes: 24 additions & 7 deletions drivers/i2c/busses/i2c-designware-platdrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion drivers/i2c/busses/i2c-octeon-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
21 changes: 16 additions & 5 deletions drivers/i2c/busses/i2c-octeon-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/i2c/busses/i2c-xgene-slimpro.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
24 changes: 13 additions & 11 deletions drivers/i2c/muxes/i2c-mux-mlxcpld.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion drivers/i2c/muxes/i2c-mux-pca954x.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 74f65bb

Please sign in to comment.