Commit 2ee93e3c authored by Paul Cercueil's avatar Paul Cercueil Committed by Stephen Boyd

clk: ingenic: Handle setting the Low-Power Mode bit

The Low-Power Mode, when enabled, will make the "wait" MIPS instruction
suspend the system.

This is not really clock-related, but this bit happens to be in the
register set of the CGU.
Signed-off-by: default avatarPaul Cercueil <paul@crapouillou.net>
Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent dbc38ad0
obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o pm.o
obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <dt-bindings/clock/jz4725b-cgu.h> #include <dt-bindings/clock/jz4725b-cgu.h>
#include "cgu.h" #include "cgu.h"
#include "pm.h"
/* CGU register offsets */ /* CGU register offsets */
#define CGU_REG_CPCCR 0x00 #define CGU_REG_CPCCR 0x00
...@@ -253,5 +254,7 @@ static void __init jz4725b_cgu_init(struct device_node *np) ...@@ -253,5 +254,7 @@ static void __init jz4725b_cgu_init(struct device_node *np)
retval = ingenic_cgu_register_clocks(cgu); retval = ingenic_cgu_register_clocks(cgu);
if (retval) if (retval)
pr_err("%s: failed to register CGU Clocks\n", __func__); pr_err("%s: failed to register CGU Clocks\n", __func__);
ingenic_cgu_register_syscore_ops(cgu);
} }
CLK_OF_DECLARE(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init); CLK_OF_DECLARE(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <dt-bindings/clock/jz4740-cgu.h> #include <dt-bindings/clock/jz4740-cgu.h>
#include <asm/mach-jz4740/clock.h> #include <asm/mach-jz4740/clock.h>
#include "cgu.h" #include "cgu.h"
#include "pm.h"
/* CGU register offsets */ /* CGU register offsets */
#define CGU_REG_CPCCR 0x00 #define CGU_REG_CPCCR 0x00
...@@ -247,6 +248,8 @@ static void __init jz4740_cgu_init(struct device_node *np) ...@@ -247,6 +248,8 @@ static void __init jz4740_cgu_init(struct device_node *np)
retval = ingenic_cgu_register_clocks(cgu); retval = ingenic_cgu_register_clocks(cgu);
if (retval) if (retval)
pr_err("%s: failed to register CGU Clocks\n", __func__); pr_err("%s: failed to register CGU Clocks\n", __func__);
ingenic_cgu_register_syscore_ops(cgu);
} }
CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init); CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
......
...@@ -9,9 +9,9 @@ ...@@ -9,9 +9,9 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/syscore_ops.h>
#include <dt-bindings/clock/jz4770-cgu.h> #include <dt-bindings/clock/jz4770-cgu.h>
#include "cgu.h" #include "cgu.h"
#include "pm.h"
/* /*
* CPM registers offset address definition * CPM registers offset address definition
...@@ -38,9 +38,6 @@ ...@@ -38,9 +38,6 @@
#define CGU_REG_MSC2CDR 0xA8 #define CGU_REG_MSC2CDR 0xA8
#define CGU_REG_BCHCDR 0xAC #define CGU_REG_BCHCDR 0xAC
/* bits within the LCR register */
#define LCR_LPM BIT(0) /* Low Power Mode */
/* bits within the OPCR register */ /* bits within the OPCR register */
#define OPCR_SPENDH BIT(5) /* UHC PHY suspend */ #define OPCR_SPENDH BIT(5) /* UHC PHY suspend */
...@@ -429,30 +426,6 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { ...@@ -429,30 +426,6 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
}, },
}; };
#if IS_ENABLED(CONFIG_PM_SLEEP)
static int jz4770_cgu_pm_suspend(void)
{
u32 val;
val = readl(cgu->base + CGU_REG_LCR);
writel(val | LCR_LPM, cgu->base + CGU_REG_LCR);
return 0;
}
static void jz4770_cgu_pm_resume(void)
{
u32 val;
val = readl(cgu->base + CGU_REG_LCR);
writel(val & ~LCR_LPM, cgu->base + CGU_REG_LCR);
}
static struct syscore_ops jz4770_cgu_pm_ops = {
.suspend = jz4770_cgu_pm_suspend,
.resume = jz4770_cgu_pm_resume,
};
#endif /* CONFIG_PM_SLEEP */
static void __init jz4770_cgu_init(struct device_node *np) static void __init jz4770_cgu_init(struct device_node *np)
{ {
int retval; int retval;
...@@ -466,9 +439,7 @@ static void __init jz4770_cgu_init(struct device_node *np) ...@@ -466,9 +439,7 @@ static void __init jz4770_cgu_init(struct device_node *np)
if (retval) if (retval)
pr_err("%s: failed to register CGU Clocks\n", __func__); pr_err("%s: failed to register CGU Clocks\n", __func__);
#if IS_ENABLED(CONFIG_PM_SLEEP) ingenic_cgu_register_syscore_ops(cgu);
register_syscore_ops(&jz4770_cgu_pm_ops);
#endif
} }
/* We only probe via devicetree, no need for a platform driver */ /* We only probe via devicetree, no need for a platform driver */
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <dt-bindings/clock/jz4780-cgu.h> #include <dt-bindings/clock/jz4780-cgu.h>
#include "cgu.h" #include "cgu.h"
#include "pm.h"
/* CGU register offsets */ /* CGU register offsets */
#define CGU_REG_CLOCKCONTROL 0x00 #define CGU_REG_CLOCKCONTROL 0x00
...@@ -730,5 +731,7 @@ static void __init jz4780_cgu_init(struct device_node *np) ...@@ -730,5 +731,7 @@ static void __init jz4780_cgu_init(struct device_node *np)
pr_err("%s: failed to register CGU Clocks\n", __func__); pr_err("%s: failed to register CGU Clocks\n", __func__);
return; return;
} }
ingenic_cgu_register_syscore_ops(cgu);
} }
CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init); CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net>
*/
#include "cgu.h"
#include "pm.h"
#include <linux/io.h>
#include <linux/syscore_ops.h>
#define CGU_REG_LCR 0x04
#define LCR_LOW_POWER_MODE BIT(0)
static void __iomem * __maybe_unused ingenic_cgu_base;
static int __maybe_unused ingenic_cgu_pm_suspend(void)
{
u32 val = readl(ingenic_cgu_base + CGU_REG_LCR);
writel(val | LCR_LOW_POWER_MODE, ingenic_cgu_base + CGU_REG_LCR);
return 0;
}
static void __maybe_unused ingenic_cgu_pm_resume(void)
{
u32 val = readl(ingenic_cgu_base + CGU_REG_LCR);
writel(val & ~LCR_LOW_POWER_MODE, ingenic_cgu_base + CGU_REG_LCR);
}
static struct syscore_ops __maybe_unused ingenic_cgu_pm_ops = {
.suspend = ingenic_cgu_pm_suspend,
.resume = ingenic_cgu_pm_resume,
};
void ingenic_cgu_register_syscore_ops(struct ingenic_cgu *cgu)
{
if (IS_ENABLED(CONFIG_PM_SLEEP)) {
ingenic_cgu_base = cgu->base;
register_syscore_ops(&ingenic_cgu_pm_ops);
}
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net>
*/
#ifndef DRIVERS_CLK_INGENIC_PM_H
#define DRIVERS_CLK_INGENIC_PM_H
struct ingenic_cgu;
void ingenic_cgu_register_syscore_ops(struct ingenic_cgu *cgu);
#endif /* DRIVERS_CLK_INGENIC_PM_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment