spi: rzv2h-rspi: make transfer clock rate finding chip-specific

The Renesas RZ/T2H (R9A09G077) and RZ/N2H (R9A09G087) SoCs have a more
complicated clocking setup for the SPI transfer clock than RZ/V2H, as
the clock from which it is generated supports multiple dividers.

To prepare for adding support for these SoCs, split out the logic for
finding the SPR and BRDV for a fixed clock into
rzv2h_rspi_find_rate_fixed(), and add and use a .find_tclk_rate()
callback into the chip-specific structure.

Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
Link: https://patch.msgid.link/20251119161434.595677-7-cosmin-gabriel.tanislav.xa@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Cosmin Tanislav 2025-11-19 18:14:27 +02:00 committed by Mark Brown
parent 8878249320
commit 77d931584d
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -67,7 +67,18 @@
#define RSPI_RESET_NUM 2
struct rzv2h_rspi_best_clock {
struct clk *clk;
unsigned long clk_rate;
unsigned long error;
u32 actual_hz;
u8 brdv;
u8 spr;
};
struct rzv2h_rspi_info {
void (*find_tclk_rate)(struct clk *clk, u32 hz, u8 spr_min, u8 spr_max,
struct rzv2h_rspi_best_clock *best_clk);
const char *tclk_name;
unsigned int fifo_size;
unsigned int num_clks;
@ -240,9 +251,13 @@ static inline u32 rzv2h_rspi_calc_bitrate(unsigned long tclk_rate, u8 spr,
return DIV_ROUND_UP(tclk_rate, (2 * (spr + 1) * (1 << brdv)));
}
static u32 rzv2h_rspi_setup_clock(struct rzv2h_rspi_priv *rspi, 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 tclk_rate;
unsigned long clk_rate;
unsigned long error;
u32 actual_hz;
int spr;
u8 brdv;
@ -255,21 +270,49 @@ static u32 rzv2h_rspi_setup_clock(struct rzv2h_rspi_priv *rspi, u32 hz)
* * n = SPR - is RSPI_SPBR.SPR (from 0 to 255)
* * N = BRDV - is RSPI_SPCMD.BRDV (from 0 to 3)
*/
tclk_rate = clk_get_rate(rspi->tclk);
clk_rate = clk_get_rate(clk);
for (brdv = RSPI_SPCMD_BRDV_MIN; brdv <= RSPI_SPCMD_BRDV_MAX; brdv++) {
spr = DIV_ROUND_UP(tclk_rate, hz * (1 << (brdv + 1)));
spr = DIV_ROUND_UP(clk_rate, hz * (1 << (brdv + 1)));
spr--;
if (spr >= RSPI_SPBR_SPR_MIN && spr <= RSPI_SPBR_SPR_MAX)
if (spr >= spr_min && spr <= spr_max)
goto clock_found;
}
return 0;
return;
clock_found:
rspi->spr = spr;
rspi->brdv = brdv;
actual_hz = rzv2h_rspi_calc_bitrate(clk_rate, spr, brdv);
error = abs((long)hz - (long)actual_hz);
return rzv2h_rspi_calc_bitrate(tclk_rate, spr, brdv);
if (error >= best->error)
return;
*best = (struct rzv2h_rspi_best_clock) {
.clk = clk,
.clk_rate = clk_rate,
.error = error,
.actual_hz = actual_hz,
.brdv = brdv,
.spr = spr,
};
}
static u32 rzv2h_rspi_setup_clock(struct rzv2h_rspi_priv *rspi, u32 hz)
{
struct rzv2h_rspi_best_clock best_clock = {
.error = ULONG_MAX,
};
rspi->info->find_tclk_rate(rspi->tclk, hz, RSPI_SPBR_SPR_MIN,
RSPI_SPBR_SPR_MAX, &best_clock);
if (!best_clock.clk_rate)
return -EINVAL;
rspi->spr = best_clock.spr;
rspi->brdv = best_clock.brdv;
return best_clock.actual_hz;
}
static int rzv2h_rspi_prepare_message(struct spi_controller *ctlr,
@ -463,6 +506,7 @@ static void rzv2h_rspi_remove(struct platform_device *pdev)
}
static const struct rzv2h_rspi_info rzv2h_info = {
.find_tclk_rate = rzv2h_rspi_find_rate_fixed,
.tclk_name = "tclk",
.fifo_size = 16,
.num_clks = 3,