[v2] i2c: tegra: Add support for Tegra194

Message ID 20180619104942.6703-1-thierry.reding@gmail.com
State New
Headers show
Series
  • [v2] i2c: tegra: Add support for Tegra194
Related show

Commit Message

Thierry Reding June 19, 2018, 10:49 a.m.
From: Thierry Reding <treding@nvidia.com>

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.

Acked-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- remove commented out code which was left over from debugging

 drivers/i2c/busses/i2c-tegra.c | 90 ++++++++++++++++++++++++++++------
 1 file changed, 76 insertions(+), 14 deletions(-)

Comments

Thierry Reding July 2, 2018, 11:48 a.m. | #1
On Tue, Jun 19, 2018 at 12:49:42PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> 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.
> 
> Acked-by: Jon Hunter <jonathanh@nvidia.com>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> Changes in v2:
> - remove commented out code which was left over from debugging
> 
>  drivers/i2c/busses/i2c-tegra.c | 90 ++++++++++++++++++++++++++++------
>  1 file changed, 76 insertions(+), 14 deletions(-)

Hi Wolfram,

do you have any comments on this patch? I'd like to get this merged into
v4.19 so that we can continue enabling more features on Tegra194.

Thanks,
Thierry

> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> index 5fccd1f1bca8..edde464dfb72 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,7 @@ 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;
> +
>  	return 0;
>  }
>  
> @@ -332,9 +363,15 @@ static int tegra_i2c_fill_tx_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);
> -	tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
> -		I2C_FIFO_STATUS_TX_SHIFT;
> +	if (i2c_dev->hw->has_mst_fifo) {
> +		val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
> +		tx_fifo_avail = (val & I2C_MST_FIFO_STATUS_TX_MASK) >>
> +			I2C_MST_FIFO_STATUS_TX_SHIFT;
> +	} else {
> +		val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
> +		tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
> +			I2C_FIFO_STATUS_TX_SHIFT;
> +	}
>  
>  	/* Rounds down to not include partial word at the end of buf */
>  	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
> @@ -516,9 +553,15 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
>  		i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2);
>  	}
>  
> -	val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
> -		0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
> -	i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
> +	if (i2c_dev->hw->has_mst_fifo) {
> +		val = I2C_MST_FIFO_CONTROL_TX_TRIG(8) |
> +		      I2C_MST_FIFO_CONTROL_RX_TRIG(1);
> +		i2c_writel(i2c_dev, val, I2C_MST_FIFO_CONTROL);
> +	} else {
> +		val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
> +			0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
> +		i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
> +	}
>  
>  	err = tegra_i2c_flush_fifos(i2c_dev);
>  	if (err)
> @@ -803,6 +846,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
>  	.has_config_load_reg = false,
>  	.has_multi_master_mode = false,
>  	.has_slcg_override_reg = false,
> +	.has_mst_fifo = false,
>  };
>  
>  static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
> @@ -815,6 +859,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
>  	.has_config_load_reg = false,
>  	.has_multi_master_mode = false,
>  	.has_slcg_override_reg = false,
> +	.has_mst_fifo = false,
>  };
>  
>  static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
> @@ -827,6 +872,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
>  	.has_config_load_reg = false,
>  	.has_multi_master_mode = false,
>  	.has_slcg_override_reg = false,
> +	.has_mst_fifo = false,
>  };
>  
>  static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
> @@ -839,6 +885,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
>  	.has_config_load_reg = true,
>  	.has_multi_master_mode = false,
>  	.has_slcg_override_reg = true,
> +	.has_mst_fifo = false,
>  };
>  
>  static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
> @@ -851,10 +898,25 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
>  	.has_config_load_reg = true,
>  	.has_multi_master_mode = true,
>  	.has_slcg_override_reg = true,
> +	.has_mst_fifo = false,
> +};
> +
> +static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
> +	.has_continue_xfer_support = true,
> +	.has_per_pkt_xfer_complete_irq = true,
> +	.has_single_clk_source = true,
> +	.clk_divisor_hs_mode = 1,
> +	.clk_divisor_std_fast_mode = 0x19,
> +	.clk_divisor_fast_plus_mode = 0x10,
> +	.has_config_load_reg = true,
> +	.has_multi_master_mode = true,
> +	.has_slcg_override_reg = true,
> +	.has_mst_fifo = true,
>  };
>  
>  /* Match table for of_platform binding */
>  static const struct of_device_id tegra_i2c_of_match[] = {
> +	{ .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
>  	{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
>  	{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
>  	{ .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, },
> -- 
> 2.17.0
>
Wolfram Sang July 3, 2018, 9:14 p.m. | #2
On Tue, Jun 19, 2018 at 12:49:42PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> 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.
> 
> Acked-by: Jon Hunter <jonathanh@nvidia.com>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

Applied to for-next, thanks!

My compiler mentions this, though:

drivers/i2c/busses/i2c-tegra.c:170: warning: Function parameter or member 'clk_divisor_fast_plus_mode' not described in 'tegra_i2c_hw_feature'
drivers/i2c/busses/i2c-tegra.c:170: warning: Function parameter or member 'has_multi_master_mode' not described in 'tegra_i2c_hw_feature'
drivers/i2c/busses/i2c-tegra.c:170: warning: Function parameter or member 'has_slcg_override_reg' not described in 'tegra_i2c_hw_feature'
drivers/i2c/busses/i2c-tegra.c:170: warning: Function parameter or member 'has_mst_fifo' not described in 'tegra_i2c_hw_feature'
drivers/i2c/busses/i2c-tegra.c:211: warning: Function parameter or member 'rst' not described in 'tegra_i2c_dev'
drivers/i2c/busses/i2c-tegra.c:211: warning: Function parameter or member 'irq_disabled' not described in 'tegra_i2c_dev'
drivers/i2c/busses/i2c-tegra.c:211: warning: Function parameter or member 'clk_divisor_non_hs_mode' not described in 'tegra_i2c_dev'
drivers/i2c/busses/i2c-tegra.c:211: warning: Function parameter or member 'is_multimaster_mode' not described in 'tegra_i2c_dev'
drivers/i2c/busses/i2c-tegra.c:211: warning: Function parameter or member 'xfer_lock' not described in 'tegra_i2c_dev'

Maybe you want to fix this incrementally?

Patch

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 5fccd1f1bca8..edde464dfb72 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,7 @@  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;
+
 	return 0;
 }
 
@@ -332,9 +363,15 @@  static int tegra_i2c_fill_tx_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);
-	tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
-		I2C_FIFO_STATUS_TX_SHIFT;
+	if (i2c_dev->hw->has_mst_fifo) {
+		val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
+		tx_fifo_avail = (val & I2C_MST_FIFO_STATUS_TX_MASK) >>
+			I2C_MST_FIFO_STATUS_TX_SHIFT;
+	} else {
+		val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+		tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
+			I2C_FIFO_STATUS_TX_SHIFT;
+	}
 
 	/* Rounds down to not include partial word at the end of buf */
 	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
@@ -516,9 +553,15 @@  static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 		i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2);
 	}
 
-	val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
-		0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
-	i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+	if (i2c_dev->hw->has_mst_fifo) {
+		val = I2C_MST_FIFO_CONTROL_TX_TRIG(8) |
+		      I2C_MST_FIFO_CONTROL_RX_TRIG(1);
+		i2c_writel(i2c_dev, val, I2C_MST_FIFO_CONTROL);
+	} else {
+		val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
+			0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
+		i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+	}
 
 	err = tegra_i2c_flush_fifos(i2c_dev);
 	if (err)
@@ -803,6 +846,7 @@  static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
 	.has_config_load_reg = false,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = false,
+	.has_mst_fifo = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -815,6 +859,7 @@  static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
 	.has_config_load_reg = false,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = false,
+	.has_mst_fifo = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -827,6 +872,7 @@  static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
 	.has_config_load_reg = false,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = false,
+	.has_mst_fifo = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -839,6 +885,7 @@  static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
 	.has_config_load_reg = true,
 	.has_multi_master_mode = false,
 	.has_slcg_override_reg = true,
+	.has_mst_fifo = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@@ -851,10 +898,25 @@  static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
 	.has_config_load_reg = true,
 	.has_multi_master_mode = true,
 	.has_slcg_override_reg = true,
+	.has_mst_fifo = false,
+};
+
+static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
+	.has_continue_xfer_support = true,
+	.has_per_pkt_xfer_complete_irq = true,
+	.has_single_clk_source = true,
+	.clk_divisor_hs_mode = 1,
+	.clk_divisor_std_fast_mode = 0x19,
+	.clk_divisor_fast_plus_mode = 0x10,
+	.has_config_load_reg = true,
+	.has_multi_master_mode = true,
+	.has_slcg_override_reg = true,
+	.has_mst_fifo = true,
 };
 
 /* Match table for of_platform binding */
 static const struct of_device_id tegra_i2c_of_match[] = {
+	{ .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
 	{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
 	{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
 	{ .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, },