From 4e292cbf3890657db2f2692942cb0f168c80167e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 10 Apr 2026 09:05:15 +0100 Subject: [PATCH 1/3] spi: rzv2h-rspi: Fix max_speed_hz advertising prohibited bit rate On RZ/V2H(P), RZ/G3E and RZ/G3L, RSPI_n_TCLK is fixed at 200MHz. The max_speed_hz was computed using clk_round_rate(tclk, ULONG_MAX) with SPR=0 and BRDV=0, resulting in 100Mbps - the exact combination prohibited on these SoCs. This could cause the SPI framework to request a speed that rzv2h_rspi_find_rate_fixed() would skip, potentially leading to a clock selection failure. On RZ/T2H and RZ/N2H the max_speed_hz was correctly calculated as 50Mbps for both the variable PCLKSPIn and fixed PCLK clock sources. Since the maximum supported bit rate is 50Mbps across all supported SoC variants, replace the clk_round_rate() based calculation with a define RSPI_MAX_SPEED_HZ set to 50MHz and use it directly for max_speed_hz. Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260410080517.2405700-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- drivers/spi/spi-rzv2h-rspi.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-rzv2h-rspi.c b/drivers/spi/spi-rzv2h-rspi.c index 23f0e92ae208..15270f19c69c 100644 --- a/drivers/spi/spi-rzv2h-rspi.c +++ b/drivers/spi/spi-rzv2h-rspi.c @@ -77,6 +77,8 @@ #define RSPI_RESET_NUM 2 +#define RSPI_MAX_SPEED_HZ 50000000 + struct rzv2h_rspi_best_clock { struct clk *clk; unsigned long clk_rate; @@ -771,13 +773,7 @@ static int rzv2h_rspi_probe(struct platform_device *pdev) RSPI_SPBR_SPR_MAX, RSPI_SPCMD_BRDV_MAX); - tclk_rate = clk_round_rate(rspi->tclk, ULONG_MAX); - if (tclk_rate < 0) - return tclk_rate; - - controller->max_speed_hz = rzv2h_rspi_calc_bitrate(tclk_rate, - RSPI_SPBR_SPR_MIN, - RSPI_SPCMD_BRDV_MIN); + controller->max_speed_hz = RSPI_MAX_SPEED_HZ; controller->dma_tx = devm_dma_request_chan(dev, "tx"); if (IS_ERR(controller->dma_tx)) { From 0335767dd8e7ade8a8e3028d08c4621515d47388 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 10 Apr 2026 09:05:16 +0100 Subject: [PATCH 2/3] spi: rzv2h-rspi: Fix invalid SPR=0/BRDV=0 clock configuration The combination of SPR=0 and BRDV=0 results in the minimum division ratio of 2, producing the maximum possible bit rate for a given clock source. This combination is not supported in two cases: - On RZ/G3E, RZ/G3L, RZ/V2H(P) and RZ/V2N, RSPI_n_TCLK is fixed at 200MHz, which would yield 100Mbps. The next hardware manual update will explicitly state that since the maximum frequency of the RSPICKn clock signal is 50MHz, settings with N=0 and n=0 resulting in 100Mbps are prohibited. - On RZ/T2H and RZ/N2H, when PCLK (125MHz) is used as the clock source, SPR=0 and BRDV=0 is explicitly listed as unsupported in the hardware manual (Table 36.7). Skip the SPR=0/BRDV=0 combination in rzv2h_rspi_find_rate_fixed() to prevent the driver from selecting an invalid clock configuration on the affected SoCs. Additionally, remove the now redundant RSPI_SPBR_SPR_PCLK_MIN define which was previously set to 1 to work around the PCLK restriction, but was overly broad as it incorrectly blocked valid combinations such as SPR=0/BRDV=1 (31.25Mbps on PCLK=125MHz). Fixes: 8b61c8919dff ("spi: Add driver for the RZ/V2H(P) RSPI IP") Fixes: 1ce3e8adc7d0 ("spi: rzv2h-rspi: add support for using PCLK for transfer clock") Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260410080517.2405700-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- drivers/spi/spi-rzv2h-rspi.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-rzv2h-rspi.c b/drivers/spi/spi-rzv2h-rspi.c index 15270f19c69c..f62223e106c0 100644 --- a/drivers/spi/spi-rzv2h-rspi.c +++ b/drivers/spi/spi-rzv2h-rspi.c @@ -50,7 +50,6 @@ /* Register SPBR */ #define RSPI_SPBR_SPR_MIN 0 -#define RSPI_SPBR_SPR_PCLK_MIN 1 #define RSPI_SPBR_SPR_MAX 255 /* Register SPCMD */ @@ -535,6 +534,17 @@ static void rzv2h_rspi_find_rate_fixed(struct clk *clk, u32 hz, for (brdv = RSPI_SPCMD_BRDV_MIN; brdv <= RSPI_SPCMD_BRDV_MAX; brdv++) { spr = DIV_ROUND_UP(clk_rate, hz * (1 << (brdv + 1))); spr--; + /* + * Skip SPR=0 and BRDV=0 as it is not a valid combination: + * - On RZ/G3E, RZ/G3L, RZ/V2H(P) and RZ/V2N, RSPI_n_TCLK is + * fixed at 200MHz and SPR=0 and BRDV=0 results in the maximum + * bit rate of 100Mbps which is prohibited. + * - On RZ/T2H and RZ/N2H, when PCLK (125MHz) is used as + * the clock source, SPR=0 and BRDV=0 is explicitly listed + * as unsupported in the hardware manual (Table 36.7). + */ + if (!spr && !brdv) + continue; if (spr >= spr_min && spr <= spr_max) goto clock_found; } @@ -568,12 +578,8 @@ static u32 rzv2h_rspi_setup_clock(struct rzv2h_rspi_priv *rspi, u32 hz) rspi->info->find_tclk_rate(rspi->tclk, hz, RSPI_SPBR_SPR_MIN, RSPI_SPBR_SPR_MAX, &best_clock); - /* - * T2H and N2H can also use PCLK as a source, which is 125MHz, but not - * when both SPR and BRDV are 0. - */ if (best_clock.error && rspi->info->find_pclk_rate) - rspi->info->find_pclk_rate(rspi->pclk, hz, RSPI_SPBR_SPR_PCLK_MIN, + rspi->info->find_pclk_rate(rspi->pclk, hz, RSPI_SPBR_SPR_MIN, RSPI_SPBR_SPR_MAX, &best_clock); if (!best_clock.clk_rate) From c958bb67b2dfd87b09d725a60162d13674fc5fd9 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 10 Apr 2026 09:05:17 +0100 Subject: [PATCH 3/3] spi: rzv2h-rspi: Simplify clock rate search function signatures The spr_min and spr_max parameters passed to rzv2h_rspi_find_rate_variable() and rzv2h_rspi_find_rate_fixed() were always called with RSPI_SPBR_SPR_MIN and RSPI_SPBR_SPR_MAX respectively. There is no need to pass these as parameters since the valid SPR range is fixed by the hardware. Signed-off-by: Lad Prabhakar Link: https://patch.msgid.link/20260410080517.2405700-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Mark Brown --- drivers/spi/spi-rzv2h-rspi.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-rzv2h-rspi.c b/drivers/spi/spi-rzv2h-rspi.c index f62223e106c0..56f2689bb048 100644 --- a/drivers/spi/spi-rzv2h-rspi.c +++ b/drivers/spi/spi-rzv2h-rspi.c @@ -88,9 +88,9 @@ struct rzv2h_rspi_best_clock { }; struct rzv2h_rspi_info { - void (*find_tclk_rate)(struct clk *clk, u32 hz, u8 spr_min, u8 spr_max, + void (*find_tclk_rate)(struct clk *clk, u32 hz, struct rzv2h_rspi_best_clock *best_clk); - void (*find_pclk_rate)(struct clk *clk, u32 hz, u8 spr_low, u8 spr_high, + void (*find_pclk_rate)(struct clk *clk, u32 hz, struct rzv2h_rspi_best_clock *best_clk); const char *tclk_name; unsigned int fifo_size; @@ -413,7 +413,6 @@ static inline u32 rzv2h_rspi_calc_bitrate(unsigned long tclk_rate, u8 spr, } static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, - u8 spr_min, u8 spr_max, struct rzv2h_rspi_best_clock *best) { long clk_rate, clk_min_rate, clk_max_rate; @@ -464,7 +463,7 @@ static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, * minimum SPR that is in the valid range. */ min_rate_spr = DIV_ROUND_CLOSEST(clk_min_rate, rate_div) - 1; - if (min_rate_spr > spr_max) + if (min_rate_spr > RSPI_SPBR_SPR_MAX) continue; /* @@ -474,14 +473,14 @@ static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, * maximum SPR that is in the valid range. */ max_rate_spr = DIV_ROUND_CLOSEST(clk_max_rate, rate_div) - 1; - if (max_rate_spr < spr_min) + if (max_rate_spr < RSPI_SPBR_SPR_MIN) break; - if (min_rate_spr < spr_min) - min_rate_spr = spr_min; + if (min_rate_spr < RSPI_SPBR_SPR_MIN) + min_rate_spr = RSPI_SPBR_SPR_MIN; - if (max_rate_spr > spr_max) - max_rate_spr = spr_max; + if (max_rate_spr > RSPI_SPBR_SPR_MAX) + max_rate_spr = RSPI_SPBR_SPR_MAX; for (spr = min_rate_spr; spr <= max_rate_spr; spr++) { clk_rate = (spr + 1) * rate_div; @@ -512,7 +511,6 @@ static void rzv2h_rspi_find_rate_variable(struct clk *clk, u32 hz, } static void rzv2h_rspi_find_rate_fixed(struct clk *clk, u32 hz, - u8 spr_min, u8 spr_max, struct rzv2h_rspi_best_clock *best) { unsigned long clk_rate; @@ -545,7 +543,7 @@ static void rzv2h_rspi_find_rate_fixed(struct clk *clk, u32 hz, */ if (!spr && !brdv) continue; - if (spr >= spr_min && spr <= spr_max) + if (spr >= RSPI_SPBR_SPR_MIN && spr <= RSPI_SPBR_SPR_MAX) goto clock_found; } @@ -575,12 +573,10 @@ static u32 rzv2h_rspi_setup_clock(struct rzv2h_rspi_priv *rspi, u32 hz) }; int ret; - rspi->info->find_tclk_rate(rspi->tclk, hz, RSPI_SPBR_SPR_MIN, - RSPI_SPBR_SPR_MAX, &best_clock); + rspi->info->find_tclk_rate(rspi->tclk, hz, &best_clock); if (best_clock.error && rspi->info->find_pclk_rate) - rspi->info->find_pclk_rate(rspi->pclk, hz, RSPI_SPBR_SPR_MIN, - RSPI_SPBR_SPR_MAX, &best_clock); + rspi->info->find_pclk_rate(rspi->pclk, hz, &best_clock); if (!best_clock.clk_rate) return -EINVAL;