* [PATCH 1/5] spi: sifive: fix division by zero in clock divisor calculation
2026-11-06 15:47 [PATCH 0/5] spi: fix division by zero with a zero transfer speed shao.mingyin
@ 2026-11-06 15:47 ` shao.mingyin
2026-11-06 15:47 ` [PATCH 2/5] spi: bcm63xx-hsspi: fix division by zero for devices without a max speed shao.mingyin
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: shao.mingyin @ 2026-11-06 15:47 UTC (permalink / raw)
To: broonie, linux-spi
Cc: linux-kernel, linux-riscv, pjw, samuel.holland, william.zhang,
kursad.oney, jonas.gorski, bcm-kernel-feedback-list, anand.gore,
florian.fainelli, rafal, linux-arm-kernel, sven, j, neal, asahi,
ryan.wanner, nicolas.ferre, alexandre.belloni, claudiu.beznea
From: Shao Mingyin <shao.mingyin@zte.com.cn>
A SPI device without a valid speed (no spi-max-frequency property, or
created through the spidev sysfs new_device interface without a speed)
gets max_speed_hz == 0. spi_setup() only clamps that to the controller
limit when host->max_speed_hz is set, and this driver does not set it, so
the zero reaches sifive_spi_prep_transfer() and DIV_ROUND_UP() divides
by it.
On RISC-V the divide instruction returns all ones instead of trapping,
so the controller is programmed with a bogus clock divider rather than
the rate the device asked for.
Clamp the divisor to 1 Hz so the divider calculation is well defined.
Fixes: 484a9a68d669 ("spi: sifive: Add driver for the SiFive SPI controller")
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c
index cee4d92e46f4..9c1f674f5921 100644
--- a/drivers/spi/spi-sifive.c
+++ b/drivers/spi/spi-sifive.c
@@ -168,10 +168,14 @@ sifive_spi_prep_transfer(struct sifive_spi *spi, struct spi_device *device,
struct spi_transfer *t)
{
u32 cr;
+ u32 speed_hz;
unsigned int mode;
+ /* A device with max_speed_hz == 0 must not divide by zero */
+ speed_hz = max_t(u32, t->speed_hz, 1);
+
/* Calculate and program the clock rate */
- cr = DIV_ROUND_UP(clk_get_rate(spi->clk) >> 1, t->speed_hz) - 1;
+ cr = DIV_ROUND_UP(clk_get_rate(spi->clk) >> 1, speed_hz) - 1;
cr &= SIFIVE_SPI_SCKDIV_DIV_MASK;
sifive_spi_write(spi, SIFIVE_SPI_REG_SCKDIV, cr);
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 2/5] spi: bcm63xx-hsspi: fix division by zero for devices without a max speed
2026-11-06 15:47 [PATCH 0/5] spi: fix division by zero with a zero transfer speed shao.mingyin
2026-11-06 15:47 ` [PATCH 1/5] spi: sifive: fix division by zero in clock divisor calculation shao.mingyin
@ 2026-11-06 15:47 ` shao.mingyin
2026-11-06 15:48 ` [PATCH 3/5] spi: bcmbca-hsspi: " shao.mingyin
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: shao.mingyin @ 2026-11-06 15:47 UTC (permalink / raw)
To: broonie, linux-spi
Cc: linux-kernel, linux-riscv, pjw, samuel.holland, william.zhang,
kursad.oney, jonas.gorski, bcm-kernel-feedback-list, anand.gore,
florian.fainelli, rafal, linux-arm-kernel, sven, j, neal, asahi,
ryan.wanner, nicolas.ferre, alexandre.belloni, claudiu.beznea
From: Shao Mingyin <shao.mingyin@zte.com.cn>
A SPI device whose max_speed_hz is zero (no spi-max-frequency property,
or created through the spidev sysfs new_device interface without a
speed) leaves the transfer speed at zero. spi_setup() would only clamp
it if host->max_speed_hz was set, which this driver does not do, so
bcm63xx_hsspi_set_clk() divides by zero in DIV_ROUND_UP().
The division does not trap on MIPS or arm64. The quotient is undefined
or zero, so the clock control register is programmed with a meaningless
value.
Clamp the requested rate to 1 Hz before computing the divider.
Fixes: 142168eba9dc ("spi: bcm63xx-hsspi: add bcm63xx HSSPI driver")
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
index abfbf97faf7b..319951fba387 100644
--- a/drivers/spi/spi-bcm63xx-hsspi.c
+++ b/drivers/spi/spi-bcm63xx-hsspi.c
@@ -469,6 +469,9 @@ static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
unsigned int profile = spi_get_chipselect(spi, 0);
u32 reg;
+ /* A device with max_speed_hz == 0 must not divide by zero */
+ hz = max_t(int, hz, 1);
+
reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
__raw_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile));
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 3/5] spi: bcmbca-hsspi: fix division by zero for devices without a max speed
2026-11-06 15:47 [PATCH 0/5] spi: fix division by zero with a zero transfer speed shao.mingyin
2026-11-06 15:47 ` [PATCH 1/5] spi: sifive: fix division by zero in clock divisor calculation shao.mingyin
2026-11-06 15:47 ` [PATCH 2/5] spi: bcm63xx-hsspi: fix division by zero for devices without a max speed shao.mingyin
@ 2026-11-06 15:48 ` shao.mingyin
2026-11-06 15:48 ` [PATCH 4/5] spi: apple: fix division by zero in clock divisor calculation shao.mingyin
2026-11-06 15:48 ` [PATCH 5/5] spi: atmel: fix division by zero when transfer speed is zero shao.mingyin
4 siblings, 0 replies; 6+ messages in thread
From: shao.mingyin @ 2026-11-06 15:48 UTC (permalink / raw)
To: broonie, linux-spi
Cc: linux-kernel, linux-riscv, pjw, samuel.holland, william.zhang,
kursad.oney, jonas.gorski, bcm-kernel-feedback-list, anand.gore,
florian.fainelli, rafal, linux-arm-kernel, sven, j, neal, asahi,
ryan.wanner, nicolas.ferre, alexandre.belloni, claudiu.beznea
From: Shao Mingyin <shao.mingyin@zte.com.cn>
A SPI device whose max_speed_hz is zero (no spi-max-frequency property,
or created through the spidev sysfs new_device interface without a
speed) leaves the transfer speed at zero. spi_setup() would only clamp
it if host->max_speed_hz was set, which this driver does not do, so
bcmbca_hsspi_set_clk() divides by zero in DIV_ROUND_UP().
On arm64 the division returns zero instead of trapping: the inner
DIV_ROUND_UP() yields zero, which is then used as the divisor of the
outer one, so the clock control register is programmed with a
meaningless value.
Clamp the requested rate to 1 Hz before computing the divider.
Fixes: a38a2233f23b ("spi: bcmbca-hsspi: Add driver for newer HSSPI controller")
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c
index 8c01475886e8..84015110557a 100644
--- a/drivers/spi/spi-bcmbca-hsspi.c
+++ b/drivers/spi/spi-bcmbca-hsspi.c
@@ -196,6 +196,9 @@ static void bcmbca_hsspi_set_clk(struct bcmbca_hsspi *bs,
unsigned int profile = spi_get_chipselect(spi, 0);
u32 reg;
+ /* A device with max_speed_hz == 0 must not divide by zero */
+ hz = max_t(int, hz, 1);
+
reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
__raw_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile));
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 4/5] spi: apple: fix division by zero in clock divisor calculation
2026-11-06 15:47 [PATCH 0/5] spi: fix division by zero with a zero transfer speed shao.mingyin
` (2 preceding siblings ...)
2026-11-06 15:48 ` [PATCH 3/5] spi: bcmbca-hsspi: " shao.mingyin
@ 2026-11-06 15:48 ` shao.mingyin
2026-11-06 15:48 ` [PATCH 5/5] spi: atmel: fix division by zero when transfer speed is zero shao.mingyin
4 siblings, 0 replies; 6+ messages in thread
From: shao.mingyin @ 2026-11-06 15:48 UTC (permalink / raw)
To: broonie, linux-spi
Cc: linux-kernel, linux-riscv, pjw, samuel.holland, william.zhang,
kursad.oney, jonas.gorski, bcm-kernel-feedback-list, anand.gore,
florian.fainelli, rafal, linux-arm-kernel, sven, j, neal, asahi,
ryan.wanner, nicolas.ferre, alexandre.belloni, claudiu.beznea
From: Shao Mingyin <shao.mingyin@zte.com.cn>
A SPI device without a valid speed (no spi-max-frequency property, or
created through the spidev sysfs new_device interface without a speed)
gets max_speed_hz == 0. spi_setup() only clamps that to the controller
limit when host->max_speed_hz is set, and this driver does not set it, so
the zero reaches apple_spi_prep_transfer() and DIV_ROUND_UP() divides by
it.
On arm64 the divide instruction returns zero instead of trapping, so
CLKDIV is programmed as zero. That selects the fastest clock and can
exceed the rate the attached device supports.
Clamp the divisor to 1 Hz so the divider calculation is well defined.
Fixes: c36212b2610d ("spi: apple: Add driver for Apple SPI controller")
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
diff --git a/drivers/spi/spi-apple.c b/drivers/spi/spi-apple.c
index 61eefb08d2a7..8dbf05936db1 100644
--- a/drivers/spi/spi-apple.c
+++ b/drivers/spi/spi-apple.c
@@ -196,9 +196,13 @@ static void apple_spi_set_cs(struct spi_device *device, bool is_high)
static bool apple_spi_prep_transfer(struct apple_spi *spi, struct spi_transfer *t)
{
u32 cr, fifo_threshold;
+ u32 speed_hz;
+
+ /* A device with max_speed_hz == 0 must not divide by zero */
+ speed_hz = max_t(u32, t->speed_hz, 1);
/* Calculate and program the clock rate */
- cr = DIV_ROUND_UP(clk_get_rate(spi->clk), t->speed_hz);
+ cr = DIV_ROUND_UP(clk_get_rate(spi->clk), speed_hz);
reg_write(spi, APPLE_SPI_CLKDIV, min_t(u32, cr, APPLE_SPI_CLKDIV_MAX));
/* Update bits per word */
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 5/5] spi: atmel: fix division by zero when transfer speed is zero
2026-11-06 15:47 [PATCH 0/5] spi: fix division by zero with a zero transfer speed shao.mingyin
` (3 preceding siblings ...)
2026-11-06 15:48 ` [PATCH 4/5] spi: apple: fix division by zero in clock divisor calculation shao.mingyin
@ 2026-11-06 15:48 ` shao.mingyin
4 siblings, 0 replies; 6+ messages in thread
From: shao.mingyin @ 2026-11-06 15:48 UTC (permalink / raw)
To: broonie, linux-spi
Cc: linux-kernel, linux-riscv, pjw, samuel.holland, william.zhang,
kursad.oney, jonas.gorski, bcm-kernel-feedback-list, anand.gore,
florian.fainelli, rafal, linux-arm-kernel, sven, j, neal, asahi,
ryan.wanner, nicolas.ferre, alexandre.belloni, claudiu.beznea
From: Shao Mingyin <shao.mingyin@zte.com.cn>
atmel_spi_one_transfer() calls atmel_spi_set_xfer_speed() for every
transfer. A device whose max_speed_hz is zero (no spi-max-frequency
property, or created through the spidev sysfs new_device interface
without a speed) leaves the transfer speed at zero, and the divider
calculation divides by it. spi_setup() would only clamp the speed if
host->max_speed_hz was set, which this driver does not do.
On cores without a hardware divider this reports "Division by zero in
kernel" and dumps a stack trace, and on cores with one the quotient is
silently zero; in both cases the existing "too high" check then rejects
the transfer.
Clamp the divisor to 1 Hz so the zero never reaches the division.
Fixes: d3b72c7e6bf3 ("spi: atmel: add support for changing message transfer speed")
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index ffc896e4621a..deebf7afabbc 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -922,8 +922,9 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
/*
* Calculate the lowest divider that satisfies the
* constraint, assuming div32/fdiv/mbz == 0.
+ * A device with max_speed_hz == 0 must not divide by zero.
*/
- scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);
+ scbr = DIV_ROUND_UP(bus_hz, max_t(u32, xfer->speed_hz, 1));
/*
* If the resulting divider doesn't fit into the
^ permalink raw reply [flat|nested] 6+ messages in thread