Re: [PATCH] i2c: tegra: Add support for Tegra194

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jun 18, 2018 at 07:59:51PM +0300, Dmitry Osipenko wrote:
> On Monday, 18 June 2018 18:04:50 MSK Thierry Reding wrote:
> > From: Thierry Reding <treding@xxxxxxxxxx>
> > 
> > In order to support advanced features, the I2C FIFO interface was
> > changed in the version of the Tegra I2C controller found in Tegra194.
> > The changes are backwards incompatible, so the driver needs to be
> > programmed in a slightly different way on new chips.
> > 
> > Add support for MST FIFO programming and add an OF match entry for
> > Tegra194. At the same time, mark all prior generations of this
> > controller as not having the MST FIFO interface.
> > 
> > Signed-off-by: Thierry Reding <treding@xxxxxxxxxx>
> > ---
> >  drivers/i2c/busses/i2c-tegra.c | 99 +++++++++++++++++++++++++++++-----
> >  1 file changed, 85 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> > index 5fccd1f1bca8..a2779e9af1ff 100644
> > --- a/drivers/i2c/busses/i2c-tegra.c
> > +++ b/drivers/i2c/busses/i2c-tegra.c
> > @@ -115,6 +115,18 @@
> > 
> >  #define I2C_CONFIG_LOAD_TIMEOUT			1000000
> > 
> > +#define I2C_MST_FIFO_CONTROL			0x0b4
> > +#define I2C_MST_FIFO_CONTROL_RX_FLUSH		BIT(0)
> > +#define I2C_MST_FIFO_CONTROL_TX_FLUSH		BIT(1)
> > +#define I2C_MST_FIFO_CONTROL_RX_TRIG(x)		(((x) - 1) <<  4)
> > +#define I2C_MST_FIFO_CONTROL_TX_TRIG(x)		(((x) - 1) << 16)
> > +
> > +#define I2C_MST_FIFO_STATUS			0x0b8
> > +#define I2C_MST_FIFO_STATUS_RX_MASK		0xff
> > +#define I2C_MST_FIFO_STATUS_RX_SHIFT		0
> > +#define I2C_MST_FIFO_STATUS_TX_MASK		0xff0000
> > +#define I2C_MST_FIFO_STATUS_TX_SHIFT		16
> > +
> >  /*
> >   * msg_end_type: The bus control which need to be send at end of transfer.
> >   * @MSG_END_STOP: Send stop pulse at end of transfer.
> > @@ -154,6 +166,7 @@ struct tegra_i2c_hw_feature {
> >  	u16 clk_divisor_fast_plus_mode;
> >  	bool has_multi_master_mode;
> >  	bool has_slcg_override_reg;
> > +	bool has_mst_fifo;
> >  };
> > 
> >  /**
> > @@ -266,13 +279,24 @@ static void tegra_i2c_unmask_irq(struct tegra_i2c_dev
> > *i2c_dev, u32 mask) static int tegra_i2c_flush_fifos(struct tegra_i2c_dev
> > *i2c_dev)
> >  {
> >  	unsigned long timeout = jiffies + HZ;
> > -	u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL);
> > +	unsigned int offset;
> > +	u32 mask, val;
> > +
> > +	if (i2c_dev->hw->has_mst_fifo) {
> > +		mask = I2C_MST_FIFO_CONTROL_TX_FLUSH |
> > +		       I2C_MST_FIFO_CONTROL_RX_FLUSH;
> > +		offset = I2C_MST_FIFO_CONTROL;
> > +	} else {
> > +		mask = I2C_FIFO_CONTROL_TX_FLUSH |
> > +		       I2C_FIFO_CONTROL_RX_FLUSH;
> > +		offset = I2C_FIFO_CONTROL;
> > +	}
> > 
> > -	val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH;
> > -	i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
> > +	val = i2c_readl(i2c_dev, offset);
> > +	val |= mask;
> > +	i2c_writel(i2c_dev, val, offset);
> > 
> > -	while (i2c_readl(i2c_dev, I2C_FIFO_CONTROL) &
> > -		(I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH)) {
> > +	while (i2c_readl(i2c_dev, offset) & mask) {
> >  		if (time_after(jiffies, timeout)) {
> >  			dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
> >  			return -ETIMEDOUT;
> > @@ -290,9 +314,15 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev
> > *i2c_dev) size_t buf_remaining = i2c_dev->msg_buf_remaining;
> >  	int words_to_transfer;
> > 
> > -	val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
> > -	rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >>
> > -		I2C_FIFO_STATUS_RX_SHIFT;
> > +	if (i2c_dev->hw->has_mst_fifo) {
> > +		val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
> > +		rx_fifo_avail = (val & I2C_MST_FIFO_STATUS_RX_MASK) >>
> > +			I2C_MST_FIFO_STATUS_RX_SHIFT;
> > +	} else {
> > +		val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
> > +		rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >>
> > +			I2C_FIFO_STATUS_RX_SHIFT;
> > +	}
> > 
> >  	/* Rounds down to not include partial word at the end of buf */
> >  	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
> > @@ -321,6 +351,16 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev
> > *i2c_dev) BUG_ON(rx_fifo_avail > 0 && buf_remaining > 0);
> >  	i2c_dev->msg_buf_remaining = buf_remaining;
> >  	i2c_dev->msg_buf = buf;
> > +
> > +	/*
> > +	 * All bytes received, mask RX_FIFO_DATA_REQ to prevent more
> > +	 * interrupts from FIFO.
> > +	 */
> > +	/*
> > +	if (i2c_dev->msg_buf_remaining == 0)
> > +		tegra_i2c_mask_irq(i2c_dev, I2C_INT_RX_FIFO_DATA_REQ);
> > +	*/
> 
> Is it a deliberately commented out code?

I think I left this in by mistake. The code certainly did work the last
time I tried with the above commented out, so I'll just remove it.

Thierry

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux