Loading drivers/i2c/busses/i2c-msm-v2.c +26 −6 Original line number Diff line number Diff line Loading @@ -2045,9 +2045,14 @@ static bool i2c_msm_qup_slv_holds_bus(struct i2c_msm_ctrl *ctrl) { u32 status = readl_relaxed(ctrl->rsrcs.base + QUP_I2C_STATUS); return !(status & QUP_I2C_SDA) && bool slv_holds_bus = !(status & QUP_I2C_SDA) && (status & QUP_BUS_ACTIVE) && !(status & QUP_BUS_MASTER); if (slv_holds_bus) dev_info(ctrl->dev, "bus lines held low by a slave detected\n"); return slv_holds_bus; } /* Loading Loading @@ -2470,6 +2475,7 @@ static int i2c_msm_qup_init(struct i2c_msm_ctrl *ctrl) static bool i2c_msm_qup_do_bus_clear(struct i2c_msm_ctrl *ctrl) { int ret; ulong min_sleep_usec; dev_info(ctrl->dev, "Executing bus recovery procedure (9 clk pulse)\n"); /* call i2c_msm_qup_init() to set core in idle state */ Loading @@ -2477,15 +2483,29 @@ static bool i2c_msm_qup_do_bus_clear(struct i2c_msm_ctrl *ctrl) if (ret) return ret; /* call i2c_msm_qup_xfer_init_run_state() to set clock dividers */ i2c_msm_qup_xfer_init_run_state(ctrl); /* must be in run state for bus clear */ ret = i2c_msm_qup_state_set(ctrl, QUP_STATE_RUN); if (ret) return ret; /* * call i2c_msm_qup_xfer_init_run_state() to set clock dividers. * the dividers are necessary for bus clear. */ i2c_msm_qup_xfer_init_run_state(ctrl); writel_relaxed(0x1, ctrl->rsrcs.base + QUP_I2C_MASTER_BUS_CLR); /* * wait for recovery (9 clock pulse cycles) to complete. * min_time = 9 clock *10 (1000% margin) * max_time = 10* min_time */ min_sleep_usec = max_t(ulong, (9 * 10 * USEC_PER_SEC) / ctrl->rsrcs.clk_freq_out, 100); usleep_range(min_sleep_usec, min_sleep_usec * 10); return 0; } Loading Loading
drivers/i2c/busses/i2c-msm-v2.c +26 −6 Original line number Diff line number Diff line Loading @@ -2045,9 +2045,14 @@ static bool i2c_msm_qup_slv_holds_bus(struct i2c_msm_ctrl *ctrl) { u32 status = readl_relaxed(ctrl->rsrcs.base + QUP_I2C_STATUS); return !(status & QUP_I2C_SDA) && bool slv_holds_bus = !(status & QUP_I2C_SDA) && (status & QUP_BUS_ACTIVE) && !(status & QUP_BUS_MASTER); if (slv_holds_bus) dev_info(ctrl->dev, "bus lines held low by a slave detected\n"); return slv_holds_bus; } /* Loading Loading @@ -2470,6 +2475,7 @@ static int i2c_msm_qup_init(struct i2c_msm_ctrl *ctrl) static bool i2c_msm_qup_do_bus_clear(struct i2c_msm_ctrl *ctrl) { int ret; ulong min_sleep_usec; dev_info(ctrl->dev, "Executing bus recovery procedure (9 clk pulse)\n"); /* call i2c_msm_qup_init() to set core in idle state */ Loading @@ -2477,15 +2483,29 @@ static bool i2c_msm_qup_do_bus_clear(struct i2c_msm_ctrl *ctrl) if (ret) return ret; /* call i2c_msm_qup_xfer_init_run_state() to set clock dividers */ i2c_msm_qup_xfer_init_run_state(ctrl); /* must be in run state for bus clear */ ret = i2c_msm_qup_state_set(ctrl, QUP_STATE_RUN); if (ret) return ret; /* * call i2c_msm_qup_xfer_init_run_state() to set clock dividers. * the dividers are necessary for bus clear. */ i2c_msm_qup_xfer_init_run_state(ctrl); writel_relaxed(0x1, ctrl->rsrcs.base + QUP_I2C_MASTER_BUS_CLR); /* * wait for recovery (9 clock pulse cycles) to complete. * min_time = 9 clock *10 (1000% margin) * max_time = 10* min_time */ min_sleep_usec = max_t(ulong, (9 * 10 * USEC_PER_SEC) / ctrl->rsrcs.clk_freq_out, 100); usleep_range(min_sleep_usec, min_sleep_usec * 10); return 0; } Loading