CLK_TO_US macro is used to calculate potential transfer time for various
timeout handling. However it overflows on transfer bigger than 512 bytes
because it first did (len * 8 * 1000000).
This controller typically operates at 45MHz. This patch did 2 things:
1. calculate clock / 1000000 first
2. add a 4M transfer size cap so that the final timeout in DMA reading
   doesn't overflow

Fixes: 881d1ee9fe81f ("spi: add support for mediatek spi-nor controller")
Cc: <sta...@vger.kernel.org>
Signed-off-by: Chuanhong Guo <gch981...@gmail.com>
---
 drivers/spi/spi-mtk-nor.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
index 6e6ca2b8e6c82..619313db42c0e 100644
--- a/drivers/spi/spi-mtk-nor.c
+++ b/drivers/spi/spi-mtk-nor.c
@@ -89,7 +89,7 @@
 // Buffered page program can do one 128-byte transfer
 #define MTK_NOR_PP_SIZE                        128
 
-#define CLK_TO_US(sp, clkcnt)          ((clkcnt) * 1000000 / sp->spi_freq)
+#define CLK_TO_US(sp, clkcnt)          DIV_ROUND_UP(clkcnt, sp->spi_freq / 
1000000)
 
 struct mtk_nor {
        struct spi_controller *ctlr;
@@ -177,6 +177,10 @@ static int mtk_nor_adjust_op_size(struct spi_mem *mem, 
struct spi_mem_op *op)
        if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) {
                if ((op->data.dir == SPI_MEM_DATA_IN) &&
                    mtk_nor_match_read(op)) {
+                       // limit size to prevent timeout calculation overflow
+                       if (op->data.nbytes > 0x2000000)
+                               op->data.nbytes = 0x2000000;
+
                        if ((op->addr.val & MTK_NOR_DMA_ALIGN_MASK) ||
                            (op->data.nbytes < MTK_NOR_DMA_ALIGN))
                                op->data.nbytes = 1;
-- 
2.26.2

Reply via email to