Message ID | 20221205082419.29170-1-bayi.cheng@mediatek.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v1] spi: spi-mtk-nor: Add recovery mechanism for dma read timeout | expand |
Il 05/12/22 09:24, Bayi Cheng ha scritto: > From: bayi cheng <bayi.cheng@mediatek.com> > > The state machine of MTK spi nor controller may be disturbed by some > glitch signals from the relevant BUS during dma read, Although the > possibility of causing the dma read to fail is next to nothing, > However, if error-handling is not implemented, which makes the feature > somewhat risky. > > Add an error-handling mechanism here, reset the state machine and > re-read the data when an error occurs. > > Signed-off-by: bayi cheng <bayi.cheng@mediatek.com> > --- > Change in v1: > -Reset the state machine when dma read fails and read again. > --- > --- > drivers/spi/spi-mtk-nor.c | 16 +++++++++++++++- > 1 file changed, 15 insertions(+), 1 deletion(-) > > diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c > index d167699a1a96..c77d79da9a4c 100644 > --- a/drivers/spi/spi-mtk-nor.c > +++ b/drivers/spi/spi-mtk-nor.c > @@ -80,6 +80,9 @@ > #define MTK_NOR_REG_DMA_FADR 0x71c > #define MTK_NOR_REG_DMA_DADR 0x720 > #define MTK_NOR_REG_DMA_END_DADR 0x724 > +#define MTK_NOR_REG_CG_DIS 0x728 > +#define MTK_NOR_SFC_SW_RST BIT(2) > + > #define MTK_NOR_REG_DMA_DADR_HB 0x738 > #define MTK_NOR_REG_DMA_END_DADR_HB 0x73c > > @@ -616,7 +619,18 @@ static int mtk_nor_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) > mtk_nor_set_addr(sp, op); > return mtk_nor_read_pio(sp, op); > } else { > - return mtk_nor_read_dma(sp, op); > + ret = mtk_nor_read_dma(sp, op); > + if (ret) { > + dev_err(sp->dev, "try to read again\n"); > + mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, 0, MTK_NOR_SFC_SW_RST); > + mb(); /* flush previous writes */ > + mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, MTK_NOR_SFC_SW_RST, 0); > + mb(); /* flush previous writes */ > + writel(MTK_NOR_ENABLE_SF_CMD, sp->base + MTK_NOR_REG_WP); From what I understand, you're introducing a way to perform a flush+reset on the controller. At this point, I'd put that in a separate function like `mtk_nor_reset()`, as to both increase readability and to possibly reuse it somewhere else in the future, if needed. So this would become... } else { ret = mtk_nor_read_dma(sp, op); if (unlikely(ret)) { /* Handle rare bus glitch */ mtk_nor_reset(sp); mtk_nor_setup_bus(sp, op); return mtk_nor_read_dma(sp, op); } return ret; } ...or something alike :-) Regards, Angelo
On Mon, 2022-12-05 at 15:01 +0100, AngeloGioacchino Del Regno wrote: > Il 05/12/22 09:24, Bayi Cheng ha scritto: > > From: bayi cheng <bayi.cheng@mediatek.com> > > > > The state machine of MTK spi nor controller may be disturbed by > > some > > glitch signals from the relevant BUS during dma read, Although the > > possibility of causing the dma read to fail is next to nothing, > > However, if error-handling is not implemented, which makes the > > feature > > somewhat risky. > > > > Add an error-handling mechanism here, reset the state machine and > > re-read the data when an error occurs. > > > > Signed-off-by: bayi cheng <bayi.cheng@mediatek.com> > > --- > > Change in v1: > > -Reset the state machine when dma read fails and read again. > > --- > > --- > > drivers/spi/spi-mtk-nor.c | 16 +++++++++++++++- > > 1 file changed, 15 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c > > index d167699a1a96..c77d79da9a4c 100644 > > --- a/drivers/spi/spi-mtk-nor.c > > +++ b/drivers/spi/spi-mtk-nor.c > > @@ -80,6 +80,9 @@ > > #define MTK_NOR_REG_DMA_FADR 0x71c > > #define MTK_NOR_REG_DMA_DADR 0x720 > > #define MTK_NOR_REG_DMA_END_DADR 0x724 > > +#define MTK_NOR_REG_CG_DIS 0x728 > > +#define MTK_NOR_SFC_SW_RST BIT(2) > > + > > #define MTK_NOR_REG_DMA_DADR_HB 0x738 > > #define MTK_NOR_REG_DMA_END_DADR_HB 0x73c > > > > @@ -616,7 +619,18 @@ static int mtk_nor_exec_op(struct spi_mem > > *mem, const struct spi_mem_op *op) > > mtk_nor_set_addr(sp, op); > > return mtk_nor_read_pio(sp, op); > > } else { > > - return mtk_nor_read_dma(sp, op); > > + ret = mtk_nor_read_dma(sp, op); > > + if (ret) { > > + dev_err(sp->dev, "try to read > > again\n"); > > + mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, 0, > > MTK_NOR_SFC_SW_RST); > > + mb(); /* flush previous writes */ > > + mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, > > MTK_NOR_SFC_SW_RST, 0); > > + mb(); /* flush previous writes */ > > + writel(MTK_NOR_ENABLE_SF_CMD, sp->base > > + MTK_NOR_REG_WP); > > From what I understand, you're introducing a way to perform a > flush+reset on > the controller. > > At this point, I'd put that in a separate function like > `mtk_nor_reset()`, as > to both increase readability and to possibly reuse it somewhere else > in the > future, if needed. > > So this would become... > > } else { > ret = mtk_nor_read_dma(sp, op); > if (unlikely(ret)) { > /* Handle rare bus glitch */ > mtk_nor_reset(sp); > mtk_nor_setup_bus(sp, op); > return mtk_nor_read_dma(sp, op); > } > return ret; > } > > ...or something alike :-) > > Regards, > Angelo > Hi Angelo, Thanks for your comments! I will fix it in the next patch. Regards, Bayi
diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index d167699a1a96..c77d79da9a4c 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -80,6 +80,9 @@ #define MTK_NOR_REG_DMA_FADR 0x71c #define MTK_NOR_REG_DMA_DADR 0x720 #define MTK_NOR_REG_DMA_END_DADR 0x724 +#define MTK_NOR_REG_CG_DIS 0x728 +#define MTK_NOR_SFC_SW_RST BIT(2) + #define MTK_NOR_REG_DMA_DADR_HB 0x738 #define MTK_NOR_REG_DMA_END_DADR_HB 0x73c @@ -616,7 +619,18 @@ static int mtk_nor_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) mtk_nor_set_addr(sp, op); return mtk_nor_read_pio(sp, op); } else { - return mtk_nor_read_dma(sp, op); + ret = mtk_nor_read_dma(sp, op); + if (ret) { + dev_err(sp->dev, "try to read again\n"); + mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, 0, MTK_NOR_SFC_SW_RST); + mb(); /* flush previous writes */ + mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, MTK_NOR_SFC_SW_RST, 0); + mb(); /* flush previous writes */ + writel(MTK_NOR_ENABLE_SF_CMD, sp->base + MTK_NOR_REG_WP); + mtk_nor_setup_bus(sp, op); + ret = mtk_nor_read_dma(sp, op); + } + return ret; } }