* [PATCH v2 0/9] Zynq PM updates
@ 2014-09-02 21:19 Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 1/9] ARM: zynq: PM: Enable A9 internal clock gating feature Soren Brinkmann
` (9 more replies)
0 siblings, 10 replies; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
here is v2 of this series. It's mostly the same and most changes are
related to reformatting comments. The only functional change is in 'ARM:
zynq: PM: Enable DDR clock stop' which does no longer enable
self-refresh too. It seems self-refresh is inflicting a non-negligible
amount of latency that degrades memory performance if enabled throughout
the whole run time.
Thanks,
S?ren
Daniel Lezcano (2):
ARM: zynq: Remove invalidate cache for cpu die
ARM: zynq: cpuidle: Remove pointless code
Soren Brinkmann (7):
ARM: zynq: PM: Enable A9 internal clock gating feature
Documentation: devicetree: Add binding for Synopsys DDR controller
ARM: zynq: DT: Add DDRC node
ARM: zynq: PM: Enable DDR clock stop
ARM: zynq: Synchronise zynq_cpu_die/kill
ARM: zynq: Remove hotplug.c
ARM: zynq: Rename 'zynq_platform_cpu_die'
.../bindings/memory-controllers/synopsys.txt | 11 +++
arch/arm/boot/dts/zynq-7000.dtsi | 5 ++
arch/arm/mach-zynq/Makefile | 3 +-
arch/arm/mach-zynq/common.c | 7 ++
arch/arm/mach-zynq/common.h | 16 ++++-
arch/arm/mach-zynq/hotplug.c | 47 +-----------
arch/arm/mach-zynq/platsmp.c | 41 ++++++++++-
arch/arm/mach-zynq/pm.c | 83 ++++++++++++++++++++++
arch/arm/mach-zynq/slcr.c | 43 ++++++++++-
drivers/cpuidle/cpuidle-zynq.c | 10 +--
10 files changed, 205 insertions(+), 61 deletions(-)
create mode 100644 Documentation/devicetree/bindings/memory-controllers/synopsys.txt
create mode 100644 arch/arm/mach-zynq/pm.c
--
2.1.0.1.g27b9230
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 1/9] ARM: zynq: PM: Enable A9 internal clock gating feature
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
@ 2014-09-02 21:19 ` Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 2/9] Documentation: devicetree: Add binding for Synopsys DDR controller Soren Brinkmann
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
v2:
- make comments comply to kernel-doc format
---
arch/arm/mach-zynq/common.c | 6 ++++++
arch/arm/mach-zynq/common.h | 11 +++++++++++
arch/arm/mach-zynq/platsmp.c | 13 +++++++++++++
3 files changed, 30 insertions(+)
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 31a6fa40ba37..3cb7c198615a 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -98,6 +98,11 @@ static int __init zynq_get_revision(void)
return revision;
}
+static void __init zynq_init_late(void)
+{
+ zynq_core_pm_init();
+}
+
/**
* zynq_init_machine - System specific initialization, intended to be
* called from board specific initialization.
@@ -204,6 +209,7 @@ DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
.map_io = zynq_map_io,
.init_irq = zynq_irq_init,
.init_machine = zynq_init_machine,
+ .init_late = zynq_init_late,
.init_time = zynq_timer_init,
.dt_compat = zynq_dt_match,
.reserve = zynq_memory_init,
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index f652f0a884a6..596ef0b5067c 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -40,4 +40,15 @@ extern void __iomem *zynq_scu_base;
/* Hotplug */
extern void zynq_platform_cpu_die(unsigned int cpu);
+static inline void zynq_core_pm_init(void)
+{
+ /* A9 clock gating */
+ asm volatile ("mrc p15, 0, r12, c15, c0, 0\n"
+ "orr r12, r12, #1\n"
+ "mcr p15, 0, r12, c15, c0, 0\n"
+ : /* no outputs */
+ : /* no inputs */
+ : "r12");
+}
+
#endif
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index abc82ef085c1..6c7843108c7f 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -112,6 +112,18 @@ static void __init zynq_smp_prepare_cpus(unsigned int max_cpus)
scu_enable(zynq_scu_base);
}
+/**
+ * zynq_secondary_init - Initialize secondary CPU cores
+ * @cpu: CPU that is initialized
+ *
+ * This function is in the hotplug path. Don't move it into the
+ * init section!!
+ */
+static void zynq_secondary_init(unsigned int cpu)
+{
+ zynq_core_pm_init();
+}
+
#ifdef CONFIG_HOTPLUG_CPU
static int zynq_cpu_kill(unsigned cpu)
{
@@ -124,6 +136,7 @@ struct smp_operations zynq_smp_ops __initdata = {
.smp_init_cpus = zynq_smp_init_cpus,
.smp_prepare_cpus = zynq_smp_prepare_cpus,
.smp_boot_secondary = zynq_boot_secondary,
+ .smp_secondary_init = zynq_secondary_init,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = zynq_platform_cpu_die,
.cpu_kill = zynq_cpu_kill,
--
2.1.0.1.g27b9230
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 2/9] Documentation: devicetree: Add binding for Synopsys DDR controller
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 1/9] ARM: zynq: PM: Enable A9 internal clock gating feature Soren Brinkmann
@ 2014-09-02 21:19 ` Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 3/9] ARM: zynq: DT: Add DDRC node Soren Brinkmann
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
.../devicetree/bindings/memory-controllers/synopsys.txt | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 Documentation/devicetree/bindings/memory-controllers/synopsys.txt
diff --git a/Documentation/devicetree/bindings/memory-controllers/synopsys.txt b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
new file mode 100644
index 000000000000..f9c6454146b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/synopsys.txt
@@ -0,0 +1,11 @@
+Binding for Synopsys IntelliDDR Multi Protocol Memory Controller
+
+Required properties:
+ - compatible: Should be 'xlnx,zynq-ddrc-a05'
+ - reg: Base address and size of the controllers memory area
+
+Example:
+ memory-controller at f8006000 {
+ compatible = "xlnx,zynq-ddrc-a05";
+ reg = <0xf8006000 0x1000>;
+ };
--
2.1.0.1.g27b9230
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 3/9] ARM: zynq: DT: Add DDRC node
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 1/9] ARM: zynq: PM: Enable A9 internal clock gating feature Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 2/9] Documentation: devicetree: Add binding for Synopsys DDR controller Soren Brinkmann
@ 2014-09-02 21:19 ` Soren Brinkmann
2014-09-03 13:49 ` Daniel Lezcano
2014-09-02 21:19 ` [PATCH v2 4/9] ARM: zynq: PM: Enable DDR clock stop Soren Brinkmann
` (6 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
Add the DDR controller to the Zynq devicetree.
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
arch/arm/boot/dts/zynq-7000.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index 6cc83d4c6c76..587cadcf7001 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -146,6 +146,11 @@
cache-level = <2>;
};
+ memory-controller at f8006000 {
+ compatible = "xlnx,zynq-ddrc-a05";
+ reg = <0xf8006000 0x1000>;
+ } ;
+
uart0: serial at e0000000 {
compatible = "xlnx,xuartps", "cdns,uart-r1p8";
status = "disabled";
--
2.1.0.1.g27b9230
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 4/9] ARM: zynq: PM: Enable DDR clock stop
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
` (2 preceding siblings ...)
2014-09-02 21:19 ` [PATCH v2 3/9] ARM: zynq: DT: Add DDRC node Soren Brinkmann
@ 2014-09-02 21:19 ` Soren Brinkmann
2014-09-04 12:16 ` Daniel Lezcano
2014-09-02 21:19 ` [PATCH v2 5/9] ARM: zynq: Remove invalidate cache for cpu die Soren Brinkmann
` (5 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
The DDR controller can detect idle periods and leverage low power
features clock stop. When new requests occur, the DDRC resumes
normal operation.
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
v2:
- properly document return value for zynq_pm_ioremap
- change zynq_pm_late_init signature to return void
- add kernel doc to late_init()
- fix kernel doc
- only enable clock-stop during boot and leave out self-refresh. The
self-refresh penalty is apparently not-negligible
---
arch/arm/mach-zynq/Makefile | 2 +-
arch/arm/mach-zynq/common.c | 1 +
arch/arm/mach-zynq/common.h | 2 ++
arch/arm/mach-zynq/pm.c | 83 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/mach-zynq/pm.c
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
index 1b25d92ebf22..820dff6e1eba 100644
--- a/arch/arm/mach-zynq/Makefile
+++ b/arch/arm/mach-zynq/Makefile
@@ -3,7 +3,7 @@
#
# Common support
-obj-y := common.o slcr.o
+obj-y := common.o slcr.o pm.o
CFLAGS_REMOVE_hotplug.o =-march=armv6k
CFLAGS_hotplug.o =-Wa,-march=armv7-a -mcpu=cortex-a9
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 3cb7c198615a..6bd13e5ce6b7 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -101,6 +101,7 @@ static int __init zynq_get_revision(void)
static void __init zynq_init_late(void)
{
zynq_core_pm_init();
+ zynq_pm_late_init();
}
/**
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index 596ef0b5067c..0edbb6997b1c 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -40,6 +40,8 @@ extern void __iomem *zynq_scu_base;
/* Hotplug */
extern void zynq_platform_cpu_die(unsigned int cpu);
+void zynq_pm_late_init(void);
+
static inline void zynq_core_pm_init(void)
{
/* A9 clock gating */
diff --git a/arch/arm/mach-zynq/pm.c b/arch/arm/mach-zynq/pm.c
new file mode 100644
index 000000000000..911fcf865be8
--- /dev/null
+++ b/arch/arm/mach-zynq/pm.c
@@ -0,0 +1,83 @@
+/*
+ * Zynq power management
+ *
+ * Copyright (C) 2012 - 2014 Xilinx
+ *
+ * S?ren Brinkmann <soren.brinkmann@xilinx.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include "common.h"
+
+/* register offsets */
+#define DDRC_CTRL_REG1_OFFS 0x60
+#define DDRC_DRAM_PARAM_REG3_OFFS 0x20
+
+/* bitfields */
+#define DDRC_CLOCKSTOP_MASK BIT(23)
+#define DDRC_SELFREFRESH_MASK BIT(12)
+
+static void __iomem *ddrc_base;
+
+/**
+ * zynq_pm_ioremap() - Create IO mappings
+ * @comp: DT compatible string
+ * Return: Pointer to the mapped memory or NULL.
+ *
+ * Remap the memory region for a compatible DT node.
+ */
+static void __iomem *zynq_pm_ioremap(const char *comp)
+{
+ struct device_node *np;
+ void __iomem *base = NULL;
+
+ np = of_find_compatible_node(NULL, NULL, comp);
+ if (np) {
+ base = of_iomap(np, 0);
+ of_node_put(np);
+ } else {
+ pr_warn("%s: no compatible node found for '%s'\n", __func__,
+ comp);
+ }
+
+ return base;
+}
+
+/**
+ * zynq_pm_late_init() - Power management init
+ *
+ * Initialization of power management related featurs and infrastructure.
+ */
+void __init zynq_pm_late_init(void)
+{
+ u32 reg;
+
+ ddrc_base = zynq_pm_ioremap("xlnx,zynq-ddrc-a05");
+ if (!ddrc_base) {
+ pr_warn("%s: Unable to map DDRC IO memory.\n", __func__);
+ } else {
+ /*
+ * Enable DDRC clock stop feature. The HW takes care of
+ * entering/exiting the correct mode depending
+ * on activity state.
+ */
+ reg = readl(ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS);
+ reg |= DDRC_CLOCKSTOP_MASK;
+ writel(reg, ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS);
+ }
+}
--
2.1.0.1.g27b9230
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 5/9] ARM: zynq: Remove invalidate cache for cpu die
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
` (3 preceding siblings ...)
2014-09-02 21:19 ` [PATCH v2 4/9] ARM: zynq: PM: Enable DDR clock stop Soren Brinkmann
@ 2014-09-02 21:19 ` Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 6/9] ARM: zynq: cpuidle: Remove pointless code Soren Brinkmann
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Daniel Lezcano <daniel.lezcano@linaro.org>
As there is no Power management unit on this board, it is not possible to power
down a core, just WFI is allowed. There is no point to invalidate the cache and
exit coherency.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-and-tested-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
arch/arm/mach-zynq/hotplug.c | 32 +-------------------------------
1 file changed, 1 insertion(+), 31 deletions(-)
diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c
index 5052c70326e4..366f46c91365 100644
--- a/arch/arm/mach-zynq/hotplug.c
+++ b/arch/arm/mach-zynq/hotplug.c
@@ -10,35 +10,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-
-#include <asm/cacheflush.h>
-#include <asm/cp15.h>
-#include "common.h"
-
-static inline void zynq_cpu_enter_lowpower(void)
-{
- unsigned int v;
-
- flush_cache_all();
- asm volatile(
- " mcr p15, 0, %1, c7, c5, 0\n"
- " dsb\n"
- /*
- * Turn off coherency
- */
- " mrc p15, 0, %0, c1, c0, 1\n"
- " bic %0, %0, #0x40\n"
- " mcr p15, 0, %0, c1, c0, 1\n"
- " mrc p15, 0, %0, c1, c0, 0\n"
- " bic %0, %0, %2\n"
- " mcr p15, 0, %0, c1, c0, 0\n"
- : "=&r" (v)
- : "r" (0), "Ir" (CR_C)
- : "cc");
-}
+#include <asm/proc-fns.h>
/*
* platform-specific code to shutdown a CPU
@@ -47,8 +19,6 @@ static inline void zynq_cpu_enter_lowpower(void)
*/
void zynq_platform_cpu_die(unsigned int cpu)
{
- zynq_cpu_enter_lowpower();
-
/*
* there is no power-control hardware on this platform, so all
* we can do is put the core into WFI; this is safe as the calling
--
2.1.0.1.g27b9230
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 6/9] ARM: zynq: cpuidle: Remove pointless code
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
` (4 preceding siblings ...)
2014-09-02 21:19 ` [PATCH v2 5/9] ARM: zynq: Remove invalidate cache for cpu die Soren Brinkmann
@ 2014-09-02 21:19 ` Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 7/9] ARM: zynq: Synchronise zynq_cpu_die/kill Soren Brinkmann
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Daniel Lezcano <daniel.lezcano@linaro.org>
The core is not powered down, it is pointless to call the cpu_pm notifiers and
switch to the global timer.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-and-tested-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
drivers/cpuidle/cpuidle-zynq.c | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/drivers/cpuidle/cpuidle-zynq.c b/drivers/cpuidle/cpuidle-zynq.c
index aded75928028..c61b8b2a7c77 100644
--- a/drivers/cpuidle/cpuidle-zynq.c
+++ b/drivers/cpuidle/cpuidle-zynq.c
@@ -26,7 +26,6 @@
*/
#include <linux/init.h>
-#include <linux/cpu_pm.h>
#include <linux/cpuidle.h>
#include <linux/platform_device.h>
#include <asm/proc-fns.h>
@@ -38,15 +37,9 @@
static int zynq_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
- /* Devices must be stopped here */
- cpu_pm_enter();
-
/* Add code for DDR self refresh start */
cpu_do_idle();
- /* Add code for DDR self refresh stop */
- cpu_pm_exit();
-
return index;
}
@@ -59,8 +52,7 @@ static struct cpuidle_driver zynq_idle_driver = {
.enter = zynq_enter_idle,
.exit_latency = 10,
.target_residency = 10000,
- .flags = CPUIDLE_FLAG_TIME_VALID |
- CPUIDLE_FLAG_TIMER_STOP,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
.name = "RAM_SR",
.desc = "WFI and RAM Self Refresh",
},
--
2.1.0.1.g27b9230
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 7/9] ARM: zynq: Synchronise zynq_cpu_die/kill
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
` (5 preceding siblings ...)
2014-09-02 21:19 ` [PATCH v2 6/9] ARM: zynq: cpuidle: Remove pointless code Soren Brinkmann
@ 2014-09-02 21:19 ` Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 8/9] ARM: zynq: Remove hotplug.c Soren Brinkmann
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
Avoid races and add synchronisation between the arch specific
kill and die routines.
The same synchronisation issue was fixed on IMX platform
by this commit:
"ARM: imx: fix sync issue between imx_cpu_die and imx_cpu_kill"
(sha1: 2f3edfd7e27ad4206acbc2ae99c9df5f46353024)
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---
arch/arm/mach-zynq/common.h | 2 ++
arch/arm/mach-zynq/hotplug.c | 2 ++
arch/arm/mach-zynq/platsmp.c | 6 ++++++
arch/arm/mach-zynq/slcr.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index 0edbb6997b1c..24d6340d3fb6 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -24,6 +24,8 @@ extern int zynq_early_slcr_init(void);
extern void zynq_slcr_system_reset(void);
extern void zynq_slcr_cpu_stop(int cpu);
extern void zynq_slcr_cpu_start(int cpu);
+extern bool zynq_slcr_cpu_state_read(int cpu);
+extern void zynq_slcr_cpu_state_write(int cpu, bool die);
extern u32 zynq_slcr_get_device_id(void);
#ifdef CONFIG_SMP
diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c
index 366f46c91365..fe44a05677e2 100644
--- a/arch/arm/mach-zynq/hotplug.c
+++ b/arch/arm/mach-zynq/hotplug.c
@@ -19,6 +19,8 @@
*/
void zynq_platform_cpu_die(unsigned int cpu)
{
+ zynq_slcr_cpu_state_write(cpu, true);
+
/*
* there is no power-control hardware on this platform, so all
* we can do is put the core into WFI; this is safe as the calling
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index 6c7843108c7f..06415eeba7e6 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -127,6 +127,12 @@ static void zynq_secondary_init(unsigned int cpu)
#ifdef CONFIG_HOTPLUG_CPU
static int zynq_cpu_kill(unsigned cpu)
{
+ unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+ while (zynq_slcr_cpu_state_read(cpu))
+ if (time_after(jiffies, timeout))
+ return 0;
+
zynq_slcr_cpu_stop(cpu);
return 1;
}
diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c
index c43a2d16e223..d4cb50cf97c0 100644
--- a/arch/arm/mach-zynq/slcr.c
+++ b/arch/arm/mach-zynq/slcr.c
@@ -138,6 +138,8 @@ void zynq_slcr_cpu_start(int cpu)
zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
reg &= ~(SLCR_A9_CPU_CLKSTOP << cpu);
zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
+
+ zynq_slcr_cpu_state_write(cpu, false);
}
/**
@@ -154,8 +156,47 @@ void zynq_slcr_cpu_stop(int cpu)
}
/**
- * zynq_slcr_init - Regular slcr driver init
+ * zynq_slcr_cpu_state - Read/write cpu state
+ * @cpu: cpu number
*
+ * SLCR_REBOOT_STATUS save upper 2 bits (31/30 cpu states for cpu0 and cpu1)
+ * 0 means cpu is running, 1 cpu is going to die.
+ *
+ * Return: true if cpu is running, false if cpu is going to die
+ */
+bool zynq_slcr_cpu_state_read(int cpu)
+{
+ u32 state;
+
+ state = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET);
+ state &= 1 << (31 - cpu);
+
+ return !state;
+}
+
+/**
+ * zynq_slcr_cpu_state - Read/write cpu state
+ * @cpu: cpu number
+ * @die: cpu state - true if cpu is going to die
+ *
+ * SLCR_REBOOT_STATUS save upper 2 bits (31/30 cpu states for cpu0 and cpu1)
+ * 0 means cpu is running, 1 cpu is going to die.
+ */
+void zynq_slcr_cpu_state_write(int cpu, bool die)
+{
+ u32 state, mask;
+
+ state = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET);
+ mask = 1 << (31 - cpu);
+ if (die)
+ state |= mask;
+ else
+ state &= ~mask;
+ writel(state, zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET);
+}
+
+/**
+ * zynq_slcr_init - Regular slcr driver init
* Return: 0 on success, negative errno otherwise.
*
* Called early during boot from platform code to remap SLCR area.
--
2.1.0.1.g27b9230
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 8/9] ARM: zynq: Remove hotplug.c
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
` (6 preceding siblings ...)
2014-09-02 21:19 ` [PATCH v2 7/9] ARM: zynq: Synchronise zynq_cpu_die/kill Soren Brinkmann
@ 2014-09-02 21:19 ` Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 9/9] ARM: zynq: Rename 'zynq_platform_cpu_die' Soren Brinkmann
2014-09-15 13:34 ` [PATCH v2 0/9] Zynq PM updates Michal Simek
9 siblings, 0 replies; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
The hotplug code contains only a single function, which is an SMP
function. Move that to platsmp.c where all other SMP runctions reside.
That allows removing hotplug.c and declaring the cpu_die function
static.
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
v2:
- don't add function prototype a second time
---
arch/arm/mach-zynq/Makefile | 1 -
arch/arm/mach-zynq/common.h | 3 ---
arch/arm/mach-zynq/hotplug.c | 17 -----------------
arch/arm/mach-zynq/platsmp.c | 18 ++++++++++++++++++
4 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
index 820dff6e1eba..c85fb3f7d5cd 100644
--- a/arch/arm/mach-zynq/Makefile
+++ b/arch/arm/mach-zynq/Makefile
@@ -6,5 +6,4 @@
obj-y := common.o slcr.o pm.o
CFLAGS_REMOVE_hotplug.o =-march=armv6k
CFLAGS_hotplug.o =-Wa,-march=armv7-a -mcpu=cortex-a9
-obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
index 24d6340d3fb6..2bc71273c73c 100644
--- a/arch/arm/mach-zynq/common.h
+++ b/arch/arm/mach-zynq/common.h
@@ -39,9 +39,6 @@ extern struct smp_operations zynq_smp_ops __initdata;
extern void __iomem *zynq_scu_base;
-/* Hotplug */
-extern void zynq_platform_cpu_die(unsigned int cpu);
-
void zynq_pm_late_init(void);
static inline void zynq_core_pm_init(void)
diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c
index fe44a05677e2..b685c89f11e4 100644
--- a/arch/arm/mach-zynq/hotplug.c
+++ b/arch/arm/mach-zynq/hotplug.c
@@ -12,20 +12,3 @@
*/
#include <asm/proc-fns.h>
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void zynq_platform_cpu_die(unsigned int cpu)
-{
- zynq_slcr_cpu_state_write(cpu, true);
-
- /*
- * there is no power-control hardware on this platform, so all
- * we can do is put the core into WFI; this is safe as the calling
- * code will have already disabled interrupts
- */
- for (;;)
- cpu_do_idle();
-}
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index 06415eeba7e6..f722b5a83a45 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -136,6 +136,24 @@ static int zynq_cpu_kill(unsigned cpu)
zynq_slcr_cpu_stop(cpu);
return 1;
}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+static void zynq_platform_cpu_die(unsigned int cpu)
+{
+ zynq_slcr_cpu_state_write(cpu, true);
+
+ /*
+ * there is no power-control hardware on this platform, so all
+ * we can do is put the core into WFI; this is safe as the calling
+ * code will have already disabled interrupts
+ */
+ for (;;)
+ cpu_do_idle();
+}
#endif
struct smp_operations zynq_smp_ops __initdata = {
--
2.1.0.1.g27b9230
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 9/9] ARM: zynq: Rename 'zynq_platform_cpu_die'
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
` (7 preceding siblings ...)
2014-09-02 21:19 ` [PATCH v2 8/9] ARM: zynq: Remove hotplug.c Soren Brinkmann
@ 2014-09-02 21:19 ` Soren Brinkmann
2014-09-15 13:34 ` [PATCH v2 0/9] Zynq PM updates Michal Simek
9 siblings, 0 replies; 13+ messages in thread
From: Soren Brinkmann @ 2014-09-02 21:19 UTC (permalink / raw)
To: linux-arm-kernel
Match the naming pattern of all other SMP ops and rename
zynq_platform_cpu_die --> zynq_cpu_die.
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
---
v2:
- make comments comply to kernel-doc format
---
arch/arm/mach-zynq/platsmp.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index f722b5a83a45..52d768ff7857 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -137,12 +137,14 @@ static int zynq_cpu_kill(unsigned cpu)
return 1;
}
-/*
- * platform-specific code to shutdown a CPU
+/**
+ * zynq_cpu_die - Let a CPU core die
+ * @cpu: Dying CPU
*
- * Called with IRQs disabled
+ * Platform-specific code to shutdown a CPU.
+ * Called with IRQs disabled on the dying CPU.
*/
-static void zynq_platform_cpu_die(unsigned int cpu)
+static void zynq_cpu_die(unsigned int cpu)
{
zynq_slcr_cpu_state_write(cpu, true);
@@ -162,7 +164,7 @@ struct smp_operations zynq_smp_ops __initdata = {
.smp_boot_secondary = zynq_boot_secondary,
.smp_secondary_init = zynq_secondary_init,
#ifdef CONFIG_HOTPLUG_CPU
- .cpu_die = zynq_platform_cpu_die,
+ .cpu_die = zynq_cpu_die,
.cpu_kill = zynq_cpu_kill,
#endif
};
--
2.1.0.1.g27b9230
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 3/9] ARM: zynq: DT: Add DDRC node
2014-09-02 21:19 ` [PATCH v2 3/9] ARM: zynq: DT: Add DDRC node Soren Brinkmann
@ 2014-09-03 13:49 ` Daniel Lezcano
0 siblings, 0 replies; 13+ messages in thread
From: Daniel Lezcano @ 2014-09-03 13:49 UTC (permalink / raw)
To: linux-arm-kernel
On 09/02/2014 11:19 PM, Soren Brinkmann wrote:
> Add the DDR controller to the Zynq devicetree.
>
> Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> arch/arm/boot/dts/zynq-7000.dtsi | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
> index 6cc83d4c6c76..587cadcf7001 100644
> --- a/arch/arm/boot/dts/zynq-7000.dtsi
> +++ b/arch/arm/boot/dts/zynq-7000.dtsi
> @@ -146,6 +146,11 @@
> cache-level = <2>;
> };
>
> + memory-controller at f8006000 {
> + compatible = "xlnx,zynq-ddrc-a05";
> + reg = <0xf8006000 0x1000>;
> + } ;
> +
> uart0: serial at e0000000 {
> compatible = "xlnx,xuartps", "cdns,uart-r1p8";
> status = "disabled";
>
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 4/9] ARM: zynq: PM: Enable DDR clock stop
2014-09-02 21:19 ` [PATCH v2 4/9] ARM: zynq: PM: Enable DDR clock stop Soren Brinkmann
@ 2014-09-04 12:16 ` Daniel Lezcano
0 siblings, 0 replies; 13+ messages in thread
From: Daniel Lezcano @ 2014-09-04 12:16 UTC (permalink / raw)
To: linux-arm-kernel
On 09/02/2014 11:19 PM, Soren Brinkmann wrote:
> The DDR controller can detect idle periods and leverage low power
> features clock stop. When new requests occur, the DDRC resumes
> normal operation.
>
> Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> v2:
> - properly document return value for zynq_pm_ioremap
> - change zynq_pm_late_init signature to return void
> - add kernel doc to late_init()
> - fix kernel doc
> - only enable clock-stop during boot and leave out self-refresh. The
> self-refresh penalty is apparently not-negligible
> ---
> arch/arm/mach-zynq/Makefile | 2 +-
> arch/arm/mach-zynq/common.c | 1 +
> arch/arm/mach-zynq/common.h | 2 ++
> arch/arm/mach-zynq/pm.c | 83 +++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 87 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm/mach-zynq/pm.c
>
> diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
> index 1b25d92ebf22..820dff6e1eba 100644
> --- a/arch/arm/mach-zynq/Makefile
> +++ b/arch/arm/mach-zynq/Makefile
> @@ -3,7 +3,7 @@
> #
>
> # Common support
> -obj-y := common.o slcr.o
> +obj-y := common.o slcr.o pm.o
> CFLAGS_REMOVE_hotplug.o =-march=armv6k
> CFLAGS_hotplug.o =-Wa,-march=armv7-a -mcpu=cortex-a9
> obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
> diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
> index 3cb7c198615a..6bd13e5ce6b7 100644
> --- a/arch/arm/mach-zynq/common.c
> +++ b/arch/arm/mach-zynq/common.c
> @@ -101,6 +101,7 @@ static int __init zynq_get_revision(void)
> static void __init zynq_init_late(void)
> {
> zynq_core_pm_init();
> + zynq_pm_late_init();
> }
>
> /**
> diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h
> index 596ef0b5067c..0edbb6997b1c 100644
> --- a/arch/arm/mach-zynq/common.h
> +++ b/arch/arm/mach-zynq/common.h
> @@ -40,6 +40,8 @@ extern void __iomem *zynq_scu_base;
> /* Hotplug */
> extern void zynq_platform_cpu_die(unsigned int cpu);
>
> +void zynq_pm_late_init(void);
> +
> static inline void zynq_core_pm_init(void)
> {
> /* A9 clock gating */
> diff --git a/arch/arm/mach-zynq/pm.c b/arch/arm/mach-zynq/pm.c
> new file mode 100644
> index 000000000000..911fcf865be8
> --- /dev/null
> +++ b/arch/arm/mach-zynq/pm.c
> @@ -0,0 +1,83 @@
> +/*
> + * Zynq power management
> + *
> + * Copyright (C) 2012 - 2014 Xilinx
> + *
> + * S?ren Brinkmann <soren.brinkmann@xilinx.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include "common.h"
> +
> +/* register offsets */
> +#define DDRC_CTRL_REG1_OFFS 0x60
> +#define DDRC_DRAM_PARAM_REG3_OFFS 0x20
> +
> +/* bitfields */
> +#define DDRC_CLOCKSTOP_MASK BIT(23)
> +#define DDRC_SELFREFRESH_MASK BIT(12)
> +
> +static void __iomem *ddrc_base;
> +
> +/**
> + * zynq_pm_ioremap() - Create IO mappings
> + * @comp: DT compatible string
> + * Return: Pointer to the mapped memory or NULL.
> + *
> + * Remap the memory region for a compatible DT node.
> + */
> +static void __iomem *zynq_pm_ioremap(const char *comp)
> +{
> + struct device_node *np;
> + void __iomem *base = NULL;
> +
> + np = of_find_compatible_node(NULL, NULL, comp);
> + if (np) {
> + base = of_iomap(np, 0);
> + of_node_put(np);
> + } else {
> + pr_warn("%s: no compatible node found for '%s'\n", __func__,
> + comp);
> + }
> +
> + return base;
> +}
> +
> +/**
> + * zynq_pm_late_init() - Power management init
> + *
> + * Initialization of power management related featurs and infrastructure.
> + */
> +void __init zynq_pm_late_init(void)
> +{
> + u32 reg;
> +
> + ddrc_base = zynq_pm_ioremap("xlnx,zynq-ddrc-a05");
> + if (!ddrc_base) {
> + pr_warn("%s: Unable to map DDRC IO memory.\n", __func__);
> + } else {
> + /*
> + * Enable DDRC clock stop feature. The HW takes care of
> + * entering/exiting the correct mode depending
> + * on activity state.
> + */
> + reg = readl(ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS);
> + reg |= DDRC_CLOCKSTOP_MASK;
> + writel(reg, ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS);
> + }
> +}
>
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 0/9] Zynq PM updates
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
` (8 preceding siblings ...)
2014-09-02 21:19 ` [PATCH v2 9/9] ARM: zynq: Rename 'zynq_platform_cpu_die' Soren Brinkmann
@ 2014-09-15 13:34 ` Michal Simek
9 siblings, 0 replies; 13+ messages in thread
From: Michal Simek @ 2014-09-15 13:34 UTC (permalink / raw)
To: linux-arm-kernel
On 09/02/2014 11:19 PM, Soren Brinkmann wrote:
> Hi all,
>
> here is v2 of this series. It's mostly the same and most changes are
> related to reformatting comments. The only functional change is in 'ARM:
> zynq: PM: Enable DDR clock stop' which does no longer enable
> self-refresh too. It seems self-refresh is inflicting a non-negligible
> amount of latency that degrades memory performance if enabled throughout
> the whole run time.
>
> Thanks,
> S?ren
>
> Daniel Lezcano (2):
> ARM: zynq: Remove invalidate cache for cpu die
> ARM: zynq: cpuidle: Remove pointless code
>
> Soren Brinkmann (7):
> ARM: zynq: PM: Enable A9 internal clock gating feature
> Documentation: devicetree: Add binding for Synopsys DDR controller
> ARM: zynq: DT: Add DDRC node
> ARM: zynq: PM: Enable DDR clock stop
> ARM: zynq: Synchronise zynq_cpu_die/kill
> ARM: zynq: Remove hotplug.c
> ARM: zynq: Rename 'zynq_platform_cpu_die'
>
> .../bindings/memory-controllers/synopsys.txt | 11 +++
> arch/arm/boot/dts/zynq-7000.dtsi | 5 ++
> arch/arm/mach-zynq/Makefile | 3 +-
> arch/arm/mach-zynq/common.c | 7 ++
> arch/arm/mach-zynq/common.h | 16 ++++-
> arch/arm/mach-zynq/hotplug.c | 47 +-----------
> arch/arm/mach-zynq/platsmp.c | 41 ++++++++++-
> arch/arm/mach-zynq/pm.c | 83 ++++++++++++++++++++++
> arch/arm/mach-zynq/slcr.c | 43 ++++++++++-
> drivers/cpuidle/cpuidle-zynq.c | 10 +--
> 10 files changed, 205 insertions(+), 61 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/memory-controllers/synopsys.txt
> create mode 100644 arch/arm/mach-zynq/pm.c
>
Applied all.
Thanks,
Michal
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140915/44223b5e/attachment.sig>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2014-09-15 13:34 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-02 21:19 [PATCH v2 0/9] Zynq PM updates Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 1/9] ARM: zynq: PM: Enable A9 internal clock gating feature Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 2/9] Documentation: devicetree: Add binding for Synopsys DDR controller Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 3/9] ARM: zynq: DT: Add DDRC node Soren Brinkmann
2014-09-03 13:49 ` Daniel Lezcano
2014-09-02 21:19 ` [PATCH v2 4/9] ARM: zynq: PM: Enable DDR clock stop Soren Brinkmann
2014-09-04 12:16 ` Daniel Lezcano
2014-09-02 21:19 ` [PATCH v2 5/9] ARM: zynq: Remove invalidate cache for cpu die Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 6/9] ARM: zynq: cpuidle: Remove pointless code Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 7/9] ARM: zynq: Synchronise zynq_cpu_die/kill Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 8/9] ARM: zynq: Remove hotplug.c Soren Brinkmann
2014-09-02 21:19 ` [PATCH v2 9/9] ARM: zynq: Rename 'zynq_platform_cpu_die' Soren Brinkmann
2014-09-15 13:34 ` [PATCH v2 0/9] Zynq PM updates Michal Simek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).