summaryrefslogtreecommitdiff
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-mtk-nor.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
index 7a62b65bf72e..aad92a58c4b8 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
@@ -147,6 +150,15 @@ static inline int mtk_nor_cmd_exec(struct mtk_nor *sp, u32 cmd, ulong clk)
return ret;
}
+static void mtk_nor_reset(struct mtk_nor *sp)
+{
+ 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);
+}
+
static void mtk_nor_set_addr(struct mtk_nor *sp, const struct spi_mem_op *op)
{
u32 addr = op->addr.val;
@@ -609,7 +621,15 @@ 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 (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;
}
}