* [PATCH V2 0/5] ARM: exynos4: Add l2 retention mode cpuidle state
@ 2011-11-11 6:29 Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 1/5] ARM: exynos4: Add support for AFTR " Amit Daniel Kachhap
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Amit Daniel Kachhap @ 2011-11-11 6:29 UTC (permalink / raw)
To: linux-arm-kernel
Changes since V1:
*rebased the whole patch against 3.2-rc1 tree
*removed GIC save/restore in AFTR cpuidle state as it is external
to cpu powerdomain
*Added L2 setup code through device tree
*Removed only l2 save/restore registers in sleep
This Patch series adds support for AFTR mode cpuidle state based on
patch (http://www.spinics.net/lists/arm-kernel/msg132243.html) earlier
submitted by Jaecheol Lee <jc.lee@samsung.com>.
This patch uses CPU PM notifiers , common l2 save/restore and
new cpu_suspend/resume interfaces and is based on the tip of
for-next branch of samsung tree.
(git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git for-next).
Amit Daniel Kachhap (5):
ARM: exynos4: Add support for AFTR mode cpuidle state
ARM: exynos4: remove useless churn in sleep.S
ARM: exynos4: add L2 early resume code
ARM: exynos4: remove useless code to save/restore L2
ARM: exynos4: Enable l2 configuration through device tree
arch/arm/mach-exynos/cpu.c | 60 +++++++++----
arch/arm/mach-exynos/cpuidle.c | 148 ++++++++++++++++++++++++++++++-
arch/arm/mach-exynos/include/mach/pmu.h | 2 +
arch/arm/mach-exynos/pm.c | 15 ---
arch/arm/plat-s5p/sleep.S | 32 +++++++-
5 files changed, 221 insertions(+), 36 deletions(-)
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH V2 1/5] ARM: exynos4: Add support for AFTR mode cpuidle state
2011-11-11 6:29 [PATCH V2 0/5] ARM: exynos4: Add l2 retention mode cpuidle state Amit Daniel Kachhap
@ 2011-11-11 6:29 ` Amit Daniel Kachhap
2011-11-11 10:17 ` Lorenzo Pieralisi
2011-11-11 6:29 ` [PATCH V2 2/5] ARM: exynos4: remove useless churn in sleep.S Amit Daniel Kachhap
` (3 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Amit Daniel Kachhap @ 2011-11-11 6:29 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds support for AFTR(ARM OFF TOP RUNNING) mode in
cpuidle driver for EXYNOS4210. L2 cache keeps their data in this mode.
This patch adds the code to the latest interfaces to
save/restore CPU state inclusive of CPU PM notifiers, l2
resume and cpu_suspend/resume.
Signed-off-by: Jaecheol Lee <jc.lee@samsung.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
---
arch/arm/mach-exynos/cpuidle.c | 148 ++++++++++++++++++++++++++++++-
arch/arm/mach-exynos/include/mach/pmu.h | 2 +
2 files changed, 146 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
index c6485d3..857ccc6 100644
--- a/arch/arm/mach-exynos/cpuidle.c
+++ b/arch/arm/mach-exynos/cpuidle.c
@@ -12,13 +12,31 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
#include <linux/io.h>
-
+#include <linux/suspend.h>
+#include <linux/err.h>
#include <asm/proc-fns.h>
+#include <asm/smp_scu.h>
+#include <asm/suspend.h>
+#include <asm/unified.h>
+#include <mach/regs-pmu.h>
+#include <mach/pmu.h>
+
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+
+#define REG_DIRECTGO_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \
+ S5P_INFORM7 : (S5P_VA_SYSRAM + 0x24))
+#define REG_DIRECTGO_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \
+ S5P_INFORM6 : (S5P_VA_SYSRAM + 0x20))
static int exynos4_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index);
+static int exynos4_enter_lowpower(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index);
static struct cpuidle_state exynos4_cpuidle_set[] = {
[0] = {
@@ -26,9 +44,17 @@ static struct cpuidle_state exynos4_cpuidle_set[] = {
.exit_latency = 1,
.target_residency = 100000,
.flags = CPUIDLE_FLAG_TIME_VALID,
- .name = "IDLE",
+ .name = "C0",
.desc = "ARM clock gating(WFI)",
},
+ [1] = {
+ .enter = exynos4_enter_lowpower,
+ .exit_latency = 300,
+ .target_residency = 100000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "C1",
+ .desc = "ARM power down",
+ },
};
static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
@@ -38,9 +64,95 @@ static struct cpuidle_driver exynos4_idle_driver = {
.owner = THIS_MODULE,
};
+/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
+static void exynos4_set_wakeupmask(void)
+{
+ __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK);
+}
+
+static unsigned int g_pwr_ctrl, g_diag_reg;
+
+static void save_cpu_arch_register(void)
+{
+ /*read power control register*/
+ asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc");
+ /*read diagnostic register*/
+ asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
+ return;
+}
+
+static void restore_cpu_arch_register(void)
+{
+ /*write power control register*/
+ asm("mcr p15, 0, %0, c15, c0, 0" : : "r"(g_pwr_ctrl) : "cc");
+ /*write diagnostic register*/
+ asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
+ return;
+}
+
+static int idle_finisher(unsigned long flags)
+{
+ cpu_do_idle();
+ return 1;
+}
+
+static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ struct timeval before, after;
+ int idle_time;
+ unsigned long tmp;
+
+ local_irq_disable();
+ do_gettimeofday(&before);
+
+ exynos4_set_wakeupmask();
+
+ /* Set value of power down register for aftr mode */
+ exynos4_sys_powerdown_conf(SYS_AFTR);
+
+ save_cpu_arch_register();
+
+ /* Setting Central Sequence Register for power down mode */
+ tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
+ __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+
+ cpu_suspend(0, idle_finisher);
+
+ scu_enable(S5P_VA_SCU);
+
+ restore_cpu_arch_register();
+
+ /*
+ * If PMU failed while entering sleep mode, WFI will be
+ * ignored by PMU and then exiting cpu_do_idle().
+ * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
+ * in this situation.
+ */
+ tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+ if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
+ tmp |= S5P_CENTRAL_LOWPWR_CFG;
+ __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+ }
+
+ /* Clear wakeup state register */
+ __raw_writel(0x0, S5P_WAKEUP_STAT);
+
+ do_gettimeofday(&after);
+
+ local_irq_enable();
+ idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+ (after.tv_usec - before.tv_usec);
+
+ dev->last_residency = idle_time;
+ return index;
+}
+
static int exynos4_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
- int index)
+ int index)
{
struct timeval before, after;
int idle_time;
@@ -59,6 +171,24 @@ static int exynos4_enter_idle(struct cpuidle_device *dev,
return index;
}
+static int exynos4_enter_lowpower(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ int new_index = index;
+
+ /* This mode only can be entered when other core's are offline */
+ if (num_online_cpus() > 1) {
+ new_index = drv->safe_state_index;
+ BUG_ON(new_index > drv->state_count);
+ }
+
+ if (new_index == 0)
+ return exynos4_enter_idle(dev, drv, new_index);
+ else
+ return exynos4_enter_core0_aftr(dev, drv, new_index);
+}
+
static int __init exynos4_init_cpuidle(void)
{
int i, max_cpuidle_state, cpu_id;
@@ -73,19 +203,29 @@ static int __init exynos4_init_cpuidle(void)
memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
sizeof(struct cpuidle_state));
}
+ drv->safe_state_index = 0;
cpuidle_register_driver(&exynos4_idle_driver);
for_each_cpu(cpu_id, cpu_online_mask) {
device = &per_cpu(exynos4_cpuidle_device, cpu_id);
device->cpu = cpu_id;
- device->state_count = drv->state_count;
+ if (cpu_id == 0)
+ device->state_count = (sizeof(exynos4_cpuidle_set) /
+ sizeof(struct cpuidle_state));
+ else
+ device->state_count = 1; /* Support IDLE only */
if (cpuidle_register_device(device)) {
printk(KERN_ERR "CPUidle register device failed\n,");
return -EIO;
}
}
+
+ __raw_writel(BSYM(virt_to_phys(s3c_cpu_resume)),
+ REG_DIRECTGO_ADDR);
+ __raw_writel(0xfcba0d10, REG_DIRECTGO_FLAG);
+
return 0;
}
device_initcall(exynos4_init_cpuidle);
diff --git a/arch/arm/mach-exynos/include/mach/pmu.h b/arch/arm/mach-exynos/include/mach/pmu.h
index 632dd56..e76b7fa 100644
--- a/arch/arm/mach-exynos/include/mach/pmu.h
+++ b/arch/arm/mach-exynos/include/mach/pmu.h
@@ -22,11 +22,13 @@ enum sys_powerdown {
NUM_SYS_POWERDOWN,
};
+extern unsigned long l2x0_regs_phys;
struct exynos4_pmu_conf {
void __iomem *reg;
unsigned int val[NUM_SYS_POWERDOWN];
};
extern void exynos4_sys_powerdown_conf(enum sys_powerdown mode);
+extern void s3c_cpu_resume(void);
#endif /* __ASM_ARCH_PMU_H */
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH V2 2/5] ARM: exynos4: remove useless churn in sleep.S
2011-11-11 6:29 [PATCH V2 0/5] ARM: exynos4: Add l2 retention mode cpuidle state Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 1/5] ARM: exynos4: Add support for AFTR " Amit Daniel Kachhap
@ 2011-11-11 6:29 ` Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 3/5] ARM: exynos4: add L2 early resume code Amit Daniel Kachhap
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Amit Daniel Kachhap @ 2011-11-11 6:29 UTC (permalink / raw)
To: linux-arm-kernel
This patch cleans up sleep code in preparation for L2 resume code
and hotplug functions
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
---
arch/arm/plat-s5p/sleep.S | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/arch/arm/plat-s5p/sleep.S b/arch/arm/plat-s5p/sleep.S
index 0fd591b..c371ba2 100644
--- a/arch/arm/plat-s5p/sleep.S
+++ b/arch/arm/plat-s5p/sleep.S
@@ -23,7 +23,6 @@
*/
#include <linux/linkage.h>
-#include <asm/assembler.h>
.text
@@ -44,6 +43,9 @@
* other way of restoring the stack pointer after sleep, and we
* must not write to the code segment (code is read-only)
*/
+ .align
+ .data
ENTRY(s3c_cpu_resume)
b cpu_resume
+ENDPROC(s3c_cpu_resume)
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH V2 3/5] ARM: exynos4: add L2 early resume code
2011-11-11 6:29 [PATCH V2 0/5] ARM: exynos4: Add l2 retention mode cpuidle state Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 1/5] ARM: exynos4: Add support for AFTR " Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 2/5] ARM: exynos4: remove useless churn in sleep.S Amit Daniel Kachhap
@ 2011-11-11 6:29 ` Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 4/5] ARM: exynos4: remove useless code to save/restore L2 Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 5/5] ARM: exynos4: Enable l2 configuration through device tree Amit Daniel Kachhap
4 siblings, 0 replies; 8+ messages in thread
From: Amit Daniel Kachhap @ 2011-11-11 6:29 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds code to save L2 register configuration at boot, and to
resume L2 before MMU is enabled in suspend and cpuidle resume paths.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
---
arch/arm/mach-exynos/cpu.c | 42 +++++++++++++++++++++++++++++++-----------
arch/arm/plat-s5p/sleep.S | 28 ++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-exynos/cpu.c b/arch/arm/mach-exynos/cpu.c
index 8e09f34..252e346 100644
--- a/arch/arm/mach-exynos/cpu.c
+++ b/arch/arm/mach-exynos/cpu.c
@@ -19,6 +19,7 @@
#include <asm/proc-fns.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/gic.h>
+#include <asm/cacheflush.h>
#include <plat/cpu.h>
#include <plat/clock.h>
@@ -34,6 +35,7 @@
#include <mach/regs-irq.h>
#include <mach/regs-pmu.h>
+#include <mach/pmu.h>
unsigned int gic_bank_offset __read_mostly;
@@ -297,20 +299,38 @@ core_initcall(exynos4_core_init);
#ifdef CONFIG_CACHE_L2X0
static int __init exynos4_l2x0_cache_init(void)
{
- /* TAG, Data Latency Control: 2cycle */
- __raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
+ if (!(__raw_readl(S5P_VA_L2CC + L2X0_CTRL) & 0x1)) {
+ l2x0_saved_regs.phy_base = EXYNOS4_PA_L2CC;
+ /* TAG, Data Latency Control: 2 cycles */
+ l2x0_saved_regs.tag_latency = 0x110;
- if (soc_is_exynos4210())
- __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
- else if (soc_is_exynos4212() || soc_is_exynos4412())
- __raw_writel(0x120, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+ if (soc_is_exynos4212() || soc_is_exynos4412())
+ l2x0_saved_regs.data_latency = 0x120;
+ else
+ l2x0_saved_regs.data_latency = 0x110;
+
+ l2x0_saved_regs.prefetch_ctrl = 0x30000007;
+ l2x0_saved_regs.pwr_ctrl =
+ (L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN);
+
+ l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
- /* L2X0 Prefetch Control */
- __raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
+ __raw_writel(l2x0_saved_regs.tag_latency,
+ S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
+ __raw_writel(l2x0_saved_regs.data_latency,
+ S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
- /* L2X0 Power Control */
- __raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
- S5P_VA_L2CC + L2X0_POWER_CTRL);
+ /* L2X0 Prefetch Control */
+ __raw_writel(l2x0_saved_regs.prefetch_ctrl,
+ S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
+
+ /* L2X0 Power Control */
+ __raw_writel(l2x0_saved_regs.pwr_ctrl,
+ S5P_VA_L2CC + L2X0_POWER_CTRL);
+
+ clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
+ clean_dcache_area(&l2x0_saved_regs, sizeof(struct l2x0_regs));
+ }
l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
diff --git a/arch/arm/plat-s5p/sleep.S b/arch/arm/plat-s5p/sleep.S
index c371ba2..40bd9bf 100644
--- a/arch/arm/plat-s5p/sleep.S
+++ b/arch/arm/plat-s5p/sleep.S
@@ -23,6 +23,8 @@
*/
#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
.text
@@ -47,5 +49,31 @@
.data
ENTRY(s3c_cpu_resume)
+#ifdef CONFIG_CACHE_L2X0
+ adr r0, l2x0_regs_phys
+ ldr r0, [r0]
+ ldr r1, [r0, #L2X0_R_PHY_BASE]
+ ldr r2, [r1, #L2X0_CTRL]
+ tst r2, #0x1
+ bne resume_l2on
+ ldr r2, [r0, #L2X0_R_AUX_CTRL]
+ str r2, [r1, #L2X0_AUX_CTRL]
+ ldr r2, [r0, #L2X0_R_TAG_LATENCY]
+ str r2, [r1, #L2X0_TAG_LATENCY_CTRL]
+ ldr r2, [r0, #L2X0_R_DATA_LATENCY]
+ str r2, [r1, #L2X0_DATA_LATENCY_CTRL]
+ ldr r2, [r0, #L2X0_R_PREFETCH_CTRL]
+ str r2, [r1, #L2X0_PREFETCH_CTRL]
+ ldr r2, [r0, #L2X0_R_PWR_CTRL]
+ str r2, [r1, #L2X0_POWER_CTRL]
+ mov r2, #1
+ str r2, [r1, #L2X0_CTRL]
+resume_l2on:
+#endif
b cpu_resume
ENDPROC(s3c_cpu_resume)
+#ifdef CONFIG_CACHE_L2X0
+ .globl l2x0_regs_phys
+l2x0_regs_phys:
+ .long 0
+#endif
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH V2 4/5] ARM: exynos4: remove useless code to save/restore L2
2011-11-11 6:29 [PATCH V2 0/5] ARM: exynos4: Add l2 retention mode cpuidle state Amit Daniel Kachhap
` (2 preceding siblings ...)
2011-11-11 6:29 ` [PATCH V2 3/5] ARM: exynos4: add L2 early resume code Amit Daniel Kachhap
@ 2011-11-11 6:29 ` Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 5/5] ARM: exynos4: Enable l2 configuration through device tree Amit Daniel Kachhap
4 siblings, 0 replies; 8+ messages in thread
From: Amit Daniel Kachhap @ 2011-11-11 6:29 UTC (permalink / raw)
To: linux-arm-kernel
Following the merge of CPU PM notifiers and L2 resume code, this patch
removes useless code to save and restore L2 registers.
This is now automatically covered by suspend calls which integrated
CPU PM notifiers and new sleep code that allows to resume L2 before MMU
is turned on.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
---
arch/arm/mach-exynos/pm.c | 15 ---------------
1 files changed, 0 insertions(+), 15 deletions(-)
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index 509a435..0c264e1 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -154,13 +154,6 @@ static struct sleep_save exynos4_core_save[] = {
SAVE_ITEM(S5P_SROM_BC3),
};
-static struct sleep_save exynos4_l2cc_save[] = {
- SAVE_ITEM(S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL),
- SAVE_ITEM(S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL),
- SAVE_ITEM(S5P_VA_L2CC + L2X0_PREFETCH_CTRL),
- SAVE_ITEM(S5P_VA_L2CC + L2X0_POWER_CTRL),
- SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
-};
/* For Cortex-A9 Diagnostic and Power control register */
static unsigned int save_arm_register[2];
@@ -181,7 +174,6 @@ static void exynos4_pm_prepare(void)
u32 tmp;
s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
- s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
@@ -404,13 +396,6 @@ static void exynos4_pm_resume(void)
exynos4_scu_enable(S5P_VA_SCU);
-#ifdef CONFIG_CACHE_L2X0
- s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
- outer_inv_all();
- /* enable L2X0*/
- writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
-#endif
-
early_wakeup:
return;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH V2 5/5] ARM: exynos4: Enable l2 configuration through device tree
2011-11-11 6:29 [PATCH V2 0/5] ARM: exynos4: Add l2 retention mode cpuidle state Amit Daniel Kachhap
` (3 preceding siblings ...)
2011-11-11 6:29 ` [PATCH V2 4/5] ARM: exynos4: remove useless code to save/restore L2 Amit Daniel Kachhap
@ 2011-11-11 6:29 ` Amit Daniel Kachhap
4 siblings, 0 replies; 8+ messages in thread
From: Amit Daniel Kachhap @ 2011-11-11 6:29 UTC (permalink / raw)
To: linux-arm-kernel
This patch enables calling generic l2 setup functions if device tree is used.
Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
---
arch/arm/mach-exynos/cpu.c | 12 ++++++++++--
1 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-exynos/cpu.c b/arch/arm/mach-exynos/cpu.c
index 252e346..b62a90f 100644
--- a/arch/arm/mach-exynos/cpu.c
+++ b/arch/arm/mach-exynos/cpu.c
@@ -37,6 +37,9 @@
#include <mach/regs-pmu.h>
#include <mach/pmu.h>
+#define L2_AUX_VAL 0x7C470001
+#define L2_AUX_MASK 0xC200ffff
+
unsigned int gic_bank_offset __read_mostly;
extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
@@ -299,6 +302,7 @@ core_initcall(exynos4_core_init);
#ifdef CONFIG_CACHE_L2X0
static int __init exynos4_l2x0_cache_init(void)
{
+#ifndef CONFIG_OF
if (!(__raw_readl(S5P_VA_L2CC + L2X0_CTRL) & 0x1)) {
l2x0_saved_regs.phy_base = EXYNOS4_PA_L2CC;
/* TAG, Data Latency Control: 2 cycles */
@@ -332,8 +336,12 @@ static int __init exynos4_l2x0_cache_init(void)
clean_dcache_area(&l2x0_saved_regs, sizeof(struct l2x0_regs));
}
- l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
-
+ l2x0_init(S5P_VA_L2CC, L2_AUX_VAL, L2_AUX_MASK);
+#else
+ l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
+ l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
+ clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
+#endif
return 0;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH V2 1/5] ARM: exynos4: Add support for AFTR mode cpuidle state
2011-11-11 6:29 ` [PATCH V2 1/5] ARM: exynos4: Add support for AFTR " Amit Daniel Kachhap
@ 2011-11-11 10:17 ` Lorenzo Pieralisi
2011-11-11 11:12 ` Amit Kachhap
0 siblings, 1 reply; 8+ messages in thread
From: Lorenzo Pieralisi @ 2011-11-11 10:17 UTC (permalink / raw)
To: linux-arm-kernel
Hi Amit,
On Fri, Nov 11, 2011 at 06:29:33AM +0000, Amit Daniel Kachhap wrote:
> This patch adds support for AFTR(ARM OFF TOP RUNNING) mode in
> cpuidle driver for EXYNOS4210. L2 cache keeps their data in this mode.
> This patch adds the code to the latest interfaces to
> save/restore CPU state inclusive of CPU PM notifiers, l2
> resume and cpu_suspend/resume.
>
> Signed-off-by: Jaecheol Lee <jc.lee@samsung.com>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
> ---
> arch/arm/mach-exynos/cpuidle.c | 148 ++++++++++++++++++++++++++++++-
> arch/arm/mach-exynos/include/mach/pmu.h | 2 +
> 2 files changed, 146 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
> index c6485d3..857ccc6 100644
> --- a/arch/arm/mach-exynos/cpuidle.c
> +++ b/arch/arm/mach-exynos/cpuidle.c
> @@ -12,13 +12,31 @@
> #include <linux/module.h>
> #include <linux/init.h>
> #include <linux/cpuidle.h>
> +#include <linux/cpu_pm.h>
Included but not used, why ? Is GIC state kept in AFTR ? Even if it
is, VFP state is certainly gone, so you must call the notifiers anyway.
> #include <linux/io.h>
> -
> +#include <linux/suspend.h>
> +#include <linux/err.h>
> #include <asm/proc-fns.h>
> +#include <asm/smp_scu.h>
> +#include <asm/suspend.h>
> +#include <asm/unified.h>
> +#include <mach/regs-pmu.h>
> +#include <mach/pmu.h>
> +
> +#include <plat/exynos4.h>
> +#include <plat/cpu.h>
> +
> +#define REG_DIRECTGO_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \
> + S5P_INFORM7 : (S5P_VA_SYSRAM + 0x24))
> +#define REG_DIRECTGO_FLAG (samsung_rev() == EXYNOS4210_REV_1_1 ? \
> + S5P_INFORM6 : (S5P_VA_SYSRAM + 0x20))
>
> static int exynos4_enter_idle(struct cpuidle_device *dev,
> struct cpuidle_driver *drv,
> int index);
> +static int exynos4_enter_lowpower(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv,
> + int index);
>
> static struct cpuidle_state exynos4_cpuidle_set[] = {
> [0] = {
> @@ -26,9 +44,17 @@ static struct cpuidle_state exynos4_cpuidle_set[] = {
> .exit_latency = 1,
> .target_residency = 100000,
> .flags = CPUIDLE_FLAG_TIME_VALID,
> - .name = "IDLE",
> + .name = "C0",
> .desc = "ARM clock gating(WFI)",
> },
> + [1] = {
> + .enter = exynos4_enter_lowpower,
> + .exit_latency = 300,
> + .target_residency = 100000,
> + .flags = CPUIDLE_FLAG_TIME_VALID,
> + .name = "C1",
> + .desc = "ARM power down",
> + },
> };
>
> static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
> @@ -38,9 +64,95 @@ static struct cpuidle_driver exynos4_idle_driver = {
> .owner = THIS_MODULE,
> };
>
> +/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
> +static void exynos4_set_wakeupmask(void)
> +{
> + __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK);
> +}
> +
> +static unsigned int g_pwr_ctrl, g_diag_reg;
> +
> +static void save_cpu_arch_register(void)
> +{
> + /*read power control register*/
> + asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc");
> + /*read diagnostic register*/
> + asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
> + return;
> +}
> +
> +static void restore_cpu_arch_register(void)
> +{
> + /*write power control register*/
> + asm("mcr p15, 0, %0, c15, c0, 0" : : "r"(g_pwr_ctrl) : "cc");
> + /*write diagnostic register*/
> + asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
> + return;
> +}
> +
> +static int idle_finisher(unsigned long flags)
> +{
> + cpu_do_idle();
> + return 1;
> +}
> +
> +static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv,
> + int index)
> +{
> + struct timeval before, after;
> + int idle_time;
> + unsigned long tmp;
> +
> + local_irq_disable();
> + do_gettimeofday(&before);
> +
> + exynos4_set_wakeupmask();
> +
> + /* Set value of power down register for aftr mode */
> + exynos4_sys_powerdown_conf(SYS_AFTR);
> +
> + save_cpu_arch_register();
> +
You must call the notifiers here, at least cpu_pm_enter();
> + /* Setting Central Sequence Register for power down mode */
> + tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
> + tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
> + __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
> +
> + cpu_suspend(0, idle_finisher);
> +
> + scu_enable(S5P_VA_SCU);
> +
Again, you need to resume (VFP, if GIC is kept) through notifiers here,
I do not understand why that code has been removed.
Lorenzo
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH V2 1/5] ARM: exynos4: Add support for AFTR mode cpuidle state
2011-11-11 10:17 ` Lorenzo Pieralisi
@ 2011-11-11 11:12 ` Amit Kachhap
0 siblings, 0 replies; 8+ messages in thread
From: Amit Kachhap @ 2011-11-11 11:12 UTC (permalink / raw)
To: linux-arm-kernel
On 11 November 2011 15:47, Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> Hi Amit,
>
> On Fri, Nov 11, 2011 at 06:29:33AM +0000, Amit Daniel Kachhap wrote:
>> This patch adds support for AFTR(ARM OFF TOP RUNNING) mode in
>> cpuidle driver for EXYNOS4210. L2 cache keeps their data in this mode.
>> This patch adds the code to the latest interfaces to
>> save/restore CPU state inclusive of CPU PM notifiers, l2
>> resume and cpu_suspend/resume.
>>
>> Signed-off-by: Jaecheol Lee <jc.lee@samsung.com>
>> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Signed-off-by: Amit Daniel Kachhap <amit.kachhap@linaro.org>
>> ---
>> ?arch/arm/mach-exynos/cpuidle.c ? ? ? ? ?| ?148 ++++++++++++++++++++++++++++++-
>> ?arch/arm/mach-exynos/include/mach/pmu.h | ? ?2 +
>> ?2 files changed, 146 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
>> index c6485d3..857ccc6 100644
>> --- a/arch/arm/mach-exynos/cpuidle.c
>> +++ b/arch/arm/mach-exynos/cpuidle.c
>> @@ -12,13 +12,31 @@
>> ?#include <linux/module.h>
>> ?#include <linux/init.h>
>> ?#include <linux/cpuidle.h>
>> +#include <linux/cpu_pm.h>
>
> Included but not used, why ? Is GIC state kept in AFTR ? Even if it
> is, VFP state is certainly gone, so you must call the notifiers anyway.
>
>> ?#include <linux/io.h>
>> -
>> +#include <linux/suspend.h>
>> +#include <linux/err.h>
>> ?#include <asm/proc-fns.h>
>> +#include <asm/smp_scu.h>
>> +#include <asm/suspend.h>
>> +#include <asm/unified.h>
>> +#include <mach/regs-pmu.h>
>> +#include <mach/pmu.h>
>> +
>> +#include <plat/exynos4.h>
>> +#include <plat/cpu.h>
>> +
>> +#define REG_DIRECTGO_ADDR ? ?(samsung_rev() == EXYNOS4210_REV_1_1 ? \
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? S5P_INFORM7 : (S5P_VA_SYSRAM + 0x24))
>> +#define REG_DIRECTGO_FLAG ? ?(samsung_rev() == EXYNOS4210_REV_1_1 ? \
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? S5P_INFORM6 : (S5P_VA_SYSRAM + 0x20))
>>
>> ?static int exynos4_enter_idle(struct cpuidle_device *dev,
>> ? ? ? ? ? ? ? ? ? ? ? struct cpuidle_driver *drv,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? int index);
>> +static int exynos4_enter_lowpower(struct cpuidle_device *dev,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct cpuidle_driver *drv,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? int index);
>>
>> ?static struct cpuidle_state exynos4_cpuidle_set[] = {
>> ? ? ? [0] = {
>> @@ -26,9 +44,17 @@ static struct cpuidle_state exynos4_cpuidle_set[] = {
>> ? ? ? ? ? ? ? .exit_latency ? ? ? ? ? = 1,
>> ? ? ? ? ? ? ? .target_residency ? ? ? = 100000,
>> ? ? ? ? ? ? ? .flags ? ? ? ? ? ? ? ? ?= CPUIDLE_FLAG_TIME_VALID,
>> - ? ? ? ? ? ? .name ? ? ? ? ? ? ? ? ? = "IDLE",
>> + ? ? ? ? ? ? .name ? ? ? ? ? ? ? ? ? = "C0",
>> ? ? ? ? ? ? ? .desc ? ? ? ? ? ? ? ? ? = "ARM clock gating(WFI)",
>> ? ? ? },
>> + ? ? [1] = {
>> + ? ? ? ? ? ? .enter ? ? ? ? ? ? ? ? ?= exynos4_enter_lowpower,
>> + ? ? ? ? ? ? .exit_latency ? ? ? ? ? = 300,
>> + ? ? ? ? ? ? .target_residency ? ? ? = 100000,
>> + ? ? ? ? ? ? .flags ? ? ? ? ? ? ? ? ?= CPUIDLE_FLAG_TIME_VALID,
>> + ? ? ? ? ? ? .name ? ? ? ? ? ? ? ? ? = "C1",
>> + ? ? ? ? ? ? .desc ? ? ? ? ? ? ? ? ? = "ARM power down",
>> + ? ? },
>> ?};
>>
>> ?static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
>> @@ -38,9 +64,95 @@ static struct cpuidle_driver exynos4_idle_driver = {
>> ? ? ? .owner ? ? ? ? ?= THIS_MODULE,
>> ?};
>>
>> +/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
>> +static void exynos4_set_wakeupmask(void)
>> +{
>> + ? ? __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK);
>> +}
>> +
>> +static unsigned int g_pwr_ctrl, g_diag_reg;
>> +
>> +static void save_cpu_arch_register(void)
>> +{
>> + ? ? /*read power control register*/
>> + ? ? asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc");
>> + ? ? /*read diagnostic register*/
>> + ? ? asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
>> + ? ? return;
>> +}
>> +
>> +static void restore_cpu_arch_register(void)
>> +{
>> + ? ? /*write power control register*/
>> + ? ? asm("mcr p15, 0, %0, c15, c0, 0" : : "r"(g_pwr_ctrl) : "cc");
>> + ? ? /*write diagnostic register*/
>> + ? ? asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
>> + ? ? return;
>> +}
>> +
>> +static int idle_finisher(unsigned long flags)
>> +{
>> + ? ? cpu_do_idle();
>> + ? ? return 1;
>> +}
>> +
>> +static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct cpuidle_driver *drv,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? int index)
>> +{
>> + ? ? struct timeval before, after;
>> + ? ? int idle_time;
>> + ? ? unsigned long tmp;
>> +
>> + ? ? local_irq_disable();
>> + ? ? do_gettimeofday(&before);
>> +
>> + ? ? exynos4_set_wakeupmask();
>> +
>> + ? ? /* Set value of power down register for aftr mode */
>> + ? ? exynos4_sys_powerdown_conf(SYS_AFTR);
>> +
>> + ? ? save_cpu_arch_register();
>> +
>
> You must call the notifiers here, at least cpu_pm_enter();
Yes lorenzo, cpu_pm_enter may be needed although it does GIC_CPU
save/restore which may not be needed.
Thanks for the review.
>
>> + ? ? /* Setting Central Sequence Register for power down mode */
>> + ? ? tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
>> + ? ? tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
>> + ? ? __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
>> +
>> + ? ? cpu_suspend(0, idle_finisher);
>> +
>> + ? ? scu_enable(S5P_VA_SCU);
>> +
>
> Again, you need to resume (VFP, if GIC is kept) through notifiers here,
> I do not understand why that code has been removed.
>
> Lorenzo
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2011-11-11 11:12 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-11 6:29 [PATCH V2 0/5] ARM: exynos4: Add l2 retention mode cpuidle state Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 1/5] ARM: exynos4: Add support for AFTR " Amit Daniel Kachhap
2011-11-11 10:17 ` Lorenzo Pieralisi
2011-11-11 11:12 ` Amit Kachhap
2011-11-11 6:29 ` [PATCH V2 2/5] ARM: exynos4: remove useless churn in sleep.S Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 3/5] ARM: exynos4: add L2 early resume code Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 4/5] ARM: exynos4: remove useless code to save/restore L2 Amit Daniel Kachhap
2011-11-11 6:29 ` [PATCH V2 5/5] ARM: exynos4: Enable l2 configuration through device tree Amit Daniel Kachhap
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).