summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-05-15 12:47:43 -0700
committerRandall Spangler <rspangler@chromium.org>2012-05-15 12:49:56 -0700
commit50e0966af8912575d6e55d8b30fde2f2c0135807 (patch)
treefdf1b7903c3cadde8027e3b75f76f71954e69d1f
parent40628f70a393a6d57b66c235289b8fe76a1a9d65 (diff)
downloadchrome-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.c38
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 */