Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f4023cd authored by Geert Uytterhoeven's avatar Geert Uytterhoeven
Browse files

clk: renesas: cpg-mssr: Add support to restore core clocks during resume



On R-Car Gen3 systems, PSCI system suspend powers down the SoC, possibly
losing clock configuration.  Hence add a notifier chain that can be used
by core clocks to save/restore clock state during system suspend/resume.

The implementation of the actual clock state save/restore operations is
clock-specific, and to be registered with the notifier chain in the SoC
or family-specific cpg_mssr_info.cpg_clk_register() callback.

Signed-off-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Tested-by: default avatarNiklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
parent 56086910
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -262,10 +262,9 @@ static unsigned int cpg_pll0_div __initdata;
static u32 cpg_mode __initdata;

struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
					       const struct cpg_core_clk *core,
					       const struct cpg_mssr_info *info,
					       struct clk **clks,
					       void __iomem *base)
	const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
	struct clk **clks, void __iomem *base,
	struct raw_notifier_head *notifiers)
{
	const struct clk_div_table *table = NULL;
	const struct clk *parent;
+3 −3
Original line number Diff line number Diff line
@@ -34,9 +34,9 @@ struct rcar_gen2_cpg_pll_config {
};

struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
				       const struct cpg_core_clk *core,
				       const struct cpg_mssr_info *info,
				       struct clk **clks, void __iomem *base);
	const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
	struct clk **clks, void __iomem *base,
	struct raw_notifier_head *notifiers);
int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
		       unsigned int pll0_div, u32 mode);

+2 −1
Original line number Diff line number Diff line
@@ -265,7 +265,8 @@ static const struct soc_device_attribute cpg_quirks_match[] __initconst = {

struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
	const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
	struct clk **clks, void __iomem *base)
	struct clk **clks, void __iomem *base,
	struct raw_notifier_head *notifiers)
{
	const struct clk *parent;
	unsigned int mult = 1;
+2 −1
Original line number Diff line number Diff line
@@ -44,7 +44,8 @@ struct rcar_gen3_cpg_pll_config {

struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
	const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
	struct clk **clks, void __iomem *base);
	struct clk **clks, void __iomem *base,
	struct raw_notifier_head *notifiers);
int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
		       unsigned int clk_extalr, u32 mode);

+11 −1
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ static const u16 srcr[] = {
 * @num_core_clks: Number of Core Clocks in clks[]
 * @num_mod_clks: Number of Module Clocks in clks[]
 * @last_dt_core_clk: ID of the last Core Clock exported to DT
 * @notifiers: Notifier chain to save/restore clock state for system resume
 * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control
 * @smstpcr_saved[].val: Saved values of SMSTPCR[]
 */
@@ -123,6 +124,7 @@ struct cpg_mssr_priv {
	unsigned int num_mod_clks;
	unsigned int last_dt_core_clk;

	struct raw_notifier_head notifiers;
	struct {
		u32 mask;
		u32 val;
@@ -312,7 +314,8 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
	default:
		if (info->cpg_clk_register)
			clk = info->cpg_clk_register(dev, core, info,
						     priv->clks, priv->base);
						     priv->clks, priv->base,
						     &priv->notifiers);
		else
			dev_err(dev, "%s has unsupported core clock type %u\n",
				core->name, core->type);
@@ -726,6 +729,9 @@ static int cpg_mssr_suspend_noirq(struct device *dev)
				readl(priv->base + SMSTPCR(reg));
	}

	/* Save core clocks */
	raw_notifier_call_chain(&priv->notifiers, PM_EVENT_SUSPEND, NULL);

	return 0;
}

@@ -739,6 +745,9 @@ static int cpg_mssr_resume_noirq(struct device *dev)
	if (!psci_ops.cpu_suspend)
		return 0;

	/* Restore core clocks */
	raw_notifier_call_chain(&priv->notifiers, PM_EVENT_RESUME, NULL);

	/* Restore module clocks */
	for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
		mask = priv->smstpcr_saved[reg].mask;
@@ -822,6 +831,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
	priv->num_core_clks = info->num_total_core_clks;
	priv->num_mod_clks = info->num_hw_mod_clks;
	priv->last_dt_core_clk = info->last_dt_core_clk;
	RAW_INIT_NOTIFIER_HEAD(&priv->notifiers);

	for (i = 0; i < nclks; i++)
		clks[i] = ERR_PTR(-ENOENT);
Loading