mirror of https://github.com/torvalds/linux.git
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:
commit
6dd13023ec
|
|
@ -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)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue