Loading drivers/i2c/busses/i2c-qcom-geni.c +30 −6 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -77,6 +77,10 @@ #define I2C_AUTO_SUSPEND_DELAY 250 #define I2C_TIMEOUT_SAFETY_COEFFICIENT 10 #define I2C_TIMEOUT_MIN_USEC 500000 enum i2c_se_mode { UNINITIALIZED, FIFO_SE_DMA, Loading @@ -89,6 +93,7 @@ struct geni_i2c_dev { unsigned int tx_wm; int irq; int err; u32 xfer_timeout; struct i2c_adapter adap; struct completion xfer; struct i2c_msg *cur; Loading Loading @@ -192,12 +197,26 @@ static inline void qcom_geni_i2c_conf(struct geni_i2c_dev *gi2c, int dfs) mb(); } static inline void qcom_geni_i2c_calc_timeout(struct geni_i2c_dev *gi2c) { struct geni_i2c_clk_fld *clk_itr = geni_i2c_clk_map + gi2c->clk_fld_idx; size_t bit_cnt = gi2c->cur->len*9; size_t bit_usec = (bit_cnt*USEC_PER_SEC)/clk_itr->clk_freq_out; size_t xfer_max_usec = (bit_usec*I2C_TIMEOUT_SAFETY_COEFFICIENT) + I2C_TIMEOUT_MIN_USEC; gi2c->xfer_timeout = usecs_to_jiffies(xfer_max_usec); } static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err) { if (gi2c->cur) GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "len:%d, slv-addr:0x%x, RD/WR:%d\n", gi2c->cur->len, gi2c->cur->addr, gi2c->cur->flags); "len:%d, slv-addr:0x%x, RD/WR:%d timeout:%u\n", gi2c->cur->len, gi2c->cur->addr, gi2c->cur->flags, gi2c->xfer_timeout); if (err == I2C_NACK || err == GENI_ABORT_DONE) { GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "%s\n", Loading Loading @@ -476,6 +495,7 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], struct device *tx_dev = gi2c->wrapper_dev; gi2c->cur = &msgs[i]; qcom_geni_i2c_calc_timeout(gi2c); if (!gi2c->cfg_sent) { segs++; sg_init_table(gi2c->tx_sg, segs); Loading Loading @@ -567,7 +587,8 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], tx_cookie = dmaengine_submit(gi2c->tx_desc); dma_async_issue_pending(gi2c->tx_c); timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (msgs[i].flags & I2C_M_RD) geni_se_iommu_unmap_buf(rx_dev, &gi2c->rx_ph, msgs[i].len, DMA_FROM_DEVICE); Loading @@ -577,7 +598,8 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (!timeout) { GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "GSI Txn timed out\n"); "GSI Txn timed out: %u len: %d\n", gi2c->xfer_timeout, gi2c->cur->len); gi2c->err = -ETIMEDOUT; } if (gi2c->err) { Loading Loading @@ -633,6 +655,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, m_param |= ((msgs[i].addr & 0x7F) << SLV_ADDR_SHFT); gi2c->cur = &msgs[i]; qcom_geni_i2c_calc_timeout(gi2c); mode = msgs[i].len > 32 ? SE_DMA : FIFO_MODE; ret = geni_se_select_mode(gi2c->base, mode); if (ret) { Loading Loading @@ -682,7 +705,8 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, } /* Ensure FIFO write go through before waiting for Done evet */ mb(); timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (!timeout) { geni_i2c_err(gi2c, GENI_TIMEOUT); gi2c->cur = NULL; Loading Loading
drivers/i2c/busses/i2c-qcom-geni.c +30 −6 Original line number Diff line number Diff line /* * Copyright (c) 2017, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -77,6 +77,10 @@ #define I2C_AUTO_SUSPEND_DELAY 250 #define I2C_TIMEOUT_SAFETY_COEFFICIENT 10 #define I2C_TIMEOUT_MIN_USEC 500000 enum i2c_se_mode { UNINITIALIZED, FIFO_SE_DMA, Loading @@ -89,6 +93,7 @@ struct geni_i2c_dev { unsigned int tx_wm; int irq; int err; u32 xfer_timeout; struct i2c_adapter adap; struct completion xfer; struct i2c_msg *cur; Loading Loading @@ -192,12 +197,26 @@ static inline void qcom_geni_i2c_conf(struct geni_i2c_dev *gi2c, int dfs) mb(); } static inline void qcom_geni_i2c_calc_timeout(struct geni_i2c_dev *gi2c) { struct geni_i2c_clk_fld *clk_itr = geni_i2c_clk_map + gi2c->clk_fld_idx; size_t bit_cnt = gi2c->cur->len*9; size_t bit_usec = (bit_cnt*USEC_PER_SEC)/clk_itr->clk_freq_out; size_t xfer_max_usec = (bit_usec*I2C_TIMEOUT_SAFETY_COEFFICIENT) + I2C_TIMEOUT_MIN_USEC; gi2c->xfer_timeout = usecs_to_jiffies(xfer_max_usec); } static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err) { if (gi2c->cur) GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "len:%d, slv-addr:0x%x, RD/WR:%d\n", gi2c->cur->len, gi2c->cur->addr, gi2c->cur->flags); "len:%d, slv-addr:0x%x, RD/WR:%d timeout:%u\n", gi2c->cur->len, gi2c->cur->addr, gi2c->cur->flags, gi2c->xfer_timeout); if (err == I2C_NACK || err == GENI_ABORT_DONE) { GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "%s\n", Loading Loading @@ -476,6 +495,7 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], struct device *tx_dev = gi2c->wrapper_dev; gi2c->cur = &msgs[i]; qcom_geni_i2c_calc_timeout(gi2c); if (!gi2c->cfg_sent) { segs++; sg_init_table(gi2c->tx_sg, segs); Loading Loading @@ -567,7 +587,8 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], tx_cookie = dmaengine_submit(gi2c->tx_desc); dma_async_issue_pending(gi2c->tx_c); timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (msgs[i].flags & I2C_M_RD) geni_se_iommu_unmap_buf(rx_dev, &gi2c->rx_ph, msgs[i].len, DMA_FROM_DEVICE); Loading @@ -577,7 +598,8 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (!timeout) { GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "GSI Txn timed out\n"); "GSI Txn timed out: %u len: %d\n", gi2c->xfer_timeout, gi2c->cur->len); gi2c->err = -ETIMEDOUT; } if (gi2c->err) { Loading Loading @@ -633,6 +655,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, m_param |= ((msgs[i].addr & 0x7F) << SLV_ADDR_SHFT); gi2c->cur = &msgs[i]; qcom_geni_i2c_calc_timeout(gi2c); mode = msgs[i].len > 32 ? SE_DMA : FIFO_MODE; ret = geni_se_select_mode(gi2c->base, mode); if (ret) { Loading Loading @@ -682,7 +705,8 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, } /* Ensure FIFO write go through before waiting for Done evet */ mb(); timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (!timeout) { geni_i2c_err(gi2c, GENI_TIMEOUT); gi2c->cur = NULL; Loading