summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnson Huang <Anson.Huang@nxp.com>2016-06-22 23:11:04 +0800
committerAnson Huang <Anson.Huang@nxp.com>2016-06-22 23:22:43 +0800
commit470f930321d7633ea9844a1ebf6784cafd8b7372 (patch)
tree914b547fc608212a4836919d3765d657e3e3b6bc
parentd86edca368b277011f5dcf444129705bd56f753c (diff)
MLK-12935 ARM: imx: switch system counter clock to 32K in suspend
During suspend, as 24MHz will be disabled, but system counter needs to be running in order to maintain accurate clock source, so we need to switch system counter's clock from base clock(24MHz) to alternate clock(32K) before system enter STOP mode, otherwise, the suspend time will NOT be counted into system time when issue a "date" command. Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
-rw-r--r--arch/arm/mach-imx/pm-imx7.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/arch/arm/mach-imx/pm-imx7.c b/arch/arm/mach-imx/pm-imx7.c
index f092e80ad786..92e1a9b0795e 100644
--- a/arch/arm/mach-imx/pm-imx7.c
+++ b/arch/arm/mach-imx/pm-imx7.c
@@ -87,6 +87,9 @@
#define BM_CCM_ROOT_MUX 0x7000000
#define BM_CCM_ROOT_ENABLE 0x10000000
+#define BM_SYS_COUNTER_CNTCR_FCR1 0x200
+#define BM_SYS_COUNTER_CNTCR_FCR0 0x100
+
#define PFD_A_OFFSET 0xc0
#define PFD_B_OFFSET 0xd0
@@ -693,6 +696,7 @@ static int imx7_pm_is_resume_from_lpsr(void)
static int imx7_pm_enter(suspend_state_t state)
{
unsigned int console_saved_reg[10] = {0};
+ u32 val;
if (!iram_tlb_base_addr) {
pr_warn("No IRAM/OCRAM memory allocated for suspend/resume \
@@ -701,6 +705,22 @@ static int imx7_pm_enter(suspend_state_t state)
return -EINVAL;
}
+ /*
+ * arm_arch_timer driver requires system counter to be
+ * a clock source with CLOCK_SOURCE_SUSPEND_NONSTOP flag
+ * set, which means hardware system counter needs to keep
+ * running during suspend, as the base clock for system
+ * counter is 24MHz which will be disabled in STOP mode,
+ * so we need to switch system counter's clock to alternate
+ * (lower) clock, it is based on 32K, from block guide, there
+ * is no special flow needs to be followed, system counter
+ * hardware will handle the clock transition.
+ */
+ val = readl_relaxed(system_counter_ctrl_base);
+ val &= ~BM_SYS_COUNTER_CNTCR_FCR0;
+ val |= BM_SYS_COUNTER_CNTCR_FCR1;
+ writel_relaxed(val, system_counter_ctrl_base);
+
switch (state) {
case PM_SUSPEND_STANDBY:
imx_anatop_pre_suspend();
@@ -797,6 +817,12 @@ static int imx7_pm_enter(suspend_state_t state)
return -EINVAL;
}
+ /* restore system counter's clock to base clock */
+ val = readl_relaxed(system_counter_ctrl_base);
+ val &= ~BM_SYS_COUNTER_CNTCR_FCR1;
+ val |= BM_SYS_COUNTER_CNTCR_FCR0;
+ writel_relaxed(val, system_counter_ctrl_base);
+
return 0;
}
@@ -1126,18 +1152,18 @@ void __init imx7d_pm_init(void)
WARN_ON(!system_counter_cmp_base);
np = of_find_node_by_path(
- "/soc/aips-bus@30400000/system-counter-ctrl@306c0000");
- if (np)
- system_counter_ctrl_base = of_iomap(np, 0);
- WARN_ON(!system_counter_ctrl_base);
-
- np = of_find_node_by_path(
"/soc/aips-bus@30000000/gpio@30200000");
if (np)
gpio1_base = of_iomap(np, 0);
WARN_ON(!gpio1_base);
}
+ np = of_find_node_by_path(
+ "/soc/aips-bus@30400000/system-counter-ctrl@306c0000");
+ if (np)
+ system_counter_ctrl_base = of_iomap(np, 0);
+ WARN_ON(!system_counter_ctrl_base);
+
if (imx_ddrc_get_ddr_type() == IMX_DDR_TYPE_LPDDR3
|| imx_ddrc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
imx7_pm_common_init(&imx7d_pm_data_lpddr3);