Hi Geert, On Wed, Jun 18, 2025 at 3:03 PM Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> wrote: > > Hi Prabhakar, > > On Wed, 18 Jun 2025 at 15:41, Lad, Prabhakar <prabhakar.csengg@xxxxxxxxx> wrote: > > On Wed, Jun 18, 2025 at 1:59 PM Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> wrote: > > > On Wed, 18 Jun 2025 at 14:06, Lad, Prabhakar <prabhakar.csengg@xxxxxxxxx> wrote: > > > > On Wed, Jun 18, 2025 at 8:03 AM Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> wrote: > > > > > On Tue, 17 Jun 2025 at 23:05, Lad, Prabhakar <prabhakar.csengg@xxxxxxxxx> wrote: > > > > > > On Mon, Mar 31, 2025 at 7:25 PM Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> wrote: > > > > > > > On Mon, 31 Mar 2025 at 17:33, Biju Das <biju.das.jz@xxxxxxxxxxxxxx> wrote: > > > > > > > > > From: Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> > > > > > > > > > On Mon, 31 Mar 2025 at 16:34, Biju Das <biju.das.jz@xxxxxxxxxxxxxx> wrote: > > > > > > > > > > > From: Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> On Mon, 31 Mar 2025 > > > > > > > > > > > at 15:54, Biju Das <biju.das.jz@xxxxxxxxxxxxxx> wrote: > > > > > > > > > > > > > From: Biju Das <biju.das.jz@xxxxxxxxxxxxxx> Document support for > > > > > > > > > > > > > the Expanded Serial Peripheral Interface (xSPI) Controller in > > > > > > > > > > > > > the Renesas RZ/G3E > > > > > > > > > > > > > (R9A09G047) SoC. > > > > > > > > > > > > > > > > > > > > > > > > > > Reviewed-by: Rob Herring (Arm) <robh@xxxxxxxxxx> > > > > > > > > > > > > > Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx> > > > > > > > > > > > > > > > > > > > > > > > > --- /dev/null > > > > > > > > > > > > > +++ b/Documentation/devicetree/bindings/memory-controllers/renes > > > > > > > > > > > > > +++ as,r > > > > > > > > > > > > > +++ zg3e > > > > > > > > > > > > > +++ -xspi.yaml > > > > > > > > > > > > > > > > > > > > > > > > + spi@11030000 { > > > > > > > > > > > > > + compatible = "renesas,r9a09g047-xspi"; > > > > > > > > > > > > > + reg = <0x11030000 0x10000>, <0x20000000 0x10000000>; > > > > > > > > > > > > > + reg-names = "regs", "dirmap"; > > > > > > > > > > > > > + interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>, > > > > > > > > > > > > > + <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>; > > > > > > > > > > > > > + interrupt-names = "pulse", "err_pulse"; > > > > > > > > > > > > > + clocks = <&cpg CPG_MOD 0x9f>, <&cpg CPG_MOD 0xa0>, > > > > > > > > > > > > > + <&cpg CPG_MOD 0xa1>, <&cpg CPG_MOD 0xa1>; > > > > > > > > > > > > > > > > > > > > > > > > On the next version I am going to update spix2 clk as <&cpg > > > > > > > > > > > > CPG_CORE R9A09G047_SPI_CLK_SPIX2> > > > > > > > > > > > > > > According to the RZ/G3E clock system diagram, (the parent of) clk_spi > > > > > > > is derived from (the parent of) clk_spix2, not the other way around? > > > > > > > So you can model clk_spi as a fixed divider clock with parent clk_spix2 > > > > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > > [A] > > > > > > > > > > and factor two. I.e. provide a new core clock R9A09G047_SPI_CLK_SPI > > > > > > > instead of your proposed R9A09G047_SPI_CLK_SPIX2? > > > > > > > > > > > > > With this approach when R9A09G047_SPI_CLK_SPI is used as a core clock > > > > > > and XSPI node is disabled the clk_summary reports the core clock is ON > > > > > > (while it's actually OFF). > > > > > > > > > > Is that a real problem, or is it purely cosmetic? > > > > Just cosmetic tbh as despite being a MOD clock we have to define it as > > > > a core clock in the DT. > > > > > > > > > > Can we maybe use a unused ON index and ON bit for example 25, 0 (ie > > > > > > 0x190) and represent this is a module clock for example for the > > > > > > spi_clk_spix2 clock and use this in the DT and let the CPG core code > > > > > > handle such turning ON/OF the module clocks based on the enable count > > > > > > which will be handled internally in the driver? > > > > > > > > > > Please do not use "unused" module clock bits. These do not describe > > > > > the hardware, and may actually exist in the hardware (try disabling > > > > > all undocumented module clocks, and observe what fails...). > > > > > > > > > Agreed, "unused" module clock bits were only used as a dummy. The > > > > read/write operations were only performed on the actual bits which are > > > > documented in the HW manual. > > > > > > > > > If spi_clk_spi really must show being disabled, you can change it > > > > > from a fixed divider clock (which does not implement .{en,dis}able()) > > > > > to a custom fixed divider clock that does implement .{en,dis}able() > > > > > and keeps track internally of the fake state, or even looks at the > > > > > state of spi_clk_spix2? > > > > > > > > > Good point. Maybe instead of implementing the dummy .{en,dis}able() I > > > > will implement the is_enabled() + (clk_fixed_factor_ops). The > > > > is_enabled() will take care of reading from the MON bits and report > > > > the actual state of the clock. > > > > > > > > > However, upon second look, spi_clk_spi is not implemented as a fixed > > > > > divider clock with parent clk_spix2, as described above: > > > > > > > > > > .smux2_xspi_clk1 0 0 0 320000000 0 0 50000 Y > > > > > .pllcm33_xspi 0 0 0 40000000 0 0 50000 Y > > > > > spi_clk_spix2 0 0 0 40000000 0 0 50000 N > > > > > spi_clk_spi 0 0 0 20000000 0 0 50000 Y > > > > > spi_aclk 0 0 0 200000000 0 0 50000 N > > > > > spi_hclk 0 0 0 200000000 0 0 50000 N > > > > > .smux2_xspi_clk0 0 0 0 533333333 0 0 50000 Y > > > > > > > > > > Instead, they both use pllcm33_xspi as the parent clock. > > > > > Apparently I missed that in the review of RZ/G3E XSPI clock support. > > > > > The changelog for that patch does describe the correct topology? > > > > > > > > > The topology is correct for RZ/G3E, spi/spix2 are sourced from > > > > pllcm33_xspi divider and there is a divider (/2) for spi. > > > > > > Both spi_clk_spix2 and spi_clk_spix have .pllcm33_xspi as > > > immediate parent. > > > > > > [A] describes something different: > > > > > > .pllcm33_xspi 0 0 0 40000000 0 0 50000 Y > > > spi_clk_spix2 0 0 0 40000000 0 0 50000 N > > > spi_clk_spi 0 0 0 20000000 0 0 50000 Y > > > > > > I.e. if spi_clk_spix2() is disabled, spi_clk_spi() is disabled, too. > > > > > Okay, thanks - got it. > > > > To clarify, to implement spi_clk_spi core clock as a parent of > > spi_clk_spix2 I will need to implement some sort of mechanism which > > registers (late) core clks after core clks and module clks are > > registered as spi_clk_spix2 is a module clock. > > Yes, I wondered about that as well, but wasn't too worried as you > already added the smux with e.g. "et0_rxclk" as parent, which also > doesn't exist at registration time ;-) > Good point. > But indeed, the smux uses clock names to find the parents, while > fixed-factor clocks in zv2h_cpg_register_core_clk() expect clock IDs > (which are converted to names), and don't handle non-core clocks yet. > So either add support for late core clocks, or modify CLK_TYPE_FF > to use cpg_core_clock.parent_names[] in case of a non-core parent? > I choose the late core registration of the clocks and with this the core clk_spi still reports `Y` in the summary while the parent is OFF (since its a FF clock). Logs for option #1 ------------------------ root@rzv2h-evk:~# modprobe spi_rpc_if [ 217.783625] 3 fixed-partitions partitions found on MTD device spi0.0 [ 217.790029] Creating 3 MTD partitions on "spi0.0": [ 217.794958] 0x000000000000-0x000000060000 : "bl2" [ 217.800464] 0x000000060000-0x000002000000 : "fip" [ 217.807788] 0x000002000000-0x000004000000 : "user" root@rzv2h-evk:~# root@rzv2h-evk:~# cat /sys/kernel/debug/clk/clk_summary | grep spi spi_aclk 0 1 0 200000000 0 0 50000 N deviceless of_clk_get_from_provider spi_hclk 0 1 0 200000000 0 0 50000 N deviceless of_clk_get_from_provider .smux2_xspi_clk0 1 1 0 533333333 0 0 50000 Y deviceless no_connection_id .smux2_xspi_clk1 1 1 0 533333333 0 0 50000 Y deviceless no_connection_id .pllcm33_xspi 1 1 0 266666667 0 0 50000 Y deviceless no_connection_id spi_clk_spix2 2 2 0 266666667 0 0 50000 Y 11030000.spi spix2 spi_clk_spi 1 1 0 133333333 0 0 50000 Y 11030000.spi spi root@rzv2h-evk:~# root@rzv2h-evk:~# modprobe -r spi_rpc_if [ 225.376563] Deleting MTD partitions on "spi0.0": [ 225.381218] Deleting bl2 MTD partition [ 225.385504] Deleting fip MTD partition [ 225.617827] Deleting user MTD partition root@rzv2h-evk:~# root@rzv2h-evk:~# root@rzv2h-evk:~# cat /sys/kernel/debug/clk/clk_summary | grep spi spi_aclk 0 0 0 200000000 0 0 50000 N deviceless no_connection_id spi_hclk 0 0 0 200000000 0 0 50000 N deviceless no_connection_id .smux2_xspi_clk0 0 0 0 533333333 0 0 50000 Y deviceless no_connection_id .smux2_xspi_clk1 0 0 0 533333333 0 0 50000 Y deviceless no_connection_id .pllcm33_xspi 0 0 0 266666667 0 0 50000 Y deviceless no_connection_id spi_clk_spix2 0 0 0 266666667 0 0 50000 N deviceless no_connection_id spi_clk_spi 0 0 0 133333333 0 0 50000 Y deviceless no_connection_id root@rzv2h-evk:~# root@rzv2h-evk:~# Code implementation for option#1 ------------------------------------------------ diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c index 9952474bcf48..ab9e9a3e8cd1 100644 --- a/drivers/clk/renesas/r9a09g057-cpg.c +++ b/drivers/clk/renesas/r9a09g057-cpg.c @@ -231,7 +231,10 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = { CLK_PLLETH_DIV_125_FIX, 1, 1), DEF_FIXED("gbeth_1_clk_ptp_ref_i", R9A09G057_GBETH_1_CLK_PTP_REF_I, CLK_PLLETH_DIV_125_FIX, 1, 1), - DEF_FIXED("spi_clk_spi", R9A09G057_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2), +}; + +static const struct cpg_core_clk r9a09g057_late_core_clks[] __initconst = { + DEF_FIXED("spi_clk_spi", R9A09G057_SPI_CLK_SPI, 0xa1, 1, 2), }; static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = { @@ -502,6 +505,8 @@ const struct rzv2h_cpg_info r9a09g057_cpg_info __initconst = { /* Core Clocks */ .core_clks = r9a09g057_core_clks, .num_core_clks = ARRAY_SIZE(r9a09g057_core_clks), + .late_core_clks = r9a09g057_late_core_clks, + .num_late_core_clks = ARRAY_SIZE(r9a09g057_late_core_clks), .last_dt_core_clk = LAST_DT_CORE_CLK, .num_total_core_clks = MOD_CLK_BASE, diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index 97bcd252fcbf..0fdac1578f8b 100644 --- a/drivers/clk/renesas/rzv2h-cpg.c +++ b/drivers/clk/renesas/rzv2h-cpg.c @@ -710,7 +710,7 @@ static struct clk static void __init rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core, - struct rzv2h_cpg_priv *priv) + struct rzv2h_cpg_priv *priv, bool late) { struct clk *clk = ERR_PTR(-EOPNOTSUPP), *parent; unsigned int id = core->id, div = core->div; @@ -727,8 +727,12 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core, break; case CLK_TYPE_FF: WARN_DEBUG(core->parent >= priv->num_core_clks); - parent = priv->clks[core->parent]; + if (late) + parent = priv->clks[priv->num_core_clks + core->parent]; + else + parent = priv->clks[core->parent]; if (IS_ERR(parent)) { + pr_err("parent clk is NULL for %s parent:%d\n", core->name, core->parent); clk = parent; goto fail; } @@ -1298,11 +1302,14 @@ static int __init rzv2h_cpg_probe(struct platform_device *pdev) clks[i] = ERR_PTR(-ENOENT); for (i = 0; i < info->num_core_clks; i++) - rzv2h_cpg_register_core_clk(&info->core_clks[i], priv); + rzv2h_cpg_register_core_clk(&info->core_clks[i], priv, false); for (i = 0; i < info->num_mod_clks; i++) rzv2h_cpg_register_mod_clk(&info->mod_clks[i], priv); + for (i = 0; i < info->num_late_core_clks; i++) + rzv2h_cpg_register_core_clk(&info->late_core_clks[i], priv, true); + error = of_clk_add_provider(np, rzv2h_cpg_clk_src_twocell_get, priv); if (error) return error; diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h index bce131bec80b..442289b9cafb 100644 --- a/drivers/clk/renesas/rzv2h-cpg.h +++ b/drivers/clk/renesas/rzv2h-cpg.h @@ -297,6 +297,8 @@ struct rzv2h_reset { * * @core_clks: Array of Core Clock definitions * @num_core_clks: Number of entries in core_clks[] + * @late_core_clks: Array of Core Clocks that are late initialized + * @num_late_core_clks: Number of entries in late_core_clks[] * @last_dt_core_clk: ID of the last Core Clock exported to DT * @num_total_core_clks: Total number of Core Clocks (exported + internal) * @@ -315,6 +317,8 @@ struct rzv2h_cpg_info { /* Core Clocks */ const struct cpg_core_clk *core_clks; unsigned int num_core_clks; + const struct cpg_core_clk *late_core_clks; + unsigned int num_late_core_clks; unsigned int last_dt_core_clk; unsigned int num_total_core_clks; # Option#2 As mentioned in the previous thread I implemented FF clock with is_enabled() with this I can see the status of core clk_spi reports correct status. Logs for option #2 --------------------- root@rzv2h-evk:~# cat /sys/kernel/debug/clk/clk_summary | grep spi spi_aclk 0 1 0 200000000 0 0 50000 N deviceless of_clk_get_from_provider spi_hclk 0 1 0 200000000 0 0 50000 N deviceless of_clk_get_from_provider .smux2_xspi_clk0 1 1 0 533333333 0 0 50000 Y deviceless no_connection_id .smux2_xspi_clk1 1 1 0 533333333 0 0 50000 Y deviceless no_connection_id .pllcm33_xspi 2 2 0 266666667 0 0 50000 Y deviceless no_connection_id spi_clk_spix2 1 1 0 266666667 0 0 50000 Y 11030000.spi spix2 spi_clk_spi 1 1 0 133333333 0 0 50000 Y 11030000.spi spi root@rzv2h-evk:~# root@rzv2h-evk:~# modprobe -r spi_rpc_if [ 58.860437] Deleting MTD partitions on "spi0.0": [ 58.865078] Deleting bl2 MTD partition [ 58.869355] Deleting fip MTD partition [ 58.907329] Deleting user MTD partition root@rzv2h-evk:~# root@rzv2h-evk:~# cat /sys/kernel/debug/clk/clk_summary | grep spi spi_aclk 0 0 0 200000000 0 0 50000 N deviceless no_connection_id spi_hclk 0 0 0 200000000 0 0 50000 N deviceless no_connection_id .smux2_xspi_clk0 0 0 0 533333333 0 0 50000 Y deviceless no_connection_id .smux2_xspi_clk1 0 0 0 533333333 0 0 50000 Y deviceless no_connection_id .pllcm33_xspi 0 0 0 266666667 0 0 50000 Y deviceless no_connection_id spi_clk_spix2 0 0 0 266666667 0 0 50000 N deviceless no_connection_id spi_clk_spi 0 0 0 133333333 0 0 50000 N deviceless no_connection_id root@rzv2h-evk:~# root@rzv2h-evk:~# modprobe spi_rpc_if [ 65.423581] 3 fixed-partitions partitions found on MTD device spi0.0 [ 65.429971] Creating 3 MTD partitions on "spi0.0": [ 65.434778] 0x000000000000-0x000000060000 : "bl2" [ 65.440203] 0x000000060000-0x000002000000 : "fip" [ 65.446337] 0x000002000000-0x000004000000 : "user" root@rzv2h-evk:~# root@rzv2h-evk:~# root@rzv2h-evk:~# cat /sys/kernel/debug/clk/clk_summary | grep spi spi_aclk 0 1 0 200000000 0 0 50000 N deviceless of_clk_get_from_provider spi_hclk 0 1 0 200000000 0 0 50000 N deviceless of_clk_get_from_provider .smux2_xspi_clk0 1 1 0 533333333 0 0 50000 Y deviceless no_connection_id .smux2_xspi_clk1 1 1 0 533333333 0 0 50000 Y deviceless no_connection_id .pllcm33_xspi 2 2 0 266666667 0 0 50000 Y deviceless no_connection_id spi_clk_spix2 1 1 0 266666667 0 0 50000 Y 11030000.spi spix2 spi_clk_spi 1 1 0 133333333 0 0 50000 Y 11030000.spi spi root@rzv2h-evk:~# Code implementation for option#2 ------------------------------------------------ diff --git a/drivers/clk/renesas/r9a09g057-cpg.c b/drivers/clk/renesas/r9a09g057-cpg.c index 9952474bcf48..c56e43492a02 100644 --- a/drivers/clk/renesas/r9a09g057-cpg.c +++ b/drivers/clk/renesas/r9a09g057-cpg.c @@ -231,7 +231,8 @@ static const struct cpg_core_clk r9a09g057_core_clks[] __initconst = { CLK_PLLETH_DIV_125_FIX, 1, 1), DEF_FIXED("gbeth_1_clk_ptp_ref_i", R9A09G057_GBETH_1_CLK_PTP_REF_I, CLK_PLLETH_DIV_125_FIX, 1, 1), - DEF_FIXED("spi_clk_spi", R9A09G057_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2), + DEF_FIXED_MOD_STATUS("spi_clk_spi", R9A09G057_SPI_CLK_SPI, CLK_PLLCM33_XSPI, 1, 2, + FIXED_MOD_CONF_XSPI), }; static const struct rzv2h_mod_clk r9a09g057_mod_clks[] __initconst = { diff --git a/drivers/clk/renesas/rzv2h-cpg.c b/drivers/clk/renesas/rzv2h-cpg.c index 97bcd252fcbf..96db6ce4460f 100644 --- a/drivers/clk/renesas/rzv2h-cpg.c +++ b/drivers/clk/renesas/rzv2h-cpg.c @@ -179,6 +179,28 @@ struct rzv2h_plldsi_div_clk { #define to_plldsi_div_clk(_hw) \ container_of(_hw, struct rzv2h_plldsi_div_clk, hw) +/** + * struct rzv2h_ff_mod_status_clk - Fixed Factor Module Status Clock + * + * @priv: CPG private data + * @conf: fixed mod configuration + * @hw: Fixed Factor Status Clock handle + * @mult: multiplier value + * @div: divider value + * @flags: flags for the clock + */ + struct rzv2h_ff_mod_status_clk { + struct rzv2h_cpg_priv *priv; + struct fixed_mod_conf conf; + struct clk_hw hw; + unsigned int mult; + unsigned int div; + unsigned int flags; +}; + +#define to_rzv2h_ff_mod_status_clk(_hw) \ + container_of(_hw, struct rzv2h_ff_mod_status_clk, hw) + static int rzv2h_cpg_pll_clk_is_enabled(struct clk_hw *hw) { struct pll_clk *pll_clk = to_pll(hw); @@ -664,6 +686,114 @@ rzv2h_cpg_mux_clk_register(const struct cpg_core_clk *core, return clk_hw->clk; } +static unsigned long +rzv2h_clk_ff_mod_status_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct rzv2h_ff_mod_status_clk *fix = to_rzv2h_ff_mod_status_clk(hw); + unsigned long long int rate; + + rate = (unsigned long long int)parent_rate * fix->mult; + do_div(rate, fix->div); + return (unsigned long)rate; +} + +static long +rzv2h_clk_ff_mod_status_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct rzv2h_ff_mod_status_clk *fix = to_rzv2h_ff_mod_status_clk(hw); + + if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { + unsigned long best_parent; + + best_parent = (rate / fix->mult) * fix->div; + *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent); + } + + return (*prate / fix->div) * fix->mult; +} + +static int rzv2h_clk_ff_mod_status_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + return 0; +} + +static unsigned long +rzv2h_clk_ff_mod_status_recalc_accuracy(struct clk_hw *hw, + unsigned long parent_accuracy) +{ + return parent_accuracy; +} + +static int +rzv2h_clk_ff_mod_status_is_enabled(struct clk_hw *hw) +{ + struct rzv2h_ff_mod_status_clk *fix = to_rzv2h_ff_mod_status_clk(hw); + struct rzv2h_cpg_priv *priv = fix->priv; + u32 offset = GET_CLK_MON_OFFSET(fix->conf.mon_index); + u32 bitmask = BIT(fix->conf.mon_bit); + u32 val; + + val = readl(priv->base + offset); + return !!(val & bitmask); +} + +static const struct clk_ops rzv2h_clk_ff_mod_status_ops = { + .round_rate = rzv2h_clk_ff_mod_status_round_rate, + .set_rate = rzv2h_clk_ff_mod_status_set_rate, + .recalc_rate = rzv2h_clk_ff_mod_status_recalc_rate, + .recalc_accuracy = rzv2h_clk_ff_mod_status_recalc_accuracy, + .is_enabled = rzv2h_clk_ff_mod_status_is_enabled, +}; + +static struct clk * __init +rzv2h_cpg_fixed_mod_status_clk_register(const struct cpg_core_clk *core, + struct rzv2h_cpg_priv *priv) +{ + struct rzv2h_ff_mod_status_clk *clk_hw_data; + struct clk_init_data init = { }; + const struct clk *parent; + const char *parent_name; + struct clk_hw *hw; + int ret; + + WARN_DEBUG(core->parent >= priv->num_core_clks); + parent = priv->clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + parent_name = __clk_get_name(parent); + parent = priv->clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); + if (!clk_hw_data) + return ERR_PTR(-ENOMEM); + + clk_hw_data->priv = priv; + clk_hw_data->conf = core->cfg.fixed_mod; + clk_hw_data->mult = core->mult; + clk_hw_data->div = core->div; + + init.name = core->name; + init.ops = &rzv2h_clk_ff_mod_status_ops; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = &parent_name; + init.num_parents = 1; + + hw = &clk_hw_data->hw; + hw->init = &init; + + ret = devm_clk_hw_register(priv->dev, hw); + if (ret) + return ERR_PTR(ret); + + return hw->clk; +} + static struct clk *rzv2h_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec, void *data) @@ -742,6 +872,9 @@ rzv2h_cpg_register_core_clk(const struct cpg_core_clk *core, else clk = clk_hw->clk; break; + case CLK_TYPE_FF_MOD_STATUS: + clk = rzv2h_cpg_fixed_mod_status_clk_register(core, priv); + break; case CLK_TYPE_PLL: clk = rzv2h_cpg_pll_clk_register(core, priv, &rzv2h_cpg_pll_ops, false); break; diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h index bce131bec80b..29e1dc841b46 100644 --- a/drivers/clk/renesas/rzv2h-cpg.h +++ b/drivers/clk/renesas/rzv2h-cpg.h @@ -94,6 +94,23 @@ struct smuxed { .width = (_width), \ }) +/** + * struct fixed_mod_conf - Structure for fixed module configuration + * + * @mon_index: monitor index + * @mon_bit: monitor bit + */ +struct fixed_mod_conf { + u8 mon_index; + u8 mon_bit; +}; + +#define FIXED_MOD_CONF_PACK(_index, _bit) \ + ((struct fixed_mod_conf){ \ + .mon_index = (_index), \ + .mon_bit = (_bit), \ + }) + #define CPG_SSEL0 (0x300) #define CPG_SSEL1 (0x304) #define CPG_CDDIV0 (0x400) @@ -137,6 +154,8 @@ struct smuxed { FIELD_PREP_CONST(BUS_MSTOP_BITS_MASK, (mask))) #define BUS_MSTOP_NONE GENMASK(31, 0) +#define FIXED_MOD_CONF_XSPI FIXED_MOD_CONF_PACK(5, 1) + /** * Definitions of CPG Core Clocks * @@ -157,6 +176,7 @@ struct cpg_core_clk { struct ddiv ddiv; struct pll pll; struct smuxed smux; + struct fixed_mod_conf fixed_mod; } cfg; const struct clk_div_table *dtable; const char * const *parent_names; @@ -169,6 +189,7 @@ enum clk_types { /* Generic */ CLK_TYPE_IN, /* External Clock Input */ CLK_TYPE_FF, /* Fixed Factor Clock */ + CLK_TYPE_FF_MOD_STATUS, /* Fixed Factor Clock which can report the status of module clock */ CLK_TYPE_PLL, CLK_TYPE_DDIV, /* Dynamic Switching Divider */ CLK_TYPE_SMUX, /* Static Mux */ @@ -186,6 +207,9 @@ enum clk_types { DEF_TYPE(_name, _id, CLK_TYPE_IN) #define DEF_FIXED(_name, _id, _parent, _mult, _div) \ DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) +#define DEF_FIXED_MOD_STATUS(_name, _id, _parent, _mult, _div, _gate) \ + DEF_BASE(_name, _id, CLK_TYPE_FF_MOD_STATUS, _parent, .div = _div, \ + .mult = _mult, .cfg.fixed_mod = _gate) #define DEF_DDIV(_name, _id, _parent, _ddiv_packed, _dtable) \ DEF_TYPE(_name, _id, CLK_TYPE_DDIV, \ .cfg.ddiv = _ddiv_packed, \ Please share your thoughts on this. Cheers, Prabhakar