summaryrefslogtreecommitdiff
path: root/cleopatre
diff options
context:
space:
mode:
authorOlivier Dufour2012-12-06 11:41:20 +0100
committerOlivier Dufour2012-12-21 15:15:46 +0100
commita90cdd132345e25e6975cdc1742d740a8fc04c7c (patch)
tree6c6a8c6b78a42367707045e944c72fffdcaf1fe5 /cleopatre
parent8ec3bc0c516b18d84a539ae9a67b77d824ad8b26 (diff)
cleo/linux/arch/arm/spc300/pm: update system time on resume, closes #3568
The system time is now updated when returning from pm procedure, with an error margin below 10ms (duration of a tick timer).
Diffstat (limited to 'cleopatre')
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-pm.c26
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/sram.S23
2 files changed, 49 insertions, 0 deletions
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-pm.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-pm.c
index a8454bad13..fe9a6bc3b6 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-pm.c
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-pm.c
@@ -21,6 +21,7 @@
#include <linux/suspend.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
+#include <linux/time.h>
#ifdef CONFIG_CHIP_FEATURE_SRAM
#include <asm/arch/ips/sram.h>
#include <asm/io.h>
@@ -37,6 +38,7 @@ sram_data_t sram_data;
static void (* pm_process) (void);
static void map_extra_registers (void);
static void unmap_extra_registers (void);
+static void system_time_update (void);
/* Map hardware registers that are not used by the kernel, but that must be
* accessed during the SRAM procedure.
@@ -55,6 +57,26 @@ static void unmap_extra_registers (void)
sram_data.spll_addr = 0;
sram_data.dsppll_addr = 0;
}
+/* Update the system time according to the number of timer ticks recorded
+ * during the SRAM procedure and the duration of the timer.
+ */
+void system_time_update ()
+{
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+ /* Tick timer is set to 10ms */
+ tv.tv_sec += (sram_data.tick_counter / 100);
+ tv.tv_usec += (sram_data.tick_counter % 100) * 10000;
+ if (tv.tv_usec >= 1000000)
+ {
+ tv.tv_sec++;
+ tv.tv_usec -= 1000000;
+ }
+
+ do_settimeofday(&tv);
+ sram_data.tick_counter = 0;
+}
#endif
static bool spc300_pm_suspend_cmd;
@@ -90,6 +112,8 @@ static int spc300_pm_enter(suspend_state_t state)
/* Unmap the registers. */
unmap_extra_registers();
+ /* Update system time. */
+ system_time_update();
#endif
/* Clear suspend request command */
spc300_pm_suspend_cmd = false;
@@ -150,6 +174,8 @@ static int __init spc300_pm_init(void)
/* Allow WDT IRQ to wake us up in low power mode. */
enable_irq_wake(INT_WDT);
+ /* Keep timer IRQ ON in low power mode. */
+ enable_irq_wake(INT_TIMER_1);
/* Create proc entry */
pm_proc_dir = proc_mkdir("pm", &proc_root);
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/sram.S b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/sram.S
index 5ea13c3b5e..5fb6e31ba8 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/sram.S
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/sram.S
@@ -89,6 +89,8 @@ pm_process:
/* Dummy reads to fill TLB with the pages we will use after SDRAM
* deactivation. This is needed to ensure that there will not be any
* access to SDRAM once it is in self-refresh mode. */
+ ldr r0, =IO_ADDRESS(ARM_TIMER1_BASE)
+ ldr r1, [r0, #TIMEREOIOFF_1]
ldr r0, =IO_ADDRESS(MARIA_REGBANK_BASE)
ldr r1, [r0]
ldr r0, =IO_ADDRESS(ARM_WDT_BASE)
@@ -237,10 +239,31 @@ pm_process:
tst r1, #(1 << MII_LINK_STATUS_SHIFT)
bne exit_sram
+wait_for_irq:
/* Put ARM in wait for interrupt mode. */
mov r0, #0
mcr p15, 0, r0, c7, c0, 4
+ /* Test if we are awaken by timer tick. If so, we need to inc the
+ counter in sram */
+ ldr r0, =IO_ADDRESS(ARM_ICTL_BASE) + IRQ_FINALSTATUS_OFFSET_L
+ ldr r1, [r0]
+ tst r1, #INTMASK_TIMER_1
+ beq 1f
+ /* Inc tick count */
+ ldr r0, =SRAM_DATA_BASE_VA + SRAM_DATA_TICK_CNT_OFFSET
+ ldr r1, [r0]
+ add r1, r1, #1
+ str r1, [r0]
+ /* Clear IRQ */
+ ldr r0, =IO_ADDRESS(ARM_TIMER1_BASE)
+ ldr r1, [r0, #TIMEREOIOFF_1]
+ nop
+ nop
+ /* Go back in wait for IRQ */
+ b wait_for_irq
+
+1:
/* Test if we are awaken by WDT. If so, we need to refresh it
and go back to wait for interrupt mode. */
ldr r0, =IO_ADDRESS(ARM_ICTL_BASE) + IRQ_FINALSTATUS_OFFSET_L