]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
i2c: tegra: Add logic to support different register offsets
authorKartik Rajput <kkartik@nvidia.com>
Tue, 24 Mar 2026 05:58:42 +0000 (11:28 +0530)
committerAndi Shyti <andi.shyti@kernel.org>
Thu, 26 Mar 2026 22:36:58 +0000 (23:36 +0100)
Tegra410 use different offsets for existing I2C registers, update
the logic to use appropriate offsets per SoC.

As the register offsets are now defined in the SoC-specific
tegra_i2c_regs structures, the tegra_i2c_reg_addr() function is no
longer needed to translate register offsets and has been removed.

Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260324055843.549808-3-kkartik@nvidia.com
drivers/i2c/busses/i2c-tegra.c

index 2ef5fba66b0f5eebc0cda8481976fe61f122c5d3..d845b8782f4fa0a6f9efd9b03aa06538f826f273 100644 (file)
 
 #define BYTES_PER_FIFO_WORD 4
 
-#define I2C_CNFG                               0x000
 #define I2C_CNFG_DEBOUNCE_CNT                  GENMASK(14, 12)
 #define I2C_CNFG_PACKET_MODE_EN                        BIT(10)
 #define I2C_CNFG_NEW_MASTER_FSM                        BIT(11)
 #define I2C_CNFG_MULTI_MASTER_MODE             BIT(17)
-#define I2C_STATUS                             0x01c
-#define I2C_SL_CNFG                            0x020
+
 #define I2C_SL_CNFG_NACK                       BIT(1)
 #define I2C_SL_CNFG_NEWSL                      BIT(2)
-#define I2C_SL_ADDR1                           0x02c
-#define I2C_SL_ADDR2                           0x030
-#define I2C_TLOW_SEXT                          0x034
-#define I2C_TX_FIFO                            0x050
-#define I2C_RX_FIFO                            0x054
-#define I2C_PACKET_TRANSFER_STATUS             0x058
-#define I2C_FIFO_CONTROL                       0x05c
+
 #define I2C_FIFO_CONTROL_TX_FLUSH              BIT(1)
 #define I2C_FIFO_CONTROL_RX_FLUSH              BIT(0)
 #define I2C_FIFO_CONTROL_TX_TRIG(x)            (((x) - 1) << 5)
 #define I2C_FIFO_CONTROL_RX_TRIG(x)            (((x) - 1) << 2)
-#define I2C_FIFO_STATUS                                0x060
+
 #define I2C_FIFO_STATUS_TX                     GENMASK(7, 4)
 #define I2C_FIFO_STATUS_RX                     GENMASK(3, 0)
-#define I2C_INT_MASK                           0x064
-#define I2C_INT_STATUS                         0x068
+
 #define I2C_INT_BUS_CLR_DONE                   BIT(11)
 #define I2C_INT_PACKET_XFER_COMPLETE           BIT(7)
 #define I2C_INT_NO_ACK                         BIT(3)
 #define I2C_INT_ARBITRATION_LOST               BIT(2)
 #define I2C_INT_TX_FIFO_DATA_REQ               BIT(1)
 #define I2C_INT_RX_FIFO_DATA_REQ               BIT(0)
-#define I2C_CLK_DIVISOR                                0x06c
+
 #define I2C_CLK_DIVISOR_STD_FAST_MODE          GENMASK(31, 16)
 #define I2C_CLK_DIVISOR_HSMODE                 GENMASK(15, 0)
 
 #define I2C_HEADER_CONTINUE_XFER               BIT(15)
 #define I2C_HEADER_SLAVE_ADDR_SHIFT            1
 
-#define I2C_BUS_CLEAR_CNFG                     0x084
 #define I2C_BC_SCLK_THRESHOLD                  GENMASK(23, 16)
 #define I2C_BC_STOP_COND                       BIT(2)
 #define I2C_BC_TERMINATE                       BIT(1)
 #define I2C_BC_ENABLE                          BIT(0)
-#define I2C_BUS_CLEAR_STATUS                   0x088
+
 #define I2C_BC_STATUS                          BIT(0)
 
-#define I2C_CONFIG_LOAD                                0x08c
 #define I2C_MSTR_CONFIG_LOAD                   BIT(0)
 
-#define I2C_CLKEN_OVERRIDE                     0x090
 #define I2C_MST_CORE_CLKEN_OVR                 BIT(0)
 
-#define I2C_INTERFACE_TIMING_0                 0x094
-#define  I2C_INTERFACE_TIMING_THIGH            GENMASK(13, 8)
-#define  I2C_INTERFACE_TIMING_TLOW             GENMASK(5, 0)
-#define I2C_INTERFACE_TIMING_1                 0x098
-#define  I2C_INTERFACE_TIMING_TBUF             GENMASK(29, 24)
-#define  I2C_INTERFACE_TIMING_TSU_STO          GENMASK(21, 16)
-#define  I2C_INTERFACE_TIMING_THD_STA          GENMASK(13, 8)
-#define  I2C_INTERFACE_TIMING_TSU_STA          GENMASK(5, 0)
-
-#define I2C_HS_INTERFACE_TIMING_0              0x09c
-#define  I2C_HS_INTERFACE_TIMING_THIGH         GENMASK(13, 8)
-#define  I2C_HS_INTERFACE_TIMING_TLOW          GENMASK(5, 0)
-#define I2C_HS_INTERFACE_TIMING_1              0x0a0
-#define  I2C_HS_INTERFACE_TIMING_TSU_STO       GENMASK(21, 16)
-#define  I2C_HS_INTERFACE_TIMING_THD_STA       GENMASK(13, 8)
-#define  I2C_HS_INTERFACE_TIMING_TSU_STA       GENMASK(5, 0)
-
-#define I2C_MST_FIFO_CONTROL                   0x0b4
+#define I2C_INTERFACE_TIMING_THIGH             GENMASK(13, 8)
+#define I2C_INTERFACE_TIMING_TLOW              GENMASK(5, 0)
+#define I2C_INTERFACE_TIMING_TBUF              GENMASK(29, 24)
+#define I2C_INTERFACE_TIMING_TSU_STO           GENMASK(21, 16)
+#define I2C_INTERFACE_TIMING_THD_STA           GENMASK(13, 8)
+#define I2C_INTERFACE_TIMING_TSU_STA           GENMASK(5, 0)
+
+#define I2C_HS_INTERFACE_TIMING_THIGH          GENMASK(13, 8)
+#define I2C_HS_INTERFACE_TIMING_TLOW           GENMASK(5, 0)
+#define I2C_HS_INTERFACE_TIMING_TSU_STO                GENMASK(21, 16)
+#define I2C_HS_INTERFACE_TIMING_THD_STA                GENMASK(13, 8)
+#define I2C_HS_INTERFACE_TIMING_TSU_STA                GENMASK(5, 0)
+
 #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_TX                 GENMASK(23, 16)
 #define I2C_MST_FIFO_STATUS_RX                 GENMASK(7, 0)
 
-#define I2C_MASTER_RESET_CNTRL                 0x0a8
-
-#define I2C_SW_MUTEX                           0x0ec
 #define I2C_SW_MUTEX_REQUEST                   GENMASK(3, 0)
 #define I2C_SW_MUTEX_GRANT                     GENMASK(7, 4)
 #define I2C_SW_MUTEX_ID_CCPLEX                 9
  */
 #define I2C_PIO_MODE_PREFERRED_LEN             32
 
+struct tegra_i2c_regs {
+       unsigned int cnfg;
+       unsigned int status;
+       unsigned int sl_cnfg;
+       unsigned int sl_addr1;
+       unsigned int sl_addr2;
+       unsigned int tlow_sext;
+       unsigned int tx_fifo;
+       unsigned int rx_fifo;
+       unsigned int packet_transfer_status;
+       unsigned int fifo_control;
+       unsigned int fifo_status;
+       unsigned int int_mask;
+       unsigned int int_status;
+       unsigned int clk_divisor;
+       unsigned int bus_clear_cnfg;
+       unsigned int bus_clear_status;
+       unsigned int config_load;
+       unsigned int clken_override;
+       unsigned int interface_timing_0;
+       unsigned int interface_timing_1;
+       unsigned int hs_interface_timing_0;
+       unsigned int hs_interface_timing_1;
+       unsigned int master_reset_cntrl;
+       unsigned int mst_fifo_control;
+       unsigned int mst_fifo_status;
+       unsigned int sw_mutex;
+};
+
+static const struct tegra_i2c_regs tegra20_i2c_regs = {
+       .cnfg = 0x000,
+       .status = 0x01c,
+       .sl_cnfg = 0x020,
+       .sl_addr1 = 0x02c,
+       .sl_addr2 = 0x030,
+       .tx_fifo = 0x050,
+       .rx_fifo = 0x054,
+       .packet_transfer_status = 0x058,
+       .fifo_control = 0x05c,
+       .fifo_status = 0x060,
+       .int_mask = 0x064,
+       .int_status = 0x068,
+       .clk_divisor = 0x06c,
+       .bus_clear_cnfg = 0x084,
+       .bus_clear_status = 0x088,
+       .config_load = 0x08c,
+       .clken_override = 0x090,
+       .interface_timing_0 = 0x094,
+       .interface_timing_1 = 0x098,
+       .hs_interface_timing_0 = 0x09c,
+       .hs_interface_timing_1 = 0x0a0,
+       .master_reset_cntrl = 0x0a8,
+       .mst_fifo_control = 0x0b4,
+       .mst_fifo_status = 0x0b8,
+};
+
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)
+static const struct tegra_i2c_regs tegra20_dvc_i2c_regs = {
+       .cnfg = 0x040,
+       .status = 0x05c,
+       .tx_fifo = 0x060,
+       .rx_fifo = 0x064,
+       .packet_transfer_status = 0x068,
+       .fifo_control = 0x06c,
+       .fifo_status = 0x070,
+       .int_mask = 0x074,
+       .int_status = 0x078,
+       .clk_divisor = 0x07c,
+       .bus_clear_cnfg = 0x094,
+       .bus_clear_status = 0x098,
+       .config_load = 0x09c,
+       .clken_override = 0x0a0,
+       .interface_timing_0 = 0x0a4,
+       .interface_timing_1 = 0x0a8,
+       .hs_interface_timing_0 = 0x0ac,
+       .hs_interface_timing_1 = 0x0b0,
+       .master_reset_cntrl = 0x0b8,
+       .mst_fifo_control = 0x0c4,
+       .mst_fifo_status = 0x0c8,
+};
+#endif
+
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
+static const struct tegra_i2c_regs tegra210_vi_i2c_regs = {
+       .cnfg = 0x0c00,
+       .status = 0x0c70,
+       .tlow_sext = 0x0cd0,
+       .tx_fifo = 0x0d40,
+       .rx_fifo = 0x0d50,
+       .packet_transfer_status = 0x0d60,
+       .fifo_control = 0x0d70,
+       .fifo_status = 0x0d80,
+       .int_mask = 0x0d90,
+       .int_status = 0x0da0,
+       .clk_divisor = 0x0db0,
+       .bus_clear_cnfg = 0x0e10,
+       .bus_clear_status = 0x0e20,
+       .config_load = 0x0e30,
+       .clken_override = 0x0e40,
+       .interface_timing_0 = 0x0e50,
+       .interface_timing_1 = 0x0e60,
+       .hs_interface_timing_0 = 0x0e70,
+       .hs_interface_timing_1 = 0x0e80,
+       .master_reset_cntrl = 0x0ea0,
+       .mst_fifo_control = 0x0ed0,
+       .mst_fifo_status = 0x0ee0,
+};
+#endif
+
+static const struct tegra_i2c_regs tegra264_i2c_regs = {
+       .cnfg = 0x000,
+       .status = 0x01c,
+       .sl_cnfg = 0x020,
+       .sl_addr1 = 0x02c,
+       .sl_addr2 = 0x030,
+       .tx_fifo = 0x050,
+       .rx_fifo = 0x054,
+       .packet_transfer_status = 0x058,
+       .fifo_control = 0x05c,
+       .fifo_status = 0x060,
+       .int_mask = 0x064,
+       .int_status = 0x068,
+       .clk_divisor = 0x06c,
+       .bus_clear_cnfg = 0x084,
+       .bus_clear_status = 0x088,
+       .config_load = 0x08c,
+       .clken_override = 0x090,
+       .interface_timing_0 = 0x094,
+       .interface_timing_1 = 0x098,
+       .hs_interface_timing_0 = 0x09c,
+       .hs_interface_timing_1 = 0x0a0,
+       .master_reset_cntrl = 0x0a8,
+       .mst_fifo_control = 0x0b4,
+       .mst_fifo_status = 0x0b8,
+       .sw_mutex = 0x0ec,
+};
+
 /*
  * msg_end_type: The bus control which needs to be sent at end of transfer.
  * @MSG_END_STOP: Send stop pulse.
@@ -236,6 +352,7 @@ enum tegra_i2c_variant {
  * @enable_hs_mode_support: Enable support for high speed (HS) mode transfers.
  * @has_mutex: Has mutex register for mutual exclusion with other firmwares or VMs.
  * @variant: This represents the I2C controller variant.
+ * @regs: Register offsets for the specific SoC variant.
  */
 struct tegra_i2c_hw_feature {
        bool has_continue_xfer_support;
@@ -268,6 +385,7 @@ struct tegra_i2c_hw_feature {
        bool enable_hs_mode_support;
        bool has_mutex;
        enum tegra_i2c_variant variant;
+       const struct tegra_i2c_regs *regs;
 };
 
 /**
@@ -351,40 +469,26 @@ static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
        return readl_relaxed(i2c_dev->base + reg);
 }
 
-/*
- * If necessary, i2c_writel() and i2c_readl() will offset the register
- * in order to talk to the I2C block inside the DVC block.
- */
-static u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
-{
-       if (IS_DVC(i2c_dev))
-               reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40;
-       else if (IS_VI(i2c_dev))
-               reg = 0xc00 + (reg << 2);
-
-       return reg;
-}
-
 static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg)
 {
-       writel_relaxed(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+       writel_relaxed(val, i2c_dev->base + reg);
 
        /* read back register to make sure that register writes completed */
-       if (reg != I2C_TX_FIFO)
-               readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+       if (reg != i2c_dev->hw->regs->tx_fifo)
+               readl_relaxed(i2c_dev->base + reg);
        else if (IS_VI(i2c_dev))
-               readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS));
+               readl_relaxed(i2c_dev->base + i2c_dev->hw->regs->int_status);
 }
 
 static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
 {
-       return readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+       return readl_relaxed(i2c_dev->base + reg);
 }
 
 static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data,
                        unsigned int reg, unsigned int len)
 {
-       writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
+       writesl(i2c_dev->base + reg, data, len);
 }
 
 static void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data,
@@ -405,12 +509,12 @@ static void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data,
 static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
                       unsigned int reg, unsigned int len)
 {
-       readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
+       readsl(i2c_dev->base + reg, data, len);
 }
 
 static bool tegra_i2c_mutex_acquired(struct tegra_i2c_dev *i2c_dev)
 {
-       unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX);
+       unsigned int reg = i2c_dev->hw->regs->sw_mutex;
        u32 val, id;
 
        val = readl(i2c_dev->base + reg);
@@ -421,7 +525,7 @@ static bool tegra_i2c_mutex_acquired(struct tegra_i2c_dev *i2c_dev)
 
 static bool tegra_i2c_mutex_trylock(struct tegra_i2c_dev *i2c_dev)
 {
-       unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX);
+       unsigned int reg = i2c_dev->hw->regs->sw_mutex;
        u32 val, id;
 
        val = readl(i2c_dev->base + reg);
@@ -459,7 +563,7 @@ static int tegra_i2c_mutex_lock(struct tegra_i2c_dev *i2c_dev)
 
 static int tegra_i2c_mutex_unlock(struct tegra_i2c_dev *i2c_dev)
 {
-       unsigned int reg = tegra_i2c_reg_addr(i2c_dev, I2C_SW_MUTEX);
+       unsigned int reg = i2c_dev->hw->regs->sw_mutex;
        u32 val, id;
 
        if (!i2c_dev->hw->has_mutex)
@@ -482,16 +586,16 @@ static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
 {
        u32 int_mask;
 
-       int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) & ~mask;
-       i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
+       int_mask = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_mask) & ~mask;
+       i2c_writel(i2c_dev, int_mask, i2c_dev->hw->regs->int_mask);
 }
 
 static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
 {
        u32 int_mask;
 
-       int_mask = i2c_readl(i2c_dev, I2C_INT_MASK) | mask;
-       i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
+       int_mask = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_mask) | mask;
+       i2c_writel(i2c_dev, int_mask, i2c_dev->hw->regs->int_mask);
 }
 
 static void tegra_i2c_dma_complete(void *args)
@@ -635,34 +739,34 @@ static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev)
 
        value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) |
                FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4);
-       i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_0);
+       i2c_writel(i2c_dev, value, i2c_dev->hw->regs->interface_timing_0);
 
        value = FIELD_PREP(I2C_INTERFACE_TIMING_TBUF, 4) |
                FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STO, 7) |
                FIELD_PREP(I2C_INTERFACE_TIMING_THD_STA, 4) |
                FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STA, 4);
-       i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_1);
+       i2c_writel(i2c_dev, value, i2c_dev->hw->regs->interface_timing_1);
 
        value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, 3) |
                FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, 8);
-       i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_0);
+       i2c_writel(i2c_dev, value, i2c_dev->hw->regs->hs_interface_timing_0);
 
        value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STO, 11) |
                FIELD_PREP(I2C_HS_INTERFACE_TIMING_THD_STA, 11) |
                FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STA, 11);
-       i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_1);
+       i2c_writel(i2c_dev, value, i2c_dev->hw->regs->hs_interface_timing_1);
 
        value = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND;
-       i2c_writel(i2c_dev, value, I2C_BUS_CLEAR_CNFG);
+       i2c_writel(i2c_dev, value, i2c_dev->hw->regs->bus_clear_cnfg);
 
-       i2c_writel(i2c_dev, 0x0, I2C_TLOW_SEXT);
+       i2c_writel(i2c_dev, 0x0, i2c_dev->hw->regs->tlow_sext);
 }
 
 static int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev,
                                   u32 reg, u32 mask, u32 delay_us,
                                   u32 timeout_us)
 {
-       void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg);
+       void __iomem *addr = i2c_dev->base + reg;
        u32 val;
 
        if (!i2c_dev->atomic_mode)
@@ -681,11 +785,11 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
        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;
+               offset = i2c_dev->hw->regs->mst_fifo_control;
        } else {
                mask = I2C_FIFO_CONTROL_TX_FLUSH |
                       I2C_FIFO_CONTROL_RX_FLUSH;
-               offset = I2C_FIFO_CONTROL;
+               offset = i2c_dev->hw->regs->fifo_control;
        }
 
        val = i2c_readl(i2c_dev, offset);
@@ -708,9 +812,9 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
        if (!i2c_dev->hw->has_config_load_reg)
                return 0;
 
-       i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
+       i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, i2c_dev->hw->regs->config_load);
 
-       err = tegra_i2c_poll_register(i2c_dev, I2C_CONFIG_LOAD, 0xffffffff,
+       err = tegra_i2c_poll_register(i2c_dev, i2c_dev->hw->regs->config_load, 0xffffffff,
                                      1000, I2C_CONFIG_LOAD_TIMEOUT);
        if (err) {
                dev_err(i2c_dev->dev, "failed to load config\n");
@@ -731,10 +835,10 @@ static int tegra_i2c_master_reset(struct tegra_i2c_dev *i2c_dev)
         * SW needs to wait for 2us after assertion and de-assertion of this soft
         * reset.
         */
-       i2c_writel(i2c_dev, 0x1, I2C_MASTER_RESET_CNTRL);
+       i2c_writel(i2c_dev, 0x1, i2c_dev->hw->regs->master_reset_cntrl);
        fsleep(2);
 
-       i2c_writel(i2c_dev, 0x0, I2C_MASTER_RESET_CNTRL);
+       i2c_writel(i2c_dev, 0x0, i2c_dev->hw->regs->master_reset_cntrl);
        fsleep(2);
 
        return 0;
@@ -776,8 +880,8 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
        if (i2c_dev->hw->has_multi_master_mode)
                val |= I2C_CNFG_MULTI_MASTER_MODE;
 
-       i2c_writel(i2c_dev, val, I2C_CNFG);
-       i2c_writel(i2c_dev, 0, I2C_INT_MASK);
+       i2c_writel(i2c_dev, val, i2c_dev->hw->regs->cnfg);
+       i2c_writel(i2c_dev, 0, i2c_dev->hw->regs->int_mask);
 
        if (IS_VI(i2c_dev))
                tegra_i2c_vi_init(i2c_dev);
@@ -822,12 +926,12 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
        clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE,
                                 i2c_dev->hw->clk_divisor_hs_mode) |
                      FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE, non_hs_mode);
-       i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR);
+       i2c_writel(i2c_dev, clk_divisor, i2c_dev->hw->regs->clk_divisor);
 
        if (i2c_dev->hw->has_interface_timing_reg) {
                val = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, thigh) |
                      FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, tlow);
-               i2c_writel(i2c_dev, val, I2C_INTERFACE_TIMING_0);
+               i2c_writel(i2c_dev, val, i2c_dev->hw->regs->interface_timing_0);
        }
 
        /*
@@ -835,7 +939,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
         * Otherwise, preserve the chip default values.
         */
        if (i2c_dev->hw->has_interface_timing_reg && tsu_thd)
-               i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1);
+               i2c_writel(i2c_dev, tsu_thd, i2c_dev->hw->regs->interface_timing_1);
 
        /* Write HS mode registers. These will get used only for HS mode*/
        if (i2c_dev->hw->enable_hs_mode_support) {
@@ -845,8 +949,8 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 
                val = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, thigh) |
                        FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, tlow);
-               i2c_writel(i2c_dev, val, I2C_HS_INTERFACE_TIMING_0);
-               i2c_writel(i2c_dev, tsu_thd, I2C_HS_INTERFACE_TIMING_1);
+               i2c_writel(i2c_dev, val, i2c_dev->hw->regs->hs_interface_timing_0);
+               i2c_writel(i2c_dev, tsu_thd, i2c_dev->hw->regs->hs_interface_timing_1);
        }
 
        clk_multiplier = (tlow + thigh + 2) * (non_hs_mode + 1);
@@ -859,12 +963,12 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
        }
 
        if (!IS_DVC(i2c_dev) && !IS_VI(i2c_dev)) {
-               u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG);
+               u32 sl_cfg = i2c_readl(i2c_dev, i2c_dev->hw->regs->sl_cnfg);
 
                sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL;
-               i2c_writel(i2c_dev, sl_cfg, I2C_SL_CNFG);
-               i2c_writel(i2c_dev, 0xfc, I2C_SL_ADDR1);
-               i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2);
+               i2c_writel(i2c_dev, sl_cfg, i2c_dev->hw->regs->sl_cnfg);
+               i2c_writel(i2c_dev, 0xfc, i2c_dev->hw->regs->sl_addr1);
+               i2c_writel(i2c_dev, 0x00, i2c_dev->hw->regs->sl_addr2);
        }
 
        err = tegra_i2c_flush_fifos(i2c_dev);
@@ -872,7 +976,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
                return err;
 
        if (i2c_dev->multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
-               i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
+               i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, i2c_dev->hw->regs->clken_override);
 
        err = tegra_i2c_wait_for_config_load(i2c_dev);
        if (err)
@@ -893,9 +997,9 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)
         */
        udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->timings.bus_freq_hz));
 
-       cnfg = i2c_readl(i2c_dev, I2C_CNFG);
+       cnfg = i2c_readl(i2c_dev, i2c_dev->hw->regs->cnfg);
        if (cnfg & I2C_CNFG_PACKET_MODE_EN)
-               i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG);
+               i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, i2c_dev->hw->regs->cnfg);
 
        return tegra_i2c_wait_for_config_load(i2c_dev);
 }
@@ -915,10 +1019,10 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
                return -EINVAL;
 
        if (i2c_dev->hw->has_mst_fifo) {
-               val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
+               val = i2c_readl(i2c_dev, i2c_dev->hw->regs->mst_fifo_status);
                rx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_RX, val);
        } else {
-               val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+               val = i2c_readl(i2c_dev, i2c_dev->hw->regs->fifo_status);
                rx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_RX, val);
        }
 
@@ -927,7 +1031,7 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
        if (words_to_transfer > rx_fifo_avail)
                words_to_transfer = rx_fifo_avail;
 
-       i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer);
+       i2c_readsl(i2c_dev, buf, i2c_dev->hw->regs->rx_fifo, words_to_transfer);
 
        buf += words_to_transfer * BYTES_PER_FIFO_WORD;
        buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
@@ -943,7 +1047,7 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
                 * when (words_to_transfer was > rx_fifo_avail) earlier
                 * in this function.
                 */
-               val = i2c_readl(i2c_dev, I2C_RX_FIFO);
+               val = i2c_readl(i2c_dev, i2c_dev->hw->regs->rx_fifo);
                val = cpu_to_le32(val);
                memcpy(buf, &val, buf_remaining);
                buf_remaining = 0;
@@ -968,10 +1072,10 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
        u32 val;
 
        if (i2c_dev->hw->has_mst_fifo) {
-               val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
+               val = i2c_readl(i2c_dev, i2c_dev->hw->regs->mst_fifo_status);
                tx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_TX, val);
        } else {
-               val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+               val = i2c_readl(i2c_dev, i2c_dev->hw->regs->fifo_status);
                tx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_TX, val);
        }
 
@@ -1002,9 +1106,9 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
                i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD;
 
                if (IS_VI(i2c_dev))
-                       i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
+                       i2c_writesl_vi(i2c_dev, buf, i2c_dev->hw->regs->tx_fifo, words_to_transfer);
                else
-                       i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
+                       i2c_writesl(i2c_dev, buf, i2c_dev->hw->regs->tx_fifo, words_to_transfer);
 
                buf += words_to_transfer * BYTES_PER_FIFO_WORD;
        }
@@ -1026,7 +1130,7 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
                i2c_dev->msg_buf_remaining = 0;
                i2c_dev->msg_buf = NULL;
 
-               i2c_writel(i2c_dev, val, I2C_TX_FIFO);
+               i2c_writel(i2c_dev, val, i2c_dev->hw->regs->tx_fifo);
        }
 
        return 0;
@@ -1038,13 +1142,13 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
        struct tegra_i2c_dev *i2c_dev = dev_id;
        u32 status;
 
-       status = i2c_readl(i2c_dev, I2C_INT_STATUS);
+       status = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_status);
 
        if (status == 0) {
                dev_warn(i2c_dev->dev, "IRQ status 0 %08x %08x %08x\n",
-                        i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS),
-                        i2c_readl(i2c_dev, I2C_STATUS),
-                        i2c_readl(i2c_dev, I2C_CNFG));
+                        i2c_readl(i2c_dev, i2c_dev->hw->regs->packet_transfer_status),
+                        i2c_readl(i2c_dev, i2c_dev->hw->regs->status),
+                        i2c_readl(i2c_dev, i2c_dev->hw->regs->cnfg));
                i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT;
                goto err;
        }
@@ -1087,7 +1191,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
                }
        }
 
-       i2c_writel(i2c_dev, status, I2C_INT_STATUS);
+       i2c_writel(i2c_dev, status, i2c_dev->hw->regs->int_status);
        if (IS_DVC(i2c_dev))
                dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
 
@@ -1125,7 +1229,7 @@ err:
        if (i2c_dev->hw->supports_bus_clear)
                tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
 
-       i2c_writel(i2c_dev, status, I2C_INT_STATUS);
+       i2c_writel(i2c_dev, status, i2c_dev->hw->regs->int_status);
 
        if (IS_DVC(i2c_dev))
                dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
@@ -1148,9 +1252,9 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
        int err;
 
        if (i2c_dev->hw->has_mst_fifo)
-               reg = I2C_MST_FIFO_CONTROL;
+               reg = i2c_dev->hw->regs->mst_fifo_control;
        else
-               reg = I2C_FIFO_CONTROL;
+               reg = i2c_dev->hw->regs->fifo_control;
 
        if (i2c_dev->dma_mode) {
                if (len & 0xF)
@@ -1161,7 +1265,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
                        dma_burst = 8;
 
                if (i2c_dev->msg_read) {
-                       reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO);
+                       reg_offset = i2c_dev->hw->regs->rx_fifo;
 
                        slv_config.src_addr = i2c_dev->base_phys + reg_offset;
                        slv_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -1172,7 +1276,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
                        else
                                val = I2C_FIFO_CONTROL_RX_TRIG(dma_burst);
                } else {
-                       reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO);
+                       reg_offset = i2c_dev->hw->regs->tx_fifo;
 
                        slv_config.dst_addr = i2c_dev->base_phys + reg_offset;
                        slv_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -1215,7 +1319,7 @@ static unsigned long tegra_i2c_poll_completion(struct tegra_i2c_dev *i2c_dev,
        ktime_t ktimeout = ktime_add_ms(ktime, timeout_ms);
 
        do {
-               u32 status = i2c_readl(i2c_dev, I2C_INT_STATUS);
+               u32 status = i2c_readl(i2c_dev, i2c_dev->hw->regs->int_status);
 
                if (status)
                        tegra_i2c_isr(i2c_dev->irq, i2c_dev);
@@ -1274,14 +1378,14 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 
        val = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND |
              I2C_BC_TERMINATE;
-       i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
+       i2c_writel(i2c_dev, val, i2c_dev->hw->regs->bus_clear_cnfg);
 
        err = tegra_i2c_wait_for_config_load(i2c_dev);
        if (err)
                return err;
 
        val |= I2C_BC_ENABLE;
-       i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
+       i2c_writel(i2c_dev, val, i2c_dev->hw->regs->bus_clear_cnfg);
        tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
 
        time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete, 50);
@@ -1292,7 +1396,7 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
                return -ETIMEDOUT;
        }
 
-       val = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS);
+       val = i2c_readl(i2c_dev, i2c_dev->hw->regs->bus_clear_status);
        if (!(val & I2C_BC_STATUS)) {
                dev_err(i2c_dev->dev, "un-recovered arbitration lost\n");
                return -EIO;
@@ -1317,14 +1421,14 @@ static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev,
        if (i2c_dev->dma_mode && !i2c_dev->msg_read)
                *dma_buf++ = packet_header;
        else
-               i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+               i2c_writel(i2c_dev, packet_header, i2c_dev->hw->regs->tx_fifo);
 
        packet_header = i2c_dev->msg_len - 1;
 
        if (i2c_dev->dma_mode && !i2c_dev->msg_read)
                *dma_buf++ = packet_header;
        else
-               i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+               i2c_writel(i2c_dev, packet_header, i2c_dev->hw->regs->tx_fifo);
 
        packet_header = I2C_HEADER_IE_ENABLE;
 
@@ -1352,7 +1456,7 @@ static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev,
        if (i2c_dev->dma_mode && !i2c_dev->msg_read)
                *dma_buf++ = packet_header;
        else
-               i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+               i2c_writel(i2c_dev, packet_header, i2c_dev->hw->regs->tx_fifo);
 }
 
 static int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev,
@@ -1473,7 +1577,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
        tegra_i2c_unmask_irq(i2c_dev, int_mask);
        dev_dbg(i2c_dev->dev, "unmasked IRQ: %02x\n",
-               i2c_readl(i2c_dev, I2C_INT_MASK));
+               i2c_readl(i2c_dev, i2c_dev->hw->regs->int_mask));
 
        if (i2c_dev->dma_mode) {
                time_left = tegra_i2c_wait_completion(i2c_dev,
@@ -1648,6 +1752,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
        .enable_hs_mode_support = false,
        .has_mutex = false,
        .variant = TEGRA_I2C_VARIANT_DEFAULT,
+       .regs = &tegra20_i2c_regs,
 };
 
 #if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)
@@ -1680,6 +1785,7 @@ static const struct tegra_i2c_hw_feature tegra20_dvc_i2c_hw = {
        .enable_hs_mode_support = false,
        .has_mutex = false,
        .variant = TEGRA_I2C_VARIANT_DVC,
+       .regs = &tegra20_dvc_i2c_regs,
 };
 #endif
 
@@ -1712,6 +1818,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
        .enable_hs_mode_support = false,
        .has_mutex = false,
        .variant = TEGRA_I2C_VARIANT_DEFAULT,
+       .regs = &tegra20_i2c_regs,
 };
 
 static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -1743,6 +1850,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
        .enable_hs_mode_support = false,
        .has_mutex = false,
        .variant = TEGRA_I2C_VARIANT_DEFAULT,
+       .regs = &tegra20_i2c_regs,
 };
 
 static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -1774,6 +1882,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
        .enable_hs_mode_support = false,
        .has_mutex = false,
        .variant = TEGRA_I2C_VARIANT_DEFAULT,
+       .regs = &tegra20_i2c_regs,
 };
 
 static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@@ -1805,6 +1914,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
        .enable_hs_mode_support = false,
        .has_mutex = false,
        .variant = TEGRA_I2C_VARIANT_DEFAULT,
+       .regs = &tegra20_i2c_regs,
 };
 
 #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
@@ -1837,6 +1947,7 @@ static const struct tegra_i2c_hw_feature tegra210_vi_i2c_hw = {
        .enable_hs_mode_support = false,
        .has_mutex = false,
        .variant = TEGRA_I2C_VARIANT_VI,
+       .regs = &tegra210_vi_i2c_regs,
 };
 #endif
 
@@ -1869,6 +1980,7 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
        .enable_hs_mode_support = false,
        .has_mutex = false,
        .variant = TEGRA_I2C_VARIANT_DEFAULT,
+       .regs = &tegra20_i2c_regs,
 };
 
 static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
@@ -1902,6 +2014,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
        .enable_hs_mode_support = true,
        .has_mutex = false,
        .variant = TEGRA_I2C_VARIANT_DEFAULT,
+       .regs = &tegra20_i2c_regs,
 };
 
 static const struct tegra_i2c_hw_feature tegra256_i2c_hw = {
@@ -1935,6 +2048,7 @@ static const struct tegra_i2c_hw_feature tegra256_i2c_hw = {
        .enable_hs_mode_support = true,
        .has_mutex = true,
        .variant = TEGRA_I2C_VARIANT_DEFAULT,
+       .regs = &tegra264_i2c_regs,
 };
 
 static const struct tegra_i2c_hw_feature tegra264_i2c_hw = {
@@ -1968,6 +2082,7 @@ static const struct tegra_i2c_hw_feature tegra264_i2c_hw = {
        .enable_hs_mode_support = true,
        .has_mutex = true,
        .variant = TEGRA_I2C_VARIANT_DEFAULT,
+       .regs = &tegra264_i2c_regs,
 };
 
 static const struct of_device_id tegra_i2c_of_match[] = {