summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorDino Li <dino.li@ite.com.tw>2015-10-20 16:55:43 +0800
committerchrome-bot <chrome-bot@chromium.org>2015-10-25 04:34:36 -0700
commit19c1e9905db46b0a669d0af8848be3f28dcedf41 (patch)
tree865aa1fbaf88bf4ca44d31c040c6f1484cbef526 /core
parent9acd84460e953dd793c9594b141ca7e38568820d (diff)
downloadchrome-ec-19c1e9905db46b0a669d0af8848be3f28dcedf41.tar.gz
it8380dev: fix clock module
1. Implement deep doze mode for CONFIG_LOW_POWER_IDLE. Signed-off-by: Dino Li <dino.li@ite.com.tw> BRANCH=none BUG=none TEST=test the following items in deep doze mode. 1. WUI interrupts wake-up OK. (For example, power button, lid, uart rx, keyboard ksi, and so on) 2. LPC access interrupt wake-up OK. 3. Enabled Hook debug, no warning message received (48hrs). Change-Id: I8702a112632cb6c1c0fa75d682badf272130a7d4 Reviewed-on: https://chromium-review.googlesource.com/307060 Commit-Ready: Dino Li <dino.li@ite.com.tw> Tested-by: Dino Li <dino.li@ite.com.tw> Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'core')
-rw-r--r--core/nds32/task.c45
1 files changed, 40 insertions, 5 deletions
diff --git a/core/nds32/task.c b/core/nds32/task.c
index 7edad8b6e4..a7a3bc6688 100644
--- a/core/nds32/task.c
+++ b/core/nds32/task.c
@@ -9,6 +9,8 @@
#include "common.h"
#include "console.h"
#include "cpu.h"
+#include "hwtimer_chip.h"
+#include "intc.h"
#include "irq_chip.h"
#include "link_defs.h"
#include "registers.h"
@@ -58,6 +60,10 @@ static uint64_t exc_total_time; /* Total time in exceptions */
static uint32_t svc_calls; /* Number of service calls */
static uint32_t task_switches; /* Number of times active task changed */
static uint32_t irq_dist[CONFIG_IRQ_COUNT]; /* Distribution of IRQ calls */
+#if defined(CONFIG_LOW_POWER_IDLE) && defined(CHIP_FAMILY_IT83XX)
+static uint32_t exc_current_fth;
+static uint32_t exc_current_ftl;
+#endif
#endif
extern int __task_start(void);
@@ -92,8 +98,10 @@ void __idle(void)
task_enable_irq(IT83XX_IRQ_WKINTAD);
#endif
+#ifdef CHIP_FAMILY_IT83XX
/* doze mode */
- IT83XX_ECPM_PLLCTRL = 0x00;
+ IT83XX_ECPM_PLLCTRL = EC_PLL_DOZE;
+#endif
asm volatile ("dsb");
/*
* Wait for the next irq event. This stops the CPU clock
@@ -341,6 +349,10 @@ void update_exc_start_time(void)
{
#ifdef CONFIG_TASK_PROFILING
exc_start_time = get_time().val;
+#if defined(CONFIG_LOW_POWER_IDLE) && defined(CHIP_FAMILY_IT83XX)
+ exc_current_fth = IT83XX_ETWD_ETXCNTOR(FREE_EXT_TIMER_H);
+ exc_current_ftl = IT83XX_ETWD_ETXCNTOR(FREE_EXT_TIMER_L);
+#endif
#endif
}
@@ -348,15 +360,20 @@ void start_irq_handler(void)
{
#ifdef CONFIG_TASK_PROFILING
int irq;
-
+#endif
/* save r0, r1, and r2 for syscall */
asm volatile ("smw.adm $r0, [$sp], $r2, 0");
-
+#if defined(CONFIG_LOW_POWER_IDLE) && defined(CHIP_FAMILY_IT83XX)
+ clock_sleep_mode_wakeup_isr();
+#endif
+#ifdef CONFIG_TASK_PROFILING
update_exc_start_time();
irq = get_sw_int();
+#ifdef CHIP_FAMILY_IT83XX
if (!irq)
irq = IT83XX_INTC_AIVCT - 16;
+#endif
/*
* Track IRQ distribution. No need for atomic add, because an IRQ
@@ -364,10 +381,9 @@ void start_irq_handler(void)
*/
if ((irq > 0) && (irq < ARRAY_SIZE(irq_dist)))
irq_dist[irq]++;
-
+#endif
/* restore r0, r1, and r2 */
asm volatile ("lmw.bim $r0, [$sp], $r2, 0");
-#endif
}
void end_irq_handler(void)
@@ -375,6 +391,9 @@ void end_irq_handler(void)
#ifdef CONFIG_TASK_PROFILING
uint64_t t, p;
+#if defined(CONFIG_LOW_POWER_IDLE) && defined(CHIP_FAMILY_IT83XX)
+ uint32_t c;
+#endif
/*
* save r0 and fp (fp for restore r0-r5, r15, fp, lp and sp
* while interrupt exit.
@@ -382,6 +401,13 @@ void end_irq_handler(void)
asm volatile ("smw.adm $r0, [$sp], $r0, 8");
t = get_time().val;
+#if defined(CONFIG_LOW_POWER_IDLE) && defined(CHIP_FAMILY_IT83XX)
+ if (exc_current_fth != IT83XX_ETWD_ETXCNTOR(FREE_EXT_TIMER_H)) {
+ c = (IT83XX_ETWD_ETXCNTLR(FREE_EXT_TIMER_L) + exc_current_ftl) -
+ IT83XX_ETWD_ETXCNTOR(FREE_EXT_TIMER_L);
+ t = exc_start_time + (c >> TIMER_COUNT_1US_SHIFT);
+ }
+#endif
p = t - exc_start_time;
exc_total_time += p;
@@ -478,12 +504,20 @@ void task_enable_all_tasks(void)
void task_enable_irq(int irq)
{
+ uint32_t int_mask = get_int_mask();
+
+ interrupt_disable();
chip_enable_irq(irq);
+ set_int_mask(int_mask);
}
void task_disable_irq(int irq)
{
+ uint32_t int_mask = get_int_mask();
+
+ interrupt_disable();
chip_disable_irq(irq);
+ set_int_mask(int_mask);
}
void task_clear_pending_irq(int irq)
@@ -494,6 +528,7 @@ void task_clear_pending_irq(int irq)
void task_trigger_irq(int irq)
{
int cpu_int = chip_trigger_irq(irq);
+
if (cpu_int > 0) {
sw_int_num = irq;
__schedule(0, 0, cpu_int);