Loading drivers/i2c/busses/i2c-msm-geni.c +69 −15 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ struct geni_i2c_dev { bool first_resume; bool gpi_reset; bool disable_dma_mode; bool prev_cancel_pending; //Halt cancel till IOS in good state }; static struct geni_i2c_dev *gi2c_dev_dbg[MAX_SE]; Loading Loading @@ -241,10 +242,45 @@ static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err) gi2c->err = gi2c_log[err].err; } static int geni_i2c_prepare(struct geni_i2c_dev *gi2c) static int do_pending_cancel(struct geni_i2c_dev *gi2c) { int timeout = 0; u32 geni_ios = 0; geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); if ((geni_ios & 0x3) != 0x3) { GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s: Can't do pending cancel, IOS bad state: 0x%x\n", __func__, geni_ios); return -EINVAL; } if (gi2c->se_mode == GSI_ONLY) { dmaengine_terminate_all(gi2c->tx_c); gi2c->cfg_sent = 0; } else { reinit_completion(&gi2c->xfer); geni_cancel_m_cmd(gi2c->base); timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); if (!timeout) { GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s:Pending Cancel failed\n", __func__); reinit_completion(&gi2c->xfer); geni_abort_m_cmd(gi2c->base); timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); if (!timeout) GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s:Abort failed\n", __func__); } } gi2c->prev_cancel_pending = false; GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s: Pending Cancel done\n", __func__); return timeout; } static int geni_i2c_prepare(struct geni_i2c_dev *gi2c) { if (gi2c->se_mode == UNINITIALIZED) { int proto = get_se_proto(gi2c->base); u32 se_mode; Loading @@ -256,16 +292,6 @@ static int geni_i2c_prepare(struct geni_i2c_dev *gi2c) return -ENXIO; } geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, "IO lines not in good state, Check power to slave\n"); if (!gi2c->is_le_vm) se_geni_resources_off(&gi2c->i2c_rsc); return -ENXIO; } se_mode = readl_relaxed(gi2c->base + GENI_IF_FIFO_DISABLE_RO); if (se_mode) { Loading Loading @@ -933,6 +959,8 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (!timeout) { u32 geni_ios = 0; GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "I2C gsi xfer timeout:%u flags:%d addr:0x%x\n", gi2c->xfer_timeout, gi2c->cur->flags, Loading @@ -940,6 +968,15 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], geni_se_dump_dbg_regs(&gi2c->i2c_rsc, gi2c->base, gi2c->ipcl); gi2c->err = -ETIMEDOUT; /* WAR: Set flag to mark cancel pending if IOS stuck */ geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, "%s: IO lines not in good state\n", __func__); gi2c->prev_cancel_pending = true; goto geni_i2c_gsi_cancel_pending; } } geni_i2c_err_prep_sg: if (gi2c->err) { Loading @@ -962,6 +999,7 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], /* Resend cfg tre for every new message on shared se */ gi2c->cfg_sent = 0; geni_i2c_gsi_cancel_pending: if (msgs[i].flags & I2C_M_RD) geni_se_iommu_unmap_buf(rx_dev, &gi2c->rx_ph, msgs[i].len, DMA_FROM_DEVICE); Loading Loading @@ -1007,6 +1045,13 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, } } // WAR : Complete previous pending cancel cmd if (gi2c->prev_cancel_pending) { ret = do_pending_cancel(gi2c); if (ret) return ret; //Don't perform xfer is cancel failed } GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "n:%d addr:0x%x\n", num, msgs[0].addr); Loading Loading @@ -1124,9 +1169,20 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (!timeout) { u32 geni_ios = 0; GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "I2C xfer timeout: %d\n", gi2c->xfer_timeout); geni_i2c_err(gi2c, GENI_TIMEOUT); /* WAR: Set flag to mark cancel pending if IOS bad */ geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, "%s: IO lines not in good state\n", __func__); gi2c->prev_cancel_pending = true; goto geni_i2c_txn_ret; } } if (gi2c->err) { Loading Loading @@ -1453,19 +1509,17 @@ static int geni_i2c_runtime_resume(struct device *dev) if (!gi2c->is_le_vm) { /* Do not control clk/gpio/icb for LE-VM */ ret = se_geni_resources_on(&gi2c->i2c_rsc); if (ret) return ret; ret = geni_i2c_prepare(gi2c); if (ret) { dev_err(gi2c->dev, "I2C prepare failed\n"); dev_err(gi2c->dev, "I2C prepare failed: %d\n", ret); return ret; } if (gi2c->se_mode == FIFO_SE_DMA) enable_irq(gi2c->irq); } else if (!gi2c->first_resume) { /* * For first resume call in le, do nothing, and in Loading @@ -1475,7 +1529,7 @@ static int geni_i2c_runtime_resume(struct device *dev) */ ret = geni_i2c_prepare(gi2c); if (ret) { dev_err(gi2c->dev, "I2C prepare failed\n"); dev_err(gi2c->dev, "I2C prepare failed:%d\n", ret); return ret; } Loading Loading
drivers/i2c/busses/i2c-msm-geni.c +69 −15 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ struct geni_i2c_dev { bool first_resume; bool gpi_reset; bool disable_dma_mode; bool prev_cancel_pending; //Halt cancel till IOS in good state }; static struct geni_i2c_dev *gi2c_dev_dbg[MAX_SE]; Loading Loading @@ -241,10 +242,45 @@ static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err) gi2c->err = gi2c_log[err].err; } static int geni_i2c_prepare(struct geni_i2c_dev *gi2c) static int do_pending_cancel(struct geni_i2c_dev *gi2c) { int timeout = 0; u32 geni_ios = 0; geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); if ((geni_ios & 0x3) != 0x3) { GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s: Can't do pending cancel, IOS bad state: 0x%x\n", __func__, geni_ios); return -EINVAL; } if (gi2c->se_mode == GSI_ONLY) { dmaengine_terminate_all(gi2c->tx_c); gi2c->cfg_sent = 0; } else { reinit_completion(&gi2c->xfer); geni_cancel_m_cmd(gi2c->base); timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); if (!timeout) { GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s:Pending Cancel failed\n", __func__); reinit_completion(&gi2c->xfer); geni_abort_m_cmd(gi2c->base); timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); if (!timeout) GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s:Abort failed\n", __func__); } } gi2c->prev_cancel_pending = false; GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s: Pending Cancel done\n", __func__); return timeout; } static int geni_i2c_prepare(struct geni_i2c_dev *gi2c) { if (gi2c->se_mode == UNINITIALIZED) { int proto = get_se_proto(gi2c->base); u32 se_mode; Loading @@ -256,16 +292,6 @@ static int geni_i2c_prepare(struct geni_i2c_dev *gi2c) return -ENXIO; } geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, "IO lines not in good state, Check power to slave\n"); if (!gi2c->is_le_vm) se_geni_resources_off(&gi2c->i2c_rsc); return -ENXIO; } se_mode = readl_relaxed(gi2c->base + GENI_IF_FIFO_DISABLE_RO); if (se_mode) { Loading Loading @@ -933,6 +959,8 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (!timeout) { u32 geni_ios = 0; GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "I2C gsi xfer timeout:%u flags:%d addr:0x%x\n", gi2c->xfer_timeout, gi2c->cur->flags, Loading @@ -940,6 +968,15 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], geni_se_dump_dbg_regs(&gi2c->i2c_rsc, gi2c->base, gi2c->ipcl); gi2c->err = -ETIMEDOUT; /* WAR: Set flag to mark cancel pending if IOS stuck */ geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, "%s: IO lines not in good state\n", __func__); gi2c->prev_cancel_pending = true; goto geni_i2c_gsi_cancel_pending; } } geni_i2c_err_prep_sg: if (gi2c->err) { Loading @@ -962,6 +999,7 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], /* Resend cfg tre for every new message on shared se */ gi2c->cfg_sent = 0; geni_i2c_gsi_cancel_pending: if (msgs[i].flags & I2C_M_RD) geni_se_iommu_unmap_buf(rx_dev, &gi2c->rx_ph, msgs[i].len, DMA_FROM_DEVICE); Loading Loading @@ -1007,6 +1045,13 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, } } // WAR : Complete previous pending cancel cmd if (gi2c->prev_cancel_pending) { ret = do_pending_cancel(gi2c); if (ret) return ret; //Don't perform xfer is cancel failed } GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "n:%d addr:0x%x\n", num, msgs[0].addr); Loading Loading @@ -1124,9 +1169,20 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (!timeout) { u32 geni_ios = 0; GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "I2C xfer timeout: %d\n", gi2c->xfer_timeout); geni_i2c_err(gi2c, GENI_TIMEOUT); /* WAR: Set flag to mark cancel pending if IOS bad */ geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, "%s: IO lines not in good state\n", __func__); gi2c->prev_cancel_pending = true; goto geni_i2c_txn_ret; } } if (gi2c->err) { Loading Loading @@ -1453,19 +1509,17 @@ static int geni_i2c_runtime_resume(struct device *dev) if (!gi2c->is_le_vm) { /* Do not control clk/gpio/icb for LE-VM */ ret = se_geni_resources_on(&gi2c->i2c_rsc); if (ret) return ret; ret = geni_i2c_prepare(gi2c); if (ret) { dev_err(gi2c->dev, "I2C prepare failed\n"); dev_err(gi2c->dev, "I2C prepare failed: %d\n", ret); return ret; } if (gi2c->se_mode == FIFO_SE_DMA) enable_irq(gi2c->irq); } else if (!gi2c->first_resume) { /* * For first resume call in le, do nothing, and in Loading @@ -1475,7 +1529,7 @@ static int geni_i2c_runtime_resume(struct device *dev) */ ret = geni_i2c_prepare(gi2c); if (ret) { dev_err(gi2c->dev, "I2C prepare failed\n"); dev_err(gi2c->dev, "I2C prepare failed:%d\n", ret); return ret; } Loading