Merge "i2c: i2c-qcom-geni: Add lock and unlock tre support in I2C GSI mode"
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
commit
db4c3fb36f
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,6 +619,10 @@ 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);
|
||||
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);
|
||||
|
||||
@@ -595,6 +630,11 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user