diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-05-08 16:56:59 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-05-09 16:09:10 -0700 |
commit | 1655c8727a82d8a344400f1708d315decb57c73c (patch) | |
tree | 8df68e9691978bdc0a320b24b36ef6dcd30302ae | |
parent | 33422ee34169123a53bf47366e3ce474a6acfb3a (diff) | |
download | chrome-ec-1655c8727a82d8a344400f1708d315decb57c73c.tar.gz |
Add hooks for chipset power transitions
This is cleaner than having x86_power explicitly know about everything
else in the system that cares about power transitions.
Signed-off-by: Randall Spangler <rspangler@chromium.org>
BUG=none
TEST=boot and shutdown system; still works. Mouse powered to system is off in S5.
Change-Id: Ib673ca2d9edd5473334e7604e98b99b02b768419
-rw-r--r-- | chip/lm4/lpc.c | 11 | ||||
-rw-r--r-- | chip/lm4/pwm.c | 16 | ||||
-rw-r--r-- | common/hooks.c | 4 | ||||
-rw-r--r-- | common/lightbar.c | 16 | ||||
-rw-r--r-- | common/usb_charge.c | 24 | ||||
-rw-r--r-- | common/x86_power.c | 55 | ||||
-rw-r--r-- | core/cortex-m/ec.lds.S | 16 | ||||
-rw-r--r-- | core/cortex-m/link_defs.h | 15 | ||||
-rw-r--r-- | include/hooks.h | 26 | ||||
-rw-r--r-- | include/usb_charge.h | 4 |
10 files changed, 134 insertions, 53 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c index 29bd66d52c..64cdfb2d50 100644 --- a/chip/lm4/lpc.c +++ b/chip/lm4/lpc.c @@ -481,3 +481,14 @@ static int lpc_init(void) return EC_SUCCESS; } DECLARE_HOOK(HOOK_INIT, lpc_init, HOOK_PRIO_DEFAULT); + + +static int lpc_resume(void) +{ + /* Mask all host events until the host unmasks them itself. */ + lpc_set_host_event_mask(LPC_HOST_EVENT_SMI, 0); + lpc_set_host_event_mask(LPC_HOST_EVENT_SCI, 0); + lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, 0); + return EC_SUCCESS; +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, lpc_resume, HOOK_PRIO_DEFAULT); diff --git a/chip/lm4/pwm.c b/chip/lm4/pwm.c index 62bd08a571..e27dbac831 100644 --- a/chip/lm4/pwm.c +++ b/chip/lm4/pwm.c @@ -342,3 +342,19 @@ static int pwm_init(void) return EC_SUCCESS; } DECLARE_HOOK(HOOK_INIT, pwm_init, HOOK_PRIO_DEFAULT); + + +static int pwm_resume(void) +{ + pwm_enable_fan(1); + return EC_SUCCESS; +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, pwm_resume, HOOK_PRIO_DEFAULT); + + +static int pwm_suspend(void) +{ + pwm_enable_fan(0); + return EC_SUCCESS; +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pwm_suspend, HOOK_PRIO_DEFAULT); diff --git a/common/hooks.c b/common/hooks.c index b2626a9aa9..f83c2e88b2 100644 --- a/common/hooks.c +++ b/common/hooks.c @@ -20,6 +20,10 @@ static const struct hook_ptrs hook_list[] = { {__hooks_init, __hooks_init_end}, {__hooks_freq_change, __hooks_freq_change_end}, {__hooks_sysjump, __hooks_sysjump_end}, + {__hooks_chipset_startup, __hooks_chipset_startup_end}, + {__hooks_chipset_resume, __hooks_chipset_resume_end}, + {__hooks_chipset_suspend, __hooks_chipset_suspend_end}, + {__hooks_chipset_shutdown, __hooks_chipset_shutdown_end}, }; diff --git a/common/lightbar.c b/common/lightbar.c index 3c90e834c5..b08542c746 100644 --- a/common/lightbar.c +++ b/common/lightbar.c @@ -8,6 +8,7 @@ #include "board.h" #include "console.h" #include "gpio.h" +#include "hooks.h" #include "host_command.h" #include "i2c.h" #include "lightbar.h" @@ -653,6 +654,21 @@ void lightbar_sequence(enum lightbar_sequence num) } +static int lightbar_resume(void) +{ + lightbar_sequence(LIGHTBAR_S3S0); + return EC_SUCCESS; +} +DECLARE_HOOK(HOOK_CHIPSET_RESUME, lightbar_resume, HOOK_PRIO_DEFAULT); + + +static int lightbar_suspend(void) +{ + lightbar_sequence(LIGHTBAR_S0S3); + return EC_SUCCESS; +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, lightbar_suspend, HOOK_PRIO_DEFAULT); + /****************************************************************************/ /* Generic command-handling (should work the same for both console & LPC) */ /****************************************************************************/ diff --git a/common/usb_charge.c b/common/usb_charge.c index 3f162a3f4d..eea5d3ec72 100644 --- a/common/usb_charge.c +++ b/common/usb_charge.c @@ -47,7 +47,7 @@ static void usb_charge_set_ilim(int port_id, int sel) } -int usb_charge_all_ports_on(void) +static int usb_charge_all_ports_on(void) { usb_charge_set_mode(0, USB_CHARGE_MODE_DOWNSTREAM_500MA); usb_charge_set_mode(1, USB_CHARGE_MODE_DOWNSTREAM_500MA); @@ -55,7 +55,7 @@ int usb_charge_all_ports_on(void) } -int usb_charge_all_ports_off(void) +static int usb_charge_all_ports_off(void) { usb_charge_set_mode(0, USB_CHARGE_MODE_DISABLED); usb_charge_set_mode(1, USB_CHARGE_MODE_DISABLED); @@ -135,7 +135,7 @@ static int command_set_mode(int argc, char **argv) DECLARE_CONSOLE_COMMAND(usbchargemode, command_set_mode); /*****************************************************************************/ -/* Initialization */ +/* Hooks */ static int usb_charge_init(void) { @@ -147,3 +147,21 @@ static int usb_charge_init(void) return EC_SUCCESS; } DECLARE_HOOK(HOOK_INIT, usb_charge_init, HOOK_PRIO_DEFAULT); + + +static int usb_charge_startup(void) +{ + /* Turn on USB ports on as we go into S3 or S0. */ + usb_charge_all_ports_on(); + return EC_SUCCESS; +} +DECLARE_HOOK(HOOK_CHIPSET_STARTUP, usb_charge_startup, HOOK_PRIO_DEFAULT); + + +static int usb_charge_shutdown(void) +{ + /* Turn on USB ports off as we go back to S5. */ + usb_charge_all_ports_off(); + return EC_SUCCESS; +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, usb_charge_shutdown, HOOK_PRIO_DEFAULT); diff --git a/common/x86_power.c b/common/x86_power.c index a2dfa08cc7..50478c8bd0 100644 --- a/common/x86_power.c +++ b/common/x86_power.c @@ -7,16 +7,12 @@ #include "board.h" #include "chipset.h" -#include "clock.h" #include "console.h" #include "gpio.h" -#include "lightbar.h" -#include "lpc.h" -#include "pwm.h" +#include "hooks.h" #include "system.h" #include "task.h" #include "timer.h" -#include "usb_charge.h" #include "util.h" #include "x86_power.h" @@ -29,9 +25,11 @@ #define DEFAULT_TIMEOUT 1000000 enum x86_state { - X86_G3 = 0, /* Initial state */ - X86_S5, /* System is off */ - X86_S3, /* RAM is on; processor is asleep */ + X86_G3 = 0, /* System is off (not technically all the + * way into G3, which means totally + * unpowered...) */ + X86_S5, /* System is soft-off */ + X86_S3, /* Suspend; RAM on, processor is asleep */ X86_S0, /* System is on */ /* Transitions */ @@ -213,6 +211,7 @@ void x86_power_reset(int cold_reset) /* Chipset interface */ /* Returns non-zero if the chipset is in the specified state. */ +/* TODO: change in_state to bitmask so multiple states can be checked */ int chipset_in_state(enum chipset_state in_state) { switch (in_state) { @@ -315,7 +314,7 @@ void x86_power_task(void) break; case X86_G3S5: - /* switch on +5V always-on */ + /* Switch on +5V always-on */ gpio_set_level(GPIO_ENABLE_5VALW, 1); /* Wait for the always-on rails to be good */ wait_in_signals(IN_PGOOD_ALWAYS_ON); @@ -330,13 +329,9 @@ void x86_power_task(void) /* Wait 5ms for SUSCLK to stabilize */ usleep(5000); - /* Turn off USB ports. */ - usb_charge_all_ports_off(); - state = X86_S5; break; - case X86_S5S3: /* Turn on power to RAM */ gpio_set_level(GPIO_ENABLE_1_5V_DDR, 1); @@ -346,8 +341,8 @@ void x86_power_task(void) gpio_set_level(GPIO_ENABLE_TOUCHPAD, 1); gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 1); - /* Turn on USB ports as we go into S3 or S0. */ - usb_charge_all_ports_on(); + /* Call hooks now that rails are up */ + hook_notify(HOOK_CHIPSET_STARTUP, 0); state = X86_S3; break; @@ -356,12 +351,6 @@ void x86_power_task(void) /* Deassert RCINn */ gpio_set_level(GPIO_PCH_RCINn, 1); - /* Mask all host events until the host unmasks - * them itself. */ - lpc_set_host_event_mask(LPC_HOST_EVENT_SMI, 0); - lpc_set_host_event_mask(LPC_HOST_EVENT_SCI, 0); - lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, 0); - /* Turn on power rails */ gpio_set_level(GPIO_ENABLE_VS, 1); @@ -370,11 +359,6 @@ void x86_power_task(void) gpio_set_level(GPIO_RADIO_ENABLE_WLAN, 1); gpio_set_level(GPIO_RADIO_ENABLE_BT, 1); - /* Enable fan, now that +5VS is turned on */ - /* TODO: On proto1+, fan is on +5VALW, so we can leave - * it on all the time. */ - pwm_enable_fan(1); - /* Wait for non-core power rails good */ wait_in_signals(IN_PGOOD_ALL_NONCORE); @@ -382,6 +366,9 @@ void x86_power_task(void) * itself will request the supplies when it's ready. */ gpio_set_level(GPIO_ENABLE_VCORE, 1); + /* Call hooks now that rails are up */ + hook_notify(HOOK_CHIPSET_RESUME, 0); + /* Wait 99ms after all voltages good */ usleep(99000); @@ -389,12 +376,11 @@ void x86_power_task(void) gpio_set_level(GPIO_PCH_PWROK, 1); state = X86_S0; - - lightbar_sequence(LIGHTBAR_S3S0); break; case X86_S0S3: - lightbar_sequence(LIGHTBAR_S0S3); + /* Call hooks before we remove power rails */ + hook_notify(HOOK_CHIPSET_SUSPEND, 0); /* Clear PCH_PWROK */ gpio_set_level(GPIO_PCH_PWROK, 0); @@ -408,11 +394,6 @@ void x86_power_task(void) /* Assert RCINn */ gpio_set_level(GPIO_PCH_RCINn, 0); - /* Disable fan, since it's powered by +5VS */ - /* TODO: On proto1+, fan is on +5VALW, so we can leave - * it on all the time. */ - pwm_enable_fan(0); - /* Disable WLAN */ gpio_set_level(GPIO_ENABLE_WLAN, 0); gpio_set_level(GPIO_RADIO_ENABLE_WLAN, 0); @@ -425,6 +406,9 @@ void x86_power_task(void) break; case X86_S3S5: + /* Call hooks before we remove power rails */ + hook_notify(HOOK_CHIPSET_SHUTDOWN, 0); + /* Disable touchpad power and reset touchscreen. */ gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0); gpio_set_level(GPIO_TOUCHSCREEN_RESETn, 0); @@ -432,9 +416,6 @@ void x86_power_task(void) /* Turn off power to RAM */ gpio_set_level(GPIO_ENABLE_1_5V_DDR, 0); - /* Turn off USB ports. */ - usb_charge_all_ports_off(); - state = X86_S5; break; diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S index ea89e241e9..8bb4997dfc 100644 --- a/core/cortex-m/ec.lds.S +++ b/core/cortex-m/ec.lds.S @@ -59,6 +59,22 @@ SECTIONS *(.rodata.HOOK_SYSJUMP) __hooks_sysjump_end = .; + __hooks_chipset_startup = .; + *(.rodata.HOOK_CHIPSET_STARTUP) + __hooks_chipset_startup_end = .; + + __hooks_chipset_resume = .; + *(.rodata.HOOK_CHIPSET_RESUME) + __hooks_chipset_resume_end = .; + + __hooks_chipset_suspend = .; + *(.rodata.HOOK_CHIPSET_SUSPEND) + __hooks_chipset_suspend_end = .; + + __hooks_chipset_shutdown = .; + *(.rodata.HOOK_CHIPSET_SHUTDOWN) + __hooks_chipset_shutdown_end = .; + . = ALIGN(4); *(.rodata*) . = ALIGN(4); diff --git a/core/cortex-m/link_defs.h b/core/cortex-m/link_defs.h index af809ad7e0..bd771ed464 100644 --- a/core/cortex-m/link_defs.h +++ b/core/cortex-m/link_defs.h @@ -13,22 +13,35 @@ #include "host_command.h" #include "task.h" +/* Console commands */ extern const struct console_command __cmds[]; extern const struct console_command __cmds_end[]; +/* Hooks */ extern const struct hook_data __hooks_init[]; extern const struct hook_data __hooks_init_end[]; extern const struct hook_data __hooks_freq_change[]; extern const struct hook_data __hooks_freq_change_end[]; extern const struct hook_data __hooks_sysjump[]; extern const struct hook_data __hooks_sysjump_end[]; - +extern const struct hook_data __hooks_chipset_startup[]; +extern const struct hook_data __hooks_chipset_startup_end[]; +extern const struct hook_data __hooks_chipset_resume[]; +extern const struct hook_data __hooks_chipset_resume_end[]; +extern const struct hook_data __hooks_chipset_suspend[]; +extern const struct hook_data __hooks_chipset_suspend_end[]; +extern const struct hook_data __hooks_chipset_shutdown[]; +extern const struct hook_data __hooks_chipset_shutdown_end[]; + +/* Host commands */ extern const struct host_command __hcmds[]; extern const struct host_command __hcmds_end[]; +/* IRQs (interrupt handlers) */ extern const struct irq_priority __irqprio[]; extern const struct irq_priority __irqprio_end[]; +/* Shared memory buffer. Use via shared_mem.h interface. */ extern uint8_t __shared_mem_buf[]; #endif /* __CROS_EC_LINK_DEFS_H */ diff --git a/include/hooks.h b/include/hooks.h index a0e12e708b..8bce2166f7 100644 --- a/include/hooks.h +++ b/include/hooks.h @@ -18,14 +18,24 @@ enum hook_priority { enum hook_type { - HOOK_INIT = 0, /* System init */ - HOOK_FREQ_CHANGE, /* System clock changed frequency */ - HOOK_SYSJUMP, /* About to jump to another image. Modules which - * need to preserve data across such a jump should - * save it here and restore it in HOOK_INIT. - * - * NOTE: This hook is called with interrupts - * disabled! */ + HOOK_INIT = 0, /* System init */ + HOOK_FREQ_CHANGE, /* System clock changed frequency */ + HOOK_SYSJUMP, /* About to jump to another image. Modules + * which need to preserve data across such a + * jump should save it here and restore it in + * HOOK_INIT. + * + * NOTE: This hook is called with interrupts + * disabled! */ + HOOK_CHIPSET_STARTUP, /* System is starting up. All suspend rails are + * now on. */ + HOOK_CHIPSET_RESUME, /* System is resuming from suspend, or booting + * and has reached the point where all voltage + * rails are on */ + HOOK_CHIPSET_SUSPEND, /* System is suspending, or shutting down; all + * voltage rails are still on */ + HOOK_CHIPSET_SHUTDOWN, /* System is shutting down. All suspend rails + * are still on. */ }; diff --git a/include/usb_charge.h b/include/usb_charge.h index 714deb5235..b73f57a684 100644 --- a/include/usb_charge.h +++ b/include/usb_charge.h @@ -27,10 +27,6 @@ enum usb_charge_mode { USB_CHARGE_MODE_COUNT }; -int usb_charge_all_ports_on(void); - -int usb_charge_all_ports_off(void); - int usb_charge_set_mode(int usb_port_id, enum usb_charge_mode); #endif /* __CROS_EC_USB_CHARGE_H */ |