i2c: tegra: Factor out hardware initialization into separate function
[linux-2.6-block.git] / drivers / i2c / busses / i2c-tegra.c
index 88d6e7bb14a2acc585bfffcab2af9c8cb94e7300..d8fc5cdcc310117c12b3eddf68178976330ec53f 100644 (file)
@@ -165,9 +165,6 @@ enum msg_end_type {
  * @has_continue_xfer_support: Continue transfer supports.
  * @has_per_pkt_xfer_complete_irq: Has enable/disable capability for transfer
  *             complete interrupt per packet basis.
- * @has_single_clk_source: The I2C controller has single clock source. Tegra30
- *             and earlier SoCs have two clock sources i.e. div-clk and
- *             fast-clk.
  * @has_config_load_reg: Has the config load register to load the new
  *             configuration.
  * @clk_divisor_hs_mode: Clock divisor in HS mode.
@@ -208,22 +205,21 @@ enum msg_end_type {
 struct tegra_i2c_hw_feature {
        bool has_continue_xfer_support;
        bool has_per_pkt_xfer_complete_irq;
-       bool has_single_clk_source;
        bool has_config_load_reg;
-       int clk_divisor_hs_mode;
-       int clk_divisor_std_mode;
-       int clk_divisor_fast_mode;
-       u16 clk_divisor_fast_plus_mode;
+       u32 clk_divisor_hs_mode;
+       u32 clk_divisor_std_mode;
+       u32 clk_divisor_fast_mode;
+       u32 clk_divisor_fast_plus_mode;
        bool has_multi_master_mode;
        bool has_slcg_override_reg;
        bool has_mst_fifo;
        const struct i2c_adapter_quirks *quirks;
        bool supports_bus_clear;
        bool has_apb_dma;
-       u8 tlow_std_mode;
-       u8 thigh_std_mode;
-       u8 tlow_fast_fastplus_mode;
-       u8 thigh_fast_fastplus_mode;
+       u32 tlow_std_mode;
+       u32 thigh_std_mode;
+       u32 tlow_fast_fastplus_mode;
+       u32 thigh_fast_fastplus_mode;
        u32 setup_hold_time_std_mode;
        u32 setup_hold_time_fast_fast_plus_mode;
        u32 setup_hold_time_hs_mode;
@@ -236,7 +232,8 @@ struct tegra_i2c_hw_feature {
  * @hw: Tegra I2C HW feature
  * @adapter: core I2C layer adapter information
  * @div_clk: clock reference for div clock of I2C controller
- * @fast_clk: clock reference for fast clock of I2C controller
+ * @clocks: array of I2C controller clocks
+ * @nclocks: number of clocks in the array
  * @rst: reset control for the I2C controller
  * @base: ioremapped registers cookie
  * @base_phys: physical base address of the I2C controller
@@ -250,7 +247,6 @@ struct tegra_i2c_hw_feature {
  * @msg_buf_remaining: size of unsent data in the message buffer
  * @msg_read: identifies read transfers
  * @bus_clk_rate: current I2C bus clock rate
- * @clk_divisor_non_hs_mode: clock divider for non-high-speed modes
  * @is_multimaster_mode: track if I2C controller is in multi-master mode
  * @tx_dma_chan: DMA transmit channel
  * @rx_dma_chan: DMA receive channel
@@ -266,35 +262,32 @@ struct tegra_i2c_dev {
        const struct tegra_i2c_hw_feature *hw;
        struct i2c_adapter adapter;
        struct clk *div_clk;
-       struct clk *fast_clk;
-       struct clk *slow_clk;
+       struct clk_bulk_data clocks[2];
+       unsigned int nclocks;
        struct reset_control *rst;
        void __iomem *base;
        phys_addr_t base_phys;
-       int cont_id;
-       int irq;
-       int is_dvc;
+       unsigned int cont_id;
+       unsigned int irq;
+       bool is_dvc;
        bool is_vi;
        struct completion msg_complete;
        int msg_err;
        u8 *msg_buf;
        size_t msg_buf_remaining;
-       int msg_read;
+       bool msg_read;
        u32 bus_clk_rate;
-       u16 clk_divisor_non_hs_mode;
        bool is_multimaster_mode;
        struct dma_chan *tx_dma_chan;
        struct dma_chan *rx_dma_chan;
        dma_addr_t dma_phys;
-       u32 *dma_buf;
+       void *dma_buf;
        unsigned int dma_buf_size;
        bool is_curr_dma_xfer;
        struct completion dma_complete;
        bool is_curr_atomic_xfer;
 };
 
-static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit);
-
 static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
                       unsigned long reg)
 {
@@ -336,13 +329,13 @@ static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg)
 }
 
 static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data,
-                       unsigned long reg, int len)
+                       unsigned long reg, unsigned int len)
 {
        writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
 }
 
 static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
-                      unsigned long reg, int len)
+                      unsigned long reg, unsigned int len)
 {
        readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
 }
@@ -445,6 +438,9 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
 
        i2c_dev->tx_dma_chan = chan;
 
+       i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len +
+                               I2C_PACKET_HEADER_SIZE;
+
        dma_buf = dma_alloc_coherent(i2c_dev->dev, i2c_dev->dma_buf_size,
                                     &dma_phys, GFP_KERNEL | __GFP_NOWARN);
        if (!dma_buf) {
@@ -468,10 +464,74 @@ err_out:
        return err;
 }
 
+/*
+ * One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller)
+ * block.  This block is identical to the rest of the I2C blocks, except that
+ * it only supports master mode, it has registers moved around, and it needs
+ * some extra init to get it into I2C mode.  The register moves are handled
+ * by i2c_readl and i2c_writel
+ */
+static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
+{
+       u32 val;
+
+       val = dvc_readl(i2c_dev, DVC_CTRL_REG3);
+       val |= DVC_CTRL_REG3_SW_PROG;
+       val |= DVC_CTRL_REG3_I2C_DONE_INTR_EN;
+       dvc_writel(i2c_dev, val, DVC_CTRL_REG3);
+
+       val = dvc_readl(i2c_dev, DVC_CTRL_REG1);
+       val |= DVC_CTRL_REG1_INTR_EN;
+       dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
+}
+
+static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev)
+{
+       u32 value;
+
+       value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) |
+               FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4);
+       i2c_writel(i2c_dev, value, I2C_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);
+
+       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);
+
+       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);
+
+       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, 0x0, I2C_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);
+       u32 val;
+
+       if (!i2c_dev->is_curr_atomic_xfer)
+               return readl_relaxed_poll_timeout(addr, val, !(val & mask),
+                                                 delay_us, timeout_us);
+
+       return readl_relaxed_poll_timeout_atomic(addr, val, !(val & mask),
+                                                delay_us, timeout_us);
+}
+
 static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
 {
-       u32 mask, val, offset, reg_offset;
-       void __iomem *addr;
+       u32 mask, val, offset;
        int err;
 
        if (i2c_dev->hw->has_mst_fifo) {
@@ -488,30 +548,167 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
        val |= mask;
        i2c_writel(i2c_dev, val, offset);
 
-       reg_offset = tegra_i2c_reg_addr(i2c_dev, offset);
-       addr = i2c_dev->base + reg_offset;
+       err = tegra_i2c_poll_register(i2c_dev, offset, mask, 1000, 1000000);
+       if (err) {
+               dev_err(i2c_dev->dev, "failed to flush FIFO\n");
+               return err;
+       }
+       return 0;
+}
 
-       if (i2c_dev->is_curr_atomic_xfer)
-               err = readl_relaxed_poll_timeout_atomic(addr, val, !(val & mask),
-                                                       1000, 1000000);
-       else
-               err = readl_relaxed_poll_timeout(addr, val, !(val & mask),
-                                                1000, 1000000);
+static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
+{
+       int err;
 
+       if (!i2c_dev->hw->has_config_load_reg)
+               return 0;
+
+       i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
+
+       err = tegra_i2c_poll_register(i2c_dev, I2C_CONFIG_LOAD, 0xffffffff,
+                                     1000, I2C_CONFIG_LOAD_TIMEOUT);
        if (err) {
-               dev_err(i2c_dev->dev, "failed to flush FIFO\n");
+               dev_warn(i2c_dev->dev, "timeout waiting for config load\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
+{
+       u32 val;
+       int err;
+       u32 clk_divisor, clk_multiplier;
+       u32 non_hs_mode;
+       u32 tsu_thd;
+       u8 tlow, thigh;
+
+       /*
+        * The reset shouldn't ever fail in practice. The failure will be a
+        * sign of a severe problem that needs to be resolved. Still we don't
+        * want to fail the initialization completely because this may break
+        * kernel boot up since voltage regulators use I2C. Hence, we will
+        * emit a noisy warning on error, which won't stay unnoticed and
+        * won't hose machine entirely.
+        */
+       err = reset_control_reset(i2c_dev->rst);
+       WARN_ON_ONCE(err);
+
+       if (i2c_dev->is_dvc)
+               tegra_dvc_init(i2c_dev);
+
+       val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
+             FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 2);
+
+       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);
+
+       if (i2c_dev->is_vi)
+               tegra_i2c_vi_init(i2c_dev);
+
+       switch (i2c_dev->bus_clk_rate) {
+       case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ:
+       default:
+               tlow = i2c_dev->hw->tlow_fast_fastplus_mode;
+               thigh = i2c_dev->hw->thigh_fast_fastplus_mode;
+               tsu_thd = i2c_dev->hw->setup_hold_time_fast_fast_plus_mode;
+
+               if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ)
+                       non_hs_mode = i2c_dev->hw->clk_divisor_fast_plus_mode;
+               else
+                       non_hs_mode = i2c_dev->hw->clk_divisor_fast_mode;
+               break;
+
+       case 0 ... I2C_MAX_STANDARD_MODE_FREQ:
+               tlow = i2c_dev->hw->tlow_std_mode;
+               thigh = i2c_dev->hw->thigh_std_mode;
+               tsu_thd = i2c_dev->hw->setup_hold_time_std_mode;
+               non_hs_mode = i2c_dev->hw->clk_divisor_std_mode;
+               break;
+       }
+
+       /* Make sure clock divisor programmed correctly */
+       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);
+
+       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);
+       }
+
+       /*
+        * configure setup and hold times only when tsu_thd is non-zero.
+        * 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);
+
+       clk_multiplier  = tlow + thigh + 2;
+       clk_multiplier *= non_hs_mode + 1;
+
+       err = clk_set_rate(i2c_dev->div_clk,
+                          i2c_dev->bus_clk_rate * clk_multiplier);
+       if (err) {
+               dev_err(i2c_dev->dev, "failed to set div-clk rate: %d\n", err);
                return err;
        }
+
+       if (!i2c_dev->is_dvc && !i2c_dev->is_vi) {
+               u32 sl_cfg = i2c_readl(i2c_dev, I2C_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);
+       }
+
+       err = tegra_i2c_flush_fifos(i2c_dev);
+       if (err)
+               return err;
+
+       if (i2c_dev->is_multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
+               i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
+
+       err = tegra_i2c_wait_for_config_load(i2c_dev);
+       if (err)
+               return err;
+
        return 0;
 }
 
+static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)
+{
+       u32 cnfg;
+
+       /*
+        * NACK interrupt is generated before the I2C controller generates
+        * the STOP condition on the bus. So wait for 2 clock periods
+        * before disabling the controller so that the STOP condition has
+        * been delivered properly.
+        */
+       udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->bus_clk_rate));
+
+       cnfg = i2c_readl(i2c_dev, I2C_CNFG);
+       if (cnfg & I2C_CNFG_PACKET_MODE_EN)
+               i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG);
+
+       return tegra_i2c_wait_for_config_load(i2c_dev);
+}
+
 static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
 {
        u32 val;
-       int rx_fifo_avail;
+       unsigned int rx_fifo_avail;
        u8 *buf = i2c_dev->msg_buf;
        size_t buf_remaining = i2c_dev->msg_buf_remaining;
-       int words_to_transfer;
+       unsigned int words_to_transfer;
 
        /*
         * Catch overflow due to message fully sent
@@ -569,10 +766,10 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
 static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
 {
        u32 val;
-       int tx_fifo_avail;
+       unsigned int tx_fifo_avail;
        u8 *buf = i2c_dev->msg_buf;
        size_t buf_remaining = i2c_dev->msg_buf_remaining;
-       int words_to_transfer;
+       unsigned int words_to_transfer;
 
        if (i2c_dev->hw->has_mst_fifo) {
                val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
@@ -591,18 +788,17 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
                        words_to_transfer = tx_fifo_avail;
 
                /*
-                * Update state before writing to FIFO.  If this casues us
-                * to finish writing all bytes (AKA buf_remaining goes to 0) we
-                * have a potential for an interrupt (PACKET_XFER_COMPLETE is
-                * not maskable).  We need to make sure that the isr sees
-                * buf_remaining as 0 and doesn't call us back re-entrantly.
+                * Update state before writing to FIFO.  Note that this may
+                * cause us to finish writing all bytes (AKA buf_remaining
+                * goes to 0), hence we have a potential for an interrupt
+                * (PACKET_XFER_COMPLETE is not maskable), but GIC interrupt
+                * is disabled at this point.
                 */
                buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
                tx_fifo_avail -= words_to_transfer;
                i2c_dev->msg_buf_remaining = buf_remaining;
                i2c_dev->msg_buf = buf +
                        words_to_transfer * BYTES_PER_FIFO_WORD;
-               barrier();
 
                i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
 
@@ -623,10 +819,8 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
                memcpy(&val, buf, buf_remaining);
                val = le32_to_cpu(val);
 
-               /* Again update before writing to FIFO to make sure isr sees. */
                i2c_dev->msg_buf_remaining = 0;
                i2c_dev->msg_buf = NULL;
-               barrier();
 
                i2c_writel(i2c_dev, val, I2C_TX_FIFO);
        }
@@ -634,262 +828,6 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
        return 0;
 }
 
-/*
- * One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller)
- * block.  This block is identical to the rest of the I2C blocks, except that
- * it only supports master mode, it has registers moved around, and it needs
- * some extra init to get it into I2C mode.  The register moves are handled
- * by i2c_readl and i2c_writel
- */
-static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
-{
-       u32 val;
-
-       val = dvc_readl(i2c_dev, DVC_CTRL_REG3);
-       val |= DVC_CTRL_REG3_SW_PROG;
-       val |= DVC_CTRL_REG3_I2C_DONE_INTR_EN;
-       dvc_writel(i2c_dev, val, DVC_CTRL_REG3);
-
-       val = dvc_readl(i2c_dev, DVC_CTRL_REG1);
-       val |= DVC_CTRL_REG1_INTR_EN;
-       dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
-}
-
-static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
-{
-       struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
-       int ret;
-
-       ret = pinctrl_pm_select_default_state(i2c_dev->dev);
-       if (ret)
-               return ret;
-
-       ret = clk_enable(i2c_dev->fast_clk);
-       if (ret < 0) {
-               dev_err(i2c_dev->dev,
-                       "Enabling fast clk failed, err %d\n", ret);
-               return ret;
-       }
-
-       ret = clk_enable(i2c_dev->slow_clk);
-       if (ret < 0) {
-               dev_err(dev, "failed to enable slow clock: %d\n", ret);
-               goto disable_fast_clk;
-       }
-
-       ret = clk_enable(i2c_dev->div_clk);
-       if (ret < 0) {
-               dev_err(i2c_dev->dev,
-                       "Enabling div clk failed, err %d\n", ret);
-               goto disable_slow_clk;
-       }
-
-       /*
-        * VI I2C device is attached to VE power domain which goes through
-        * power ON/OFF during PM runtime resume/suspend. So, controller
-        * should go through reset and need to re-initialize after power
-        * domain ON.
-        */
-       if (i2c_dev->is_vi) {
-               ret = tegra_i2c_init(i2c_dev, true);
-               if (ret)
-                       goto disable_div_clk;
-       }
-
-       return 0;
-
-disable_div_clk:
-       clk_disable(i2c_dev->div_clk);
-disable_slow_clk:
-       clk_disable(i2c_dev->slow_clk);
-disable_fast_clk:
-       clk_disable(i2c_dev->fast_clk);
-       return ret;
-}
-
-static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev)
-{
-       struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
-
-       clk_disable(i2c_dev->div_clk);
-       clk_disable(i2c_dev->slow_clk);
-       clk_disable(i2c_dev->fast_clk);
-
-       return pinctrl_pm_select_idle_state(i2c_dev->dev);
-}
-
-static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
-{
-       unsigned long reg_offset;
-       void __iomem *addr;
-       u32 val;
-       int err;
-
-       if (i2c_dev->hw->has_config_load_reg) {
-               reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_CONFIG_LOAD);
-               addr = i2c_dev->base + reg_offset;
-               i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
-
-               if (i2c_dev->is_curr_atomic_xfer)
-                       err = readl_relaxed_poll_timeout_atomic(
-                                               addr, val, val == 0, 1000,
-                                               I2C_CONFIG_LOAD_TIMEOUT);
-               else
-                       err = readl_relaxed_poll_timeout(
-                                               addr, val, val == 0, 1000,
-                                               I2C_CONFIG_LOAD_TIMEOUT);
-
-               if (err) {
-                       dev_warn(i2c_dev->dev,
-                                "timeout waiting for config load\n");
-                       return err;
-               }
-       }
-
-       return 0;
-}
-
-static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev)
-{
-       u32 value;
-
-       value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) |
-               FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4);
-       i2c_writel(i2c_dev, value, I2C_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);
-
-       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);
-
-       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);
-
-       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, 0x0, I2C_TLOW_SEXT);
-}
-
-static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
-{
-       u32 val;
-       int err;
-       u32 clk_divisor, clk_multiplier;
-       u32 tsu_thd;
-       u8 tlow, thigh;
-
-       reset_control_assert(i2c_dev->rst);
-       udelay(2);
-       reset_control_deassert(i2c_dev->rst);
-
-       if (i2c_dev->is_dvc)
-               tegra_dvc_init(i2c_dev);
-
-       val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
-             FIELD_PREP(I2C_CNFG_DEBOUNCE_CNT, 2);
-
-       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);
-
-       if (i2c_dev->is_vi)
-               tegra_i2c_vi_init(i2c_dev);
-
-       /* Make sure clock divisor programmed correctly */
-       clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE,
-                                i2c_dev->hw->clk_divisor_hs_mode) |
-                     FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE,
-                                i2c_dev->clk_divisor_non_hs_mode);
-       i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR);
-
-       if (i2c_dev->bus_clk_rate > I2C_MAX_STANDARD_MODE_FREQ &&
-           i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_PLUS_FREQ) {
-               tlow = i2c_dev->hw->tlow_fast_fastplus_mode;
-               thigh = i2c_dev->hw->thigh_fast_fastplus_mode;
-               tsu_thd = i2c_dev->hw->setup_hold_time_fast_fast_plus_mode;
-       } else {
-               tlow = i2c_dev->hw->tlow_std_mode;
-               thigh = i2c_dev->hw->thigh_std_mode;
-               tsu_thd = i2c_dev->hw->setup_hold_time_std_mode;
-       }
-
-       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);
-       }
-
-       /*
-        * configure setup and hold times only when tsu_thd is non-zero.
-        * 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);
-
-       if (!clk_reinit) {
-               clk_multiplier = (tlow + thigh + 2);
-               clk_multiplier *= (i2c_dev->clk_divisor_non_hs_mode + 1);
-               err = clk_set_rate(i2c_dev->div_clk,
-                                  i2c_dev->bus_clk_rate * clk_multiplier);
-               if (err) {
-                       dev_err(i2c_dev->dev,
-                               "failed changing clock rate: %d\n", err);
-                       return err;
-               }
-       }
-
-       if (!i2c_dev->is_dvc && !i2c_dev->is_vi) {
-               u32 sl_cfg = i2c_readl(i2c_dev, I2C_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);
-       }
-
-       err = tegra_i2c_flush_fifos(i2c_dev);
-       if (err)
-               return err;
-
-       if (i2c_dev->is_multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
-               i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
-
-       err = tegra_i2c_wait_for_config_load(i2c_dev);
-       if (err)
-               return err;
-
-       return 0;
-}
-
-static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)
-{
-       u32 cnfg;
-
-       /*
-        * NACK interrupt is generated before the I2C controller generates
-        * the STOP condition on the bus. So wait for 2 clock periods
-        * before disabling the controller so that the STOP condition has
-        * been delivered properly.
-        */
-       udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->bus_clk_rate));
-
-       cnfg = i2c_readl(i2c_dev, I2C_CNFG);
-       if (cnfg & I2C_CNFG_PACKET_MODE_EN)
-               i2c_writel(i2c_dev, cnfg & ~I2C_CNFG_PACKET_MODE_EN, I2C_CNFG);
-
-       return tegra_i2c_wait_for_config_load(i2c_dev);
-}
-
 static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
 {
        u32 status;
@@ -907,7 +845,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
                goto err;
        }
 
-       if (unlikely(status & status_err)) {
+       if (status & status_err) {
                tegra_i2c_disable_packet_mode(i2c_dev);
                if (status & I2C_INT_NO_ACK)
                        i2c_dev->msg_err |= I2C_ERR_NO_ACK;
@@ -1065,10 +1003,9 @@ out:
        i2c_writel(i2c_dev, val, reg);
 }
 
-static unsigned long
-tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev,
-                                 struct completion *complete,
-                                 unsigned int timeout_ms)
+static unsigned long tegra_i2c_poll_completion(struct tegra_i2c_dev *i2c_dev,
+                                              struct completion *complete,
+                                              unsigned int timeout_ms)
 {
        ktime_t ktime = ktime_get();
        ktime_t ktimeout = ktime_add_ms(ktime, timeout_ms);
@@ -1092,16 +1029,14 @@ tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev,
        return 0;
 }
 
-static unsigned long
-tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
-                                 struct completion *complete,
-                                 unsigned int timeout_ms)
+static unsigned long tegra_i2c_wait_completion(struct tegra_i2c_dev *i2c_dev,
+                                              struct completion *complete,
+                                              unsigned int timeout_ms)
 {
        unsigned long ret;
 
        if (i2c_dev->is_curr_atomic_xfer) {
-               ret = tegra_i2c_poll_completion_timeout(i2c_dev, complete,
-                                                       timeout_ms);
+               ret = tegra_i2c_poll_completion(i2c_dev, complete, timeout_ms);
        } else {
                enable_irq(i2c_dev->irq);
                ret = wait_for_completion_timeout(complete,
@@ -1119,8 +1054,7 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
                 * needs to be checked after timeout.
                 */
                if (ret == 0)
-                       ret = tegra_i2c_poll_completion_timeout(i2c_dev,
-                                                               complete, 0);
+                       ret = tegra_i2c_poll_completion(i2c_dev, complete, 0);
        }
 
        return ret;
@@ -1137,18 +1071,18 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
        reg = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND |
              I2C_BC_TERMINATE;
        i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG);
-       if (i2c_dev->hw->has_config_load_reg) {
-               err = tegra_i2c_wait_for_config_load(i2c_dev);
-               if (err)
-                       return err;
-       }
+
+       err = tegra_i2c_wait_for_config_load(i2c_dev);
+       if (err)
+               return err;
 
        reg |= I2C_BC_ENABLE;
        i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG);
        tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
 
-       time_left = tegra_i2c_wait_completion_timeout(
-                       i2c_dev, &i2c_dev->msg_complete, 50);
+       time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete, 50);
+       tegra_i2c_mask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
+
        if (time_left == 0) {
                dev_err(i2c_dev->dev, "timed out for bus clear\n");
                return -ETIMEDOUT;
@@ -1164,17 +1098,91 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
        return -EAGAIN;
 }
 
+static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev,
+                                        struct i2c_msg *msg,
+                                        enum msg_end_type end_state)
+{
+       u32 *dma_buf = i2c_dev->dma_buf;
+       u32 packet_header;
+
+       packet_header = FIELD_PREP(PACKET_HEADER0_HEADER_SIZE, 0) |
+                       FIELD_PREP(PACKET_HEADER0_PROTOCOL,
+                                  PACKET_HEADER0_PROTOCOL_I2C) |
+                       FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) |
+                       FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1);
+
+       if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
+               *dma_buf++ = packet_header;
+       else
+               i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+       packet_header = msg->len - 1;
+
+       if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
+               *dma_buf++ = packet_header;
+       else
+               i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+       packet_header = I2C_HEADER_IE_ENABLE;
+
+       if (end_state == MSG_END_CONTINUE)
+               packet_header |= I2C_HEADER_CONTINUE_XFER;
+       else if (end_state == MSG_END_REPEAT_START)
+               packet_header |= I2C_HEADER_REPEAT_START;
+
+       if (msg->flags & I2C_M_TEN) {
+               packet_header |= msg->addr;
+               packet_header |= I2C_HEADER_10BIT_ADDR;
+       } else {
+               packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
+       }
+
+       if (msg->flags & I2C_M_IGNORE_NAK)
+               packet_header |= I2C_HEADER_CONT_ON_NAK;
+
+       if (msg->flags & I2C_M_RD)
+               packet_header |= I2C_HEADER_READ;
+
+       if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
+               *dma_buf++ = packet_header;
+       else
+               i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+}
+
+static int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev,
+                                  struct i2c_msg *msg)
+{
+       if (i2c_dev->msg_err == I2C_ERR_NONE)
+               return 0;
+
+       tegra_i2c_init(i2c_dev);
+
+       /* start recovery upon arbitration loss in single master mode */
+       if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) {
+               if (!i2c_dev->is_multimaster_mode)
+                       return i2c_recover_bus(&i2c_dev->adapter);
+
+               return -EAGAIN;
+       }
+
+       if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
+               if (msg->flags & I2C_M_IGNORE_NAK)
+                       return 0;
+
+               return -EREMOTEIO;
+       }
+
+       return -EIO;
+}
+
 static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                              struct i2c_msg *msg,
                              enum msg_end_type end_state)
 {
-       u32 packet_header;
        u32 int_mask;
        unsigned long time_left;
        size_t xfer_size;
-       u32 *buffer = NULL;
        int err = 0;
-       bool dma;
        u16 xfer_time = 100;
 
        err = tegra_i2c_flush_fifos(i2c_dev);
@@ -1184,7 +1192,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
        i2c_dev->msg_buf = msg->buf;
        i2c_dev->msg_buf_remaining = msg->len;
        i2c_dev->msg_err = I2C_ERR_NONE;
-       i2c_dev->msg_read = (msg->flags & I2C_M_RD);
+       i2c_dev->msg_read = !!(msg->flags & I2C_M_RD);
        reinit_completion(&i2c_dev->msg_complete);
 
        if (i2c_dev->msg_read)
@@ -1197,7 +1205,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                                    i2c_dev->dma_buf &&
                                    !i2c_dev->is_curr_atomic_xfer;
        tegra_i2c_config_fifo_trig(i2c_dev, xfer_size);
-       dma = i2c_dev->is_curr_dma_xfer;
+
        /*
         * Transfer time in mSec = Total bits / transfer rate
         * Total bits = 9 bits per byte (including ACK bit) + Start & stop bits
@@ -1207,7 +1215,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
        int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
        tegra_i2c_unmask_irq(i2c_dev, int_mask);
-       if (dma) {
+       if (i2c_dev->is_curr_dma_xfer) {
                if (i2c_dev->msg_read) {
                        dma_sync_single_for_device(i2c_dev->dev,
                                                   i2c_dev->dma_phys,
@@ -1215,60 +1223,26 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                                                   DMA_FROM_DEVICE);
                        err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
                        if (err < 0) {
-                               dev_err(i2c_dev->dev,
-                                       "starting RX DMA failed, err %d\n",
-                                       err);
-                               return err;
-                       }
-
-               } else {
-                       dma_sync_single_for_cpu(i2c_dev->dev,
-                                               i2c_dev->dma_phys,
-                                               xfer_size,
-                                               DMA_TO_DEVICE);
-                       buffer = i2c_dev->dma_buf;
-               }
-       }
-
-       packet_header = FIELD_PREP(PACKET_HEADER0_HEADER_SIZE, 0) |
-                       FIELD_PREP(PACKET_HEADER0_PROTOCOL,
-                                  PACKET_HEADER0_PROTOCOL_I2C) |
-                       FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) |
-                       FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1);
-       if (dma && !i2c_dev->msg_read)
-               *buffer++ = packet_header;
-       else
-               i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
-
-       packet_header = msg->len - 1;
-       if (dma && !i2c_dev->msg_read)
-               *buffer++ = packet_header;
-       else
-               i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
-
-       packet_header = I2C_HEADER_IE_ENABLE;
-       if (end_state == MSG_END_CONTINUE)
-               packet_header |= I2C_HEADER_CONTINUE_XFER;
-       else if (end_state == MSG_END_REPEAT_START)
-               packet_header |= I2C_HEADER_REPEAT_START;
-       if (msg->flags & I2C_M_TEN) {
-               packet_header |= msg->addr;
-               packet_header |= I2C_HEADER_10BIT_ADDR;
-       } else {
-               packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
+                               dev_err(i2c_dev->dev,
+                                       "starting RX DMA failed, err %d\n",
+                                       err);
+                               return err;
+                       }
+
+               } else {
+                       dma_sync_single_for_cpu(i2c_dev->dev,
+                                               i2c_dev->dma_phys,
+                                               xfer_size,
+                                               DMA_TO_DEVICE);
+               }
        }
-       if (msg->flags & I2C_M_IGNORE_NAK)
-               packet_header |= I2C_HEADER_CONT_ON_NAK;
-       if (msg->flags & I2C_M_RD)
-               packet_header |= I2C_HEADER_READ;
-       if (dma && !i2c_dev->msg_read)
-               *buffer++ = packet_header;
-       else
-               i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+       tegra_i2c_push_packet_header(i2c_dev, msg, end_state);
 
        if (!i2c_dev->msg_read) {
-               if (dma) {
-                       memcpy(buffer, msg->buf, msg->len);
+               if (i2c_dev->is_curr_dma_xfer) {
+                       memcpy(i2c_dev->dma_buf + I2C_PACKET_HEADER_SIZE,
+                              msg->buf, msg->len);
                        dma_sync_single_for_device(i2c_dev->dev,
                                                   i2c_dev->dma_phys,
                                                   xfer_size,
@@ -1287,7 +1261,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
        if (i2c_dev->hw->has_per_pkt_xfer_complete_irq)
                int_mask |= I2C_INT_PACKET_XFER_COMPLETE;
-       if (!dma) {
+       if (!i2c_dev->is_curr_dma_xfer) {
                if (msg->flags & I2C_M_RD)
                        int_mask |= I2C_INT_RX_FIFO_DATA_REQ;
                else if (i2c_dev->msg_buf_remaining)
@@ -1298,9 +1272,10 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
        dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n",
                i2c_readl(i2c_dev, I2C_INT_MASK));
 
-       if (dma) {
-               time_left = tegra_i2c_wait_completion_timeout(
-                               i2c_dev, &i2c_dev->dma_complete, xfer_time);
+       if (i2c_dev->is_curr_dma_xfer) {
+               time_left = tegra_i2c_wait_completion(i2c_dev,
+                                                     &i2c_dev->dma_complete,
+                                                     xfer_time);
 
                /*
                 * Synchronize DMA first, since dmaengine_terminate_sync()
@@ -1317,7 +1292,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
                if (!time_left && !completion_done(&i2c_dev->dma_complete)) {
                        dev_err(i2c_dev->dev, "DMA transfer timeout\n");
-                       tegra_i2c_init(i2c_dev, true);
+                       tegra_i2c_init(i2c_dev);
                        return -ETIMEDOUT;
                }
 
@@ -1331,14 +1306,14 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                }
        }
 
-       time_left = tegra_i2c_wait_completion_timeout(
-                       i2c_dev, &i2c_dev->msg_complete, xfer_time);
+       time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete,
+                                             xfer_time);
 
        tegra_i2c_mask_irq(i2c_dev, int_mask);
 
        if (time_left == 0) {
                dev_err(i2c_dev->dev, "i2c transfer timed out\n");
-               tegra_i2c_init(i2c_dev, true);
+               tegra_i2c_init(i2c_dev);
                return -ETIMEDOUT;
        }
 
@@ -1347,24 +1322,12 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
                i2c_dev->msg_err);
 
        i2c_dev->is_curr_dma_xfer = false;
-       if (likely(i2c_dev->msg_err == I2C_ERR_NONE))
-               return 0;
-
-       tegra_i2c_init(i2c_dev, true);
-       /* start recovery upon arbitration loss in single master mode */
-       if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) {
-               if (!i2c_dev->is_multimaster_mode)
-                       return i2c_recover_bus(&i2c_dev->adapter);
-               return -EAGAIN;
-       }
 
-       if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
-               if (msg->flags & I2C_M_IGNORE_NAK)
-                       return 0;
-               return -EREMOTEIO;
-       }
+       err = tegra_i2c_error_recover(i2c_dev, msg);
+       if (err)
+               return err;
 
-       return -EIO;
+       return 0;
 }
 
 static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
@@ -1424,21 +1387,6 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap)
        return ret;
 }
 
-static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
-{
-       struct device_node *np = i2c_dev->dev->of_node;
-       int ret;
-       bool multi_mode;
-
-       ret = of_property_read_u32(np, "clock-frequency",
-                                  &i2c_dev->bus_clk_rate);
-       if (ret)
-               i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; /* default clock rate */
-
-       multi_mode = of_property_read_bool(np, "multi-master");
-       i2c_dev->is_multimaster_mode = multi_mode;
-}
-
 static const struct i2c_algorithm tegra_i2c_algo = {
        .master_xfer            = tegra_i2c_xfer,
        .master_xfer_atomic     = tegra_i2c_xfer_atomic,
@@ -1464,7 +1412,6 @@ static struct i2c_bus_recovery_info tegra_i2c_recovery_info = {
 static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
        .has_continue_xfer_support = false,
        .has_per_pkt_xfer_complete_irq = false,
-       .has_single_clk_source = false,
        .clk_divisor_hs_mode = 3,
        .clk_divisor_std_mode = 0,
        .clk_divisor_fast_mode = 0,
@@ -1489,7 +1436,6 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
 static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
        .has_continue_xfer_support = true,
        .has_per_pkt_xfer_complete_irq = false,
-       .has_single_clk_source = false,
        .clk_divisor_hs_mode = 3,
        .clk_divisor_std_mode = 0,
        .clk_divisor_fast_mode = 0,
@@ -1514,7 +1460,6 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
 static const struct tegra_i2c_hw_feature tegra114_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_mode = 0x19,
        .clk_divisor_fast_mode = 0x19,
@@ -1539,7 +1484,6 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
 static const struct tegra_i2c_hw_feature tegra124_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_mode = 0x19,
        .clk_divisor_fast_mode = 0x19,
@@ -1564,7 +1508,6 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
 static const struct tegra_i2c_hw_feature tegra210_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_mode = 0x19,
        .clk_divisor_fast_mode = 0x19,
@@ -1589,7 +1532,6 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
 static const struct tegra_i2c_hw_feature tegra186_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_mode = 0x16,
        .clk_divisor_fast_mode = 0x19,
@@ -1614,7 +1556,6 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
 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_mode = 0x4f,
        .clk_divisor_fast_mode = 0x3c,
@@ -1651,123 +1592,146 @@ static const struct of_device_id tegra_i2c_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
 
-static int tegra_i2c_probe(struct platform_device *pdev)
+static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
 {
-       struct device *dev = &pdev->dev;
-       struct tegra_i2c_dev *i2c_dev;
-       struct resource *res;
-       struct clk *div_clk;
-       struct clk *fast_clk;
-       void __iomem *base;
-       phys_addr_t base_phys;
-       int irq;
+       struct device_node *np = i2c_dev->dev->of_node;
        int ret;
+       bool multi_mode;
+
+       ret = of_property_read_u32(np, "clock-frequency",
+                                  &i2c_dev->bus_clk_rate);
+       if (ret)
+               i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; /* default clock rate */
+
+       multi_mode = of_property_read_bool(np, "multi-master");
+       i2c_dev->is_multimaster_mode = multi_mode;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       base_phys = res->start;
-       base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
+       if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
+               i2c_dev->is_dvc = true;
 
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "no irq resource\n");
-               return -EINVAL;
-       }
-       irq = res->start;
+       if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
+               i2c_dev->is_vi = true;
+}
+
+static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
+{
+       int err;
+
+       i2c_dev->clocks[i2c_dev->nclocks++].id = "div-clk";
+
+       if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw)
+               i2c_dev->clocks[i2c_dev->nclocks++].id = "fast-clk";
+
+       if (i2c_dev->is_vi)
+               i2c_dev->clocks[i2c_dev->nclocks++].id = "slow";
 
-       div_clk = devm_clk_get(&pdev->dev, "div-clk");
-       if (IS_ERR(div_clk)) {
-               if (PTR_ERR(div_clk) != -EPROBE_DEFER)
-                       dev_err(&pdev->dev, "missing controller clock\n");
+       err = devm_clk_bulk_get(i2c_dev->dev, i2c_dev->nclocks,
+                               i2c_dev->clocks);
+       if (err)
+               return err;
+
+       err = clk_bulk_prepare(i2c_dev->nclocks, i2c_dev->clocks);
+       if (err)
+               return err;
+
+       i2c_dev->div_clk = i2c_dev->clocks[0].clk;
+
+       if (!i2c_dev->is_multimaster_mode)
+               return 0;
 
-               return PTR_ERR(div_clk);
+       err = clk_enable(i2c_dev->div_clk);
+       if (err) {
+               dev_err(i2c_dev->dev, "failed to enable div-clk: %d\n", err);
+               goto unprepare_clocks;
        }
 
+       return 0;
+
+unprepare_clocks:
+       clk_bulk_unprepare(i2c_dev->nclocks, i2c_dev->clocks);
+
+       return err;
+}
+
+static void tegra_i2c_release_clocks(struct tegra_i2c_dev *i2c_dev)
+{
+       if (i2c_dev->is_multimaster_mode)
+               clk_disable(i2c_dev->div_clk);
+
+       clk_bulk_unprepare(i2c_dev->nclocks, i2c_dev->clocks);
+}
+
+static int tegra_i2c_init_hardware(struct tegra_i2c_dev *i2c_dev)
+{
+       int ret;
+
+       ret = pm_runtime_get_sync(i2c_dev->dev);
+       if (ret < 0)
+               dev_err(i2c_dev->dev, "runtime resume failed: %d\n", ret);
+       else
+               ret = tegra_i2c_init(i2c_dev);
+
+       pm_runtime_put(i2c_dev->dev);
+
+       return ret;
+}
+
+static int tegra_i2c_probe(struct platform_device *pdev)
+{
+       struct tegra_i2c_dev *i2c_dev;
+       struct resource *res;
+       int ret;
+
        i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
        if (!i2c_dev)
                return -ENOMEM;
 
-       i2c_dev->base = base;
-       i2c_dev->base_phys = base_phys;
-       i2c_dev->div_clk = div_clk;
-       i2c_dev->adapter.algo = &tegra_i2c_algo;
-       i2c_dev->adapter.retries = 1;
-       i2c_dev->adapter.timeout = 6 * HZ;
-       i2c_dev->irq = irq;
-       i2c_dev->cont_id = pdev->id;
-       i2c_dev->dev = &pdev->dev;
-
-       i2c_dev->rst = devm_reset_control_get_exclusive(&pdev->dev, "i2c");
-       if (IS_ERR(i2c_dev->rst)) {
-               dev_err(&pdev->dev, "missing controller reset\n");
-               return PTR_ERR(i2c_dev->rst);
-       }
-
-       tegra_i2c_parse_dt(i2c_dev);
+       platform_set_drvdata(pdev, i2c_dev);
 
-       i2c_dev->hw = of_device_get_match_data(&pdev->dev);
-       i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
-                                                 "nvidia,tegra20-i2c-dvc");
-       i2c_dev->is_vi = of_device_is_compatible(dev->of_node,
-                                                "nvidia,tegra210-i2c-vi");
-       i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
-       i2c_dev->dma_buf_size = i2c_dev->adapter.quirks->max_write_len +
-                               I2C_PACKET_HEADER_SIZE;
        init_completion(&i2c_dev->msg_complete);
        init_completion(&i2c_dev->dma_complete);
 
-       if (!i2c_dev->hw->has_single_clk_source) {
-               fast_clk = devm_clk_get(&pdev->dev, "fast-clk");
-               if (IS_ERR(fast_clk)) {
-                       dev_err(&pdev->dev, "missing fast clock\n");
-                       return PTR_ERR(fast_clk);
-               }
-               i2c_dev->fast_clk = fast_clk;
-       }
+       i2c_dev->hw = of_device_get_match_data(&pdev->dev);
+       i2c_dev->cont_id = pdev->id;
+       i2c_dev->dev = &pdev->dev;
 
-       if (i2c_dev->is_vi) {
-               i2c_dev->slow_clk = devm_clk_get(dev, "slow");
-               if (IS_ERR(i2c_dev->slow_clk)) {
-                       if (PTR_ERR(i2c_dev->slow_clk) != -EPROBE_DEFER)
-                               dev_err(dev, "failed to get slow clock: %ld\n",
-                                       PTR_ERR(i2c_dev->slow_clk));
+       i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+       if (IS_ERR(i2c_dev->base))
+               return PTR_ERR(i2c_dev->base);
 
-                       return PTR_ERR(i2c_dev->slow_clk);
-               }
-       }
+       i2c_dev->base_phys = res->start;
 
-       platform_set_drvdata(pdev, i2c_dev);
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0)
+               return ret;
 
-       ret = clk_prepare(i2c_dev->fast_clk);
-       if (ret < 0) {
-               dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
+       i2c_dev->irq = ret;
+
+       /* interrupt will be enabled during of transfer time */
+       irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN);
+
+       ret = devm_request_irq(&pdev->dev, i2c_dev->irq, tegra_i2c_isr,
+                              IRQF_NO_SUSPEND, dev_name(&pdev->dev),
+                              i2c_dev);
+       if (ret)
                return ret;
-       }
 
-       ret = clk_prepare(i2c_dev->slow_clk);
-       if (ret < 0) {
-               dev_err(dev, "failed to prepare slow clock: %d\n", ret);
-               goto unprepare_fast_clk;
+       i2c_dev->rst = devm_reset_control_get_exclusive(&pdev->dev, "i2c");
+       if (IS_ERR(i2c_dev->rst)) {
+               dev_err_probe(&pdev->dev, PTR_ERR(i2c_dev->rst),
+                             "failed to get reset control\n");
+               return PTR_ERR(i2c_dev->rst);
        }
 
-       if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ &&
-           i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_PLUS_FREQ)
-               i2c_dev->clk_divisor_non_hs_mode =
-                               i2c_dev->hw->clk_divisor_fast_plus_mode;
-       else if (i2c_dev->bus_clk_rate > I2C_MAX_STANDARD_MODE_FREQ &&
-                i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_FREQ)
-               i2c_dev->clk_divisor_non_hs_mode =
-                               i2c_dev->hw->clk_divisor_fast_mode;
-       else
-               i2c_dev->clk_divisor_non_hs_mode =
-                               i2c_dev->hw->clk_divisor_std_mode;
+       tegra_i2c_parse_dt(i2c_dev);
 
-       ret = clk_prepare(i2c_dev->div_clk);
-       if (ret < 0) {
-               dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
-               goto unprepare_slow_clk;
-       }
+       ret = tegra_i2c_init_clocks(i2c_dev);
+       if (ret)
+               return ret;
+
+       ret = tegra_i2c_init_dma(i2c_dev);
+       if (ret)
+               goto release_clocks;
 
        /*
         * VI I2C is in VE power domain which is not always on and not
@@ -1779,92 +1743,40 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        if (!i2c_dev->is_vi)
                pm_runtime_irq_safe(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
-       if (!pm_runtime_enabled(&pdev->dev)) {
-               ret = tegra_i2c_runtime_resume(&pdev->dev);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "runtime resume failed\n");
-                       goto unprepare_div_clk;
-               }
-       } else {
-               ret = pm_runtime_get_sync(i2c_dev->dev);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "runtime resume failed\n");
-                       goto put_rpm;
-               }
-       }
-
-       if (i2c_dev->is_multimaster_mode) {
-               ret = clk_enable(i2c_dev->div_clk);
-               if (ret < 0) {
-                       dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
-                               ret);
-                       goto put_rpm;
-               }
-       }
-
-       if (i2c_dev->hw->supports_bus_clear)
-               i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
-
-       ret = tegra_i2c_init_dma(i2c_dev);
-       if (ret < 0)
-               goto disable_div_clk;
-
-       ret = tegra_i2c_init(i2c_dev, false);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to initialize i2c controller\n");
-               goto release_dma;
-       }
-
-       irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN);
 
-       ret = devm_request_irq(&pdev->dev, i2c_dev->irq, tegra_i2c_isr,
-                              IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c_dev);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
-               goto release_dma;
-       }
+       ret = tegra_i2c_init_hardware(i2c_dev);
+       if (ret)
+               goto release_rpm;
 
        i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
+       i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
+       i2c_dev->adapter.dev.parent = &pdev->dev;
+       i2c_dev->adapter.retries = 1;
+       i2c_dev->adapter.timeout = 6 * HZ;
+       i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
        i2c_dev->adapter.owner = THIS_MODULE;
        i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
+       i2c_dev->adapter.algo = &tegra_i2c_algo;
+       i2c_dev->adapter.nr = pdev->id;
+
+       if (i2c_dev->hw->supports_bus_clear)
+               i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
+
        strlcpy(i2c_dev->adapter.name, dev_name(&pdev->dev),
                sizeof(i2c_dev->adapter.name));
-       i2c_dev->adapter.dev.parent = &pdev->dev;
-       i2c_dev->adapter.nr = pdev->id;
-       i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
 
        ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
        if (ret)
-               goto release_dma;
-
-       pm_runtime_put(&pdev->dev);
+               goto release_rpm;
 
        return 0;
 
-release_dma:
-       tegra_i2c_release_dma(i2c_dev);
-
-disable_div_clk:
-       if (i2c_dev->is_multimaster_mode)
-               clk_disable(i2c_dev->div_clk);
-
-put_rpm:
-       if (pm_runtime_enabled(&pdev->dev))
-               pm_runtime_put_sync(&pdev->dev);
-       else
-               tegra_i2c_runtime_suspend(&pdev->dev);
-
-       if (pm_runtime_enabled(&pdev->dev))
-               pm_runtime_disable(&pdev->dev);
-
-unprepare_div_clk:
-       clk_unprepare(i2c_dev->div_clk);
-
-unprepare_slow_clk:
-       clk_unprepare(i2c_dev->slow_clk);
+release_rpm:
+       pm_runtime_disable(&pdev->dev);
 
-unprepare_fast_clk:
-       clk_unprepare(i2c_dev->fast_clk);
+       tegra_i2c_release_dma(i2c_dev);
+release_clocks:
+       tegra_i2c_release_clocks(i2c_dev);
 
        return ret;
 }
@@ -1875,19 +1787,53 @@ static int tegra_i2c_remove(struct platform_device *pdev)
 
        i2c_del_adapter(&i2c_dev->adapter);
 
-       if (i2c_dev->is_multimaster_mode)
-               clk_disable(i2c_dev->div_clk);
-
        pm_runtime_disable(&pdev->dev);
-       if (!pm_runtime_status_suspended(&pdev->dev))
-               tegra_i2c_runtime_suspend(&pdev->dev);
-
-       clk_unprepare(i2c_dev->div_clk);
-       clk_unprepare(i2c_dev->slow_clk);
-       clk_unprepare(i2c_dev->fast_clk);
 
        tegra_i2c_release_dma(i2c_dev);
+       tegra_i2c_release_clocks(i2c_dev);
+       return 0;
+}
+
+static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
+{
+       struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+       int ret;
+
+       ret = pinctrl_pm_select_default_state(i2c_dev->dev);
+       if (ret)
+               return ret;
+
+       ret = clk_bulk_enable(i2c_dev->nclocks, i2c_dev->clocks);
+       if (ret)
+               return ret;
+
+       /*
+        * VI I2C device is attached to VE power domain which goes through
+        * power ON/OFF during PM runtime resume/suspend. So, controller
+        * should go through reset and need to re-initialize after power
+        * domain ON.
+        */
+       if (i2c_dev->is_vi) {
+               ret = tegra_i2c_init(i2c_dev);
+               if (ret)
+                       goto disable_clocks;
+       }
+
        return 0;
+
+disable_clocks:
+       clk_bulk_disable(i2c_dev->nclocks, i2c_dev->clocks);
+
+       return ret;
+}
+
+static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev)
+{
+       struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+
+       clk_bulk_disable(i2c_dev->nclocks, i2c_dev->clocks);
+
+       return pinctrl_pm_select_idle_state(i2c_dev->dev);
 }
 
 static int __maybe_unused tegra_i2c_suspend(struct device *dev)
@@ -1916,7 +1862,7 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)
        if (err)
                return err;
 
-       err = tegra_i2c_init(i2c_dev, false);
+       err = tegra_i2c_init(i2c_dev);
        if (err)
                return err;