diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index bbff90f59757..063779335540 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -447,7 +447,8 @@ struct gpi_dev { struct dentry *dentry; }; -static struct gpi_dev *gpi_dev_dbg; +static struct gpi_dev *gpi_dev_dbg[5]; +static int arr_idx; struct reg_info { char *name; @@ -581,6 +582,7 @@ struct gpii { struct gpi_reg_table dbg_reg_table; bool reg_table_dump; u32 dbg_gpi_irq_cnt; + bool ieob_set; }; struct gpi_desc { @@ -1496,20 +1498,6 @@ static void gpi_process_imed_data_event(struct gpii_chan *gpii_chan, return; } gpi_desc = to_gpi_desc(vd); - - /* Event TR RP gen. don't match descriptor TR */ - if (gpi_desc->wp != tre) { - spin_unlock_irqrestore(&gpii_chan->vc.lock, flags); - GPII_ERR(gpii, gpii_chan->chid, - "EOT/EOB received for wrong TRE 0x%0llx != 0x%0llx\n", - to_physical(ch_ring, gpi_desc->wp), - to_physical(ch_ring, tre)); - gpi_generate_cb_event(gpii_chan, MSM_GPI_QUP_EOT_DESC_MISMATCH, - __LINE__); - return; - } - - list_del(&vd->node); spin_unlock_irqrestore(&gpii_chan->vc.lock, flags); @@ -1525,6 +1513,9 @@ static void gpi_process_imed_data_event(struct gpii_chan *gpii_chan, /* make sure rp updates are immediately visible to all cores */ smp_wmb(); + if (imed_event->code == MSM_GPI_TCE_EOT && gpii->ieob_set) + return; + tx_cb_param = vd->tx.callback_param; if (vd->tx.callback && tx_cb_param) { struct msm_gpi_tre *imed_tre = &tx_cb_param->imed_tre; @@ -1540,7 +1531,12 @@ static void gpi_process_imed_data_event(struct gpii_chan *gpii_chan, tx_cb_param->status = imed_event->status; vd->tx.callback(tx_cb_param); } + + spin_lock_irqsave(&gpii_chan->vc.lock, flags); + list_del(&vd->node); + spin_unlock_irqrestore(&gpii_chan->vc.lock, flags); kfree(gpi_desc); + gpi_desc = NULL; } /* processing transfer completion events */ @@ -1583,20 +1579,6 @@ static void gpi_process_xfer_compl_event(struct gpii_chan *gpii_chan, } gpi_desc = to_gpi_desc(vd); - - /* TRE Event generated didn't match descriptor's TRE */ - if (gpi_desc->wp != ev_rp) { - spin_unlock_irqrestore(&gpii_chan->vc.lock, flags); - GPII_ERR(gpii, gpii_chan->chid, - "EOT\EOB received for wrong TRE 0x%0llx != 0x%0llx\n", - to_physical(ch_ring, gpi_desc->wp), - to_physical(ch_ring, ev_rp)); - gpi_generate_cb_event(gpii_chan, MSM_GPI_QUP_EOT_DESC_MISMATCH, - __LINE__); - return; - } - - list_del(&vd->node); spin_unlock_irqrestore(&gpii_chan->vc.lock, flags); @@ -1612,6 +1594,9 @@ static void gpi_process_xfer_compl_event(struct gpii_chan *gpii_chan, /* update must be visible to other cores */ smp_wmb(); + if (compl_event->code == MSM_GPI_TCE_EOT && gpii->ieob_set) + return; + tx_cb_param = vd->tx.callback_param; if (vd->tx.callback && tx_cb_param) { GPII_VERB(gpii, gpii_chan->chid, @@ -1623,7 +1608,13 @@ static void gpi_process_xfer_compl_event(struct gpii_chan *gpii_chan, tx_cb_param->status = compl_event->status; vd->tx.callback(tx_cb_param); } + + spin_lock_irqsave(&gpii_chan->vc.lock, flags); + list_del(&vd->node); + spin_unlock_irqrestore(&gpii_chan->vc.lock, flags); kfree(gpi_desc); + gpi_desc = NULL; + } /* process all events */ @@ -2299,6 +2290,7 @@ void gpi_desc_free(struct virt_dma_desc *vd) struct gpi_desc *gpi_desc = to_gpi_desc(vd); kfree(gpi_desc); + gpi_desc = NULL; } /* copy tre into transfer ring */ @@ -2319,6 +2311,7 @@ struct dma_async_tx_descriptor *gpi_prep_slave_sg(struct dma_chan *chan, void *tre, *wp = NULL; const gfp_t gfp = GFP_ATOMIC; struct gpi_desc *gpi_desc; + gpii->ieob_set = false; GPII_VERB(gpii, gpii_chan->chid, "enter\n"); @@ -2352,10 +2345,22 @@ struct dma_async_tx_descriptor *gpi_prep_slave_sg(struct dma_chan *chan, } /* copy each tre into transfer ring */ - for_each_sg(sgl, sg, sg_len, i) - for (j = 0, tre = sg_virt(sg); j < sg->length; + for_each_sg(sgl, sg, sg_len, i) { + tre = sg_virt(sg); + + /* Check if last tre has ieob set */ + if (i == sg_len - 1) { + if ((((struct msm_gpi_tre *)tre)->dword[3] & + GPI_IEOB_BMSK) >> GPI_IEOB_BMSK_SHIFT) + gpii->ieob_set = true; + else + gpii->ieob_set = false; + } + + for (j = 0; j < sg->length; j += ch_ring->el_size, tre += ch_ring->el_size) gpi_queue_xfer(gpii, gpii_chan, tre, &wp); + } /* set up the descriptor */ gpi_desc->db = ch_ring->wp; @@ -2807,7 +2812,8 @@ static int gpi_probe(struct platform_device *pdev) return -ENOMEM; /* debug purpose */ - gpi_dev_dbg = gpi_dev; + gpi_dev_dbg[arr_idx] = gpi_dev; + arr_idx++; gpi_dev->dev = &pdev->dev; gpi_dev->klog_lvl = DEFAULT_KLOG_LVL; diff --git a/drivers/dma/qcom/msm_gpi_mmio.h b/drivers/dma/qcom/msm_gpi_mmio.h index 46ed27e3ed92..74a390b21dab 100644 --- a/drivers/dma/qcom/msm_gpi_mmio.h +++ b/drivers/dma/qcom/msm_gpi_mmio.h @@ -228,3 +228,7 @@ enum CNTXT_OFFS { #define GPI_DEBUG_QSB_LOG_1 (0x5068) #define GPI_DEBUG_QSB_LOG_2 (0x506C) #define GPI_DEBUG_QSB_LOG_LAST_MISC_ID(n) (0x5070 + (0x4*n)) + +/* IEOB bit set */ +#define GPI_IEOB_BMSK (0x100) +#define GPI_IEOB_BMSK_SHIFT (8) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 3cd43f53d6ca..07bb152d09ad 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -98,6 +98,8 @@ struct geni_i2c_dev { int clk_fld_idx; struct dma_chan *tx_c; struct dma_chan *rx_c; + struct msm_gpi_tre lock_t; + struct msm_gpi_tre unlock_t; struct msm_gpi_tre cfg0_t; struct msm_gpi_tre go_t; struct msm_gpi_tre tx_t; @@ -370,9 +372,9 @@ static void gi2c_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb_str, } if (cb_str->cb_event != MSM_GPI_QUP_NOTIFY) GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, - "GSI QN err:0x%x, status:0x%x, err:%d\n", - cb_str->error_log.error_code, - m_stat, cb_str->cb_event); + "GSI QN err:0x%x, status:0x%x, err:%d slv_addr: 0x%x R/W: %d\n", + cb_str->error_log.error_code, m_stat, + cb_str->cb_event, gi2c->cur->addr, gi2c->cur->flags); } static void gi2c_gsi_cb_err(struct msm_gpi_dma_async_tx_cb_param *cb, @@ -398,7 +400,9 @@ static void gi2c_gsi_tx_cb(void *ptr) struct msm_gpi_dma_async_tx_cb_param *tx_cb = ptr; struct geni_i2c_dev *gi2c = tx_cb->userdata; - if (!(gi2c->cur->flags & I2C_M_RD)) { + if (tx_cb->completion_code == MSM_GPI_TCE_EOB) { + complete(&gi2c->xfer); + } else if (!(gi2c->cur->flags & I2C_M_RD)) { gi2c_gsi_cb_err(tx_cb, "TX"); complete(&gi2c->xfer); } @@ -460,6 +464,23 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], } } + if (gi2c->is_shared) { + struct msm_gpi_tre *lock_t = &gi2c->lock_t; + struct msm_gpi_tre *unlock_t = &gi2c->unlock_t; + + /* lock */ + lock_t->dword[0] = MSM_GPI_LOCK_TRE_DWORD0; + lock_t->dword[1] = MSM_GPI_LOCK_TRE_DWORD1; + lock_t->dword[2] = MSM_GPI_LOCK_TRE_DWORD2; + lock_t->dword[3] = MSM_GPI_LOCK_TRE_DWORD3(0, 0, 0, 0, 1); + + /* unlock */ + unlock_t->dword[0] = MSM_GPI_UNLOCK_TRE_DWORD0; + unlock_t->dword[1] = MSM_GPI_UNLOCK_TRE_DWORD1; + unlock_t->dword[2] = MSM_GPI_UNLOCK_TRE_DWORD2; + unlock_t->dword[3] = MSM_GPI_UNLOCK_TRE_DWORD3(0, 0, 0, 1, 0); + } + if (!gi2c->cfg_sent) { struct geni_i2c_clk_fld *itr = geni_i2c_clk_map + gi2c->clk_fld_idx; @@ -499,24 +520,34 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], } qcom_geni_i2c_calc_timeout(gi2c); - if (!gi2c->cfg_sent) { + + if (!gi2c->cfg_sent) segs++; + if (gi2c->is_shared && (i == 0 || i == num-1)) { + segs++; + if (num == 1) + segs++; sg_init_table(gi2c->tx_sg, segs); - sg_set_buf(gi2c->tx_sg, &gi2c->cfg0_t, - sizeof(gi2c->cfg0_t)); - gi2c->cfg_sent = 1; - index++; + if (i == 0) + sg_set_buf(&gi2c->tx_sg[index++], &gi2c->lock_t, + sizeof(gi2c->lock_t)); } else { sg_init_table(gi2c->tx_sg, segs); } + if (!gi2c->cfg_sent) { + sg_set_buf(&gi2c->tx_sg[index++], &gi2c->cfg0_t, + sizeof(gi2c->cfg0_t)); + gi2c->cfg_sent = 1; + } + go_t->dword[0] = MSM_GPI_I2C_GO_TRE_DWORD0((stretch << 2), msgs[i].addr, op); go_t->dword[1] = MSM_GPI_I2C_GO_TRE_DWORD1; if (msgs[i].flags & I2C_M_RD) { go_t->dword[2] = MSM_GPI_I2C_GO_TRE_DWORD2(msgs[i].len); - go_t->dword[3] = MSM_GPI_I2C_GO_TRE_DWORD3(1, 0, 0, 1, + go_t->dword[3] = MSM_GPI_I2C_GO_TRE_DWORD3(1, 0, 0, 0, 0); } else { go_t->dword[2] = MSM_GPI_I2C_GO_TRE_DWORD2(0); @@ -588,13 +619,22 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], MSM_GPI_DMA_W_BUFFER_TRE_DWORD1(gi2c->tx_ph); gi2c->tx_t.dword[2] = MSM_GPI_DMA_W_BUFFER_TRE_DWORD2(msgs[i].len); - gi2c->tx_t.dword[3] = + if (gi2c->is_shared && i == num-1) + gi2c->tx_t.dword[3] = + MSM_GPI_DMA_W_BUFFER_TRE_DWORD3(0, 0, 1, 0, 1); + else + gi2c->tx_t.dword[3] = MSM_GPI_DMA_W_BUFFER_TRE_DWORD3(0, 0, 1, 0, 0); sg_set_buf(&gi2c->tx_sg[index++], &gi2c->tx_t, sizeof(gi2c->tx_t)); } + if (gi2c->is_shared && i == num-1) { + sg_set_buf(&gi2c->tx_sg[index++], + &gi2c->unlock_t, sizeof(gi2c->unlock_t)); + } + gi2c->tx_desc = dmaengine_prep_slave_sg(gi2c->tx_c, gi2c->tx_sg, segs, DMA_MEM_TO_DEV, (DMA_PREP_INTERRUPT | @@ -616,8 +656,9 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], gi2c->xfer_timeout); if (!timeout) { GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, - "GSI Txn timed out: %u len: %d\n", - gi2c->xfer_timeout, gi2c->cur->len); + "GSI Txn timed out: %u len: %d slv:addr: 0x%x R/W: %d\n", + gi2c->xfer_timeout, gi2c->cur->len, + gi2c->cur->addr, gi2c->cur->flags); geni_se_dump_dbg_regs(&gi2c->i2c_rsc, gi2c->base, gi2c->ipcl); gi2c->err = -ETIMEDOUT; @@ -1001,7 +1042,7 @@ static int geni_i2c_runtime_resume(struct device *dev) if (!gi2c->ipcl) { char ipc_name[I2C_NAME_SIZE]; - snprintf(ipc_name, I2C_NAME_SIZE, "i2c-%d", gi2c->adap.nr); + snprintf(ipc_name, I2C_NAME_SIZE, "%s", dev_name(gi2c->dev)); gi2c->ipcl = ipc_log_context_create(2, ipc_name, 0); } diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index e704a96cce74..373e5f00ec01 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -397,7 +397,7 @@ static struct msm_gpi_tre *setup_go_tre(int cmd, int cs, int rx_len, int flags, if (cmd == SPI_RX_ONLY) { eot = 0; chain = 0; - eob = 1; + eob = 0; } else { eot = 0; chain = 1; diff --git a/include/linux/msm_gpi.h b/include/linux/msm_gpi.h index b048ac0f2d61..11f9cf7bd2a2 100644 --- a/include/linux/msm_gpi.h +++ b/include/linux/msm_gpi.h @@ -27,6 +27,22 @@ enum msm_gpi_tre_type { #define MSM_GPI_TRE_TYPE(tre) ((tre->dword[3] >> 16) & 0xFF) +/* Lock TRE */ +#define MSM_GPI_LOCK_TRE_DWORD0 (0) +#define MSM_GPI_LOCK_TRE_DWORD1 (0) +#define MSM_GPI_LOCK_TRE_DWORD2 (0) +#define MSM_GPI_LOCK_TRE_DWORD3(link_rx, bei, ieot, ieob, ch) \ + ((0x3 << 20) | (0x0 << 16) | (link_rx << 11) | (bei << 10) | \ + (ieot << 9) | (ieob << 8) | ch) + +/* Unlock TRE */ +#define MSM_GPI_UNLOCK_TRE_DWORD0 (0) +#define MSM_GPI_UNLOCK_TRE_DWORD1 (0) +#define MSM_GPI_UNLOCK_TRE_DWORD2 (0) +#define MSM_GPI_UNLOCK_TRE_DWORD3(link_rx, bei, ieot, ieob, ch) \ + ((0x3 << 20) | (0x1 << 16) | (link_rx << 11) | (bei << 10) | \ + (ieot << 9) | (ieob << 8) | ch) + /* DMA w. Buffer TRE */ #ifdef CONFIG_ARM64 #define MSM_GPI_DMA_W_BUFFER_TRE_DWORD0(ptr) ((u32)ptr)