summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2016-08-18 18:35:45 -0700
committerMary Ruthven <mruthven@chromium.org>2016-09-22 18:04:57 +0000
commit96b7e491e80a4cd7a419fa4872dcf7146fc95cf3 (patch)
tree3fd5d717eba78c3d6e8c73bd8e2a4bbeed942e71
parentb9f5a3d6baae84950f5ff0c4f7c588e55944818a (diff)
downloadchrome-ec-96b7e491e80a4cd7a419fa4872dcf7146fc95cf3.tar.gz
cr50: notify chipset hooks when the AP state changes
Cr50 monitors UART1 RX to sense the state of the AP. This signal can be used to tell if it is in S0. If the signal is pulled up then the AP is on. If it is not pulled up then the AP is not in S0. This change notifies HOOK_CHIPSET_SUSPEND when UART1 RX is not pulled up, and then notifies HOOK_CHIPSET_RESUME when the signal is high again. The AP usb can be disabled during suspend, so this change changes the hook that triggers disabling the AP usb to be attached to HOOK_CHIPSET_SUSPEND instead of HOOK_CHIPSET_RESUME. BUG=chrome-os-partner:55747 BRANCH=none TEST=buildall Change-Id: I47fb38a4bbcd72424ec2535d61e87f820cf1bcd7 Signed-off-by: Mary Ruthven <mruthven@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/383978 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--board/cr50/board.c38
-rw-r--r--board/cr50/rdd.c7
-rw-r--r--common/device_state.c60
-rw-r--r--include/device_state.h8
4 files changed, 34 insertions, 79 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index ccdc4a626f..96182c7865 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -139,7 +139,6 @@ void pmu_wakeup_interrupt(void)
/* Trigger timer1 interrupt */
if (wakeup_src & GC_PMU_EXITPD_SRC_TIMELS0_PD_EXIT_TIMER1_MASK)
task_trigger_irq(GC_IRQNUM_TIMELS0_TIMINT1);
-
}
DECLARE_IRQ(GC_IRQNUM_PMU_INTR_WAKEUP_INT, pmu_wakeup_interrupt, 1);
@@ -402,15 +401,19 @@ void nvmem_compute_sha(uint8_t *p_buf, int num_bytes,
memcpy(p_sha, sha1_digest, sha_len);
}
-static void device_state_changed(enum device_type device,
+static int device_state_changed(enum device_type device,
enum device_state state)
{
+ int state_changed = state != device_states[device].last_known_state;
+
device_set_state(device, state);
/*
* We've determined the device state, so cancel any deferred callbacks.
*/
hook_call_deferred(device_states[device].deferred, -1);
+
+ return state_changed;
}
/*
@@ -426,12 +429,13 @@ static int servo_state_unknown(void)
return 0;
}
-static void device_powered_off(enum device_type device, int uart)
+static int device_powered_off(enum device_type device, int uart)
{
if (device_get_state(device) == DEVICE_STATE_ON)
- return;
+ return EC_ERROR_UNKNOWN;
- device_state_changed(device, DEVICE_STATE_OFF);
+ if (!device_state_changed(device, DEVICE_STATE_OFF))
+ return EC_ERROR_UNKNOWN;
if (uart) {
/* Disable RX and TX on the UART peripheral */
@@ -440,6 +444,7 @@ static void device_powered_off(enum device_type device, int uart)
/* Disconnect the TX pin from the UART peripheral */
uartn_tx_disconnect(uart);
}
+ return EC_SUCCESS;
}
static void servo_deferred(void)
@@ -453,7 +458,8 @@ DECLARE_DEFERRED(servo_deferred);
static void ap_deferred(void)
{
- device_powered_off(DEVICE_AP, UART_AP);
+ if (device_powered_off(DEVICE_AP, UART_AP) == EC_SUCCESS)
+ hook_notify(HOOK_CHIPSET_SHUTDOWN);
}
DECLARE_DEFERRED(ap_deferred);
@@ -482,10 +488,12 @@ struct device_config device_states[] = {
};
BUILD_ASSERT(ARRAY_SIZE(device_states) == DEVICE_COUNT);
-static void device_powered_on(enum device_type device, int uart)
+/* Returns EC_SUCCESS if the device state changed to on */
+static int device_powered_on(enum device_type device, int uart)
{
/* Update the device state */
- device_state_changed(device, DEVICE_STATE_ON);
+ if (!device_state_changed(device, DEVICE_STATE_ON))
+ return EC_ERROR_UNKNOWN;
/* Enable RX and TX on the UART peripheral */
uartn_enable(uart);
@@ -494,6 +502,8 @@ static void device_powered_on(enum device_type device, int uart)
if (device_get_state(DEVICE_SERVO) != DEVICE_STATE_ON &&
!uartn_enabled(uart))
uartn_tx_connect(uart);
+
+ return EC_SUCCESS;
}
static void servo_attached(void)
@@ -515,7 +525,8 @@ void device_state_on(enum gpio_signal signal)
switch (signal) {
case GPIO_DETECT_AP:
- device_powered_on(DEVICE_AP, UART_AP);
+ if (device_powered_on(DEVICE_AP, UART_AP) == EC_SUCCESS)
+ hook_notify(HOOK_CHIPSET_RESUME);
break;
case GPIO_DETECT_EC:
device_powered_on(DEVICE_EC, UART_EC);
@@ -546,10 +557,13 @@ void board_update_device_state(enum device_type device)
gpio_enable_interrupt(device_states[device].detect);
/*
- * Wait a bit. If cr50 detects this device is ever powered on
- * during this time then the status wont be set to powered off.
+ * The signal is low now, but the detect signals are on UART RX
+ * which may be receiving something. Wait long enough for an
+ * entire data chunk to be sent to declare that the device is
+ * off. If the detect signal remains low for 100us then the
+ * signal is low because the device is off.
*/
- hook_call_deferred(device_states[device].deferred, 50);
+ hook_call_deferred(device_states[device].deferred, 100);
}
}
diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c
index a01c35cea7..ac2557ef3e 100644
--- a/board/cr50/rdd.c
+++ b/board/cr50/rdd.c
@@ -102,17 +102,12 @@ void rdd_attached(void)
ccd_set_mode(CCD_MODE_ENABLED);
enable_usb_wakeup = 1;
- uartn_tx_connect(UART_AP);
- /* Enable device state monitoring */
- device_detect_state_enable(1);
+ uartn_tx_connect(UART_AP);
}
void rdd_detached(void)
{
- /* Disable device state monitoring */
- device_detect_state_enable(0);
-
/* Disconnect from AP and EC UART TX peripheral from gpios */
uartn_tx_disconnect(UART_EC);
uartn_tx_disconnect(UART_AP);
diff --git a/common/device_state.c b/common/device_state.c
index 0c4024880a..17c32a7054 100644
--- a/common/device_state.c
+++ b/common/device_state.c
@@ -7,8 +7,6 @@
#include "device_state.h"
#include "hooks.h"
-static int enabled = 1;
-
int device_get_state(enum device_type device)
{
return device_states[device].state;
@@ -19,6 +17,9 @@ void device_set_state(enum device_type device, enum device_state state)
if (device_states[device].state == state)
return;
+ if (state != DEVICE_STATE_UNKNOWN)
+ device_states[device].last_known_state = state;
+
device_states[device].state = state;
}
@@ -26,57 +27,11 @@ static void check_device_state(void)
{
int i;
- if (!enabled)
- return;
-
for (i = 0; i < DEVICE_COUNT; i++)
board_update_device_state(i);
}
DECLARE_HOOK(HOOK_SECOND, check_device_state, HOOK_PRIO_DEFAULT);
-static int device_has_interrupts(enum device_type device)
-{
- return (device_states[device].deferred &&
- device_states[device].detect != GPIO_COUNT);
-}
-
-static void disable_interrupts(enum device_type device)
-{
- if (!device_has_interrupts(device))
- return;
-
- /* Cancel any deferred callbacks */
- hook_call_deferred(device_states[device].deferred, -1);
-
- /* Disable gpio interrupts */
- gpio_disable_interrupt(device_states[device].detect);
-}
-
-static void enable_interrupts(enum device_type device)
-{
- if (!device_has_interrupts(device))
- return;
-
- /* Enable gpio interrupts */
- gpio_enable_interrupt(device_states[device].detect);
-}
-
-void device_detect_state_enable(int enable)
-{
- int i;
-
- enabled = enable;
- for (i = 0; i < DEVICE_COUNT; i++) {
- if (enabled) {
- enable_interrupts(i);
- board_update_device_state(i);
- } else {
- disable_interrupts(i);
- device_set_state(i, DEVICE_STATE_UNKNOWN);
- }
- }
-}
-
static void print_state(const char *name, enum device_state state)
{
ccprintf("%-9s %s\n", name, state == DEVICE_STATE_ON ? "on" :
@@ -87,12 +42,9 @@ static int command_devices(int argc, char **argv)
{
int i;
- if (!enabled)
- ccprintf("Device monitoring disabled\n");
- else
- for (i = 0; i < DEVICE_COUNT; i++)
- print_state(device_states[i].name,
- device_states[i].state);
+ for (i = 0; i < DEVICE_COUNT; i++)
+ print_state(device_states[i].name,
+ device_states[i].state);
return EC_SUCCESS;
}
diff --git a/include/device_state.h b/include/device_state.h
index 1ad78f002c..379cdb2f47 100644
--- a/include/device_state.h
+++ b/include/device_state.h
@@ -19,6 +19,7 @@ enum device_state {
struct device_config {
const char *name; /* Device name */
enum device_state state; /* Device status */
+ enum device_state last_known_state; /* Either off or on */
/* Deferred handler to detect power off */
const struct deferred_data *deferred;
enum gpio_signal detect; /* GPIO detecting power on */
@@ -41,11 +42,4 @@ void device_set_state(enum device_type device, enum device_state state);
/* Update the device state based on the device gpios */
void board_update_device_state(enum device_type device);
-
-/**
- * Enables or disables all device gpio interrupts
- *
- * @param enable enable or disable detection
- */
-void device_detect_state_enable(int enable);
#endif /* __CROS_DEVICE_STATE_H */