Re: [PATCH v3 1/9] dt-bindings: memory: Document RZ/G3E support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux