Commit 74f65bbf authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+24 −7
Original line number Diff line number Diff line
@@ -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;
+3 −1
Original line number Diff line number Diff line
@@ -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;
+16 −5
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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) {
+13 −11
Original line number Diff line number Diff line
@@ -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,
		ret = adap->algo->smbus_xfer(adap, client->addr,
					     client->flags, I2C_SMBUS_WRITE,
					     pdata->sel_reg_addr,
					     I2C_SMBUS_BYTE_DATA, &data);
	} else
		return -ENODEV;
	}

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