q2spi-msm-geni: Add snapshot q2spi geni driver

Add snapshot of q2spi geni driver from qcom-6.6
'commit<67a44689f373f2> ("Merge "i3c: i3c-master-msm-geni:
Remove duplicated register dump call")'.

Change-Id: I9f21f7cf054343b55841e7f58df9e62201226988
Signed-off-by: Chandana Kishori Chiluveru <quic_cchiluve@quicinc.com>
This commit is contained in:
Chandana Kishori Chiluveru 2024-07-11 00:37:26 -07:00
parent b0e9354523
commit 8b705c0efd
6 changed files with 545 additions and 223 deletions

View file

@ -1939,8 +1939,7 @@ static void gpi_process_ch_ctrl_irq(struct gpii *gpii)
/* notifying clients if in error state */
if (gpii_chan->ch_state == CH_STATE_ERROR)
gpi_generate_cb_event(gpii_chan, MSM_GPI_QUP_CH_ERROR,
ch_irq);
gpi_generate_cb_event(gpii_chan, MSM_GPI_QUP_CH_ERROR, ch_irq);
}
}
@ -2522,7 +2521,7 @@ gpi_process_xfer_q2spi_cr_header(struct gpii_chan *gpii_chan,
q2spi_cr_header_event->cr_hdr[0], q2spi_cr_header_event->cr_hdr[1],
q2spi_cr_header_event->cr_hdr[2], q2spi_cr_header_event->cr_hdr[3]);
GPII_VERB(gpii_ptr, gpii_chan->chid,
"cr_byte_0:0x%x cr_byte_1:0x%x cr_byte_2:0x%x cr_byte_3h:0x%x\n",
"cr_ed_byte_0:0x%x cr_ed_byte_1:0x%x cr_ed_byte_2:0x%x cr_ed_byte_3:0x%x\n",
q2spi_cr_header_event->cr_ed_byte[0], q2spi_cr_header_event->cr_ed_byte[1],
q2spi_cr_header_event->cr_ed_byte[2], q2spi_cr_header_event->cr_ed_byte[3]);
GPII_VERB(gpii_ptr, gpii_chan->chid, "code:0x%x\n", q2spi_cr_header_event->code);
@ -2530,6 +2529,13 @@ gpi_process_xfer_q2spi_cr_header(struct gpii_chan *gpii_chan,
"cr_byte_0_len:0x%x cr_byte_0_err:0x%x type:0x%x ch_id:0x%x\n",
q2spi_cr_header_event->byte0_len, q2spi_cr_header_event->byte0_err,
q2spi_cr_header_event->type, q2spi_cr_header_event->ch_id);
if (q2spi_cr_header_event->code == Q2SPI_CR_HEADER_LEN_ZERO)
GPII_ERR(gpii_ptr, gpii_chan->chid, "Err negative 1H doorbell response\n");
if (q2spi_cr_header_event->code == Q2SPI_CR_HEADER_INCORRECT)
GPII_ERR(gpii_ptr, gpii_chan->chid, "Err unexpected CR Header is received\n");
msm_gpi_cb.cb_event = MSM_GPI_QUP_CR_HEADER;
msm_gpi_cb.q2spi_cr_header_event = *q2spi_cr_header_event;
GPII_VERB(gpii_chan->gpii, gpii_chan->chid, "sending CB event:%s\n",
@ -3165,7 +3171,7 @@ static void gpi_noop_tre(struct gpii_chan *gpii_chan)
while (local_rp != local_wp) {
/* dump the channel ring at the time of error */
tre = (struct msm_gpi_tre *)cntxt_rp;
GPII_ERR(gpii, gpii_chan->chid, "local_rp:0x%011x TRE: %08x %08x %08x %08x\n",
GPII_ERR(gpii, gpii_chan->chid, "local_rp:%llu TRE: %08x %08x %08x %08x\n",
local_rp, tre->dword[0], tre->dword[1],
tre->dword[2], tre->dword[3]);
tre->dword[3] &= noop_mask;
@ -4242,7 +4248,7 @@ static int gpi_probe(struct platform_device *pdev)
/* setup debug capabilities */
gpi_setup_debug(gpi_dev);
GPI_LOG(gpi_dev, "probe success\n");
GPI_LOG(gpi_dev, "%s: probe success\n", __func__);
return ret;
}

View file

@ -40,7 +40,7 @@ static void q2spi_rx_xfer_completion_event(struct msm_gpi_dma_async_tx_cb_param
status = cb_param->status;
if (cb_param->length <= xfer->rx_len) {
xfer->rx_len = cb_param->length;
q2spi_dump_ipc(q2spi, q2spi->ipc, "rx_xfer_completion_event RX",
q2spi_dump_ipc(q2spi, "rx_xfer_completion_event RX",
(char *)xfer->rx_buf, cb_param->length);
if (q2spi_pkt->m_cmd_param == Q2SPI_RX_ONLY) {
Q2SPI_DEBUG(q2spi, "%s call db_rx_cb\n", __func__);
@ -52,16 +52,30 @@ static void q2spi_rx_xfer_completion_event(struct msm_gpi_dma_async_tx_cb_param
Q2SPI_DEBUG(q2spi, "%s q2spi_pkt:%p state=%d vtype:%d\n",
__func__, q2spi_pkt, q2spi_pkt->state, q2spi_pkt->vtype);
} else {
Q2SPI_ERROR(q2spi, "%s Err length miss-match %d %d\n",
Q2SPI_DEBUG(q2spi, "%s Err length miss-match %d %d\n",
__func__, cb_param->length, xfer->rx_len);
}
}
static void q2spi_tx_xfer_completion_event(struct msm_gpi_dma_async_tx_cb_param *cb_param)
{
struct q2spi_packet *q2spi_pkt = cb_param->userdata;
struct q2spi_geni *q2spi = q2spi_pkt->q2spi;
struct q2spi_dma_transfer *xfer = q2spi_pkt->xfer;
struct q2spi_packet *q2spi_pkt;
struct q2spi_geni *q2spi;
struct q2spi_dma_transfer *xfer;
q2spi_pkt = cb_param->userdata;
if (!q2spi_pkt) {
pr_err("%s Err Invalid q2spi_packet\n", __func__);
return;
}
q2spi = q2spi_pkt->q2spi;
if (!q2spi || !q2spi_pkt->xfer) {
pr_err("%s Err Invalid q2spi or xfer\n", __func__);
return;
}
xfer = q2spi_pkt->xfer;
Q2SPI_DEBUG(q2spi, "%s xfer->tx_len:%d cb_param_length:%d\n", __func__,
xfer->tx_len, cb_param->length);
@ -69,7 +83,7 @@ static void q2spi_tx_xfer_completion_event(struct msm_gpi_dma_async_tx_cb_param
Q2SPI_DEBUG(q2spi, "%s complete_tx_cb\n", __func__);
complete_all(&q2spi->tx_cb);
} else {
Q2SPI_ERROR(q2spi, "%s Err length miss-match\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Err length miss-match\n", __func__);
}
}
@ -111,11 +125,12 @@ static void q2spi_gsi_tx_callback(void *cb)
}
if (cb_param->status == MSM_GPI_TCE_UNEXP_ERR) {
Q2SPI_DEBUG(q2spi, "%s Unexpected CB status\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Unexpected CB status:0x%x\n", __func__, cb_param->status);
return;
}
if (cb_param->completion_code == MSM_GPI_TCE_UNEXP_ERR) {
Q2SPI_DEBUG(q2spi, "%s Unexpected GSI CB completion code\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Unexpected GSI CB completion code CB status:0x%x\n",
__func__, cb_param->status);
return;
} else if (cb_param->completion_code == MSM_GPI_TCE_EOT) {
Q2SPI_DEBUG(q2spi, "%s MSM_GPI_TCE_EOT\n", __func__);
@ -152,12 +167,13 @@ static void q2spi_gsi_rx_callback(void *cb)
}
if (cb_param->status == MSM_GPI_TCE_UNEXP_ERR) {
Q2SPI_ERROR(q2spi, "%s Err cb_status:%d\n", __func__, cb_param->status);
Q2SPI_DEBUG(q2spi, "%s Err cb_status:0x%x\n", __func__, cb_param->status);
return;
}
if (cb_param->completion_code == MSM_GPI_TCE_UNEXP_ERR) {
Q2SPI_ERROR(q2spi, "%s Err MSM_GPI_TCE_UNEXP_ERR\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Err MSM_GPI_TCE_UNEXP_ERR CB status:0x%x\n",
__func__, cb_param->status);
return;
} else if (cb_param->completion_code == MSM_GPI_TCE_EOT) {
Q2SPI_DEBUG(q2spi, "%s MSM_GPI_TCE_EOT\n", __func__);
@ -214,7 +230,7 @@ int q2spi_geni_gsi_setup(struct q2spi_geni *q2spi)
q2spi->gsi = gsi;
Q2SPI_DEBUG(q2spi, "%s gsi:%p\n", __func__, gsi);
if (gsi->chan_setup) {
Q2SPI_ERROR(q2spi, "%s Err GSI channel already configured\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Err GSI channel already configured\n", __func__);
return ret;
}
@ -324,7 +340,7 @@ static struct msm_gpi_tre *setup_cfg0_tre(struct q2spi_geni *q2spi)
Q2SPI_DEBUG(q2spi, "%s Start PID=%d\n", __func__, current->pid);
ret = get_q2spi_clk_cfg(q2spi->cur_speed_hz, q2spi, &idx, &div);
if (ret) {
Q2SPI_ERROR(q2spi, "%s Err setting clks:%d\n", __func__, ret);
Q2SPI_DEBUG(q2spi, "%s Err setting clks:%d\n", __func__, ret);
return ERR_PTR(ret);
}
@ -423,13 +439,19 @@ int check_gsi_transfer_completion_db_rx(struct q2spi_geni *q2spi)
xfer_timeout = XFER_TIMEOUT_OFFSET;
timeout = wait_for_completion_timeout(&q2spi->db_rx_cb, msecs_to_jiffies(xfer_timeout));
if (!timeout) {
Q2SPI_ERROR(q2spi, "%s Rx[%d] timeout%lu\n", __func__, i, timeout);
Q2SPI_DEBUG(q2spi, "%s Rx[%d] timeout%lu\n", __func__, i, timeout);
ret = -ETIMEDOUT;
goto err_gsi_geni_transfer;
} else {
Q2SPI_DEBUG(q2spi, "%s rx completed\n", __func__);
}
err_gsi_geni_transfer:
if (q2spi->gsi->qup_gsi_err) {
ret = -EIO;
Q2SPI_DEBUG(q2spi, "%s Err QUP GSI Error\n", __func__);
q2spi->gsi->qup_gsi_err = false;
q2spi->setup_config0 = false;
dmaengine_terminate_all(q2spi->gsi->tx_c);
}
return ret;
}
@ -445,7 +467,7 @@ int check_gsi_transfer_completion(struct q2spi_geni *q2spi)
timeout =
wait_for_completion_timeout(&q2spi->tx_cb, msecs_to_jiffies(xfer_timeout));
if (!timeout) {
Q2SPI_ERROR(q2spi, "%s PID:%d Tx[%d] timeout\n", __func__, current->pid, i);
Q2SPI_DEBUG(q2spi, "%s PID:%d Tx[%d] timeout\n", __func__, current->pid, i);
ret = -ETIMEDOUT;
goto err_gsi_geni_transfer;
} else {
@ -457,7 +479,7 @@ int check_gsi_transfer_completion(struct q2spi_geni *q2spi)
timeout =
wait_for_completion_timeout(&q2spi->rx_cb, msecs_to_jiffies(xfer_timeout));
if (!timeout) {
Q2SPI_ERROR(q2spi, "%s PID:%d Rx[%d] timeout\n", __func__, current->pid, i);
Q2SPI_DEBUG(q2spi, "%s PID:%d Rx[%d] timeout\n", __func__, current->pid, i);
ret = -ETIMEDOUT;
goto err_gsi_geni_transfer;
} else {
@ -467,7 +489,7 @@ int check_gsi_transfer_completion(struct q2spi_geni *q2spi)
err_gsi_geni_transfer:
if (q2spi->gsi->qup_gsi_err || !timeout) {
ret = -ETIMEDOUT;
Q2SPI_ERROR(q2spi, "%s Err QUP Gsi Error\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Err QUP Gsi Error\n", __func__);
q2spi->gsi->qup_gsi_err = false;
q2spi->setup_config0 = false;
dmaengine_terminate_all(q2spi->gsi->tx_c);
@ -506,6 +528,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
q2spi->gsi->num_tx_eot = 0;
q2spi->gsi->num_rx_eot = 0;
q2spi->gsi->qup_gsi_err = false;
q2spi->gsi->qup_gsi_global_err = false;
xfer_tx_sg = q2spi->gsi->tx_sg;
xfer_rx_sg = q2spi->gsi->rx_sg;
c0_tre = &q2spi->gsi->config0_tre;
@ -549,7 +572,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
tx_tre = &q2spi->gsi->tx_dma_tre;
tx_tre = setup_dma_tre(tx_tre, xfer->tx_dma, xfer->tx_len, q2spi, 1);
if (IS_ERR_OR_NULL(tx_tre)) {
Q2SPI_ERROR(q2spi, "%s Err setting up tx tre\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Err setting up tx tre\n", __func__);
return -EINVAL;
}
sg_set_buf(xfer_tx_sg++, tx_tre, sizeof(*tx_tre));
@ -558,7 +581,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
q2spi->gsi->tx_desc = dmaengine_prep_slave_sg(q2spi->gsi->tx_c, q2spi->gsi->tx_sg, tx_nent,
DMA_MEM_TO_DEV, flags);
if (IS_ERR_OR_NULL(q2spi->gsi->tx_desc)) {
Q2SPI_ERROR(q2spi, "%s Err setting up tx desc\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Err setting up tx desc\n", __func__);
return -EIO;
}
q2spi->gsi->tx_ev.init.cb_param = q2spi_pkt;
@ -568,7 +591,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
q2spi->gsi->tx_cookie = dmaengine_submit(q2spi->gsi->tx_desc);
Q2SPI_DEBUG(q2spi, "%s Tx cb_param:%p\n", __func__, q2spi->gsi->tx_desc->callback_param);
if (dma_submit_error(q2spi->gsi->tx_cookie)) {
Q2SPI_ERROR(q2spi, "%s Err dmaengine_submit failed (%d)\n",
Q2SPI_DEBUG(q2spi, "%s Err dmaengine_submit failed (%d)\n",
__func__, q2spi->gsi->tx_cookie);
dmaengine_terminate_all(q2spi->gsi->tx_c);
return -EINVAL;
@ -578,14 +601,14 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
rx_tre = &q2spi->gsi->rx_dma_tre;
rx_tre = setup_dma_tre(rx_tre, xfer->rx_dma, xfer->rx_len, q2spi, 1);
if (IS_ERR_OR_NULL(rx_tre)) {
Q2SPI_ERROR(q2spi, "%s Err setting up rx tre\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Err setting up rx tre\n", __func__);
return -EINVAL;
}
sg_set_buf(xfer_rx_sg, rx_tre, sizeof(*rx_tre));
q2spi->gsi->rx_desc = dmaengine_prep_slave_sg(q2spi->gsi->rx_c, q2spi->gsi->rx_sg,
rx_nent, DMA_DEV_TO_MEM, flags);
if (IS_ERR_OR_NULL(q2spi->gsi->rx_desc)) {
Q2SPI_ERROR(q2spi, "%s rx_desc fail\n", __func__);
Q2SPI_DEBUG(q2spi, "%s rx_desc fail\n", __func__);
return -EIO;
}
q2spi->gsi->rx_ev.init.cb_param = q2spi_pkt;
@ -597,7 +620,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
Q2SPI_DEBUG(q2spi, "%s Rx cb_param:%p\n", __func__,
q2spi->gsi->rx_desc->callback_param);
if (dma_submit_error(q2spi->gsi->rx_cookie)) {
Q2SPI_ERROR(q2spi, "%s Err dmaengine_submit failed (%d)\n",
Q2SPI_DEBUG(q2spi, "%s Err dmaengine_submit failed (%d)\n",
__func__, q2spi->gsi->rx_cookie);
dmaengine_terminate_all(q2spi->gsi->rx_c);
return -EINVAL;
@ -606,7 +629,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
rx_tre = &q2spi->gsi->rx_dma_tre;
rx_tre = setup_dma_tre(rx_tre, xfer->rx_dma, xfer->rx_len, q2spi, 1);
if (IS_ERR_OR_NULL(rx_tre)) {
Q2SPI_ERROR(q2spi, "%s Err setting up rx tre\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Err setting up rx tre\n", __func__);
return -EINVAL;
}
sg_set_buf(xfer_rx_sg, rx_tre, sizeof(*rx_tre));
@ -614,7 +637,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
q2spi->gsi->rx_sg,
rx_nent, DMA_DEV_TO_MEM, flags);
if (IS_ERR_OR_NULL(q2spi->gsi->db_rx_desc)) {
Q2SPI_ERROR(q2spi, "%s Err db_rx_desc fail\n", __func__);
Q2SPI_DEBUG(q2spi, "%s Err db_rx_desc fail\n", __func__);
return -EIO;
}
q2spi->gsi->db_rx_desc->callback = q2spi_gsi_rx_callback;
@ -625,7 +648,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
Q2SPI_DEBUG(q2spi, "%s DB cb_param:%p\n", __func__,
q2spi->gsi->db_rx_desc->callback_param);
if (dma_submit_error(q2spi->gsi->rx_cookie)) {
Q2SPI_ERROR(q2spi, "%s Err dmaengine_submit failed (%d)\n",
Q2SPI_DEBUG(q2spi, "%s Err dmaengine_submit failed (%d)\n",
__func__, q2spi->gsi->rx_cookie);
dmaengine_terminate_all(q2spi->gsi->rx_c);
return -EINVAL;
@ -633,7 +656,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
}
if (cmd & Q2SPI_RX_ONLY) {
Q2SPI_DEBUG(q2spi, "%s rx_c dma_async_issue_pending\n", __func__);
q2spi_dump_ipc(q2spi, q2spi->ipc, "GSI DMA-RX", (char *)xfer->rx_buf, tx_rx_len);
q2spi_dump_ipc(q2spi, "GSI DMA-RX", (char *)xfer->rx_buf, tx_rx_len);
if (q2spi_pkt->m_cmd_param == Q2SPI_RX_ONLY)
reinit_completion(&q2spi->db_rx_cb);
else
@ -642,8 +665,8 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
}
if (cmd & Q2SPI_TX_ONLY)
q2spi_dump_ipc(q2spi, q2spi->ipc, "GSI DMA TX", (char *)xfer->tx_buf,
Q2SPI_HEADER_LEN + tx_rx_len);
q2spi_dump_ipc(q2spi, "GSI DMA TX",
(char *)xfer->tx_buf, Q2SPI_HEADER_LEN + tx_rx_len);
Q2SPI_DEBUG(q2spi, "%s tx_c dma_async_issue_pending\n", __func__);
reinit_completion(&q2spi->tx_cb);
@ -672,10 +695,10 @@ void q2spi_gsi_ch_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb, void *
case MSM_GPI_QUP_PENDING_EVENT:
case MSM_GPI_QUP_EOT_DESC_MISMATCH:
case MSM_GPI_QUP_SW_ERROR:
Q2SPI_ERROR(q2spi, "%s cb_ev %d status %llu ts %llu count %llu\n",
__func__, cb->cb_event, cb->status,
Q2SPI_DEBUG(q2spi, "%s cb_ev %s status %llu ts %llu count %llu\n",
__func__, TO_GPI_CB_EVENT_STR(cb->cb_event), cb->status,
cb->timestamp, cb->count);
Q2SPI_ERROR(q2spi, "%s err_routine:%u err_type:%u err.code%u\n",
Q2SPI_DEBUG(q2spi, "%s err_routine:%u err_type:%u err.code%u\n",
__func__, cb->error_log.routine, cb->error_log.type,
cb->error_log.error_code);
q2spi->gsi->qup_gsi_err = true;
@ -683,8 +706,19 @@ void q2spi_gsi_ch_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb, void *
complete_all(&q2spi->rx_cb);
break;
case MSM_GPI_QUP_CR_HEADER:
/* Update last access time of a device for autosuspend */
pm_runtime_mark_last_busy(q2spi->dev);
q2spi_cr_hdr_event = &cb->q2spi_cr_header_event;
num_crs = q2spi_cr_hdr_event->byte0_len;
if (q2spi_cr_hdr_event->code == Q2SPI_CR_HEADER_LEN_ZERO ||
q2spi_cr_hdr_event->code == Q2SPI_CR_HEADER_INCORRECT ||
num_crs > MAX_RX_CRS) {
Q2SPI_DEBUG(q2spi, "%s Invalid num_crs:%d or Negative DB header code:%d\n",
__func__, num_crs, q2spi_cr_hdr_event->code);
q2spi->q2spi_cr_hdr_err = true;
break;
}
for (i = 0; i < num_crs; i++) {
if (q2spi_cr_hdr_event->cr_hdr[i] == CR_ADDR_LESS_RD) {
reinit_completion(&q2spi->sma_rd_comp);
@ -707,8 +741,9 @@ void q2spi_gsi_ch_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb, void *
break;
}
if (cb->cb_event == MSM_GPI_QUP_FW_ERROR) {
q2spi_geni_se_dump_regs(q2spi);
Q2SPI_ERROR(q2spi, "%s dump GSI regs\n", __func__);
}
if (cb->cb_event == MSM_GPI_QUP_ERROR)
q2spi->gsi->qup_gsi_global_err = true;
if (q2spi->gsi->qup_gsi_err)
Q2SPI_DEBUG(q2spi, "%s set qup_gsi_err\n", __func__);
}

View file

@ -50,6 +50,7 @@
* num_tx_eot: Represents number of TX End of Transfers
* num_rx_eot: Represents number of RX End of Transfers
* qup_gsi_err: flag to represent gsi error if any
* qup_gsi_global_err: flag to represent gsi global error
*/
struct q2spi_gsi {
struct dma_chan *tx_c;
@ -74,6 +75,7 @@ struct q2spi_gsi {
int num_tx_eot;
int num_rx_eot;
bool qup_gsi_err;
bool qup_gsi_global_err;
};
#endif /* __SPI_Q2SPI_GPI_H_ */

File diff suppressed because it is too large Load diff

View file

@ -11,13 +11,17 @@
#include <linux/ipc_logging.h>
#include <linux/kthread.h>
#include <linux/msm_gpi.h>
#include <linux/pm_runtime.h>
#include <linux/poll.h>
#include <linux/soc/qcom/geni-se.h>
#include <linux/qcom-geni-se-common.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <uapi/linux/q2spi/q2spi.h>
#include "q2spi-gsi.h"
#define GENI_SE_Q2SPI_PROTO (0xE)
#define DATA_WORD_LEN 4
#define SMA_BUF_SIZE (4096)
#define MAX_CR_SIZE 24 /* Max CR size is 24 bytes per CR */
@ -32,7 +36,7 @@
#define TIMEOUT_MSECONDS 10 /* 10 milliseconds */
#define RETRIES 1
#define Q2SPI_MAX_DATA_LEN 4096
#define Q2SPI_MAX_TX_RETRIES 5
#define Q2SPI_MAX_TX_RETRIES 3
/* Host commands */
#define HC_DB_REPORT_LEN_READ 1
#define HC_DB_REPORT_BODY_READ 2
@ -163,7 +167,14 @@
#define CR_EXTENSION_DATA_BYTES 5 /* 1 for EXTID + 4 Bytes for one 1DW */
#define Q2SPI_HRF_SLEEP_CMD 0x100
#define Q2SPI_AUTOSUSPEND_DELAY (XFER_TIMEOUT_OFFSET + 3000)
#define Q2SPI_AUTOSUSPEND_DELAY (XFER_TIMEOUT_OFFSET + 50)
#define Q2SPI_SLAVE_SLEEP_TIME_MSECS 100
#define Q2SPI_SOFT_RESET_CMD_BIT BIT(0)
#define Q2SPI_SLEEP_CMD_BIT BIT(1)
#define Q2SPI_CR_TRANSACTION_ERROR 1
#define PINCTRL_DEFAULT "default"
#define PINCTRL_ACTIVE "active"
#define PINCTRL_SLEEP "sleep"
@ -430,7 +441,6 @@ struct q2spi_dma_transfer {
* q2spi_chrdev: cdev structure
* @geni_se: stores info parsed from device tree
* @gsi: stores GSI structure information
* @qup_gsi_err: flahg to set incase of gsi errors
* @db_xfer: reference to q2spi_dma_transfer structure for doorbell
* @req: reference to q2spi request structure
* @c_req: reference to q2spi client request structure
@ -455,8 +465,9 @@ struct q2spi_dma_transfer {
* @tx_cb: completion for tx dma
* @rx_cb: completion for rx dma
* @db_rx_cb: completion for doobell rx dma
* @restart_handler: notifier callback for restart
* @wait_for_ext_cr: completion for extension cr
* @rx_avail: used to notify the client for avaialble rx data
* @rx_avail: used to notify the client for available rx data
* @tid_idr: tid id allocator
* @readq: waitqueue for rx data
* @hrf_flow: flag to indicate HRF flow
@ -480,9 +491,11 @@ struct q2spi_dma_transfer {
* @sma_wait: completion for SMA
* @ipc: pointer for ipc
* @q2spi_doorbell_work: work to queue for doorbell process
* @doorbell_wq: workqueue pointer fir doorbell
* @doorbell_wq: workqueue pointer for doorbell
* @q2spi_wakeup_work: work to queue for wakeup process
* @wakeup_wq: workqueue pointer for wakeup
* @q2spi_sleep_work: work to queue for client sleep
* @sleep_wq: workqueue pointer for client_sleep
* @hw_state_is_bad: used when HW is in un-recoverable state
* @max_dump_data_size: max size of data to be dumped as part of dump_ipc function
* @doorbell_pending: Set when independent doorbell CR received
@ -497,6 +510,12 @@ struct q2spi_dma_transfer {
* @doorbell_irq: doorbell irq
* @wake_clk_gpio: GPIO for clk pin
* @wake_mosi_gpio: GPIO for mosi pin
* @slave_sleep_timer: used for initiating sleep command to slave
* @slave_in_sleep: reflects sleep command sent to slave
* @sys_mem_read_in_progress: reflects system memory read request is in progress
* @q2spi_cr_txn_err: reflects Q2SPI_CR_TRANSACTION_ERROR in CR body
* @q2spi_sleep_cmd_enable: reflects start sending the sleep command to slave
* @q2spi_cr_hdr_err: reflects CR Header incorrect in CR Header
*/
struct q2spi_geni {
struct device *wrapper_dev;
@ -513,7 +532,6 @@ struct q2spi_geni {
struct q2spi_chrdev chrdev;
struct geni_se se;
struct q2spi_gsi *gsi;
bool qup_gsi_err;
struct q2spi_dma_transfer *db_xfer;
struct q2spi_request *req;
struct q2spi_client_request *c_req;
@ -545,6 +563,7 @@ struct q2spi_geni {
struct completion tx_cb;
struct completion rx_cb;
struct completion db_rx_cb;
struct notifier_block restart_handler;
struct completion wait_for_ext_cr;
atomic_t rx_avail;
struct idr tid_idr;
@ -576,6 +595,8 @@ struct q2spi_geni {
struct workqueue_struct *doorbell_wq;
struct work_struct q2spi_wakeup_work;
struct workqueue_struct *wakeup_wq;
struct work_struct q2spi_sleep_work;
struct workqueue_struct *sleep_wq;
bool doorbell_setup;
struct qup_q2spi_cr_header_event q2spi_cr_hdr_event;
wait_queue_head_t read_wq;
@ -595,6 +616,12 @@ struct q2spi_geni {
int doorbell_irq;
int wake_clk_gpio;
int wake_mosi_gpio;
struct timer_list slave_sleep_timer;
atomic_t slave_in_sleep;
bool sys_mem_read_in_progress;
bool q2spi_cr_txn_err;
bool q2spi_sleep_cmd_enable;
bool q2spi_cr_hdr_err;
};
/**
@ -703,7 +730,7 @@ struct q2spi_packet {
void q2spi_doorbell(struct q2spi_geni *q2spi, const struct qup_q2spi_cr_header_event *event);
void q2spi_gsi_ch_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb, void *ptr);
void q2spi_geni_se_dump_regs(struct q2spi_geni *q2spi);
void q2spi_dump_ipc(struct q2spi_geni *q2spi, void *ipc_ctx, char *prefix, char *str, int size);
void q2spi_dump_ipc(struct q2spi_geni *q2spi, char *prefix, char *str, int size);
void q2spi_trace_log(struct device *dev, const char *fmt, ...);
void dump_ipc(struct q2spi_geni *q2spi, void *ctx, char *prefix, char *str, int size);
void *q2spi_kzalloc(struct q2spi_geni *q2spi, int size, int line);
@ -719,8 +746,10 @@ void q2spi_dump_client_error_regs(struct q2spi_geni *q2spi);
int q2spi_geni_resources_on(struct q2spi_geni *q2spi);
void q2spi_geni_resources_off(struct q2spi_geni *q2spi);
int __q2spi_send_messages(struct q2spi_geni *q2spi, void *ptr);
int q2spi_wakeup_hw_through_gpio(struct q2spi_geni *q2spi);
int q2spi_wakeup_slave_through_gpio(struct q2spi_geni *q2spi);
int q2spi_process_hrf_flow_after_lra(struct q2spi_geni *q2spi, struct q2spi_packet *q2spi_pkt);
void q2spi_transfer_soft_reset(struct q2spi_geni *q2spi);
void q2spi_transfer_abort(struct q2spi_geni *q2spi);
int q2spi_put_slave_to_sleep(struct q2spi_geni *q2spi);
#endif /* _SPI_Q2SPI_MSM_H_ */

View file

@ -254,6 +254,12 @@ enum msm_gpi_ctrl_cmd {
MSM_GPI_DEEP_SLEEP_INIT,
};
enum Q2SPI_CR_HEADER_CODE {
Q2SPI_CR_CODE_SUCCESS = 0x1,
Q2SPI_CR_HEADER_LEN_ZERO = 0xB,
Q2SPI_CR_HEADER_INCORRECT = 0xC,
};
enum msm_gpi_cb_event {
/* These events are hardware generated events */
MSM_GPI_QUP_NOTIFY,