clk: rockchip: Support MMC clocks in GRF region
authorYao Zi <ziyao@disroot.org>
Tue, 6 May 2025 09:22:03 +0000 (09:22 +0000)
committerHeiko Stuebner <heiko@sntech.de>
Thu, 8 May 2025 18:03:27 +0000 (20:03 +0200)
Registers of MMC drive/sample clocks in Rockchip RV1106 and RK3528
locate in GRF regions. Adjust MMC clock code to support register
operations through regmap.

Signed-off-by: Yao Zi <ziyao@disroot.org>
Link: https://lore.kernel.org/r/20250506092206.46143-3-ziyao@disroot.org
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
drivers/clk/rockchip/clk-mmc-phase.c
drivers/clk/rockchip/clk.c
drivers/clk/rockchip/clk.h

index 91012078681bf1e01608220598f29d896fb7dff0..b3ed8e7523e50f4fd5cab69353e94bb1d6949e2e 100644 (file)
@@ -9,11 +9,14 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/regmap.h>
 #include "clk.h"
 
 struct rockchip_mmc_clock {
        struct clk_hw   hw;
        void __iomem    *reg;
+       struct regmap   *grf;
+       int             grf_reg;
        int             shift;
        int             cached_phase;
        struct notifier_block clk_rate_change_nb;
@@ -54,7 +57,12 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
        if (!rate)
                return 0;
 
-       raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
+       if (mmc_clock->grf)
+               regmap_read(mmc_clock->grf, mmc_clock->grf_reg, &raw_value);
+       else
+               raw_value = readl(mmc_clock->reg);
+
+       raw_value >>= mmc_clock->shift;
 
        degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
 
@@ -134,8 +142,12 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
        raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
        raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
        raw_value |= nineties;
-       writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift),
-              mmc_clock->reg);
+       raw_value = HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift);
+
+       if (mmc_clock->grf)
+               regmap_write(mmc_clock->grf, mmc_clock->grf_reg, raw_value);
+       else
+               writel(raw_value, mmc_clock->reg);
 
        pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
                clk_hw_get_name(hw), degrees, delay_num,
@@ -189,7 +201,9 @@ static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb,
 
 struct clk *rockchip_clk_register_mmc(const char *name,
                                const char *const *parent_names, u8 num_parents,
-                               void __iomem *reg, int shift)
+                               void __iomem *reg,
+                               struct regmap *grf, int grf_reg,
+                               int shift)
 {
        struct clk_init_data init;
        struct rockchip_mmc_clock *mmc_clock;
@@ -208,6 +222,8 @@ struct clk *rockchip_clk_register_mmc(const char *name,
 
        mmc_clock->hw.init = &init;
        mmc_clock->reg = reg;
+       mmc_clock->grf = grf;
+       mmc_clock->grf_reg = grf_reg;
        mmc_clock->shift = shift;
 
        clk = clk_register(NULL, &mmc_clock->hw);
index 34d96aa7cd51b8bde380b4a81ce07ffdf24b8593..43d7ed5c3418ac795ca4bb0e02ee87ef8e33b7fd 100644 (file)
@@ -509,8 +509,10 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
                clk = NULL;
 
                /* for GRF-dependent branches, choose the right grf first */
-               if ((list->branch_type == branch_muxgrf || list->branch_type == branch_grf_gate) &&
-                               list->grf_type != grf_type_sys) {
+               if ((list->branch_type == branch_muxgrf ||
+                    list->branch_type == branch_grf_gate ||
+                    list->branch_type == branch_grf_mmc) &&
+                   list->grf_type != grf_type_sys) {
                        hash_for_each_possible(ctx->aux_grf_table, agrf, node, list->grf_type) {
                                if (agrf->type == list->grf_type) {
                                        grf = agrf->grf;
@@ -612,6 +614,16 @@ void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
                                list->name,
                                list->parent_names, list->num_parents,
                                ctx->reg_base + list->muxdiv_offset,
+                               NULL, 0,
+                               list->div_shift
+                       );
+                       break;
+               case branch_grf_mmc:
+                       clk = rockchip_clk_register_mmc(
+                               list->name,
+                               list->parent_names, list->num_parents,
+                               0,
+                               grf, list->muxdiv_offset,
                                list->div_shift
                        );
                        break;
index ebaed429a30dc2c41c866f973f8cf78b32136311..d411de7a6f4a920d8afb5e4f353e75ffd323b567 100644 (file)
@@ -619,7 +619,9 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
 
 struct clk *rockchip_clk_register_mmc(const char *name,
                                const char *const *parent_names, u8 num_parents,
-                               void __iomem *reg, int shift);
+                               void __iomem *reg,
+                               struct regmap *grf, int grf_reg,
+                               int shift);
 
 /*
  * DDRCLK flags, including method of setting the rate
@@ -664,6 +666,7 @@ enum rockchip_clk_branch_type {
        branch_grf_gate,
        branch_linked_gate,
        branch_mmc,
+       branch_grf_mmc,
        branch_inverter,
        branch_factor,
        branch_ddrclk,
@@ -1030,6 +1033,18 @@ struct rockchip_clk_branch {
                .div_shift      = shift,                        \
        }
 
+#define MMC_GRF(_id, cname, pname, offset, shift, grftype)     \
+       {                                                       \
+               .id             = _id,                          \
+               .branch_type    = branch_grf_mmc,               \
+               .name           = cname,                        \
+               .parent_names   = (const char *[]){ pname },    \
+               .num_parents    = 1,                            \
+               .muxdiv_offset  = offset,                       \
+               .div_shift      = shift,                        \
+               .grf_type       = grftype,                      \
+       }
+
 #define INVERTER(_id, cname, pname, io, is, if)                        \
        {                                                       \
                .id             = _id,                          \