diff options
author | Satish Kamuju <skamuj@codeaurora.org> | 2014-07-30 05:43:13 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2014-07-30 10:07:40 -0700 |
commit | c317c7eb2266ec64ab6ca0de76066982d64e9198 (patch) | |
tree | f5fac573dccc18039f27e4ac9bfc8ffe8aa37b5c | |
parent | 5ee23639e63726f71362e1dd0df3d5a796e2015f (diff) |
Revert "i2c-msm-v2: Add support for block mode"original-stock-qrd
This reverts commit 33fade0f16c6060f9af2c68ac534f3fc100a2368
Change-Id: Ifc4e618802f8a61397db4f76f0222029b7aff1d3
Signed-off-by: Satish Kamuju <skamuj@codeaurora.org>
-rw-r--r-- | drivers/i2c/busses/i2c-msm-v2.c | 558 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-msm-v2.h | 33 |
2 files changed, 72 insertions, 519 deletions
diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c index da4945331617..50738e3381ef 100644 --- a/drivers/i2c/busses/i2c-msm-v2.c +++ b/drivers/i2c/busses/i2c-msm-v2.c @@ -47,7 +47,7 @@ static const enum msm_i2_debug_level DEFAULT_DBG_LVL = MSM_ERR; /* string table for enum i2c_msm_xfer_mode_id */ static const char * const i2c_msm_mode_str_tbl[] = { - "FIFO", "BLOCK", "BAM", "None", + "FIFO", "BAM", "None", }; /* string table for qup_io_modes register */ @@ -58,17 +58,14 @@ static const char * const i2c_msm_qup_mode_str_tbl[] = { /* from enum i2c_msm_xfer_mode_id to qup_io_modes register values */ static const u32 i2c_msm_mode_to_reg_tbl[] = { 0x0, /* map I2C_MSM_XFER_MODE_FIFO -> binary 00 */ - 0x1, /* map I2C_MSM_XFER_MODE_BLOCK -> binary 01 */ 0x3 /* map I2C_MSM_XFER_MODE_BAM -> binary 11 */ }; /* Forward declarations */ static bool i2c_msm_xfer_next_buf(struct i2c_msm_ctrl *ctrl); -static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl, - struct completion *complete); +static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl); static int i2c_msm_bam_xfer(struct i2c_msm_ctrl *ctrl); static int i2c_msm_fifo_xfer(struct i2c_msm_ctrl *ctrl); -static int i2c_msm_blk_xfer(struct i2c_msm_ctrl *ctrl); static void i2c_msm_pm_resume_adptr(struct i2c_msm_ctrl *ctrl); static void i2c_msm_pm_suspend_adptr(struct i2c_msm_ctrl *ctrl); static int i2c_msm_qup_init(struct i2c_msm_ctrl *ctrl); @@ -102,20 +99,6 @@ static void i2c_msm_fifo_set_struct(struct i2c_msm_ctrl *ctrl, (struct i2c_msm_xfer_mode *) fifo; } -static struct i2c_msm_xfer_mode_blk *i2c_msm_blk_get_struct( - struct i2c_msm_ctrl *ctrl) -{ - return (struct i2c_msm_xfer_mode_blk *) - ctrl->ver.xfer_mode[I2C_MSM_XFER_MODE_BLOCK]; -} - -static void i2c_msm_blk_set_struct(struct i2c_msm_ctrl *ctrl, - struct i2c_msm_xfer_mode_blk *blk) -{ - ctrl->ver.xfer_mode[I2C_MSM_XFER_MODE_BLOCK] = - (struct i2c_msm_xfer_mode *) blk; -} - static const char * const i2c_msm_mini_core_str_tbl[] = { "null", "SPI", "I2C", "reserved", }; @@ -262,7 +245,7 @@ static struct i2c_msm_qup_reg_fld i2c_msm_qup_op_fields_map[] = { { "MX_OUT_DN", 10, 1}, { "MX_IN_DN", 11, 1}, { "OUT_BLK_WR", 12, 1}, - { "IN_BLK_RD", 13, 1}, + { "IN_BLK_WR", 13, 1}, { "DONE_TGL", 14, 1}, { "NWD", 15, 1}, { NULL, 0, 1}, @@ -369,9 +352,7 @@ static const struct i2c_msm_qup_reg_dump i2c_msm_qup_reg_dump_map[] = { {QUP_OUT_FIFO_CNT, "QUP_OUT_CNT" }, {QUP_MX_READ_COUNT, "MX_RD_CNT" }, {QUP_MX_WRITE_COUNT, "MX_WR_CNT" }, -{QUP_MX_INPUT_COUNT, "MX_IN_CNT" }, -{QUP_MX_OUTPUT_COUNT, "MX_OUT_CNT" }, -{0, NULL }, +{0, NULL }, }; /* @@ -966,10 +947,8 @@ i2c_msm_qup_xfer_init_reset_state(struct i2c_msm_ctrl *ctrl) { struct i2c_msm_xfer *xfer = &ctrl->xfer; void __iomem * const base = ctrl->rsrcs.base; - u32 mx_rd_cnt = 0; - u32 mx_wr_cnt = 0; - u32 mx_in_cnt = 0; - u32 mx_out_cnt = 0; + u32 in_cnt = 0; + u32 out_cnt = 0; u32 no_input = 0; u32 no_output = 0; u32 input_mode = i2c_msm_mode_to_reg_tbl[xfer->mode_id] << 12; @@ -977,8 +956,7 @@ i2c_msm_qup_xfer_init_reset_state(struct i2c_msm_ctrl *ctrl) u32 config_reg; u32 io_modes_reg; u32 op_mask; - u32 rx_cnt = 0; - u32 tx_cnt = 0; + /* * BAM mode: * 1. QUP_MX_*_COUNT must be zero in all cases. @@ -988,32 +966,20 @@ i2c_msm_qup_xfer_init_reset_state(struct i2c_msm_ctrl *ctrl) * 2. QUP_MX_READ_COUNT and QUP_MX_WRITE_COUNT reflect true count * 3. QUP_NO_INPUT and QUP_NO_OUPUT are set according to counts */ - if (xfer->mode_id != I2C_MSM_XFER_MODE_BAM) { - rx_cnt = xfer->rx_cnt + xfer->rx_ovrhd_cnt; - tx_cnt = xfer->tx_cnt + xfer->tx_ovrhd_cnt; - no_input = rx_cnt ? 0 : QUP_NO_INPUT; - - switch (xfer->mode_id) { - case I2C_MSM_XFER_MODE_FIFO: - mx_rd_cnt = rx_cnt; - mx_wr_cnt = tx_cnt; - break; - case I2C_MSM_XFER_MODE_BLOCK: - mx_in_cnt = rx_cnt; - mx_out_cnt = tx_cnt; - break; - default: - break; - } + if (xfer->mode_id == I2C_MSM_XFER_MODE_FIFO) { + in_cnt = xfer->rx_cnt + xfer->rx_ovrhd_cnt; + out_cnt = xfer->tx_cnt + xfer->tx_ovrhd_cnt; + no_input = in_cnt ? 0 : QUP_NO_INPUT; + no_output = out_cnt ? 0 : QUP_NO_OUPUT; } - /* init BAM/BLOCK modes counter */ - writel_relaxed(mx_in_cnt, base + QUP_MX_INPUT_COUNT); - writel_relaxed(mx_out_cnt, base + QUP_MX_OUTPUT_COUNT); + /* BAM counter initializers */ + writel_relaxed(0, base + QUP_MX_INPUT_COUNT); + writel_relaxed(0, base + QUP_MX_OUTPUT_COUNT); - /* int FIFO mode counter */ - writel_relaxed(mx_rd_cnt, base + QUP_MX_READ_COUNT); - writel_relaxed(mx_wr_cnt, base + QUP_MX_WRITE_COUNT); + /* FIFO counter initializers */ + writel_relaxed(in_cnt , base + QUP_MX_READ_COUNT); + writel_relaxed(out_cnt, base + QUP_MX_WRITE_COUNT); /* * Set QUP mini-core to I2C tags ver-2 @@ -1309,7 +1275,7 @@ static int i2c_msm_fifo_xfer_process(struct i2c_msm_ctrl *ctrl) return ret; /* wait for input done interrupt */ - ret = i2c_msm_xfer_wait_for_completion(ctrl, &ctrl->xfer.complete); + ret = i2c_msm_xfer_wait_for_completion(ctrl); if (ret < 0) return ret; @@ -1372,348 +1338,6 @@ static int i2c_msm_fifo_create_struct(struct i2c_msm_ctrl *ctrl) return 0; } -static void i2c_msm_blk_teardown(struct i2c_msm_ctrl *ctrl) {} - -static void i2c_msm_blk_destroy_struct(struct i2c_msm_ctrl *ctrl) -{ - struct i2c_msm_xfer_mode_blk *blk = i2c_msm_blk_get_struct(ctrl); - kfree(blk->tx_cache); - kfree(blk->rx_cache); - kfree(blk); - i2c_msm_blk_set_struct(ctrl, NULL); -} - -/* - * i2c_msm_blk_create_struct: Allocate memory and initialize blk structure - * - * @return 0 on success or error code - */ -static int i2c_msm_blk_create_struct(struct i2c_msm_ctrl *ctrl) -{ - u32 reg_data; - int ret; - struct i2c_msm_xfer_mode_blk *blk = kmalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) { - dev_err(ctrl->dev, - "error on allocating memory for block mode. malloc(size:%zu)\n", - sizeof(*blk)); - return -ENOMEM; - } - - reg_data = readl_relaxed(ctrl->rsrcs.base + QUP_IO_MODES); - - *blk = (struct i2c_msm_xfer_mode_blk) { - .in_blk_sz = i2c_msm_reg_io_modes_in_blk_sz(reg_data), - .out_blk_sz = i2c_msm_reg_io_modes_out_blk_sz(reg_data), - .ops = (struct i2c_msm_xfer_mode) { - .xfer = i2c_msm_blk_xfer, - .teardown = i2c_msm_blk_teardown, - }, - }; - - blk->tx_cache = kmalloc(blk->out_blk_sz, GFP_KERNEL); - if (!blk->tx_cache) { - dev_err(ctrl->dev, - "error on allocating memory for block tx_cache. malloc(size:%zu)\n", - blk->out_blk_sz); - ret = -ENOMEM; - goto out_buf_err; - } - - blk->rx_cache = kmalloc(blk->in_blk_sz, GFP_KERNEL); - if (!blk->tx_cache) { - dev_err(ctrl->dev, - "error on allocating memory for block tx_cache. malloc(size:%zu)\n", - blk->out_blk_sz); - ret = -ENOMEM; - goto in_buf_err; - } - - i2c_msm_blk_set_struct(ctrl, blk); - return 0; - -in_buf_err: - kfree(blk->tx_cache); -out_buf_err: - kfree(blk); - - return ret; -} - -/* - * i2c_msm_blk_wr_flush: flushes internal cached block to FIFO - * - * @return 0 on success or error code - */ -static int i2c_msm_blk_wr_flush(struct i2c_msm_ctrl *ctrl) -{ - int byte_num; - int ret = 0; - struct i2c_msm_xfer_mode_blk *blk = i2c_msm_blk_get_struct(ctrl); - u32 *buf_u32_ptr; - - if (!blk->tx_cache_idx) - return 0; - - /* if no blocks availble wait for interrupt */ - ret = i2c_msm_xfer_wait_for_completion(ctrl, &blk->wait_tx_blk); - if (ret) - return ret; - - /* - * pause the controller until we finish loading the block in order to - * avoid race conditions - */ - ret = i2c_msm_qup_state_set(ctrl, QUP_STATE_PAUSE); - if (ret < 0) - return ret; - i2c_msm_dbg(ctrl, MSM_DBG, "OUT-BLK:%*phC", blk->tx_cache_idx, - blk->tx_cache); - - for (byte_num = 0; byte_num < blk->tx_cache_idx; - byte_num += sizeof(u32)) { - buf_u32_ptr = (u32 *) (blk->tx_cache + byte_num); - writel_relaxed(*buf_u32_ptr, - ctrl->rsrcs.base + QUP_OUT_FIFO_BASE); - *buf_u32_ptr = 0; - } - - /* now cache is empty */ - blk->tx_cache_idx = 0; - ret = i2c_msm_qup_state_set(ctrl, QUP_STATE_RUN); - if (ret < 0) - return ret; - - return ret; -} - -/* - * i2c_msm_blk_wr_buf: - * - * @len buf size (in bytes) - * @return number of bytes from buf which have been processed (written to - * FIFO or kept in out buffer and will be written later) - */ -static size_t -i2c_msm_blk_wr_buf(struct i2c_msm_ctrl *ctrl, const u8 *buf, size_t len) -{ - struct i2c_msm_xfer_mode_blk *blk = i2c_msm_blk_get_struct(ctrl); - int byte_num; - int ret = 0; - - for (byte_num = 0; byte_num < len; ++byte_num, ++buf) { - blk->tx_cache[blk->tx_cache_idx] = *buf; - ++blk->tx_cache_idx; - - /* flush cached buffer to HW FIFO when full */ - if (blk->tx_cache_idx == blk->out_blk_sz) { - ret = i2c_msm_blk_wr_flush(ctrl); - if (ret) - return ret; - } - } - return byte_num; -} - -/* - * i2c_msm_blk_xfer_wr_tag: buffered writing the tag of current buf - * @return zero on success - */ -static int i2c_msm_blk_xfer_wr_tag(struct i2c_msm_ctrl *ctrl) -{ - struct i2c_msm_xfer_buf *buf = &ctrl->xfer.cur_buf; - size_t len = 0; - - if (!buf->out_tag.len) - return 0; - - len = i2c_msm_blk_wr_buf(ctrl, (u8 *) &buf->out_tag.val, - buf->out_tag.len); - if (len != buf->out_tag.len) - return -EFAULT; - - buf->out_tag = (struct i2c_msm_tag) {0}; - return 0; -} - -/* - * i2c_msm_blk_wr_xfer_buf: writes ctrl->xfer.cur_buf to HW - * - * @return zero on success - */ -static int i2c_msm_blk_wr_xfer_buf(struct i2c_msm_ctrl *ctrl) -{ - struct i2c_msm_xfer_buf *buf = &ctrl->xfer.cur_buf; - size_t len; - size_t buf_has_bc = buf->len - buf->byte_idx; - int ret; - ret = i2c_msm_blk_xfer_wr_tag(ctrl); - if (ret) - return ret; - - len = i2c_msm_blk_wr_buf(ctrl, i2c_msm_buf_to_ptr(buf), buf_has_bc); - if (len < buf_has_bc) - return -EFAULT; - - buf->byte_idx += len; - buf->prcsed_bc = len; - return 0; -} - -/* - * i2c_msm_blk_rd_blk: read a block from HW FIFO to internal cache - * - * @return number of bytes read or negative error value - * @need_bc number of bytes that we need - * - * uses internal counter to keep track of number of available blocks. When - * zero, waits for interrupt. - */ -static int i2c_msm_blk_rd_blk(struct i2c_msm_ctrl *ctrl, size_t need_bc) -{ - int byte_num; - int ret = 0; - struct i2c_msm_xfer_mode_blk *blk = i2c_msm_blk_get_struct(ctrl); - u32 *cache_ptr = (u32 *) blk->rx_cache; - int read_bc = min_t(size_t, blk->in_blk_sz, need_bc); - - /* wait for block avialble interrupt */ - ret = i2c_msm_xfer_wait_for_completion(ctrl, &blk->wait_rx_blk); - if (ret) - return ret; - - /* Read block from HW to cache */ - for (byte_num = 0; byte_num < blk->in_blk_sz; - byte_num += sizeof(u32)) { - if (byte_num < read_bc) { - *cache_ptr = readl_relaxed(ctrl->rsrcs.base + - QUP_IN_FIFO_BASE); - ++cache_ptr; - } - } - blk->rx_cache_idx = 0; - return read_bc; -} - -/* - * i2c_msm_blk_rd_xfer_buf: fill in ctrl->xfer.cur_buf from HW - * - * @return zero on success - */ -static int i2c_msm_blk_rd_xfer_buf(struct i2c_msm_ctrl *ctrl) -{ - struct i2c_msm_xfer_mode_blk *blk = i2c_msm_blk_get_struct(ctrl); - struct i2c_msm_xfer_buf *buf = &ctrl->xfer.cur_buf; - size_t bc_to_prcs = buf->len - buf->byte_idx; - struct i2c_msg *msg = ctrl->xfer.msgs + buf->msg_idx; - size_t copy_bc; /* number of bytes to copy to user's buffer */ - int cache_avail_bc; - int ret = 0; - - /* write tag to out FIFO */ - ret = i2c_msm_blk_xfer_wr_tag(ctrl); - if (ret) - return ret; - i2c_msm_blk_wr_flush(ctrl); - - while (bc_to_prcs || buf->in_tag.len) { - cache_avail_bc = i2c_msm_blk_rd_blk(ctrl, - bc_to_prcs + buf->in_tag.len); - - i2c_msm_dbg(ctrl, MSM_DBG, "IN-BLK:%*phC\n", cache_avail_bc, - blk->rx_cache + blk->rx_cache_idx); - - if (cache_avail_bc < 0) - return cache_avail_bc; - - /* discard tag from input FIFO */ - if (buf->in_tag.len) { - size_t discard_bc = min_t(size_t, cache_avail_bc, - buf->in_tag.len); - blk->rx_cache_idx += discard_bc; - buf->in_tag.len -= discard_bc; - cache_avail_bc -= discard_bc; - } - - /* copy bytes from cached block to user's buffer */ - copy_bc = min_t(size_t, cache_avail_bc, bc_to_prcs); - memcpy(msg->buf + buf->byte_idx, - blk->rx_cache + blk->rx_cache_idx, copy_bc); - - blk->rx_cache_idx += copy_bc; - bc_to_prcs -= copy_bc; - buf->byte_idx += copy_bc; - } - return ret; -} - -/* - * i2c_msm_blk_xfer: process transfer using block mode - */ -static int i2c_msm_blk_xfer(struct i2c_msm_ctrl *ctrl) -{ - int ret = 0; - struct i2c_msm_xfer_buf *buf = &ctrl->xfer.cur_buf; - struct i2c_msm_xfer_mode_blk *blk = i2c_msm_blk_get_struct(ctrl); - - if (!blk) { - ret = i2c_msm_blk_create_struct(ctrl); - if (ret) - return ret; - blk = i2c_msm_blk_get_struct(ctrl); - } - - init_completion(&blk->wait_rx_blk); - init_completion(&blk->wait_tx_blk); - - /* tx_cnt > 0 always */ - blk->complete_mask = QUP_MAX_OUTPUT_DONE_FLAG; - if (&ctrl->xfer.rx_cnt) - blk->complete_mask |= QUP_MAX_INPUT_DONE_FLAG; - - /* initialize block mode for new transfer */ - blk->tx_cache_idx = 0; - blk->rx_cache_idx = 0; - - ret = i2c_msm_qup_state_set(ctrl, QUP_STATE_RESET); - if (ret < 0) - return ret; - - /* program qup registers */ - i2c_msm_qup_xfer_init_reset_state(ctrl); - - ret = i2c_msm_qup_state_set(ctrl, QUP_STATE_RUN); - if (ret < 0) - return ret; - - /* program qup registers which must be set *after* reset */ - i2c_msm_qup_xfer_init_run_state(ctrl); - - while (i2c_msm_xfer_next_buf(ctrl)) { - if (buf->is_rx) { - ret = i2c_msm_blk_rd_xfer_buf(ctrl); - if (ret) - return ret; - /* - * SW workaround to wait for extra interrupt from - * hardware for last block in block mode for read - */ - if (buf->is_last) { - ret = i2c_msm_xfer_wait_for_completion(ctrl, - &blk->wait_rx_blk); - if (!ret) - complete(&ctrl->xfer.complete); - } - } else { - ret = i2c_msm_blk_wr_xfer_buf(ctrl); - if (ret) - return ret; - } - } - i2c_msm_blk_wr_flush(ctrl); - return i2c_msm_xfer_wait_for_completion(ctrl, &ctrl->xfer.complete); -} - /* * i2c_msm_bam_xfer_prepare: map DMA buffers, and create tags. * @return zero on success or negative error value @@ -1938,7 +1562,7 @@ static int i2c_msm_bam_xfer_process(struct i2c_msm_ctrl *ctrl) } } - ret = i2c_msm_xfer_wait_for_completion(ctrl, &ctrl->xfer.complete); + ret = i2c_msm_xfer_wait_for_completion(ctrl); bam_xfer_end: return ret; @@ -2624,12 +2248,10 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid) { struct i2c_msm_ctrl *ctrl = devid; void __iomem *base = ctrl->rsrcs.base; - struct i2c_msm_xfer *xfer = &ctrl->xfer; - struct i2c_msm_xfer_mode_blk *blk; - u32 i2c_status = 0; - u32 err_flags = 0; - u32 qup_op = 0; - u32 clr_flds = 0; + u32 i2c_status = 0; + u32 err_flags = 0; + u32 qup_op = 0; + u32 clr_flds = 0; bool dump_details = false; bool log_event = false; bool signal_complete = false; @@ -2657,21 +2279,6 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid) "IRQ MASTER_STATUS:0x%08x ERROR_FLAGS:0x%08x OPERATIONAL:0x%08x\n", i2c_status, err_flags, qup_op); - /* clear interrupts fields */ - clr_flds = i2c_status & QUP_MSTR_STTS_ERR_MASK; - if (clr_flds) - writel_relaxed(clr_flds, base + QUP_I2C_STATUS); - - clr_flds = err_flags & QUP_ERR_FLGS_MASK; - if (clr_flds) - writel_relaxed(clr_flds, base + QUP_ERROR_FLAGS); - - clr_flds = qup_op & (QUP_OUTPUT_SERVICE_FLAG | QUP_INPUT_SERVICE_FLAG); - - if (clr_flds) - writel_relaxed(clr_flds, base + QUP_OPERATIONAL); - mb(); - if (err_flags & QUP_ERR_FLGS_MASK) { dump_details = true; signal_complete = true; @@ -2700,57 +2307,31 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid) ctrl->xfer.err |= I2C_MSM_ERR_BUS_ERR; } - blk = i2c_msm_blk_get_struct(ctrl); - - if (xfer->mode_id == I2C_MSM_XFER_MODE_BLOCK) { - /*For Block Mode */ - /* block ready for writing */ - if (qup_op & QUP_OUTPUT_SERVICE_FLAG) { - log_event = true; - if (qup_op & QUP_OUT_BLOCK_WRITE_REQ) - complete(&blk->wait_tx_blk); - - if ((qup_op & blk->complete_mask) - == blk->complete_mask) { - log_event = true; - signal_complete = true; - } - } - /* block ready for reading */ - if (qup_op & QUP_INPUT_SERVICE_FLAG) { - log_event = true; - complete(&blk->wait_rx_blk); - } - } else { - /* for FIFO/BAM Mode*/ - if (qup_op & QUP_MAX_INPUT_DONE_FLAG) { - log_event = true; - /* - * If last transaction is an input then the entire - * transfer is done - */ - if (ctrl->xfer.last_is_rx) - signal_complete = true; - } + if (qup_op & QUP_MAX_INPUT_DONE_FLAG) { + log_event = true; /* - * Ideally, would like to check QUP_MAX_OUTPUT_DONE_FLAG. - * However, QUP_MAX_OUTPUT_DONE_FLAG is lagging behind - * QUP_OUTPUT_SERVICE_FLAG. The only reason for - * QUP_OUTPUT_SERVICE_FLAG to be set in FIFO mode is - * QUP_MAX_OUTPUT_DONE_FLAG condition. The code checking - * here QUP_OUTPUT_SERVICE_FLAG and assumes that - * QUP_MAX_OUTPUT_DONE_FLAG. + * If last transaction is an input then the entire transfer + * is done */ - if (qup_op & (QUP_OUTPUT_SERVICE_FLAG | - QUP_MAX_OUTPUT_DONE_FLAG)) { - log_event = true; - /* - * If last transaction is an output then the - * entire transfer is done - */ - if (!ctrl->xfer.last_is_rx) - signal_complete = true; - } + if (ctrl->xfer.last_is_rx) + signal_complete = true; + } + /* + * Ideally, would like to check QUP_MAX_OUTPUT_DONE_FLAG. However, + * QUP_MAX_OUTPUT_DONE_FLAG is lagging behind QUP_OUTPUT_SERVICE_FLAG. + * The only reason for QUP_OUTPUT_SERVICE_FLAG to be set in FIFO mode + * is QUP_MAX_OUTPUT_DONE_FLAG condition. + * The code checking here QUP_OUTPUT_SERVICE_FLAG and assumes that + * QUP_MAX_OUTPUT_DONE_FLAG. + */ + if (qup_op & (QUP_OUTPUT_SERVICE_FLAG | QUP_MAX_OUTPUT_DONE_FLAG)) { + log_event = true; + /* + * If last transaction is an output then the entire transfer + * is done + */ + if (!ctrl->xfer.last_is_rx) + signal_complete = true; } if (dump_details && (ctrl->dbgfs.dbg_lvl >= MSM_DBG)) { @@ -2760,6 +2341,18 @@ static irqreturn_t i2c_msm_qup_isr(int irq, void *devid) i2c_msm_dbg_qup_reg_dump(ctrl); } + clr_flds = i2c_status & QUP_MSTR_STTS_ERR_MASK; + if (clr_flds) + writel_relaxed(clr_flds, base + QUP_I2C_STATUS); + + clr_flds = err_flags & QUP_ERR_FLGS_MASK; + if (clr_flds) + writel_relaxed(clr_flds, base + QUP_ERROR_FLAGS); + + clr_flds = qup_op & (QUP_OUTPUT_SERVICE_FLAG | QUP_INPUT_SERVICE_FLAG); + if (clr_flds) + writel_relaxed(clr_flds, base + QUP_OPERATIONAL); + isr_end: if (dump_details || log_event || (ctrl->dbgfs.dbg_lvl >= MSM_DBG)) i2c_msm_prof_evnt_add(ctrl, MSM_PROF, @@ -2800,10 +2393,6 @@ static int i2c_msm_qup_create_struct(struct i2c_msm_ctrl *ctrl) if (ret) i2c_msm_bam_destroy_struct(ctrl); - ret = i2c_msm_blk_create_struct(ctrl); - if (ret) - return ret; - return ret; } @@ -2811,7 +2400,6 @@ static void i2c_msm_qup_destroy_struct(struct i2c_msm_ctrl *ctrl) { i2c_msm_fifo_destroy_struct(ctrl); i2c_msm_bam_destroy_struct(ctrl); - i2c_msm_blk_destroy_struct(ctrl); } static int i2c_msm_qup_init(struct i2c_msm_ctrl *ctrl) @@ -2940,8 +2528,7 @@ static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err) return err; } -static enum i2c_msm_xfer_mode_id -i2c_msm_qup_choose_mode(struct i2c_msm_ctrl *ctrl) +static void i2c_msm_qup_choose_mode(struct i2c_msm_ctrl *ctrl) { struct i2c_msm_xfer_mode_fifo *fifo; struct i2c_msm_xfer *xfer = &ctrl->xfer; @@ -2951,16 +2538,13 @@ i2c_msm_qup_choose_mode(struct i2c_msm_ctrl *ctrl) fifo = i2c_msm_fifo_get_struct(ctrl); if (ctrl->dbgfs.force_xfer_mode != I2C_MSM_XFER_MODE_NONE) - return ctrl->dbgfs.force_xfer_mode; - - if (((rx_cnt_sum < fifo->input_fifo_sz) && - (tx_cnt_sum < fifo->output_fifo_sz))) - return I2C_MSM_XFER_MODE_FIFO; - - if (ctrl->rsrcs.disable_dma) - return I2C_MSM_XFER_MODE_BLOCK; - - return I2C_MSM_XFER_MODE_BAM; + xfer->mode_id = ctrl->dbgfs.force_xfer_mode; + else if (((rx_cnt_sum < fifo->input_fifo_sz) && + (tx_cnt_sum < fifo->output_fifo_sz)) || + ctrl->rsrcs.disable_dma) + xfer->mode_id = I2C_MSM_XFER_MODE_FIFO; + else + xfer->mode_id = I2C_MSM_XFER_MODE_BAM; } /* @@ -3032,14 +2616,14 @@ static void i2c_msm_xfer_calc_timeout(struct i2c_msm_ctrl *ctrl) ctrl->xfer.timeout = usecs_to_jiffies(xfer_max_usec); } -static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl, - struct completion *complete) +static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl) { struct i2c_msm_xfer *xfer = &ctrl->xfer; long time_left; int ret = 0; - time_left = wait_for_completion_timeout(complete, xfer->timeout); + time_left = wait_for_completion_timeout(&xfer->complete, + xfer->timeout); if (!time_left) { i2c_msm_prof_evnt_add(ctrl, MSM_ERR, i2c_msm_prof_dump_cmplt_fl, xfer->timeout, time_left, 0); @@ -3234,7 +2818,7 @@ i2c_msm_frmwrk_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) i2c_msm_xfer_scan(ctrl); i2c_msm_xfer_calc_timeout(ctrl); - xfer->mode_id = (*ctrl->ver.choose_mode)(ctrl); + (*ctrl->ver.choose_mode)(ctrl); i2c_msm_prof_evnt_add(ctrl, MSM_PROF, i2c_msm_prof_dump_scan_sum, ((xfer->rx_cnt & 0xff) | ((xfer->rx_ovrhd_cnt & 0xff) << 16)), diff --git a/drivers/i2c/busses/i2c-msm-v2.h b/drivers/i2c/busses/i2c-msm-v2.h index 382e8133676a..e1fa540f819f 100644 --- a/drivers/i2c/busses/i2c-msm-v2.h +++ b/drivers/i2c/busses/i2c-msm-v2.h @@ -17,8 +17,6 @@ #ifndef _I2C_MSM_V2_H #define _I2C_MSM_V2_H -#include <linux/bitops.h> - enum msm_i2_debug_level { MSM_ERR, /* Error messages only. Always on */ MSM_PROF, /* High level events. Use for profiling */ @@ -102,8 +100,6 @@ enum { QUP_INPUT_SERVICE_FLAG = 1U << 9, QUP_MAX_OUTPUT_DONE_FLAG = 1U << 10, QUP_MAX_INPUT_DONE_FLAG = 1U << 11, - QUP_OUT_BLOCK_WRITE_REQ = BIT(12), - QUP_IN_BLOCK_READ_REQ = BIT(13), }; /* Register:QUP_OPERATIONAL_MASK fields */ @@ -430,36 +426,9 @@ struct i2c_msm_xfer_mode_fifo { int out_buf_idx; }; -/* i2c_msm_xfer_mode_blk: operations and state of Block mode - * - * @in_blk_sz size of input/rx block - * @out_blk_sz size of output/tx block - * @tx_cache internal buffer to store tx data - * @rx_cache internal buffer to store rx data - * @rx_cache_idx points to the next unread index in rx cache - * @tx_cache_idx points to the next unwritten index in tx cache - * @wait_rx_blk completion object to wait on for end of blk rx transfer. - * @wait_tx_blk completion object to wait on for end of blk tx transfer. - * @complete_mask applied to QUP_OPERATIONAL to determine when blk - * xfer is complete. - */ -struct i2c_msm_xfer_mode_blk { - struct i2c_msm_xfer_mode ops; - size_t in_blk_sz; - size_t out_blk_sz; - u8 *tx_cache; - u8 *rx_cache; - int rx_cache_idx; - int tx_cache_idx; - struct completion wait_rx_blk; - struct completion wait_tx_blk; - u32 complete_mask; -}; - /* INPUT_MODE and OUTPUT_MODE filds of QUP_IO_MODES register */ enum i2c_msm_xfer_mode_id { I2C_MSM_XFER_MODE_FIFO, - I2C_MSM_XFER_MODE_BLOCK, I2C_MSM_XFER_MODE_BAM, I2C_MSM_XFER_MODE_NONE, /* keep last as a counter */ }; @@ -491,7 +460,7 @@ struct i2c_msm_ctrl_ver { int (*reset) (struct i2c_msm_ctrl *); int (*init_rsrcs) (struct platform_device *, struct i2c_msm_ctrl *); - enum i2c_msm_xfer_mode_id (*choose_mode)(struct i2c_msm_ctrl *); + void (*choose_mode)(struct i2c_msm_ctrl *); int (*post_xfer) (struct i2c_msm_ctrl *, int err); |