summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAseda Aboagye <aaboagye@google.com>2018-01-25 15:16:19 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-02-05 19:08:39 -0800
commit06bbd9dd6c65bb9197bf362a2229134b090813d8 (patch)
tree35c5272f98745e95415080190376105f6f9a0104
parentbce23786d0bf606326b7acd752017732da896d11 (diff)
downloadchrome-ec-06bbd9dd6c65bb9197bf362a2229134b090813d8.tar.gz
meowth: zoombini: Add HPD support.
The HPD pins for meowth and zoombini go from the EC to the AP. This commit drives the HPD correctly. BUG=b:72413020 BRANCH=None TEST=Flash meowth; Use a couple charge-through hubs, unplug HDMI cable, replug, verify AP sees new DP sink. Change-Id: Ie1f86378c59fc4a717edc537ff8afe01b21d9b68 Signed-off-by: Aseda Aboagye <aaboagye@google.com> Reviewed-on: https://chromium-review.googlesource.com/888226 Commit-Ready: Aseda Aboagye <aaboagye@chromium.org> Tested-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Edward Hill <ecgh@chromium.org>
-rw-r--r--board/zoombini/gpio.inc5
-rw-r--r--board/zoombini/usb_pd_policy.c47
2 files changed, 51 insertions, 1 deletions
diff --git a/board/zoombini/gpio.inc b/board/zoombini/gpio.inc
index 7b04a0651a..025841e1d9 100644
--- a/board/zoombini/gpio.inc
+++ b/board/zoombini/gpio.inc
@@ -87,6 +87,9 @@ GPIO(USB_C2_BC12_CHG_DET, PIN(E, 4), GPIO_INPUT)
GPIO(USB_C0_OC_L, PIN(6, 7), GPIO_ODR_HIGH)
GPIO(USB_C1_OC_L, PIN(7, 0), GPIO_ODR_HIGH)
GPIO(USB_C2_OC_L, PIN(6, 3), GPIO_ODR_HIGH)
+GPIO(USB_C0_DP_HPD, PIN(C, 5), GPIO_OUT_LOW)
+GPIO(USB_C1_DP_HPD, PIN(C, 6), GPIO_OUT_LOW)
+GPIO(USB_C2_DP_HPD, PIN(C, 7), GPIO_OUT_LOW)
GPIO(BOARD_VERSION1, PIN(9, 6), GPIO_INPUT)
GPIO(BOARD_VERSION2, PIN(9, 3), GPIO_INPUT)
@@ -164,6 +167,8 @@ GPIO(PMIC_EN, PIN(8, 6), GPIO_ODR_LOW)
GPIO(USB_C0_OC_L, PIN(6, 7), GPIO_ODR_HIGH)
GPIO(USB_C1_OC_L, PIN(7, 0), GPIO_ODR_HIGH)
GPIO(ENABLE_BACKLIGHT, PIN(D, 3), GPIO_ODR_LOW) /* EC_BL_EN_OD */
+GPIO(USB_C0_DP_HPD, PIN(C, 5), GPIO_OUT_LOW)
+GPIO(USB_C1_DP_HPD, PIN(C, 6), GPIO_OUT_LOW)
GPIO(PCH_DSW_PWROK, PIN(3, 7), GPIO_OUT_LOW) /* EC_PCH_DSW_PWROK */
GPIO(PCH_RSMRST_L, PIN(C, 2), GPIO_OUT_LOW) /* EC_PCH_RSMRST_L */
diff --git a/board/zoombini/usb_pd_policy.c b/board/zoombini/usb_pd_policy.c
index e5c7a975f7..2a0f580718 100644
--- a/board/zoombini/usb_pd_policy.c
+++ b/board/zoombini/usb_pd_policy.c
@@ -293,6 +293,18 @@ static int svdm_dp_config(int port, uint32_t *payload)
return 2;
};
+/*
+ * timestamp of the next possible toggle to ensure the 2-ms spacing
+ * between IRQ_HPD.
+ */
+static uint64_t hpd_deadline[CONFIG_USB_PD_PORT_COUNT];
+
+#ifdef BOARD_MEOWTH
+#define PORT_TO_HPD(port) ((port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD)
+#else
+#define PORT_TO_HPD(port) ((port == 2) ? GPIO_USB_C2_DP_HPD : \
+ (port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD)
+#endif /* defined(BOARD_MEOWTH) */
static void svdm_dp_post_config(int port)
{
const struct usb_mux *mux = &usb_muxes[port];
@@ -300,23 +312,55 @@ static void svdm_dp_post_config(int port)
dp_flags[port] |= DP_FLAGS_DP_ON;
if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING))
return;
+
+ gpio_set_level(PORT_TO_HPD(port), 1);
+
+ /* set the minimum time delay (2ms) for the next HPD IRQ */
+ hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
+
mux->hpd_update(port, 1, 0);
}
static int svdm_dp_attention(int port, uint32_t *payload)
{
+ int cur_lvl;
int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]);
int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]);
+ enum gpio_signal hpd = PORT_TO_HPD(port);
const struct usb_mux *mux = &usb_muxes[port];
+ cur_lvl = gpio_get_level(hpd);
dp_status[port] = payload[1];
+
+ /* Its initial DP status message prior to config */
if (!(dp_flags[port] & DP_FLAGS_DP_ON)) {
if (lvl)
dp_flags[port] |= DP_FLAGS_HPD_HI_PENDING;
return 1;
}
- mux->hpd_update(port, lvl, irq);
+ if (irq & cur_lvl) {
+ uint64_t now = get_time().val;
+ /* wait for the minimum spacing between IRQ_HPD if needed */
+ if (now < hpd_deadline[port])
+ usleep(hpd_deadline[port] - now);
+
+ /* generate IRQ_HPD pulse */
+ gpio_set_level(hpd, 0);
+ usleep(HPD_DSTREAM_DEBOUNCE_IRQ);
+ gpio_set_level(hpd, 1);
+
+ /* set the minimum time delay (2ms) for the next HPD IRQ */
+ hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
+ } else if (irq & !cur_lvl) {
+ CPRINTF("ERR:HPD:IRQ&LOW\n");
+ return 0; /* nak */
+ } else {
+ gpio_set_level(hpd, lvl);
+ /* set the minimum time delay (2ms) for the next HPD IRQ */
+ hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
+ }
+ mux->hpd_update(port, lvl, irq);
/* ack */
return 1;
}
@@ -326,6 +370,7 @@ static void svdm_exit_dp_mode(int port)
const struct usb_mux *mux = &usb_muxes[port];
svdm_safe_dp_mode(port);
+ gpio_set_level(PORT_TO_HPD(port), 0);
mux->hpd_update(port, 0, 0);
}