summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-05-08 16:56:59 -0700
committerRandall Spangler <rspangler@chromium.org>2012-05-09 16:09:10 -0700
commit1655c8727a82d8a344400f1708d315decb57c73c (patch)
tree8df68e9691978bdc0a320b24b36ef6dcd30302ae
parent33422ee34169123a53bf47366e3ce474a6acfb3a (diff)
downloadchrome-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.c11
-rw-r--r--chip/lm4/pwm.c16
-rw-r--r--common/hooks.c4
-rw-r--r--common/lightbar.c16
-rw-r--r--common/usb_charge.c24
-rw-r--r--common/x86_power.c55
-rw-r--r--core/cortex-m/ec.lds.S16
-rw-r--r--core/cortex-m/link_defs.h15
-rw-r--r--include/hooks.h26
-rw-r--r--include/usb_charge.h4
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 */