summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx6/cpu.c
diff options
context:
space:
mode:
authorRanjani Vaidyanathan <ra5478@freescale.com>2012-05-16 12:43:27 -0500
committerJason Liu <r64343@freescale.com>2012-07-20 13:37:46 +0800
commit40f361bcc5f8c61dac1ea15acfdd34e32d32f84e (patch)
tree6f93f147e5d89e8989b66ae9ee323f8950cb2de7 /arch/arm/mach-mx6/cpu.c
parent49f744921cfa19f2250d5f55cda6157aad6b8234 (diff)
ENGR00209617 MX6x - Add WAIT mode workaround
To avoid the ARM from accepting an interrupt in the dangerous window, reduce the ARM core freq just before the sytem is about to enter WAIT state. Reduce the ARM freq so as to maintain 12:5 ARM_CLK to IPG ratio. Use the ARM_PODF to drop the frequency. In a multicore case the frequency is dropped only when all the 4 cores are going to be in WFI. In case of single core environment, its easy to drop the ARM core freq just before WFI since there is no need to identify the state of the other cores. Some other points to note: 1. If "mem_clk_on" is added to the command line, the memory clocks will not be gated in WAIT mode. This will increase the system IDLE power. This mode is valid only on MX6sl, MX6DQ TO1.2 and MX6DL TO1.1. 2. In case the IPG clk is too low (for ex 50MHz) and ARM is at 1GHz, we cannot match the 12:5 ratio using ARM_PODF only. In this case, donot clock gate the memories in WAIT mode (available on MX6SL, MXDQ TO1.2 and MXDL TO1.1). For MXDQ TO1.1 and MX6DL TO1.0, disable system wide WAIT entry in this case. In STOP mode, always ensure that the memory clocks are gated, else power impact will be significant. WAIT mode is enabled by default with this commit. Signed-off-by: Ranjani Vaidyanathan <ra5478@freescale.com>
Diffstat (limited to 'arch/arm/mach-mx6/cpu.c')
-rw-r--r--arch/arm/mach-mx6/cpu.c60
1 files changed, 46 insertions, 14 deletions
diff --git a/arch/arm/mach-mx6/cpu.c b/arch/arm/mach-mx6/cpu.c
index 0f1b0321bdea..2822d2d7f17c 100644
--- a/arch/arm/mach-mx6/cpu.c
+++ b/arch/arm/mach-mx6/cpu.c
@@ -31,19 +31,16 @@
#include "crm_regs.h"
#include "cpu_op-mx6.h"
-extern unsigned int num_cpu_idle_lock;
-
-void *mx6_wait_in_iram_base;
-void (*mx6_wait_in_iram)(void);
-extern void mx6_wait(void);
-
struct cpu_op *(*get_cpu_op)(int *op);
-bool enable_wait_mode;
+bool enable_wait_mode = true;
u32 arm_max_freq = CPU_AT_1GHz;
+bool mem_clk_on_in_wait;
void __iomem *gpc_base;
void __iomem *ccm_base;
+extern unsigned int num_cpu_idle_lock;
+
static int cpu_silicon_rev = -1;
#define MX6_USB_ANALOG_DIGPROG 0x260
#define MX6SL_USB_ANALOG_DIGPROG 0x280
@@ -140,13 +137,11 @@ static int __init post_cpu_init(void)
__raw_writel(reg, base + 0x50);
iounmap(base);
- if (enable_wait_mode) {
- /* Allow SCU_CLK to be disabled when all cores are in WFI*/
- base = IO_ADDRESS(SCU_BASE_ADDR);
- reg = __raw_readl(base);
- reg |= 0x20;
- __raw_writel(reg, base);
- }
+ /* Allow SCU_CLK to be disabled when all cores are in WFI*/
+ base = IO_ADDRESS(SCU_BASE_ADDR);
+ reg = __raw_readl(base);
+ reg |= 0x20;
+ __raw_writel(reg, base);
/* Disable SRC warm reset to work aound system reboot issue */
base = IO_ADDRESS(SRC_BASE_ADDR);
@@ -158,6 +153,33 @@ static int __init post_cpu_init(void)
ccm_base = MX6_IO_ADDRESS(CCM_BASE_ADDR);
num_cpu_idle_lock = 0x0;
+ if (cpu_is_mx6dl())
+ num_cpu_idle_lock = 0xffff0000;
+
+#ifdef CONFIG_SMP
+ switch (setup_max_cpus) {
+ case 3:
+ num_cpu_idle_lock = 0xff000000;
+ break;
+ case 2:
+ num_cpu_idle_lock = 0xffff0000;
+ break;
+ case 1:
+ case 0:
+ num_cpu_idle_lock = 0xffffff00;
+ break;
+ }
+#endif
+ /*
+ * The option to keep ARM memory clocks enabled during WAIT
+ * is only available on MX6SL, MX6DQ TO1.2 (or later) and
+ * MX6DL TO1.1 (or later)
+ * So if the user specifies "mem_clk_on" on any other chip,
+ * ensure that it is disabled.
+ */
+ if (!cpu_is_mx6sl() && (mx6q_revision() < IMX_CHIP_REVISION_1_2) &&
+ (mx6dl_revision() < IMX_CHIP_REVISION_1_1))
+ mem_clk_on_in_wait = false;
return 0;
}
@@ -193,4 +215,14 @@ static int __init arm_core_max(char *p)
early_param("arm_freq", arm_core_max);
+static int __init enable_mem_clk_in_wait(char *p)
+{
+ mem_clk_on_in_wait = true;
+
+ return 0;
+}
+
+early_param("mem_clk_on", enable_mem_clk_in_wait);
+
+