diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-05-15 12:47:43 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-05-15 12:49:56 -0700 |
commit | 50e0966af8912575d6e55d8b30fde2f2c0135807 (patch) | |
tree | fdf1b7903c3cadde8027e3b75f76f71954e69d1f | |
parent | 40628f70a393a6d57b66c235289b8fe76a1a9d65 (diff) | |
download | chrome-ec-50e0966af8912575d6e55d8b30fde2f2c0135807.tar.gz |
Add option to pll command to divide down system clock
Also fix sleep command triggering watchdog timer in spin-idle
Signed-off-by: Randall Spangler <rspangler@chromium.org>
BUG=chrome-os-partner:7454
TEST=manual
1) check PLL operation - system keeps operating
pll on
pll off
pll 4
pll 16
2) check sleep operation - no watchdog
sleep 0
(reboot)
sleep 1
Change-Id: Ib3079634a883d7c96b221f9e06a148221628cc3c
-rw-r--r-- | chip/lm4/clock.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/chip/lm4/clock.c b/chip/lm4/clock.c index 5be90207e6..aaa2e9403c 100644 --- a/chip/lm4/clock.c +++ b/chip/lm4/clock.c @@ -16,9 +16,12 @@ #include "task.h" #include "timer.h" #include "util.h" +#include "watchdog.h" #define PLL_CLOCK 66666667 /* System clock = 200MHz PLL/3 = 66.667MHz */ +static int freq; + /* Disable the PLL; run off internal oscillator. */ static void disable_pll(void) { @@ -29,6 +32,8 @@ static void disable_pll(void) LM4_SYSTEM_RCC_OSCSRC(1) | LM4_SYSTEM_RCC_MOSCDIS; LM4_SYSTEM_RCC2 &= ~LM4_SYSTEM_RCC2_USERCC2; + + freq = INTERNAL_CLOCK; } @@ -53,6 +58,8 @@ static void enable_pll(void) /* Remove bypass on PLL */ LM4_SYSTEM_RCC &= ~LM4_SYSTEM_RCC_BYPASS; + + freq = PLL_CLOCK; } @@ -77,7 +84,7 @@ void clock_wait_cycles(uint32_t cycles) int clock_get_freq(void) { - return (LM4_SYSTEM_PLLSTAT & 1) ? PLL_CLOCK : INTERNAL_CLOCK; + return freq; } @@ -180,10 +187,13 @@ static int command_sleep(int argc, char **argv) LM4_SCB_SYSCTRL |= 0x4; /* go to low power mode (forever ...) */ if (level > 1) - while (1) + while (1) { asm("wfi"); + watchdog_reload(); + } else - while(1); + while (1) + watchdog_reload(); return EC_SUCCESS; } @@ -192,14 +202,32 @@ DECLARE_CONSOLE_COMMAND(sleep, command_sleep); static int command_pll(int argc, char **argv) { + int div = 1; + /* Toggle the PLL */ if (argc > 1) { if (!strcasecmp(argv[1], "off")) clock_enable_pll(0); else if (!strcasecmp(argv[1], "on")) clock_enable_pll(1); - else - ccputs("Usage: pll [off | on]\n"); + else { + /* Disable PLL and set extra divider */ + char *e; + div = strtoi(argv[1], &e, 10); + if (e && *e) + return EC_ERROR_INVAL; + + LM4_SYSTEM_RCC = LM4_SYSTEM_RCC_SYSDIV(div - 1) | + LM4_SYSTEM_RCC_BYPASS | + LM4_SYSTEM_RCC_PWRDN | + LM4_SYSTEM_RCC_OSCSRC(1) | + LM4_SYSTEM_RCC_MOSCDIS; + + freq = INTERNAL_CLOCK / div; + + /* Notify modules of frequency change */ + hook_notify(HOOK_FREQ_CHANGE, 0); + } } /* Print current PLL state */ |