From 7ecb8358b9ae4594abc9cc6251719283e079a494 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Tue, 24 Apr 2012 09:59:31 -0700 Subject: Disable PLL at end of init This saves power. Signed-off-by: Randall Spangler BUG=chrome-os-partner:8798 TEST=manual Get a proto1 system modified with INA current sensor 1) From chroot: dut-control i2c_mux_en:on i2c_mux:rem dut-control pp3300_alw_mv pp3300_alw_ma 2) From EC console: pll (this should turn the PLL back on; it'll report clock frequency ~66MHz) 3) From chroot: dut-control i2c_mux_en:on i2c_mux:rem dut-control pp3300_alw_mv pp3300_alw_ma Current (ma) should be bigger than in step 1 Change-Id: I806953684c57fd60bf481acb01dddffe2f2ad0ed --- chip/lm4/clock.c | 33 ++++++++++++++++++++++++--------- common/main.c | 6 ++++-- include/clock.h | 5 ++++- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/chip/lm4/clock.c b/chip/lm4/clock.c index 290af0223f..84608f7ee7 100644 --- a/chip/lm4/clock.c +++ b/chip/lm4/clock.c @@ -21,7 +21,7 @@ #define PLL_CLOCK 66666667 /* System clock = 200MHz PLL/3 = 66.667MHz */ /* Disable the PLL; run off internal oscillator. */ -static void clock_disable_pll(void) +static void disable_pll(void) { /* Switch to 16MHz internal oscillator and power down the PLL */ LM4_SYSTEM_RCC = LM4_SYSTEM_RCC_SYSDIV(0) | @@ -33,11 +33,11 @@ static void clock_disable_pll(void) } -/* Enable the PLL to run at full clock speed */ -static void clock_enable_pll(void) +/* Enable the PLL to run at full clock speed. */ +static void enable_pll(void) { /* Disable the PLL so we can reconfigure it */ - clock_disable_pll(); + disable_pll(); /* Enable the PLL (PWRDN is no longer set) and set divider. PLL is * still bypassed, since it hasn't locked yet. */ @@ -57,6 +57,18 @@ static void clock_enable_pll(void) } +int clock_enable_pll(int enable) +{ + if (enable) + enable_pll(); + else + disable_pll(); + + /* Notify modules of frequency change */ + return hook_notify(HOOK_FREQ_CHANGE, 0); +} + + void clock_wait_cycles(uint32_t cycles) { asm("1: subs %0, #1\n" @@ -179,12 +191,14 @@ static int command_sleep(int argc, char **argv) DECLARE_CONSOLE_COMMAND(sleep, command_sleep); -static int command_disable_pll(int argc, char **argv) +static int command_pll(int argc, char **argv) { - /* Notify modules of frequency change */ - return hook_notify(HOOK_FREQ_CHANGE, 0); + /* Toggle the PLL */ + clock_enable_pll(LM4_SYSTEM_RCC & LM4_SYSTEM_RCC_BYPASS ? 1 : 0); + uart_printf("Clock frequency is now %d\n", clock_get_freq()); + return EC_SUCCESS; } -DECLARE_CONSOLE_COMMAND(nopll, command_disable_pll); +DECLARE_CONSOLE_COMMAND(pll, command_pll); /*****************************************************************************/ /* Initialization */ @@ -219,7 +233,8 @@ int clock_init(void) if (!system_jumped_to_this_image()) clock_wait_cycles(500000); - clock_enable_pll(); + /* Start out with PLL enabled */ + enable_pll(); return EC_SUCCESS; } diff --git a/common/main.c b/common/main.c index 5293820e9b..8252a231d0 100644 --- a/common/main.c +++ b/common/main.c @@ -95,13 +95,15 @@ int main(void) * RO image and once in the RW image. */ vboot_init(); - /* TODO: reduce core clock now that vboot is done */ - /* Initialize other driver modules. These can occur in any order. * Non-driver modules with tasks do their inits from their task * functions, not here. */ hook_notify(HOOK_INIT, 0); +#ifdef BOARD_link + /* Reduce core clock now that init is done */ + clock_enable_pll(0); +#endif /* Print the init time and reset cause. Init time isn't completely * accurate because it can't take into account the time for the first * few module inits, but it'll at least catch the majority of them. */ diff --git a/include/clock.h b/include/clock.h index 081c9c95a9..209f42c0f0 100644 --- a/include/clock.h +++ b/include/clock.h @@ -13,9 +13,12 @@ /* Set the CPU clocks and PLLs. */ int clock_init(void); -/* Returns the current clock frequency in Hz. */ +/* Return the current clock frequency in Hz. */ int clock_get_freq(void); +/* Enable or disable the PLL. */ +int clock_enable_pll(int enable); + /* Wait system clock cycles. Simple busy waiting for before * clocks/timers are initialized. */ void clock_wait_cycles(uint32_t cycles); -- cgit v1.2.1