Skip to content

Commit 09febae

Browse files
committed
Merge tag 'v6.16-rockchip-clk1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into clk-rockchip
Pull Rockchip clk driver updates from Heiko Stuebner: - Ability to handle different "General Register Files" syscons, not just a single system-one, plus ability to model individual gates found there. - For whatever reason Rockchip also moved the mmc-phase-clocks from the clock-unit for the GRF on some newer socs like the rk3528 (before moving them fully to the mmc controller itself on the rk3576), so add a new clock-variant for the phases, reusing the new GRF handling. - The old rk3036 got real handling of the usb480m mux and some PLL rates were added. * tag 'v6.16-rockchip-clk1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip: clk: rockchip: rk3528: add slab.h header include clk: rockchip: rk3576: add missing slab.h include clk: rockchip: rename gate-grf clk file clk: rockchip: rename branch_muxgrf to branch_grf_mux clk: rockchip: Pass NULL as reg pointer when registering GRF MMC clocks clk: rockchip: rk3036: mark ddrphy as critical clk: rockchip: rk3036: fix implementation of usb480m clock mux dt-bindings: clock: rk3036: add SCLK_USB480M clock-id clk: rockchip: rk3528: Add SD/SDIO tuning clocks in GRF region clk: rockchip: Support MMC clocks in GRF region dt-bindings: clock: Add GRF clock definition for RK3528 clk: rockchip: add GATE_GRFs for SAI MCLKOUT to rk3576 clk: rockchip: introduce GRF gates clk: rockchip: introduce auxiliary GRFs dt-bindings: clock: rk3576: add IOC gated clocks clk: rockchip: rk3568: Add PLL rate for 33.3MHz clk: rockchip: Drop empty init callback for rk3588 PLL type clk: rockchip: rk3588: Add PLL rate for 1500 MHz
2 parents 0af2f6b + 2760362 commit 09febae

File tree

17 files changed

+390
-49
lines changed

17 files changed

+390
-49
lines changed

drivers/clk/rockchip/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ obj-$(CONFIG_COMMON_CLK_ROCKCHIP) += clk-rockchip.o
88
clk-rockchip-y += clk.o
99
clk-rockchip-y += clk-pll.o
1010
clk-rockchip-y += clk-cpu.o
11+
clk-rockchip-y += clk-gate-grf.o
1112
clk-rockchip-y += clk-half-divider.o
1213
clk-rockchip-y += clk-inverter.o
1314
clk-rockchip-y += clk-mmc-phase.o

drivers/clk/rockchip/clk-gate-grf.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* Copyright (c) 2025 Collabora Ltd.
4+
* Author: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
5+
*
6+
* Certain clocks on Rockchip are "gated" behind an additional register bit
7+
* write in a GRF register, such as the SAI MCLKs on RK3576. This code
8+
* implements a clock driver for these types of gates, based on regmaps.
9+
*/
10+
11+
#include <linux/clk.h>
12+
#include <linux/clk-provider.h>
13+
#include <linux/regmap.h>
14+
#include <linux/slab.h>
15+
#include "clk.h"
16+
17+
struct rockchip_gate_grf {
18+
struct clk_hw hw;
19+
struct regmap *regmap;
20+
unsigned int reg;
21+
unsigned int shift;
22+
u8 flags;
23+
};
24+
25+
#define to_gate_grf(_hw) container_of(_hw, struct rockchip_gate_grf, hw)
26+
27+
static int rockchip_gate_grf_enable(struct clk_hw *hw)
28+
{
29+
struct rockchip_gate_grf *gate = to_gate_grf(hw);
30+
u32 val = !(gate->flags & CLK_GATE_SET_TO_DISABLE) ? BIT(gate->shift) : 0;
31+
u32 hiword = ((gate->flags & CLK_GATE_HIWORD_MASK) ? 1 : 0) << (gate->shift + 16);
32+
int ret;
33+
34+
ret = regmap_update_bits(gate->regmap, gate->reg,
35+
hiword | BIT(gate->shift), hiword | val);
36+
37+
return ret;
38+
}
39+
40+
static void rockchip_gate_grf_disable(struct clk_hw *hw)
41+
{
42+
struct rockchip_gate_grf *gate = to_gate_grf(hw);
43+
u32 val = !(gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : BIT(gate->shift);
44+
u32 hiword = ((gate->flags & CLK_GATE_HIWORD_MASK) ? 1 : 0) << (gate->shift + 16);
45+
46+
regmap_update_bits(gate->regmap, gate->reg,
47+
hiword | BIT(gate->shift), hiword | val);
48+
}
49+
50+
static int rockchip_gate_grf_is_enabled(struct clk_hw *hw)
51+
{
52+
struct rockchip_gate_grf *gate = to_gate_grf(hw);
53+
bool invert = !!(gate->flags & CLK_GATE_SET_TO_DISABLE);
54+
int ret;
55+
56+
ret = regmap_test_bits(gate->regmap, gate->reg, BIT(gate->shift));
57+
if (ret < 0)
58+
ret = 0;
59+
60+
return invert ? 1 - ret : ret;
61+
62+
}
63+
64+
static const struct clk_ops rockchip_gate_grf_ops = {
65+
.enable = rockchip_gate_grf_enable,
66+
.disable = rockchip_gate_grf_disable,
67+
.is_enabled = rockchip_gate_grf_is_enabled,
68+
};
69+
70+
struct clk *rockchip_clk_register_gate_grf(const char *name,
71+
const char *parent_name, unsigned long flags,
72+
struct regmap *regmap, unsigned int reg, unsigned int shift,
73+
u8 gate_flags)
74+
{
75+
struct rockchip_gate_grf *gate;
76+
struct clk_init_data init;
77+
struct clk *clk;
78+
79+
if (IS_ERR(regmap)) {
80+
pr_err("%s: regmap not available\n", __func__);
81+
return ERR_PTR(-EOPNOTSUPP);
82+
}
83+
84+
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
85+
if (!gate)
86+
return ERR_PTR(-ENOMEM);
87+
88+
init.name = name;
89+
init.flags = flags;
90+
init.num_parents = parent_name ? 1 : 0;
91+
init.parent_names = parent_name ? &parent_name : NULL;
92+
init.ops = &rockchip_gate_grf_ops;
93+
94+
gate->hw.init = &init;
95+
gate->regmap = regmap;
96+
gate->reg = reg;
97+
gate->shift = shift;
98+
gate->flags = gate_flags;
99+
100+
clk = clk_register(NULL, &gate->hw);
101+
if (IS_ERR(clk))
102+
kfree(gate);
103+
104+
return clk;
105+
}

drivers/clk/rockchip/clk-mmc-phase.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
#include <linux/clk-provider.h>
1010
#include <linux/io.h>
1111
#include <linux/kernel.h>
12+
#include <linux/regmap.h>
1213
#include "clk.h"
1314

1415
struct rockchip_mmc_clock {
1516
struct clk_hw hw;
1617
void __iomem *reg;
18+
struct regmap *grf;
19+
int grf_reg;
1720
int shift;
1821
int cached_phase;
1922
struct notifier_block clk_rate_change_nb;
@@ -54,7 +57,12 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
5457
if (!rate)
5558
return 0;
5659

57-
raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
60+
if (mmc_clock->grf)
61+
regmap_read(mmc_clock->grf, mmc_clock->grf_reg, &raw_value);
62+
else
63+
raw_value = readl(mmc_clock->reg);
64+
65+
raw_value >>= mmc_clock->shift;
5866

5967
degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
6068

@@ -134,8 +142,12 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
134142
raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
135143
raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
136144
raw_value |= nineties;
137-
writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift),
138-
mmc_clock->reg);
145+
raw_value = HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift);
146+
147+
if (mmc_clock->grf)
148+
regmap_write(mmc_clock->grf, mmc_clock->grf_reg, raw_value);
149+
else
150+
writel(raw_value, mmc_clock->reg);
139151

140152
pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
141153
clk_hw_get_name(hw), degrees, delay_num,
@@ -189,7 +201,9 @@ static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb,
189201

190202
struct clk *rockchip_clk_register_mmc(const char *name,
191203
const char *const *parent_names, u8 num_parents,
192-
void __iomem *reg, int shift)
204+
void __iomem *reg,
205+
struct regmap *grf, int grf_reg,
206+
int shift)
193207
{
194208
struct clk_init_data init;
195209
struct rockchip_mmc_clock *mmc_clock;
@@ -208,6 +222,8 @@ struct clk *rockchip_clk_register_mmc(const char *name,
208222

209223
mmc_clock->hw.init = &init;
210224
mmc_clock->reg = reg;
225+
mmc_clock->grf = grf;
226+
mmc_clock->grf_reg = grf_reg;
211227
mmc_clock->shift = shift;
212228

213229
clk = clk_register(NULL, &mmc_clock->hw);

drivers/clk/rockchip/clk-pll.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,16 +1027,6 @@ static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw)
10271027
return !(pllcon & RK3588_PLLCON1_PWRDOWN);
10281028
}
10291029

1030-
static int rockchip_rk3588_pll_init(struct clk_hw *hw)
1031-
{
1032-
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
1033-
1034-
if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
1035-
return 0;
1036-
1037-
return 0;
1038-
}
1039-
10401030
static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = {
10411031
.recalc_rate = rockchip_rk3588_pll_recalc_rate,
10421032
.enable = rockchip_rk3588_pll_enable,
@@ -1051,7 +1041,6 @@ static const struct clk_ops rockchip_rk3588_pll_clk_ops = {
10511041
.enable = rockchip_rk3588_pll_enable,
10521042
.disable = rockchip_rk3588_pll_disable,
10531043
.is_enabled = rockchip_rk3588_pll_is_enabled,
1054-
.init = rockchip_rk3588_pll_init,
10551044
};
10561045

10571046
/*

drivers/clk/rockchip/clk-rk3036.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" };
123123
PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll", "usb480m" };
124124
PNAME(mux_pll_src_dmyapll_dpll_gpll_xin24_p) = { "dummy_apll", "dpll", "gpll", "xin24m" };
125125

126+
PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" };
126127
PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" };
127128
PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
128129
PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" };
@@ -423,6 +424,9 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
423424
GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
424425
GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
425426
GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
427+
428+
MUX(SCLK_USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT,
429+
RK2928_MISC_CON, 15, 1, MFLAGS),
426430
};
427431

428432
static const char *const rk3036_critical_clocks[] __initconst = {
@@ -431,14 +435,14 @@ static const char *const rk3036_critical_clocks[] __initconst = {
431435
"hclk_peri",
432436
"pclk_peri",
433437
"pclk_ddrupctl",
438+
"ddrphy",
434439
};
435440

436441
static void __init rk3036_clk_init(struct device_node *np)
437442
{
438443
struct rockchip_clk_provider *ctx;
439444
unsigned long clk_nr_clks;
440445
void __iomem *reg_base;
441-
struct clk *clk;
442446

443447
reg_base = of_iomap(np, 0);
444448
if (!reg_base) {
@@ -462,11 +466,6 @@ static void __init rk3036_clk_init(struct device_node *np)
462466
return;
463467
}
464468

465-
clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
466-
if (IS_ERR(clk))
467-
pr_warn("%s: could not register clock usb480m: %ld\n",
468-
__func__, PTR_ERR(clk));
469-
470469
rockchip_clk_register_plls(ctx, rk3036_pll_clks,
471470
ARRAY_SIZE(rk3036_pll_clks),
472471
RK3036_GRF_SOC_STATUS0);

drivers/clk/rockchip/clk-rk3288.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
418418
RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
419419
RK3288_CLKGATE_CON(3), 11, GFLAGS),
420420
MUXGRF(0, "aclk_vcodec_pre", mux_aclk_vcodec_pre_p, CLK_SET_RATE_PARENT,
421-
RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS),
421+
RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS, grf_type_sys),
422422
GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0,
423423
RK3288_CLKGATE_CON(9), 0, GFLAGS),
424424

drivers/clk/rockchip/clk-rk3328.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -677,9 +677,9 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
677677
RK3328_CLKSEL_CON(27), 15, 1, MFLAGS, 8, 5, DFLAGS,
678678
RK3328_CLKGATE_CON(3), 5, GFLAGS),
679679
MUXGRF(SCLK_MAC2IO, "clk_mac2io", mux_mac2io_src_p, CLK_SET_RATE_NO_REPARENT,
680-
RK3328_GRF_MAC_CON1, 10, 1, MFLAGS),
680+
RK3328_GRF_MAC_CON1, 10, 1, MFLAGS, grf_type_sys),
681681
MUXGRF(SCLK_MAC2IO_EXT, "clk_mac2io_ext", mux_mac2io_ext_p, CLK_SET_RATE_NO_REPARENT,
682-
RK3328_GRF_SOC_CON4, 14, 1, MFLAGS),
682+
RK3328_GRF_SOC_CON4, 14, 1, MFLAGS, grf_type_sys),
683683

684684
COMPOSITE(SCLK_MAC2PHY_SRC, "clk_mac2phy_src", mux_2plls_p, 0,
685685
RK3328_CLKSEL_CON(26), 7, 1, MFLAGS, 0, 5, DFLAGS,
@@ -692,7 +692,7 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
692692
RK3328_CLKSEL_CON(26), 8, 2, DFLAGS,
693693
RK3328_CLKGATE_CON(9), 2, GFLAGS),
694694
MUXGRF(SCLK_MAC2PHY, "clk_mac2phy", mux_mac2phy_src_p, CLK_SET_RATE_NO_REPARENT,
695-
RK3328_GRF_MAC_CON2, 10, 1, MFLAGS),
695+
RK3328_GRF_MAC_CON2, 10, 1, MFLAGS, grf_type_sys),
696696

697697
FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
698698

drivers/clk/rockchip/clk-rk3528.c

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <linux/of.h>
1111
#include <linux/of_device.h>
1212
#include <linux/platform_device.h>
13+
#include <linux/mfd/syscon.h>
14+
#include <linux/minmax.h>
15+
#include <linux/slab.h>
1316

1417
#include <dt-bindings/clock/rockchip,rk3528-cru.h>
1518

@@ -1061,23 +1064,65 @@ static struct rockchip_clk_branch rk3528_clk_branches[] __initdata = {
10611064
0, 1, 1),
10621065
};
10631066

1067+
static struct rockchip_clk_branch rk3528_vo_clk_branches[] __initdata = {
1068+
MMC_GRF(SCLK_SDMMC_DRV, "sdmmc_drv", "cclk_src_sdmmc0",
1069+
RK3528_SDMMC_CON(0), 1, grf_type_vo),
1070+
MMC_GRF(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "cclk_src_sdmmc0",
1071+
RK3528_SDMMC_CON(1), 1, grf_type_vo),
1072+
};
1073+
1074+
static struct rockchip_clk_branch rk3528_vpu_clk_branches[] __initdata = {
1075+
MMC_GRF(SCLK_SDIO0_DRV, "sdio0_drv", "cclk_src_sdio0",
1076+
RK3528_SDIO0_CON(0), 1, grf_type_vpu),
1077+
MMC_GRF(SCLK_SDIO0_SAMPLE, "sdio0_sample", "cclk_src_sdio0",
1078+
RK3528_SDIO0_CON(1), 1, grf_type_vpu),
1079+
MMC_GRF(SCLK_SDIO1_DRV, "sdio1_drv", "cclk_src_sdio1",
1080+
RK3528_SDIO1_CON(0), 1, grf_type_vpu),
1081+
MMC_GRF(SCLK_SDIO1_SAMPLE, "sdio1_sample", "cclk_src_sdio1",
1082+
RK3528_SDIO1_CON(1), 1, grf_type_vpu),
1083+
};
1084+
10641085
static int __init clk_rk3528_probe(struct platform_device *pdev)
10651086
{
1066-
struct rockchip_clk_provider *ctx;
1087+
unsigned long nr_vpu_branches = ARRAY_SIZE(rk3528_vpu_clk_branches);
1088+
unsigned long nr_vo_branches = ARRAY_SIZE(rk3528_vo_clk_branches);
1089+
unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
1090+
unsigned long nr_clks, nr_vo_clks, nr_vpu_clks;
1091+
struct rockchip_aux_grf *vo_grf_e, *vpu_grf_e;
1092+
struct regmap *vo_grf, *vpu_grf;
10671093
struct device *dev = &pdev->dev;
10681094
struct device_node *np = dev->of_node;
1069-
unsigned long nr_branches = ARRAY_SIZE(rk3528_clk_branches);
1070-
unsigned long nr_clks;
1095+
struct rockchip_clk_provider *ctx;
10711096
void __iomem *reg_base;
10721097

1073-
nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
1074-
nr_branches) + 1;
1075-
10761098
reg_base = devm_platform_ioremap_resource(pdev, 0);
10771099
if (IS_ERR(reg_base))
10781100
return dev_err_probe(dev, PTR_ERR(reg_base),
10791101
"could not map cru region");
10801102

1103+
nr_clks = rockchip_clk_find_max_clk_id(rk3528_clk_branches,
1104+
nr_branches) + 1;
1105+
1106+
vo_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vo-grf");
1107+
if (!IS_ERR(vo_grf)) {
1108+
nr_vo_clks = rockchip_clk_find_max_clk_id(rk3528_vo_clk_branches,
1109+
nr_vo_branches) + 1;
1110+
nr_clks = max(nr_clks, nr_vo_clks);
1111+
} else if (PTR_ERR(vo_grf) != -ENODEV) {
1112+
return dev_err_probe(dev, PTR_ERR(vo_grf),
1113+
"failed to look up VO GRF\n");
1114+
}
1115+
1116+
vpu_grf = syscon_regmap_lookup_by_compatible("rockchip,rk3528-vpu-grf");
1117+
if (!IS_ERR(vpu_grf)) {
1118+
nr_vpu_clks = rockchip_clk_find_max_clk_id(rk3528_vpu_clk_branches,
1119+
nr_vpu_branches) + 1;
1120+
nr_clks = max(nr_clks, nr_vpu_clks);
1121+
} else if (PTR_ERR(vpu_grf) != -ENODEV) {
1122+
return dev_err_probe(dev, PTR_ERR(vpu_grf),
1123+
"failed to look up VPU GRF\n");
1124+
}
1125+
10811126
ctx = rockchip_clk_init(np, reg_base, nr_clks);
10821127
if (IS_ERR(ctx))
10831128
return dev_err_probe(dev, PTR_ERR(ctx),
@@ -1092,6 +1137,32 @@ static int __init clk_rk3528_probe(struct platform_device *pdev)
10921137
ARRAY_SIZE(rk3528_cpuclk_rates));
10931138
rockchip_clk_register_branches(ctx, rk3528_clk_branches, nr_branches);
10941139

1140+
if (!IS_ERR(vo_grf)) {
1141+
vo_grf_e = devm_kzalloc(dev, sizeof(*vo_grf_e), GFP_KERNEL);
1142+
if (!vo_grf_e)
1143+
return -ENOMEM;
1144+
1145+
vo_grf_e->grf = vo_grf;
1146+
vo_grf_e->type = grf_type_vo;
1147+
hash_add(ctx->aux_grf_table, &vo_grf_e->node, grf_type_vo);
1148+
1149+
rockchip_clk_register_branches(ctx, rk3528_vo_clk_branches,
1150+
nr_vo_branches);
1151+
}
1152+
1153+
if (!IS_ERR(vpu_grf)) {
1154+
vpu_grf_e = devm_kzalloc(dev, sizeof(*vpu_grf_e), GFP_KERNEL);
1155+
if (!vpu_grf_e)
1156+
return -ENOMEM;
1157+
1158+
vpu_grf_e->grf = vpu_grf;
1159+
vpu_grf_e->type = grf_type_vpu;
1160+
hash_add(ctx->aux_grf_table, &vpu_grf_e->node, grf_type_vpu);
1161+
1162+
rockchip_clk_register_branches(ctx, rk3528_vpu_clk_branches,
1163+
nr_vpu_branches);
1164+
}
1165+
10951166
rk3528_rst_init(np, reg_base);
10961167

10971168
rockchip_register_restart_notifier(ctx, RK3528_GLB_SRST_FST, NULL);

0 commit comments

Comments
 (0)