summaryrefslogtreecommitdiff
path: root/drivers/spi/spi-mtk-nor.c
diff options
context:
space:
mode:
authorChuanhong Guo <gch981213@gmail.com>2020-09-22 19:49:02 +0800
committerMark Brown <broonie@kernel.org>2020-09-25 21:40:20 +0100
commit4cafaddedb5fbef9531202ee547784409fd0de33 (patch)
tree05d0630df3338599fd36794f8df4039a98f3b575 /drivers/spi/spi-mtk-nor.c
parentf09a433b1e4057e6379b7e1207548fff30d5dca3 (diff)
spi: spi-mtk-nor: fix timeout calculation overflow
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: <stable@vger.kernel.org> Signed-off-by: Chuanhong Guo <gch981213@gmail.com> Link: https://lore.kernel.org/r/20200922114905.2942859-1-gch981213@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-mtk-nor.c')
-rw-r--r--drivers/spi/spi-mtk-nor.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
index 6e6ca2b8e6c8..62f5ff277988 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 > 0x400000)
+ op->data.nbytes = 0x400000;
+
if ((op->addr.val & MTK_NOR_DMA_ALIGN_MASK) ||
(op->data.nbytes < MTK_NOR_DMA_ALIGN))
op->data.nbytes = 1;