Skip to content

Commit 6faf7f6

Browse files
Mukesh Kumar Savaliyamukesh-savaliya
authored andcommitted
FROMLIST: i2c: i2c-qcom-geni: Parse Error correctly in i2c GSI mode
I2C driver currently reports "DMA txn failed" error even though it's NACK OR BUS_PROTO OR ARB_LOST. Detect NACK error when no device ACKs on the bus instead of generic transfer failure which doesn't give any specific clue. Make Changes inside i2c driver callback handler function i2c_gpi_cb_result() to parse these errors and make sure GSI driver stores the error status during error interrupt. Co-developed-by: Viken Dadhaniya <quic_vdadhani@quicinc.com> Signed-off-by: Viken Dadhaniya <quic_vdadhani@quicinc.com> Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy@quicinc.com> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
1 parent ed0f1f8 commit 6faf7f6

3 files changed

Lines changed: 37 additions & 5 deletions

File tree

drivers/dma/qcom/gpi.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,17 @@ static void gpi_process_xfer_compl_event(struct gchan *gchan,
10721072
dev_dbg(gpii->gpi_dev->dev, "Residue %d\n", result.residue);
10731073

10741074
dma_cookie_complete(&vd->tx);
1075-
dmaengine_desc_get_callback_invoke(&vd->tx, &result);
1075+
if (gchan->protocol == QCOM_GPI_I2C) {
1076+
struct dmaengine_desc_callback cb;
1077+
struct gpi_i2c_result *i2c;
1078+
1079+
dmaengine_desc_get_callback(&vd->tx, &cb);
1080+
i2c = cb.callback_param;
1081+
i2c->status = compl_event->status;
1082+
dmaengine_desc_callback_invoke(&cb, &result);
1083+
} else {
1084+
dmaengine_desc_get_callback_invoke(&vd->tx, &result);
1085+
}
10761086

10771087
gpi_free_desc:
10781088
spin_lock_irqsave(&gchan->vc.lock, flags);

drivers/i2c/busses/i2c-qcom-geni.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
33

44
#include <linux/acpi.h>
5+
#include <linux/bitfield.h>
56
#include <linux/clk.h>
67
#include <linux/dmaengine.h>
78
#include <linux/dma-mapping.h>
@@ -67,6 +68,7 @@ enum geni_i2c_err_code {
6768
GENI_TIMEOUT,
6869
};
6970

71+
#define I2C_DMA_TX_IRQ_MASK GENMASK(12, 5)
7072
#define DM_I2C_CB_ERR ((BIT(NACK) | BIT(BUS_PROTO) | BIT(ARB_LOST)) \
7173
<< 5)
7274

@@ -100,6 +102,7 @@ struct geni_i2c_dev {
100102
struct dma_chan *rx_c;
101103
bool gpi_mode;
102104
bool abort_done;
105+
struct gpi_i2c_result i2c_result;
103106
};
104107

105108
struct geni_i2c_desc {
@@ -499,9 +502,18 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
499502

500503
static void i2c_gpi_cb_result(void *cb, const struct dmaengine_result *result)
501504
{
502-
struct geni_i2c_dev *gi2c = cb;
503-
504-
if (result->result != DMA_TRANS_NOERROR) {
505+
struct gpi_i2c_result *i2c_res = cb;
506+
struct geni_i2c_dev *gi2c = container_of(i2c_res, struct geni_i2c_dev, i2c_result);
507+
u32 status;
508+
509+
status = FIELD_GET(I2C_DMA_TX_IRQ_MASK, i2c_res->status);
510+
if (status == BIT(NACK)) {
511+
geni_i2c_err(gi2c, NACK);
512+
} else if (status == BIT(BUS_PROTO)) {
513+
geni_i2c_err(gi2c, BUS_PROTO);
514+
} else if (status == BIT(ARB_LOST)) {
515+
geni_i2c_err(gi2c, ARB_LOST);
516+
} else if (result->result != DMA_TRANS_NOERROR) {
505517
dev_err(gi2c->se.dev, "DMA txn failed:%d\n", result->result);
506518
gi2c->err = -EIO;
507519
} else if (result->residue) {
@@ -583,7 +595,7 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
583595
}
584596

585597
desc->callback_result = i2c_gpi_cb_result;
586-
desc->callback_param = gi2c;
598+
desc->callback_param = &gi2c->i2c_result;
587599

588600
dmaengine_submit(desc);
589601
*buf = dma_buf;

include/linux/dma/qcom-gpi-dma.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,14 @@ struct gpi_i2c_config {
8080
bool multi_msg;
8181
};
8282

83+
/**
84+
* struct gpi_i2c_result - i2c transfer status result in GSI mode
85+
*
86+
* @status: store txfer status value as part of callback
87+
*
88+
*/
89+
struct gpi_i2c_result {
90+
u32 status;
91+
};
92+
8393
#endif /* QCOM_GPI_DMA_H */

0 commit comments

Comments
 (0)