clk: ingenic: Handle setting the Low-Power Mode bit
authorPaul Cercueil <paul@crapouillou.net>
Tue, 11 Jun 2019 18:07:54 +0000 (20:07 +0200)
committerStephen Boyd <sboyd@kernel.org>
Tue, 25 Jun 2019 22:43:15 +0000 (15:43 -0700)
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: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/ingenic/Makefile
drivers/clk/ingenic/jz4725b-cgu.c
drivers/clk/ingenic/jz4740-cgu.c
drivers/clk/ingenic/jz4770-cgu.c
drivers/clk/ingenic/jz4780-cgu.c
drivers/clk/ingenic/pm.c [new file with mode: 0644]
drivers/clk/ingenic/pm.h [new file with mode: 0644]

index 00a79b2fba1083044eaa88fd20da115d0d609e99..589a2b772b0d5fb9940b98a4d9a232931f61a616 100644 (file)
@@ -1,4 +1,4 @@
-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_JZ4725B)      += jz4725b-cgu.o
 obj-$(CONFIG_INGENIC_CGU_JZ4770)       += jz4770-cgu.o
index 47287956824b3ea4d264384e0543db6184de235e..2642d36d1e2cb685a10af21c3b32c95d12f123ec 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/of.h>
 #include <dt-bindings/clock/jz4725b-cgu.h>
 #include "cgu.h"
+#include "pm.h"
 
 /* CGU register offsets */
 #define CGU_REG_CPCCR          0x00
@@ -253,5 +254,7 @@ static void __init jz4725b_cgu_init(struct device_node *np)
        retval = ingenic_cgu_register_clocks(cgu);
        if (retval)
                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);
index e6b462f9bfe5f6033a5f2ea89b5aa7a9fbb3d311..75651544cb30ec806fb8b62dbf04eaa673bbaf81 100644 (file)
@@ -22,6 +22,7 @@
 #include <dt-bindings/clock/jz4740-cgu.h>
 #include <asm/mach-jz4740/clock.h>
 #include "cgu.h"
+#include "pm.h"
 
 /* CGU register offsets */
 #define CGU_REG_CPCCR          0x00
@@ -247,6 +248,8 @@ static void __init jz4740_cgu_init(struct device_node *np)
        retval = ingenic_cgu_register_clocks(cgu);
        if (retval)
                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);
 
index 2a29da442a8eb0c08020e0e1ccc68b0c4ee16a09..eebc1bea3841ea6938a1954f056ce8544952dced 100644 (file)
@@ -9,9 +9,9 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of.h>
-#include <linux/syscore_ops.h>
 #include <dt-bindings/clock/jz4770-cgu.h>
 #include "cgu.h"
+#include "pm.h"
 
 /*
  * CPM registers offset address definition
@@ -38,9 +38,6 @@
 #define CGU_REG_MSC2CDR                0xA8
 #define CGU_REG_BCHCDR         0xAC
 
-/* bits within the LCR register */
-#define LCR_LPM                        BIT(0)          /* Low Power Mode */
-
 /* bits within the OPCR register */
 #define OPCR_SPENDH            BIT(5)          /* UHC PHY suspend */
 
@@ -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)
 {
        int retval;
@@ -466,9 +439,7 @@ static void __init jz4770_cgu_init(struct device_node *np)
        if (retval)
                pr_err("%s: failed to register CGU Clocks\n", __func__);
 
-#if IS_ENABLED(CONFIG_PM_SLEEP)
-       register_syscore_ops(&jz4770_cgu_pm_ops);
-#endif
+       ingenic_cgu_register_syscore_ops(cgu);
 }
 
 /* We only probe via devicetree, no need for a platform driver */
index d03b7fcfd82be88c761b82fde5d98df781560fc1..4cfcef98accc8de46bb5fe6b0a6c2c54c4684ac1 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/of.h>
 #include <dt-bindings/clock/jz4780-cgu.h>
 #include "cgu.h"
+#include "pm.h"
 
 /* CGU register offsets */
 #define CGU_REG_CLOCKCONTROL   0x00
@@ -730,5 +731,7 @@ static void __init jz4780_cgu_init(struct device_node *np)
                pr_err("%s: failed to register CGU Clocks\n", __func__);
                return;
        }
+
+       ingenic_cgu_register_syscore_ops(cgu);
 }
 CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
diff --git a/drivers/clk/ingenic/pm.c b/drivers/clk/ingenic/pm.c
new file mode 100644 (file)
index 0000000..341752b
--- /dev/null
@@ -0,0 +1,45 @@
+// 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);
+       }
+}
diff --git a/drivers/clk/ingenic/pm.h b/drivers/clk/ingenic/pm.h
new file mode 100644 (file)
index 0000000..fa75404
--- /dev/null
@@ -0,0 +1,12 @@
+/* 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 */