summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@chromium.org>2018-01-05 13:59:03 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-01-05 12:10:01 -0800
commit13f3e27c80598cd066696cd413ac6b651f7a8006 (patch)
tree70164eca90c8285789c17c30e93e77f09d2fd0bf
parent1c0d70d1b0796fc339e7b59eeeed118a081f5908 (diff)
downloadchrome-ec-13f3e27c80598cd066696cd413ac6b651f7a8006.tar.gz
poppy: Move base detection logic to separate file
wand will have a very different detection logic: moving this to a separate file will make it easier and cleaner to implement. BRANCH=none BUG=b:67029560 TEST=make buildall -j TEST=soraka: Base detection still works, power is cut in S5. Change-Id: Ibc4ad0d9f5ad9a0df7834c712145035f7c62f335 Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/851554 Reviewed-by: Furquan Shaikh <furquan@chromium.org>
-rw-r--r--board/poppy/base_detect_poppy.c219
-rw-r--r--board/poppy/board.c202
-rw-r--r--board/poppy/board.h2
-rw-r--r--board/poppy/build.mk2
4 files changed, 223 insertions, 202 deletions
diff --git a/board/poppy/base_detect_poppy.c b/board/poppy/base_detect_poppy.c
new file mode 100644
index 0000000000..0361e89c66
--- /dev/null
+++ b/board/poppy/base_detect_poppy.c
@@ -0,0 +1,219 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Poppy/Soraka base detection code */
+
+#include "adc.h"
+#include "adc_chip.h"
+#include "board.h"
+#include "chipset.h"
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "system.h"
+#include "tablet_mode.h"
+#include "timer.h"
+#include "util.h"
+
+#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
+#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
+
+/* Base detection and debouncing */
+#define BASE_DETECT_DEBOUNCE_US (20 * MSEC)
+
+/*
+ * If the base status is unclear (i.e. not within expected ranges, read
+ * the ADC value again every 500ms.
+ */
+#define BASE_DETECT_RETRY_US (500 * MSEC)
+
+/*
+ * rev0: Lid has 100K pull-up, base has 5.1K pull-down, so the ADC
+ * value should be around 5.1/(100+5.1)*3300 = 160.
+ * >=rev1: Lid has 604K pull-up, base has 30.1K pull-down, so the
+ * ADC value should be around 30.1/(604+30.1)*3300 = 156
+ *
+ * We add a significant marging on the maximum value, due to noise on the line,
+ * especially when PWM is active. See b/64193554 for details.
+ */
+#define BASE_DETECT_MIN_MV 120
+#define BASE_DETECT_MAX_MV 300
+
+/*
+ * When the base is connected in reverse, it presents a 100K pull-down,
+ * so the ADC value should be around 100/(604+100)*3300 = 469
+ *
+ * TODO(b:64370797): Do something with these values.
+ */
+#define BASE_DETECT_REVERSE_MIN_MV 450
+#define BASE_DETECT_REVERSE_MAX_MV 500
+
+/* Minimum ADC value to indicate base is disconnected for sure */
+#define BASE_DETECT_DISCONNECT_MIN_MV 1500
+
+/*
+ * Base EC pulses detection pin for 500 us to signal out of band USB wake (that
+ * can be used to wake system from deep S3).
+ */
+#define BASE_DETECT_PULSE_MIN_US 400
+#define BASE_DETECT_PULSE_MAX_US 650
+
+static uint64_t base_detect_debounce_time;
+
+static void base_detect_deferred(void);
+DECLARE_DEFERRED(base_detect_deferred);
+
+enum base_status {
+ BASE_UNKNOWN = 0,
+ BASE_DISCONNECTED = 1,
+ BASE_CONNECTED = 2,
+};
+
+static enum base_status current_base_status;
+
+/*
+ * This function is called whenever there is a change in the base detect
+ * status. Actions taken include:
+ * 1. Change in power to base
+ * 2. Indicate mode change to host.
+ * 3. Indicate tablet mode to host. Current assumption is that if base is
+ * disconnected then the system is in tablet mode, else if the base is
+ * connected, then the system is not in tablet mode.
+ */
+static void base_detect_change(enum base_status status)
+{
+ int connected = (status == BASE_CONNECTED);
+
+ if (current_base_status == status)
+ return;
+
+ CPRINTS("Base %sconnected", connected ? "" : "not ");
+ gpio_set_level(GPIO_PP3300_DX_BASE, connected);
+ host_set_single_event(EC_HOST_EVENT_MODE_CHANGE);
+ tablet_set_mode(!connected);
+ current_base_status = status;
+}
+
+/* Measure detection pin pulse duration (used to wake AP from deep S3). */
+static uint64_t pulse_start;
+static uint32_t pulse_width;
+
+static void print_base_detect_value(int v, int tmp_pulse_width)
+{
+ CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name,
+ v, tmp_pulse_width);
+}
+
+static void base_detect_deferred(void)
+{
+ uint64_t time_now = get_time().val;
+ int v;
+ uint32_t tmp_pulse_width = pulse_width;
+
+ if (base_detect_debounce_time > time_now) {
+ hook_call_deferred(&base_detect_deferred_data,
+ base_detect_debounce_time - time_now);
+ return;
+ }
+
+ v = adc_read_channel(ADC_BASE_DET);
+ if (v == ADC_READ_ERROR)
+ return;
+
+ if (v >= BASE_DETECT_MIN_MV && v <= BASE_DETECT_MAX_MV) {
+ if (current_base_status != BASE_CONNECTED) {
+ print_base_detect_value(v, tmp_pulse_width);
+ base_detect_change(BASE_CONNECTED);
+ } else if (tmp_pulse_width >= BASE_DETECT_PULSE_MIN_US &&
+ tmp_pulse_width <= BASE_DETECT_PULSE_MAX_US) {
+ print_base_detect_value(v, tmp_pulse_width);
+ CPRINTS("Sending event to AP");
+ host_set_single_event(EC_HOST_EVENT_KEY_PRESSED);
+ }
+ } else if ((v >= BASE_DETECT_REVERSE_MIN_MV &&
+ v <= BASE_DETECT_REVERSE_MAX_MV) ||
+ v >= BASE_DETECT_DISCONNECT_MIN_MV) {
+ /* TODO(b/35585396): Handle reverse connection separately. */
+
+ print_base_detect_value(v, tmp_pulse_width);
+
+ base_detect_change(BASE_DISCONNECTED);
+ } else {
+ /* Unclear base status, schedule again in a while. */
+ hook_call_deferred(&base_detect_deferred_data,
+ BASE_DETECT_RETRY_US);
+ }
+}
+
+static inline int detect_pin_connected(enum gpio_signal det_pin)
+{
+ return gpio_get_level(det_pin) == 0;
+}
+
+void base_detect_interrupt(enum gpio_signal signal)
+{
+ uint64_t time_now = get_time().val;
+
+ if (base_detect_debounce_time <= time_now) {
+ /*
+ * Detect and measure detection pin pulse, when base is
+ * connected. Only a single pulse is measured over a debounce
+ * period. If no pulse, or multiple pulses are detected,
+ * pulse_width is set to 0.
+ */
+ if (current_base_status == BASE_CONNECTED &&
+ !detect_pin_connected(signal)) {
+ pulse_start = time_now;
+ } else {
+ pulse_start = 0;
+ }
+ pulse_width = 0;
+
+ hook_call_deferred(&base_detect_deferred_data,
+ BASE_DETECT_DEBOUNCE_US);
+ } else {
+ if (current_base_status == BASE_CONNECTED &&
+ detect_pin_connected(signal) && !pulse_width &&
+ pulse_start) {
+ /* First pulse within period. */
+ pulse_width = time_now - pulse_start;
+ } else {
+ pulse_start = 0;
+ pulse_width = 0;
+ }
+ }
+
+ base_detect_debounce_time = time_now + BASE_DETECT_DEBOUNCE_US;
+}
+
+static void base_enable(void)
+{
+ /* Enable base detection interrupt. */
+ base_detect_debounce_time = get_time().val;
+ hook_call_deferred(&base_detect_deferred_data, 0);
+ gpio_enable_interrupt(GPIO_BASE_DET_A);
+}
+DECLARE_HOOK(HOOK_CHIPSET_STARTUP, base_enable, HOOK_PRIO_DEFAULT);
+
+static void base_disable(void)
+{
+ /* Disable base detection interrupt and disable power to base. */
+ gpio_disable_interrupt(GPIO_BASE_DET_A);
+ base_detect_change(BASE_DISCONNECTED);
+}
+DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, base_disable, HOOK_PRIO_DEFAULT);
+
+static void base_init(void)
+{
+ /*
+ * If we jumped to this image and chipset is already in S0, enable
+ * base.
+ */
+ if (system_jumped_to_this_image() && chipset_in_state(CHIPSET_STATE_ON))
+ base_enable();
+}
+DECLARE_HOOK(HOOK_INIT, base_init, HOOK_PRIO_DEFAULT+1);
diff --git a/board/poppy/board.c b/board/poppy/board.c
index ce54be5e97..3cc8100728 100644
--- a/board/poppy/board.c
+++ b/board/poppy/board.c
@@ -139,86 +139,6 @@ void anx74xx_cable_det_interrupt(enum gpio_signal signal)
}
#endif
-/* Base detection and debouncing */
-#define BASE_DETECT_DEBOUNCE_US (20 * MSEC)
-
-/*
- * If the base status is unclear (i.e. not within expected ranges, read
- * the ADC value again every 500ms.
- */
-#define BASE_DETECT_RETRY_US (500 * MSEC)
-
-/*
- * rev0: Lid has 100K pull-up, base has 5.1K pull-down, so the ADC
- * value should be around 5.1/(100+5.1)*3300 = 160.
- * >=rev1: Lid has 604K pull-up, base has 30.1K pull-down, so the
- * ADC value should be around 30.1/(604+30.1)*3300 = 156
- *
- * We add a significant marging on the maximum value, due to noise on the line,
- * especially when PWM is active. See b/64193554 for details.
- */
-#define BASE_DETECT_MIN_MV 120
-#define BASE_DETECT_MAX_MV 300
-
-/*
- * When the base is connected in reverse, it presents a 100K pull-down,
- * so the ADC value should be around 100/(604+100)*3300 = 469
- *
- * TODO(b:64370797): Do something with these values.
- */
-#define BASE_DETECT_REVERSE_MIN_MV 450
-#define BASE_DETECT_REVERSE_MAX_MV 500
-
-/* Minimum ADC value to indicate base is disconnected for sure */
-#define BASE_DETECT_DISCONNECT_MIN_MV 1500
-
-/*
- * Base EC pulses detection pin for 500 us to signal out of band USB wake (that
- * can be used to wake system from deep S3).
- */
-#define BASE_DETECT_PULSE_MIN_US 400
-#define BASE_DETECT_PULSE_MAX_US 650
-
-static uint64_t base_detect_debounce_time;
-
-static void base_detect_deferred(void);
-DECLARE_DEFERRED(base_detect_deferred);
-
-enum base_status {
- BASE_UNKNOWN = 0,
- BASE_DISCONNECTED = 1,
- BASE_CONNECTED = 2,
-};
-
-static enum base_status current_base_status;
-
-/*
- * This function is called whenever there is a change in the base detect
- * status. Actions taken include:
- * 1. Change in power to base
- * 2. Indicate mode change to host.
- * 3. Indicate tablet mode to host. Current assumption is that if base is
- * disconnected then the system is in tablet mode, else if the base is
- * connected, then the system is not in tablet mode.
- */
-static void base_detect_change(enum base_status status)
-{
- int connected = (status == BASE_CONNECTED);
-
- if (current_base_status == status)
- return;
-
- CPRINTS("Base %sconnected", connected ? "" : "not ");
- gpio_set_level(GPIO_PP3300_DX_BASE, connected);
- host_set_single_event(EC_HOST_EVENT_MODE_CHANGE);
- tablet_set_mode(!connected);
- current_base_status = status;
-}
-
-/* Measure detection pin pulse duration (used to wake AP from deep S3). */
-static uint64_t pulse_start;
-static uint32_t pulse_width;
-
static int command_attach_base(int argc, char **argv)
{
host_set_single_event(EC_HOST_EVENT_MODE_CHANGE);
@@ -237,109 +157,6 @@ static int command_detach_base(int argc, char **argv)
DECLARE_CONSOLE_COMMAND(detachbase, command_detach_base,
NULL, "Simulate detach base");
-static void print_base_detect_value(int v, int tmp_pulse_width)
-{
- CPRINTS("%s = %d (pulse %d)", adc_channels[ADC_BASE_DET].name,
- v, tmp_pulse_width);
-}
-
-static void base_detect_deferred(void)
-{
- uint64_t time_now = get_time().val;
- int v;
- uint32_t tmp_pulse_width = pulse_width;
-
- if (base_detect_debounce_time > time_now) {
- hook_call_deferred(&base_detect_deferred_data,
- base_detect_debounce_time - time_now);
- return;
- }
-
- v = adc_read_channel(ADC_BASE_DET);
- if (v == ADC_READ_ERROR)
- return;
-
- if (v >= BASE_DETECT_MIN_MV && v <= BASE_DETECT_MAX_MV) {
- if (current_base_status != BASE_CONNECTED) {
- print_base_detect_value(v, tmp_pulse_width);
- base_detect_change(BASE_CONNECTED);
- } else if (tmp_pulse_width >= BASE_DETECT_PULSE_MIN_US &&
- tmp_pulse_width <= BASE_DETECT_PULSE_MAX_US) {
- print_base_detect_value(v, tmp_pulse_width);
- CPRINTS("Sending event to AP");
- host_set_single_event(EC_HOST_EVENT_KEY_PRESSED);
- }
- } else if ((v >= BASE_DETECT_REVERSE_MIN_MV &&
- v <= BASE_DETECT_REVERSE_MAX_MV) ||
- v >= BASE_DETECT_DISCONNECT_MIN_MV) {
- /* TODO(b/35585396): Handle reverse connection separately. */
-
- print_base_detect_value(v, tmp_pulse_width);
-
- base_detect_change(BASE_DISCONNECTED);
- } else {
- /* Unclear base status, schedule again in a while. */
- hook_call_deferred(&base_detect_deferred_data,
- BASE_DETECT_RETRY_US);
- }
-}
-
-static inline int detect_pin_connected(enum gpio_signal det_pin)
-{
- return gpio_get_level(det_pin) == 0;
-}
-
-void base_detect_interrupt(enum gpio_signal signal)
-{
- uint64_t time_now = get_time().val;
-
- if (base_detect_debounce_time <= time_now) {
- /*
- * Detect and measure detection pin pulse, when base is
- * connected. Only a single pulse is measured over a debounce
- * period. If no pulse, or multiple pulses are detected,
- * pulse_width is set to 0.
- */
- if (current_base_status == BASE_CONNECTED &&
- !detect_pin_connected(signal)) {
- pulse_start = time_now;
- } else {
- pulse_start = 0;
- }
- pulse_width = 0;
-
- hook_call_deferred(&base_detect_deferred_data,
- BASE_DETECT_DEBOUNCE_US);
- } else {
- if (current_base_status == BASE_CONNECTED &&
- detect_pin_connected(signal) && !pulse_width &&
- pulse_start) {
- /* First pulse within period. */
- pulse_width = time_now - pulse_start;
- } else {
- pulse_start = 0;
- pulse_width = 0;
- }
- }
-
- base_detect_debounce_time = time_now + BASE_DETECT_DEBOUNCE_US;
-}
-
-static void base_enable(void)
-{
- /* Enable base detection interrupt. */
- base_detect_debounce_time = get_time().val;
- hook_call_deferred(&base_detect_deferred_data, 0);
- gpio_enable_interrupt(GPIO_BASE_DET_A);
-}
-
-static void base_disable(void)
-{
- /* Disable base detection interrupt and disable power to base. */
- gpio_disable_interrupt(GPIO_BASE_DET_A);
- base_detect_change(BASE_DISCONNECTED);
-}
-
#include "gpio_list.h"
/* power signal list. Must match order of enum power_signal. */
@@ -730,13 +547,6 @@ static void board_init(void)
gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L);
/*
- * If we jumped to this image and chipset is already in S0, enable
- * base.
- */
- if (system_jumped_to_this_image() && chipset_in_state(CHIPSET_STATE_ON))
- base_enable();
-
- /*
* Set unused GPIO_LED_YELLO_C0[_OLD] as INPUT | PULL_UP
* for better S0ix/S3 power
*/
@@ -1120,18 +930,6 @@ static void board_chipset_suspend(void)
}
DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT);
-static void board_chipset_startup(void)
-{
- base_enable();
-}
-DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT);
-
-static void board_chipset_shutdown(void)
-{
- base_disable();
-}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, HOOK_PRIO_DEFAULT);
-
int board_has_working_reset_flags(void)
{
int version = system_get_board_version();
diff --git a/board/poppy/board.h b/board/poppy/board.h
index 083f764c17..41aa1f19d9 100644
--- a/board/poppy/board.h
+++ b/board/poppy/board.h
@@ -250,6 +250,8 @@ int board_get_version(void);
void board_reset_pd_mcu(void);
void board_set_tcpc_power_mode(int port, int mode);
+void base_detect_interrupt(enum gpio_signal signal);
+
#endif /* !__ASSEMBLER__ */
#endif /* __CROS_EC_BOARD_H */
diff --git a/board/poppy/build.mk b/board/poppy/build.mk
index d8ae2af836..194869ba1b 100644
--- a/board/poppy/build.mk
+++ b/board/poppy/build.mk
@@ -13,3 +13,5 @@ board-y=board.o
board-$(CONFIG_BATTERY_SMART)+=battery.o
board-$(CONFIG_LED_COMMON)+=led.o
board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o
+board-$(BOARD_POPPY)+=base_detect_poppy.o
+board-$(BOARD_SORAKA)+=base_detect_poppy.o