Skip to content

Commit 6aa1754

Browse files
morimotogeertu
authored andcommitted
clk: renesas: cpg-mssr: Ignore all clocks assigned to non-Linux system
Some boards might use Linux and another OS at the same time. In such case, currently, during booting, Linux will stop necessary module clocks which are not used on the Linux side, but are used by another OS. To avoid such situation, renesas-cpg-mssr tries to find status = "reserved" devices (A), and adds CLK_IGNORE_UNUSED flag to its <&cgp CPG_MOD xxx> clock (B). Table 2.4: Values for status property https://github.com/devicetree-org/devicetree-specification/releases/download/v0.4/devicetree-specification-v0.4.pdf "reserved" Indicates that the device is operational, but should not be used. Typically this is used for devices that are controlled by another software component, such as platform firmware. ex) scif5: serial@e6f30000 { ... (B) clocks = <&cpg CPG_MOD 202>, <&cpg CPG_CORE R8A7795_CLK_S3D1>, <&scif_clk>; ... (A) status = "reserved"; }; Cc: Aymeric Aillet <[email protected]> Signed-off-by: Kuninori Morimoto <[email protected]> Tested-by: Yusuke Goda <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Geert Uytterhoeven <[email protected]>
1 parent 28c5d4e commit 6aa1754

File tree

1 file changed

+104
-7
lines changed

1 file changed

+104
-7
lines changed

drivers/clk/renesas/renesas-cpg-mssr.c

Lines changed: 104 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ static const u16 srstclr_for_gen4[] = {
142142
* @reset_clear_regs: Pointer to reset clearing registers array
143143
* @smstpcr_saved: [].mask: Mask of SMSTPCR[] bits under our control
144144
* [].val: Saved values of SMSTPCR[]
145+
* @reserved_ids: Temporary used, reserved id list
146+
* @num_reserved_ids: Temporary used, number of reserved id list
145147
* @clks: Array containing all Core and Module Clocks
146148
*/
147149
struct cpg_mssr_priv {
@@ -168,6 +170,9 @@ struct cpg_mssr_priv {
168170
u32 val;
169171
} smstpcr_saved[ARRAY_SIZE(mstpsr_for_gen4)];
170172

173+
unsigned int *reserved_ids;
174+
unsigned int num_reserved_ids;
175+
171176
struct clk *clks[];
172177
};
173178

@@ -453,6 +458,19 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
453458
break;
454459
}
455460

461+
/*
462+
* Ignore reserved device.
463+
* see
464+
* cpg_mssr_reserved_init()
465+
*/
466+
for (i = 0; i < priv->num_reserved_ids; i++) {
467+
if (id == priv->reserved_ids[i]) {
468+
dev_info(dev, "Ignore Linux non-assigned mod (%s)\n", mod->name);
469+
init.flags |= CLK_IGNORE_UNUSED;
470+
break;
471+
}
472+
}
473+
456474
clk = clk_register(NULL, &clock->hw);
457475
if (IS_ERR(clk))
458476
goto fail;
@@ -949,6 +967,78 @@ static const struct dev_pm_ops cpg_mssr_pm = {
949967
#define DEV_PM_OPS NULL
950968
#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
951969

970+
static void __init cpg_mssr_reserved_exit(struct cpg_mssr_priv *priv)
971+
{
972+
kfree(priv->reserved_ids);
973+
}
974+
975+
static int __init cpg_mssr_reserved_init(struct cpg_mssr_priv *priv,
976+
const struct cpg_mssr_info *info)
977+
{
978+
struct device_node *soc = of_find_node_by_path("/soc");
979+
struct device_node *node;
980+
uint32_t args[MAX_PHANDLE_ARGS];
981+
unsigned int *ids = NULL;
982+
unsigned int num = 0;
983+
984+
/*
985+
* Because clk_disable_unused() will disable all unused clocks, the device which is assigned
986+
* to a non-Linux system will be disabled when Linux is booted.
987+
*
988+
* To avoid such situation, renesas-cpg-mssr assumes the device which has
989+
* status = "reserved" is assigned to a non-Linux system, and adds CLK_IGNORE_UNUSED flag
990+
* to its CPG_MOD clocks.
991+
* see also
992+
* cpg_mssr_register_mod_clk()
993+
*
994+
* scif5: serial@e6f30000 {
995+
* ...
996+
* => clocks = <&cpg CPG_MOD 202>,
997+
* <&cpg CPG_CORE R8A7795_CLK_S3D1>,
998+
* <&scif_clk>;
999+
* ...
1000+
* status = "reserved";
1001+
* };
1002+
*/
1003+
for_each_reserved_child_of_node(soc, node) {
1004+
struct of_phandle_iterator it;
1005+
int rc;
1006+
1007+
of_for_each_phandle(&it, rc, node, "clocks", "#clock-cells", -1) {
1008+
int idx;
1009+
1010+
if (it.node != priv->np)
1011+
continue;
1012+
1013+
if (of_phandle_iterator_args(&it, args, MAX_PHANDLE_ARGS) != 2)
1014+
continue;
1015+
1016+
if (args[0] != CPG_MOD)
1017+
continue;
1018+
1019+
ids = krealloc_array(ids, (num + 1), sizeof(*ids), GFP_KERNEL);
1020+
if (!ids) {
1021+
of_node_put(it.node);
1022+
return -ENOMEM;
1023+
}
1024+
1025+
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
1026+
idx = MOD_CLK_PACK_10(args[1]); /* for DEF_MOD_STB() */
1027+
else
1028+
idx = MOD_CLK_PACK(args[1]); /* for DEF_MOD() */
1029+
1030+
ids[num] = info->num_total_core_clks + idx;
1031+
1032+
num++;
1033+
}
1034+
}
1035+
1036+
priv->num_reserved_ids = num;
1037+
priv->reserved_ids = ids;
1038+
1039+
return 0;
1040+
}
1041+
9521042
static int __init cpg_mssr_common_init(struct device *dev,
9531043
struct device_node *np,
9541044
const struct cpg_mssr_info *info)
@@ -1003,14 +1093,20 @@ static int __init cpg_mssr_common_init(struct device *dev,
10031093
for (i = 0; i < nclks; i++)
10041094
priv->clks[i] = ERR_PTR(-ENOENT);
10051095

1006-
error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv);
1096+
error = cpg_mssr_reserved_init(priv, info);
10071097
if (error)
10081098
goto out_err;
10091099

1100+
error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv);
1101+
if (error)
1102+
goto reserve_err;
1103+
10101104
cpg_mssr_priv = priv;
10111105

10121106
return 0;
10131107

1108+
reserve_err:
1109+
cpg_mssr_reserved_exit(priv);
10141110
out_err:
10151111
if (priv->base)
10161112
iounmap(priv->base);
@@ -1070,22 +1166,23 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
10701166
cpg_mssr_del_clk_provider,
10711167
np);
10721168
if (error)
1073-
return error;
1169+
goto reserve_exit;
10741170

10751171
error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks,
10761172
info->num_core_pm_clks);
10771173
if (error)
1078-
return error;
1174+
goto reserve_exit;
10791175

10801176
/* Reset Controller not supported for Standby Control SoCs */
10811177
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
1082-
return 0;
1178+
goto reserve_exit;
10831179

10841180
error = cpg_mssr_reset_controller_register(priv);
1085-
if (error)
1086-
return error;
10871181

1088-
return 0;
1182+
reserve_exit:
1183+
cpg_mssr_reserved_exit(priv);
1184+
1185+
return error;
10891186
}
10901187

10911188
static struct platform_driver cpg_mssr_driver = {

0 commit comments

Comments
 (0)