spi: rzv2h-rspi: Fix max_speed_hz and clock configuration issues

Prabhakar <prabhakar.csengg@gmail.com> says:

This patch series addresses three issues in the RZV2H RSPI driver:
1. The max_speed_hz field was advertising a prohibited bit rate, which
   could lead to incorrect behavior when userspace applications attempt
   to set the SPI clock speed.
2. The clock configuration logic allowed for an invalid combination of
   SPR=0 and BRDV=0, which is not supported by the hardware.
3. Simplified  the clock rate search function as min/max speed parameters
   are not needed.

Note, patches apply on top of next-20260409.
This commit is contained in:
Mark Brown 2026-04-10 13:20:01 +01:00
commit 6dd13023ec
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
1 changed files with 25 additions and 27 deletions

View File

@ -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 */
@ -77,6 +76,8 @@
#define RSPI_RESET_NUM 2
#define RSPI_MAX_SPEED_HZ 50000000
struct rzv2h_rspi_best_clock {
struct clk *clk;
unsigned long clk_rate;
@ -87,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;
@ -412,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;
@ -463,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;
/*
@ -473,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;
@ -511,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;
@ -533,7 +532,18 @@ 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--;
if (spr >= spr_min && spr <= spr_max)
/*
* 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 >= RSPI_SPBR_SPR_MIN && spr <= RSPI_SPBR_SPR_MAX)
goto clock_found;
}
@ -563,16 +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);
/*
* 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_SPBR_SPR_MAX, &best_clock);
rspi->info->find_pclk_rate(rspi->pclk, hz, &best_clock);
if (!best_clock.clk_rate)
return -EINVAL;
@ -771,13 +775,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)) {