Loading drivers/i2c/busses/i2c-msm-v2.c +91 −64 Original line number Diff line number Diff line Loading @@ -391,6 +391,21 @@ static const struct i2c_msm_qup_reg_dump i2c_msm_qup_reg_dump_map[] = { {0, NULL }, }; const char *i2c_msm_err_str_table[] = { [I2C_MSM_ERR_NACK] = "NACK: slave not responding, ensure its powered", [I2C_MSM_ERR_ARB_LOST] = "arb_lost", [I2C_MSM_ERR_BUS_ERR] = "BUS ERROR : noisy bus or unexpected start/stop tag", [I2C_MSM_ERR_TIMEOUT] = "", [I2C_MSM_ERR_CORE_CLK] = "CLOCK OFF : Check Core Clock", [I2C_MSM_ERR_OVR_UNDR_RUN] = "OVER_UNDER_RUN_ERROR", [I2C_MSM_ERR_INVALID_WRITE] = "invalid data write", [I2C_MSM_ERR_INVALID_TAG] = "invalid tag", [I2C_MSM_ERR_INVALID_READ_ADDR] = "Invalid slave addr", [I2C_MSM_ERR_INVALID_READ_SEQ] = "start tag error for read", [I2C_MSM_ERR_FAILED] = "I2C transfer failed", }; /* * see: struct i2c_msm_qup_reg_dump for more */ Loading @@ -416,47 +431,43 @@ static void i2c_msm_dbg_dump_diag(struct i2c_msm_ctrl *ctrl, bool use_param_vals, u32 status, u32 qup_op) { struct i2c_msm_xfer *xfer = &ctrl->xfer; const char *str = "DEBUG"; char buf[I2C_MSM_REG_2_STR_BUF_SZ]; char str[I2C_MSM_MAX_ERR_BUF_SZ] = {'\0'}; char *p_str = str; const char **diag_msg = i2c_msm_err_str_table; int err = xfer->err; if (!use_param_vals) { void __iomem *base = ctrl->rsrcs.base; status = readl_relaxed(base + QUP_I2C_STATUS); qup_op = readl_relaxed(base + QUP_OPERATIONAL); } /* In case of NACK, bus and controller are in a good state */ if (xfer->err & I2C_MSM_ERR_NACK) { str = "NACK: slave not responding, ensure its powered " "and out of reset"; /* clock off may be the root cause of all errors below */ } else if (xfer->err & I2C_MSM_ERR_CORE_CLK) { str = "CLOCK OFF: Check Core Clock"; /* on arb lost we cant control the bus. root cause may be gpios or slv*/ } else if (xfer->err & I2C_MSM_ERR_ARB_LOST) { str = "ARB LOST"; } else if (xfer->err & I2C_MSM_ERR_TIMEOUT) { if ((err & BIT(I2C_MSM_ERR_TIMEOUT))) { /* * if we are not the bus master or SDA/SCL is low then it may be * that slave is pulling the lines low. Otherwise it is likely a * GPIO issue * if we are not the bus master or SDA/SCL is * low then it may be that slave is pulling the * lines low. Otherwise it is likely a GPIO * issue */ if (!(status & QUP_BUS_MASTER)) snprintf(buf, I2C_MSM_REG_2_STR_BUF_SZ, "TIMEOUT(val:%dmsec) check GPIO config if SDA/SCL line(s) low", p_str += snprintf(p_str, I2C_MSM_MAX_ERR_BUF_SZ, "TIMEOUT(val:%dmsec) check GPIO config if SDA/SCL line(s) low, ", jiffies_to_msecs(xfer->timeout)); else snprintf(buf, I2C_MSM_REG_2_STR_BUF_SZ, "TIMEOUT(val:%dmsec)", jiffies_to_msecs(xfer->timeout)); p_str += snprintf(p_str, I2C_MSM_MAX_ERR_BUF_SZ, "TIMEOUT(val:%dmsec), ", jiffies_to_msecs(xfer->timeout)); } for (; err; err >>= 1, ++diag_msg) { str = buf; /* invalid electric signal on the bus, may be noise or bad slave */ } else if (xfer->err & I2C_MSM_ERR_BUS_ERR) { str = "BUS ERROR: noisy bus or unexpected start/stop tag"; /* error occur due to INPUT/OUTPUT over or under run */ } else if (xfer->err & I2C_MSM_ERR_OVR_UNDR_RUN) { str = "OVER_UNDER_RUN_ERROR"; if (err & 1) p_str += snprintf(p_str, (I2C_MSM_MAX_ERR_BUF_SZ - (p_str - str)), "%s, ", *diag_msg); } /* dump xfer details */ dev_err(ctrl->dev, "%s: msgs(n:%d cur:%d %s) bc(rx:%zu tx:%zu) mode:%s " Loading Loading @@ -970,7 +981,7 @@ static int i2c_msm_qup_sw_reset(struct i2c_msm_ctrl *ctrl) ret = i2c_msm_qup_state_wait_valid(ctrl, QUP_STATE_RESET, false); if (ret) { if (atomic_read(&ctrl->xfer.is_active)) ctrl->xfer.err |= I2C_MSM_ERR_CORE_CLK; ctrl->xfer.err |= BIT(I2C_MSM_ERR_CORE_CLK); dev_err(ctrl->dev, "error on issuing QUP software-reset\n"); } return ret; Loading Loading @@ -2736,43 +2747,38 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid) log_event = true; if (i2c_status & QUP_PACKET_NACKED) ctrl->xfer.err |= I2C_MSM_ERR_NACK; ctrl->xfer.err |= BIT(I2C_MSM_ERR_NACK); if (i2c_status & QUP_ARB_LOST) ctrl->xfer.err |= I2C_MSM_ERR_ARB_LOST; ctrl->xfer.err |= BIT(I2C_MSM_ERR_ARB_LOST); if (i2c_status & QUP_BUS_ERROR) ctrl->xfer.err |= I2C_MSM_ERR_BUS_ERR; ctrl->xfer.err |= BIT(I2C_MSM_ERR_BUS_ERR); if (i2c_status & QUP_INVALID_WRITE) ctrl->xfer.err |= BIT(I2C_MSM_ERR_INVALID_WRITE); if (i2c_status & QUP_INVALID_TAG) ctrl->xfer.err |= BIT(I2C_MSM_ERR_INVALID_TAG); if (i2c_status & QUP_INVALID_READ_ADDR) ctrl->xfer.err |= BIT(I2C_MSM_ERR_INVALID_READ_ADDR); if (i2c_status & QUP_INVALID_READ_SEQ) ctrl->xfer.err |= BIT(I2C_MSM_ERR_INVALID_READ_SEQ); if (i2c_status & QUP_FAILED) ctrl->xfer.err |= BIT(I2C_MSM_ERR_FAILED); } /* check for FIFO over/under runs error */ if (err_flags & QUP_ERR_FLGS_MASK) ctrl->xfer.err |= I2C_MSM_ERR_OVR_UNDR_RUN; ctrl->xfer.err = BIT(I2C_MSM_ERR_OVR_UNDR_RUN); /* Reset and bail out on error */ if (ctrl->xfer.err) { /* Dump the register values before reset the core */ if (ctrl->dbgfs.dbg_lvl >= MSM_DBG) if (ctrl->xfer.err && ctrl->dbgfs.dbg_lvl >= MSM_DBG) i2c_msm_dbg_qup_reg_dump(ctrl); /* Flush for the tags in case of an error and BAM Mode*/ if (ctrl->xfer.mode_id == I2C_MSM_XFER_MODE_BAM) writel_relaxed(QUP_I2C_FLUSH, ctrl->rsrcs.base + QUP_STATE); /* HW workaround: when interrupt is level triggerd, more * than one interrupt may fire in error cases. Thus we * reset the core immidiatly in the ISR to ward off the * next interrupt. */ i2c_msm_qup_sw_reset(ctrl); need_wmb = true; signal_complete = true; log_event = true; goto isr_end; } /* clear interrupts fields */ clr_flds = i2c_status & QUP_MSTR_STTS_ERR_MASK; if (clr_flds) { Loading @@ -2792,6 +2798,27 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid) need_wmb = true; } /* Reset and bail out on error */ if (ctrl->xfer.err) { /* Flush for the tags in case of an error and BAM Mode*/ if (ctrl->xfer.mode_id == I2C_MSM_XFER_MODE_BAM) writel_relaxed(QUP_I2C_FLUSH, ctrl->rsrcs.base + QUP_STATE); /* HW workaround: when interrupt is level triggerd, more * than one interrupt may fire in error cases. Thus we * reset the core immidiatly in the ISR to ward off the * next interrupt. */ i2c_msm_qup_sw_reset(ctrl); need_wmb = true; signal_complete = true; log_event = true; goto isr_end; } /* handle data completion */ if (xfer->mode_id == I2C_MSM_XFER_MODE_BLOCK) { /*For Block Mode */ Loading Loading @@ -3011,9 +3038,9 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err) { /* poll until bus is released */ if (i2c_msm_qup_poll_bus_active_unset(ctrl)) { if ((ctrl->xfer.err & I2C_MSM_ERR_ARB_LOST) || (ctrl->xfer.err & I2C_MSM_ERR_BUS_ERR) || (ctrl->xfer.err & I2C_MSM_ERR_TIMEOUT)) { if ((ctrl->xfer.err & BIT(I2C_MSM_ERR_ARB_LOST)) || (ctrl->xfer.err & BIT(I2C_MSM_ERR_BUS_ERR)) || (ctrl->xfer.err & BIT(I2C_MSM_ERR_TIMEOUT))) { if (i2c_msm_qup_slv_holds_bus(ctrl)) qup_i2c_recover_bus_busy(ctrl); Loading @@ -3026,7 +3053,7 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err) /* flush bam data and reset the qup core in timeout error. * for other error case, its handled by the ISR */ if (ctrl->xfer.err & I2C_MSM_ERR_TIMEOUT) { if (ctrl->xfer.err & BIT(I2C_MSM_ERR_TIMEOUT)) { /* Flush for the BAM registers */ if (ctrl->xfer.mode_id == I2C_MSM_XFER_MODE_BAM) writel_relaxed(QUP_I2C_FLUSH, ctrl->rsrcs.base Loading @@ -3037,12 +3064,12 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err) err = -ETIMEDOUT; } if (ctrl->xfer.err & I2C_MSM_ERR_BUS_ERR) { if (ctrl->xfer.err & BIT(I2C_MSM_ERR_BUS_ERR)) { if (!err) err = -EIO; } if (ctrl->xfer.err & I2C_MSM_ERR_NACK) if (ctrl->xfer.err & BIT(I2C_MSM_ERR_NACK)) err = -ENOTCONN; return err; Loading Loading @@ -3148,7 +3175,7 @@ static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl, time_left = wait_for_completion_timeout(complete, xfer->timeout); if (!time_left) { xfer->err |= I2C_MSM_ERR_TIMEOUT; xfer->err |= BIT(I2C_MSM_ERR_TIMEOUT); i2c_msm_dbg_dump_diag(ctrl, false, 0, 0); ret = -EIO; i2c_msm_prof_evnt_add(ctrl, MSM_ERR, i2c_msm_prof_dump_cmplt_fl, Loading drivers/i2c/busses/i2c-msm-v2.h +16 −8 Original line number Diff line number Diff line Loading @@ -127,6 +127,8 @@ enum { QUP_BUS_ERROR = 1U << 2, QUP_PACKET_NACKED = 1U << 3, QUP_ARB_LOST = 1U << 4, QUP_INVALID_WRITE = 1U << 5, QUP_FAILED = 3U << 6, QUP_BUS_ACTIVE = 1U << 8, QUP_BUS_MASTER = 1U << 9, QUP_INVALID_TAG = 1U << 23, Loading @@ -134,7 +136,7 @@ enum { QUP_INVALID_READ_SEQ = 1U << 25, QUP_I2C_SDA = 1U << 26, QUP_I2C_SCL = 1U << 27, QUP_MSTR_STTS_ERR_MASK = 0x380003C, QUP_MSTR_STTS_ERR_MASK = 0x38000FC, }; /* Register:QUP_I2C_MASTER_CONFIG fields */ Loading Loading @@ -209,6 +211,8 @@ enum msm_i2c_power_state { #define I2C_MSM_BAM_PROD_SZ (32) /* producer pipe n entries */ #define I2C_MSM_BAM_DESC_ARR_SIZ (I2C_MSM_BAM_CONS_SZ + I2C_MSM_BAM_PROD_SZ) #define I2C_MSM_REG_2_STR_BUF_SZ (128) /* Optimal value to hold the error strings */ #define I2C_MSM_MAX_ERR_BUF_SZ (256) #define I2C_MSM_BUF_DUMP_MAX_BC (20) #define I2C_MSM_MAX_POLL_MSEC (100) #define I2C_MSM_TIMEOUT_SAFTY_COEF (10) Loading Loading @@ -599,13 +603,17 @@ struct i2c_msm_prof_event { }; enum i2c_msm_err_bit_field { I2C_MSM_ERR_NONE = 0, I2C_MSM_ERR_NACK = 1U << 0, I2C_MSM_ERR_ARB_LOST = 1U << 1, I2C_MSM_ERR_BUS_ERR = 1U << 2, I2C_MSM_ERR_TIMEOUT = 1U << 3, I2C_MSM_ERR_CORE_CLK = 1U << 4, I2C_MSM_ERR_OVR_UNDR_RUN = 1U << 5, I2C_MSM_ERR_NACK = 0, I2C_MSM_ERR_ARB_LOST, I2C_MSM_ERR_BUS_ERR, I2C_MSM_ERR_TIMEOUT, I2C_MSM_ERR_CORE_CLK, I2C_MSM_ERR_OVR_UNDR_RUN, I2C_MSM_ERR_INVALID_WRITE, I2C_MSM_ERR_INVALID_TAG, I2C_MSM_ERR_INVALID_READ_ADDR, I2C_MSM_ERR_INVALID_READ_SEQ, I2C_MSM_ERR_FAILED, }; /* Loading Loading
drivers/i2c/busses/i2c-msm-v2.c +91 −64 Original line number Diff line number Diff line Loading @@ -391,6 +391,21 @@ static const struct i2c_msm_qup_reg_dump i2c_msm_qup_reg_dump_map[] = { {0, NULL }, }; const char *i2c_msm_err_str_table[] = { [I2C_MSM_ERR_NACK] = "NACK: slave not responding, ensure its powered", [I2C_MSM_ERR_ARB_LOST] = "arb_lost", [I2C_MSM_ERR_BUS_ERR] = "BUS ERROR : noisy bus or unexpected start/stop tag", [I2C_MSM_ERR_TIMEOUT] = "", [I2C_MSM_ERR_CORE_CLK] = "CLOCK OFF : Check Core Clock", [I2C_MSM_ERR_OVR_UNDR_RUN] = "OVER_UNDER_RUN_ERROR", [I2C_MSM_ERR_INVALID_WRITE] = "invalid data write", [I2C_MSM_ERR_INVALID_TAG] = "invalid tag", [I2C_MSM_ERR_INVALID_READ_ADDR] = "Invalid slave addr", [I2C_MSM_ERR_INVALID_READ_SEQ] = "start tag error for read", [I2C_MSM_ERR_FAILED] = "I2C transfer failed", }; /* * see: struct i2c_msm_qup_reg_dump for more */ Loading @@ -416,47 +431,43 @@ static void i2c_msm_dbg_dump_diag(struct i2c_msm_ctrl *ctrl, bool use_param_vals, u32 status, u32 qup_op) { struct i2c_msm_xfer *xfer = &ctrl->xfer; const char *str = "DEBUG"; char buf[I2C_MSM_REG_2_STR_BUF_SZ]; char str[I2C_MSM_MAX_ERR_BUF_SZ] = {'\0'}; char *p_str = str; const char **diag_msg = i2c_msm_err_str_table; int err = xfer->err; if (!use_param_vals) { void __iomem *base = ctrl->rsrcs.base; status = readl_relaxed(base + QUP_I2C_STATUS); qup_op = readl_relaxed(base + QUP_OPERATIONAL); } /* In case of NACK, bus and controller are in a good state */ if (xfer->err & I2C_MSM_ERR_NACK) { str = "NACK: slave not responding, ensure its powered " "and out of reset"; /* clock off may be the root cause of all errors below */ } else if (xfer->err & I2C_MSM_ERR_CORE_CLK) { str = "CLOCK OFF: Check Core Clock"; /* on arb lost we cant control the bus. root cause may be gpios or slv*/ } else if (xfer->err & I2C_MSM_ERR_ARB_LOST) { str = "ARB LOST"; } else if (xfer->err & I2C_MSM_ERR_TIMEOUT) { if ((err & BIT(I2C_MSM_ERR_TIMEOUT))) { /* * if we are not the bus master or SDA/SCL is low then it may be * that slave is pulling the lines low. Otherwise it is likely a * GPIO issue * if we are not the bus master or SDA/SCL is * low then it may be that slave is pulling the * lines low. Otherwise it is likely a GPIO * issue */ if (!(status & QUP_BUS_MASTER)) snprintf(buf, I2C_MSM_REG_2_STR_BUF_SZ, "TIMEOUT(val:%dmsec) check GPIO config if SDA/SCL line(s) low", p_str += snprintf(p_str, I2C_MSM_MAX_ERR_BUF_SZ, "TIMEOUT(val:%dmsec) check GPIO config if SDA/SCL line(s) low, ", jiffies_to_msecs(xfer->timeout)); else snprintf(buf, I2C_MSM_REG_2_STR_BUF_SZ, "TIMEOUT(val:%dmsec)", jiffies_to_msecs(xfer->timeout)); p_str += snprintf(p_str, I2C_MSM_MAX_ERR_BUF_SZ, "TIMEOUT(val:%dmsec), ", jiffies_to_msecs(xfer->timeout)); } for (; err; err >>= 1, ++diag_msg) { str = buf; /* invalid electric signal on the bus, may be noise or bad slave */ } else if (xfer->err & I2C_MSM_ERR_BUS_ERR) { str = "BUS ERROR: noisy bus or unexpected start/stop tag"; /* error occur due to INPUT/OUTPUT over or under run */ } else if (xfer->err & I2C_MSM_ERR_OVR_UNDR_RUN) { str = "OVER_UNDER_RUN_ERROR"; if (err & 1) p_str += snprintf(p_str, (I2C_MSM_MAX_ERR_BUF_SZ - (p_str - str)), "%s, ", *diag_msg); } /* dump xfer details */ dev_err(ctrl->dev, "%s: msgs(n:%d cur:%d %s) bc(rx:%zu tx:%zu) mode:%s " Loading Loading @@ -970,7 +981,7 @@ static int i2c_msm_qup_sw_reset(struct i2c_msm_ctrl *ctrl) ret = i2c_msm_qup_state_wait_valid(ctrl, QUP_STATE_RESET, false); if (ret) { if (atomic_read(&ctrl->xfer.is_active)) ctrl->xfer.err |= I2C_MSM_ERR_CORE_CLK; ctrl->xfer.err |= BIT(I2C_MSM_ERR_CORE_CLK); dev_err(ctrl->dev, "error on issuing QUP software-reset\n"); } return ret; Loading Loading @@ -2736,43 +2747,38 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid) log_event = true; if (i2c_status & QUP_PACKET_NACKED) ctrl->xfer.err |= I2C_MSM_ERR_NACK; ctrl->xfer.err |= BIT(I2C_MSM_ERR_NACK); if (i2c_status & QUP_ARB_LOST) ctrl->xfer.err |= I2C_MSM_ERR_ARB_LOST; ctrl->xfer.err |= BIT(I2C_MSM_ERR_ARB_LOST); if (i2c_status & QUP_BUS_ERROR) ctrl->xfer.err |= I2C_MSM_ERR_BUS_ERR; ctrl->xfer.err |= BIT(I2C_MSM_ERR_BUS_ERR); if (i2c_status & QUP_INVALID_WRITE) ctrl->xfer.err |= BIT(I2C_MSM_ERR_INVALID_WRITE); if (i2c_status & QUP_INVALID_TAG) ctrl->xfer.err |= BIT(I2C_MSM_ERR_INVALID_TAG); if (i2c_status & QUP_INVALID_READ_ADDR) ctrl->xfer.err |= BIT(I2C_MSM_ERR_INVALID_READ_ADDR); if (i2c_status & QUP_INVALID_READ_SEQ) ctrl->xfer.err |= BIT(I2C_MSM_ERR_INVALID_READ_SEQ); if (i2c_status & QUP_FAILED) ctrl->xfer.err |= BIT(I2C_MSM_ERR_FAILED); } /* check for FIFO over/under runs error */ if (err_flags & QUP_ERR_FLGS_MASK) ctrl->xfer.err |= I2C_MSM_ERR_OVR_UNDR_RUN; ctrl->xfer.err = BIT(I2C_MSM_ERR_OVR_UNDR_RUN); /* Reset and bail out on error */ if (ctrl->xfer.err) { /* Dump the register values before reset the core */ if (ctrl->dbgfs.dbg_lvl >= MSM_DBG) if (ctrl->xfer.err && ctrl->dbgfs.dbg_lvl >= MSM_DBG) i2c_msm_dbg_qup_reg_dump(ctrl); /* Flush for the tags in case of an error and BAM Mode*/ if (ctrl->xfer.mode_id == I2C_MSM_XFER_MODE_BAM) writel_relaxed(QUP_I2C_FLUSH, ctrl->rsrcs.base + QUP_STATE); /* HW workaround: when interrupt is level triggerd, more * than one interrupt may fire in error cases. Thus we * reset the core immidiatly in the ISR to ward off the * next interrupt. */ i2c_msm_qup_sw_reset(ctrl); need_wmb = true; signal_complete = true; log_event = true; goto isr_end; } /* clear interrupts fields */ clr_flds = i2c_status & QUP_MSTR_STTS_ERR_MASK; if (clr_flds) { Loading @@ -2792,6 +2798,27 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid) need_wmb = true; } /* Reset and bail out on error */ if (ctrl->xfer.err) { /* Flush for the tags in case of an error and BAM Mode*/ if (ctrl->xfer.mode_id == I2C_MSM_XFER_MODE_BAM) writel_relaxed(QUP_I2C_FLUSH, ctrl->rsrcs.base + QUP_STATE); /* HW workaround: when interrupt is level triggerd, more * than one interrupt may fire in error cases. Thus we * reset the core immidiatly in the ISR to ward off the * next interrupt. */ i2c_msm_qup_sw_reset(ctrl); need_wmb = true; signal_complete = true; log_event = true; goto isr_end; } /* handle data completion */ if (xfer->mode_id == I2C_MSM_XFER_MODE_BLOCK) { /*For Block Mode */ Loading Loading @@ -3011,9 +3038,9 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err) { /* poll until bus is released */ if (i2c_msm_qup_poll_bus_active_unset(ctrl)) { if ((ctrl->xfer.err & I2C_MSM_ERR_ARB_LOST) || (ctrl->xfer.err & I2C_MSM_ERR_BUS_ERR) || (ctrl->xfer.err & I2C_MSM_ERR_TIMEOUT)) { if ((ctrl->xfer.err & BIT(I2C_MSM_ERR_ARB_LOST)) || (ctrl->xfer.err & BIT(I2C_MSM_ERR_BUS_ERR)) || (ctrl->xfer.err & BIT(I2C_MSM_ERR_TIMEOUT))) { if (i2c_msm_qup_slv_holds_bus(ctrl)) qup_i2c_recover_bus_busy(ctrl); Loading @@ -3026,7 +3053,7 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err) /* flush bam data and reset the qup core in timeout error. * for other error case, its handled by the ISR */ if (ctrl->xfer.err & I2C_MSM_ERR_TIMEOUT) { if (ctrl->xfer.err & BIT(I2C_MSM_ERR_TIMEOUT)) { /* Flush for the BAM registers */ if (ctrl->xfer.mode_id == I2C_MSM_XFER_MODE_BAM) writel_relaxed(QUP_I2C_FLUSH, ctrl->rsrcs.base Loading @@ -3037,12 +3064,12 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err) err = -ETIMEDOUT; } if (ctrl->xfer.err & I2C_MSM_ERR_BUS_ERR) { if (ctrl->xfer.err & BIT(I2C_MSM_ERR_BUS_ERR)) { if (!err) err = -EIO; } if (ctrl->xfer.err & I2C_MSM_ERR_NACK) if (ctrl->xfer.err & BIT(I2C_MSM_ERR_NACK)) err = -ENOTCONN; return err; Loading Loading @@ -3148,7 +3175,7 @@ static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl, time_left = wait_for_completion_timeout(complete, xfer->timeout); if (!time_left) { xfer->err |= I2C_MSM_ERR_TIMEOUT; xfer->err |= BIT(I2C_MSM_ERR_TIMEOUT); i2c_msm_dbg_dump_diag(ctrl, false, 0, 0); ret = -EIO; i2c_msm_prof_evnt_add(ctrl, MSM_ERR, i2c_msm_prof_dump_cmplt_fl, Loading
drivers/i2c/busses/i2c-msm-v2.h +16 −8 Original line number Diff line number Diff line Loading @@ -127,6 +127,8 @@ enum { QUP_BUS_ERROR = 1U << 2, QUP_PACKET_NACKED = 1U << 3, QUP_ARB_LOST = 1U << 4, QUP_INVALID_WRITE = 1U << 5, QUP_FAILED = 3U << 6, QUP_BUS_ACTIVE = 1U << 8, QUP_BUS_MASTER = 1U << 9, QUP_INVALID_TAG = 1U << 23, Loading @@ -134,7 +136,7 @@ enum { QUP_INVALID_READ_SEQ = 1U << 25, QUP_I2C_SDA = 1U << 26, QUP_I2C_SCL = 1U << 27, QUP_MSTR_STTS_ERR_MASK = 0x380003C, QUP_MSTR_STTS_ERR_MASK = 0x38000FC, }; /* Register:QUP_I2C_MASTER_CONFIG fields */ Loading Loading @@ -209,6 +211,8 @@ enum msm_i2c_power_state { #define I2C_MSM_BAM_PROD_SZ (32) /* producer pipe n entries */ #define I2C_MSM_BAM_DESC_ARR_SIZ (I2C_MSM_BAM_CONS_SZ + I2C_MSM_BAM_PROD_SZ) #define I2C_MSM_REG_2_STR_BUF_SZ (128) /* Optimal value to hold the error strings */ #define I2C_MSM_MAX_ERR_BUF_SZ (256) #define I2C_MSM_BUF_DUMP_MAX_BC (20) #define I2C_MSM_MAX_POLL_MSEC (100) #define I2C_MSM_TIMEOUT_SAFTY_COEF (10) Loading Loading @@ -599,13 +603,17 @@ struct i2c_msm_prof_event { }; enum i2c_msm_err_bit_field { I2C_MSM_ERR_NONE = 0, I2C_MSM_ERR_NACK = 1U << 0, I2C_MSM_ERR_ARB_LOST = 1U << 1, I2C_MSM_ERR_BUS_ERR = 1U << 2, I2C_MSM_ERR_TIMEOUT = 1U << 3, I2C_MSM_ERR_CORE_CLK = 1U << 4, I2C_MSM_ERR_OVR_UNDR_RUN = 1U << 5, I2C_MSM_ERR_NACK = 0, I2C_MSM_ERR_ARB_LOST, I2C_MSM_ERR_BUS_ERR, I2C_MSM_ERR_TIMEOUT, I2C_MSM_ERR_CORE_CLK, I2C_MSM_ERR_OVR_UNDR_RUN, I2C_MSM_ERR_INVALID_WRITE, I2C_MSM_ERR_INVALID_TAG, I2C_MSM_ERR_INVALID_READ_ADDR, I2C_MSM_ERR_INVALID_READ_SEQ, I2C_MSM_ERR_FAILED, }; /* Loading