summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWai-Hong Tam <waihong@google.com>2019-09-16 13:10:20 -0700
committerCommit Bot <commit-bot@chromium.org>2020-05-01 23:47:20 +0000
commit20b848c444f13b66266f3e582e69bff954701f1c (patch)
tree5f13fbc7f1f2130b368e134364a747e4e65fba8e
parent5517aa585a2b0a6529cd1e2d5506dfe41d794343 (diff)
downloadchrome-ec-20b848c444f13b66266f3e582e69bff954701f1c.tar.gz
servo_v4: Monitor HPD and signal DUT over PD comm
It monitors the HPD coming from the external monitor and generates the PD message to signal DUT for HPD high/low or HPD IRQ event. This monitoring logic is only enabled when CCD mode disabled. BRANCH=servo BUG=b:137219603 TEST=Configured to disable dts-mode, plugged a monitor, plugged the Type-C cable to DUT, tried pluging and unplugging the monitor working well. Change-Id: I6b3f9c635dc8d5907a16c3bd9cf203da94e64f7b Signed-off-by: Wai-Hong Tam <waihong@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1868925 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r--board/servo_v4/board.c96
-rw-r--r--board/servo_v4/gpio.inc2
2 files changed, 93 insertions, 5 deletions
diff --git a/board/servo_v4/board.c b/board/servo_v4/board.c
index 0cd5af7f24..5dc2b18ed5 100644
--- a/board/servo_v4/board.c
+++ b/board/servo_v4/board.c
@@ -29,10 +29,14 @@
#include "usb_gpio.h"
#include "usb_i2c.h"
#include "usb_pd.h"
+#include "usb_pd_config.h"
#include "usb_spi.h"
#include "usb-stream.h"
#include "util.h"
+#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
+#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
+
/******************************************************************************
* GPIO interrupt handlers.
*/
@@ -47,10 +51,88 @@ static void vbus1_evt(enum gpio_signal signal)
task_wake(TASK_ID_PD_C1);
}
-#include "gpio_list.h"
+static volatile uint64_t hpd_prev_ts;
+static volatile int hpd_prev_level;
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
+/**
+ * Hotplug detect deferred task
+ *
+ * Called after level change on hpd GPIO to evaluate (and debounce) what event
+ * has occurred. There are 3 events that occur on HPD:
+ * 1. low : downstream display sink is deattached
+ * 2. high : downstream display sink is attached
+ * 3. irq : downstream display sink signalling an interrupt.
+ *
+ * The debounce times for these various events are:
+ * HPD_USTREAM_DEBOUNCE_LVL : min pulse width of level value.
+ * HPD_USTREAM_DEBOUNCE_IRQ : min pulse width of IRQ low pulse.
+ *
+ * lvl(n-2) lvl(n-1) lvl prev_delta now_delta event
+ * ----------------------------------------------------
+ * 1 0 1 <IRQ n/a low glitch (ignore)
+ * 1 0 1 >IRQ <LVL irq
+ * x 0 1 n/a >LVL high
+ * 0 1 0 <LVL n/a high glitch (ignore)
+ * x 1 0 n/a >LVL low
+ */
+
+void hpd_irq_deferred(void)
+{
+ int dp_mode = pd_alt_mode(1, USB_SID_DISPLAYPORT);
+
+ if (dp_mode) {
+ pd_send_hpd(DUT, hpd_irq);
+ CPRINTS("HPD IRQ");
+ }
+}
+DECLARE_DEFERRED(hpd_irq_deferred);
+
+void hpd_lvl_deferred(void)
+{
+ int level = gpio_get_level(GPIO_DP_HPD);
+ int dp_mode = pd_alt_mode(1, USB_SID_DISPLAYPORT);
+
+ if (level != hpd_prev_level) {
+ /* It's a glitch while in deferred or canceled action */
+ return;
+ }
+
+ if (dp_mode) {
+ pd_send_hpd(DUT, level ? hpd_high : hpd_low);
+ CPRINTS("HPD: %d", level);
+ }
+}
+DECLARE_DEFERRED(hpd_lvl_deferred);
+
+void hpd_evt(enum gpio_signal signal)
+{
+ timestamp_t now = get_time();
+ int level = gpio_get_level(signal);
+ uint64_t cur_delta = now.val - hpd_prev_ts;
+
+ /* Store current time */
+ hpd_prev_ts = now.val;
+
+ /* All previous hpd level events need to be re-triggered */
+ hook_call_deferred(&hpd_lvl_deferred_data, -1);
+
+ /* It's a glitch. Previous time moves but level is the same. */
+ if (cur_delta < HPD_USTREAM_DEBOUNCE_IRQ)
+ return;
+
+ if ((!hpd_prev_level && level) &&
+ (cur_delta < HPD_USTREAM_DEBOUNCE_LVL)) {
+ /* It's an irq */
+ hook_call_deferred(&hpd_irq_deferred_data, 0);
+ } else if (cur_delta >= HPD_USTREAM_DEBOUNCE_LVL) {
+ hook_call_deferred(&hpd_lvl_deferred_data,
+ HPD_USTREAM_DEBOUNCE_LVL);
+ }
+
+ hpd_prev_level = level;
+}
+
+#include "gpio_list.h"
/******************************************************************************
* Board pre-init function.
@@ -390,8 +472,15 @@ static void ccd_measure_sbu(void)
void ccd_enable(int enable)
{
if (enable) {
+ gpio_disable_interrupt(GPIO_DP_HPD);
hook_call_deferred(&ccd_measure_sbu_data, 0);
} else {
+ timestamp_t now = get_time();
+
+ hpd_prev_level = gpio_get_level(GPIO_DP_HPD);
+ hpd_prev_ts = now.val;
+ gpio_enable_interrupt(GPIO_DP_HPD);
+
gpio_set_level(GPIO_SBU_MUX_EN, 0);
hook_call_deferred(&ccd_measure_sbu_data, -1);
}
@@ -462,6 +551,5 @@ static void board_init(void)
gpio_enable_interrupt(GPIO_USB_DET_PP_DUT);
hook_call_deferred(&ccd_measure_sbu_data, 1000 * MSEC);
-
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
diff --git a/board/servo_v4/gpio.inc b/board/servo_v4/gpio.inc
index f087c633ca..76b9a06d0f 100644
--- a/board/servo_v4/gpio.inc
+++ b/board/servo_v4/gpio.inc
@@ -7,6 +7,7 @@
GPIO_INT(USB_DET_PP_CHG, PIN(C, 13), GPIO_INT_BOTH, vbus0_evt)
GPIO_INT(USB_DET_PP_DUT, PIN(C, 12), GPIO_INT_BOTH, vbus1_evt)
+GPIO_INT(DP_HPD, PIN(A, 14), GPIO_INT_BOTH, hpd_evt)
/* Outputs */
GPIO(DUT_CHG_EN, PIN(A, 10), GPIO_OUT_LOW)
@@ -26,7 +27,6 @@ GPIO(EMMC_MUX_EN_L, PIN(F, 0), GPIO_OUT_HIGH)
GPIO(EMMC_PWR_EN, PIN(F, 1), GPIO_OUT_LOW)
/* Inputs */
-GPIO(DP_HPD, PIN(A, 14), GPIO_INPUT)
GPIO(USERVO_FAULT_L, PIN(A, 8), GPIO_INPUT)
GPIO(USB_FAULT_L, PIN(A, 9), GPIO_INPUT)
GPIO(DONGLE_DET, PIN(C, 15), GPIO_INPUT)