Merge "i3c-master-msm-geni: add changes for ibi stuck in gsi mode"

This commit is contained in:
qctecmdr 2023-10-04 01:45:01 -07:00 committed by Gerrit - the friendly Code Review server
commit bfa0380f01

View File

@ -381,6 +381,7 @@ struct geni_i3c_clk_fld {
u32 i2c_t_cycle_cnt;
};
static int geni_i3c_gsi_stop_on_bus(struct geni_i3c_dev *gi3c);
static void geni_i3c_enable_ibi_ctrl(struct geni_i3c_dev *gi3c, bool enable);
static void geni_i3c_enable_ibi_irq(struct geni_i3c_dev *gi3c, bool enable);
static int geni_i3c_enable_naon_ibi_clks(struct geni_i3c_dev *gi3c, bool enable);
@ -794,7 +795,6 @@ static void i3c_setup_go_tre(struct geni_i3c_dev *gi3c, struct geni_i3c_xfer_par
{
struct msm_gpi_tre *go_t = &gi3c->gsi.tx.tre.go_t;
struct gsi_tre_queue *tx_tre_q = &gi3c->gsi.tx.tre_queue;
bool stretch = (xfer->m_param & STOP_STRETCH) ? 1 : 0;
bool use_7e = (xfer->m_param & USE_7E) ? 1 : 0;
bool nack_ibi = (xfer->m_param & IBI_NACK_TBL_CTRL) ? 1 : 0;
bool cont_mode = (xfer->m_param & CONTINUOUS_MODE_DAA) ? 1 : 0;
@ -808,7 +808,7 @@ static void i3c_setup_go_tre(struct geni_i3c_dev *gi3c, struct geni_i3c_xfer_par
else
cur_len = gi3c->cur_len;
go_t->dword[0] = MSM_GPI_I3C_GO_TRE_DWORD0((stretch << 2 | bypass_addrspace << 7), ccc,
go_t->dword[0] = MSM_GPI_I3C_GO_TRE_DWORD0((1 << 2 | bypass_addrspace << 7), ccc,
addr, xfer->m_cmd);
go_t->dword[1] = MSM_GPI_I3C_GO_TRE_DWORD1(use_7e << 0 | nack_ibi << 1 | cont_mode << 2);
if (gi3c->cur_rnw == READ_TRANSACTION) {
@ -1850,6 +1850,7 @@ geni_i3c_master_gsi_priv_xfers(struct geni_i3c_dev *gi3c, struct i3c_priv_xfer *
I3C_LOG_DBG(gi3c->ipcl, false, gi3c->se.dev, "%s Time took for %d xfers = %llu nsecs\n",
__func__, num_xfers, (sched_clock() - start_time));
geni_i3c_gsi_stop_on_bus(gi3c);
return ret;
}
@ -2135,6 +2136,55 @@ static void geni_i3c_perform_daa(struct geni_i3c_dev *gi3c)
kfree(rx_buf);
}
/*
* geni_i3c_gsi_stop_on_bus() - Does gsi i3c stop command on the bus
*
* @gi3c: i3c master device handle
*
* Return: 0 on success, error code on failure
*/
static int geni_i3c_gsi_stop_on_bus(struct geni_i3c_dev *gi3c)
{
struct msm_gpi_tre *go_t = &gi3c->gsi.tx.tre.go_t;
int tre_cnt = 0, ret = 0, time_remaining = 0;
bool tx_chan = true;
gi3c->err = 0;
gi3c->gsi_err = false;
gi3c->gsi.tx.tre.flags = 0;
reinit_completion(&gi3c->done);
go_t->dword[0] = MSM_GPI_I3C_GO_TRE_DWORD0(0, 0, 0, I2C_STOP_ON_BUS);
go_t->dword[1] = 0x0;
go_t->dword[2] = 0x0;
go_t->dword[3] = MSM_GPI_I3C_GO_TRE_DWORD3(0, 0, 1, 0, 0);
I3C_LOG_DBG(gi3c->ipcl, false, gi3c->se.dev,
"%s: dword[0]:0x%x dword[1]:0x%x dword[2]:0x%x dword[3]:0x%x\n",
__func__, go_t->dword[0], go_t->dword[1], go_t->dword[2], go_t->dword[3]);
gi3c->gsi.tx.tre.flags |= GO_TRE_SET;
tre_cnt = gsi_common_fill_tre_buf(&gi3c->gsi, tx_chan);
ret = gsi_common_prep_desc_and_submit(&gi3c->gsi, tre_cnt, tx_chan, false);
if (ret < 0)
gi3c->err = ret;
time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
if (!time_remaining) {
I3C_LOG_ERR(gi3c->ipcl, false, gi3c->se.dev,
"%s:wait_for_completion timed out\n", __func__);
geni_i3c_err(gi3c, GENI_TIMEOUT);
gi3c->cur_buf = NULL;
gi3c->cur_len = 0;
gi3c->cur_idx = 0;
gi3c->cur_rnw = 0;
reinit_completion(&gi3c->done);
}
I3C_LOG_DBG(gi3c->ipcl, false, gi3c->se.dev, "%s: ret:%d\n", __func__, ret);
return ret;
}
/*
* geni_i3c_master_send_ccc_cmd() - Does i3c master send ccc commands
*
@ -3423,6 +3473,14 @@ static int geni_i3c_probe(struct platform_device *pdev)
"I3C bus freq:%ld, I2C bus fres:%ld\n",
gi3c->ctrlr.bus.scl_rate.i3c, gi3c->ctrlr.bus.scl_rate.i2c);
if (gi3c->se_mode == GENI_GPI_DMA) {
if (geni_i3c_gsi_stop_on_bus(gi3c)) {
I3C_LOG_ERR(gi3c->ipcl, false, gi3c->se.dev,
"I3C gsi stop on bus failed\n");
return -EINVAL;
}
}
// hot-join
gi3c->hj_wl = wakeup_source_register(gi3c->se.dev,
dev_name(gi3c->se.dev));
@ -3542,6 +3600,7 @@ static int geni_i3c_runtime_suspend(struct device *dev)
if (gi3c->se_mode != GENI_GPI_DMA) {
disable_irq(gi3c->irq);
} else {
geni_i3c_gsi_stop_on_bus(gi3c);
ret = geni_i3c_gpi_pause_resume(gi3c, true);
if (ret) {
I3C_LOG_ERR(gi3c->ipcl, false, gi3c->se.dev,