summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYilun Lin <yllin@google.com>2018-09-12 17:24:18 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-11-27 04:29:08 -0800
commit434793f29c1515d0317ba3a64afd2ef1bfd2d0fd (patch)
tree7252c5eb74f6106b97a3953a1992cf329348bf0c
parent3397a5374e6ba7dac7ba06d6a4e74be95fa98d1f (diff)
downloadchrome-ec-434793f29c1515d0317ba3a64afd2ef1bfd2d0fd.tar.gz
kukui: Enable DP.
On plug DP dongle, we sohuld: 1. set USB_C0_DP_POLARITY bit accordingly 2. set USB_C0_DP_OE_L low 3. set USB_C0_HPD_OD high On unplug DP dongle, we should: 1. set USB_C0_DP_OE_L high 2. set USB_C0_HPD_OD low TEST=pd 0 dualrole on; plug DP dongle, see GPIO pins set accordingly. TEST=unplug DP dongle, see GPIO pins set accordingly. TEST=plug dp and seeing output to external display for both polarity. BUG=b:114162810 BRANCH=None Change-Id: I4e4755e3b757d25a081fd65f8eb68235766d6e0b Signed-off-by: Yilun Lin <yllin@google.com> Reviewed-on: https://chromium-review.googlesource.com/1221406 Commit-Ready: Yilun Lin <yllin@chromium.org> Tested-by: Yilun Lin <yllin@chromium.org> Reviewed-by: Yilun Lin <yllin@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
-rw-r--r--board/kukui/gpio.inc2
-rw-r--r--board/kukui/usb_pd_policy.c67
2 files changed, 58 insertions, 11 deletions
diff --git a/board/kukui/gpio.inc b/board/kukui/gpio.inc
index b67489fb60..720eaa42c5 100644
--- a/board/kukui/gpio.inc
+++ b/board/kukui/gpio.inc
@@ -99,7 +99,7 @@ GPIO(EC_INT_L, PIN(B, 12), GPIO_ODR_HIGH) /* EC_AP_INT_ODL */
GPIO(EC_BOARD_ID_EN_L, PIN(C, 15), GPIO_ODR_HIGH) /* EC_BOARD_ID_EN_ODL */
GPIO(USB_C0_DISCHARGE, PIN(B, 0), GPIO_OUT_LOW)
GPIO(USB_C0_DP_POLARITY, PIN(C, 14), GPIO_OUT_LOW)
-GPIO(USB_C0_HPD_OD, PIN(F, 1), GPIO_ODR_HIGH)
+GPIO(USB_C0_HPD_OD, PIN(F, 1), GPIO_ODR_LOW)
GPIO(BOOTBLOCK_MUX_OE, PIN(C, 4), GPIO_ODR_HIGH)
GPIO(BOOTBLOCK_EN_L, PIN(C, 1), GPIO_ODR_HIGH)
#if BOARD_REV == 0
diff --git a/board/kukui/usb_pd_policy.c b/board/kukui/usb_pd_policy.c
index c3bfa25760..42b0ce7e03 100644
--- a/board/kukui/usb_pd_policy.c
+++ b/board/kukui/usb_pd_policy.c
@@ -273,37 +273,84 @@ 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];
+
static void svdm_dp_post_config(int port)
{
+ const struct usb_mux * const mux = &usb_muxes[port];
+
dp_flags[port] |= DP_FLAGS_DP_ON;
+ if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING))
+ return;
+
+ gpio_set_level(GPIO_USB_C0_HPD_OD, 1);
+ gpio_set_level(GPIO_USB_C0_DP_OE_L, 0);
+ gpio_set_level(GPIO_USB_C0_DP_POLARITY, pd_get_polarity(port));
+
+ /* 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)
{
- const struct usb_mux *mux = &usb_muxes[port];
+ int cur_lvl = gpio_get_level(GPIO_USB_C0_HPD_OD);
int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]);
int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]);
- int mf_pref = PD_VDO_DPSTS_MF_PREF(payload[1]);
+ const struct usb_mux * const mux = &usb_muxes[port];
dp_status[port] = payload[1];
- mux->hpd_update(port, lvl, irq);
+ /* 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;
+ }
- if (lvl)
- usb_mux_set(port, mf_pref ? TYPEC_MUX_DOCK : TYPEC_MUX_DP,
- USB_SWITCH_CONNECT, pd_get_polarity(port));
- else
- usb_mux_set(port, mf_pref ? TYPEC_MUX_USB : TYPEC_MUX_NONE,
- USB_SWITCH_CONNECT, pd_get_polarity(port));
+ 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(GPIO_USB_C0_HPD_OD, 0);
+ usleep(HPD_DSTREAM_DEBOUNCE_IRQ);
+ gpio_set_level(GPIO_USB_C0_HPD_OD, 1);
+
+ gpio_set_level(GPIO_USB_C0_DP_OE_L, 0);
+ gpio_set_level(GPIO_USB_C0_DP_POLARITY, pd_get_polarity(port));
+
+ /* 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(GPIO_USB_C0_HPD_OD, lvl);
+ gpio_set_level(GPIO_USB_C0_DP_OE_L, !lvl);
+ gpio_set_level(GPIO_USB_C0_DP_POLARITY, pd_get_polarity(port));
+ /* 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;
}
static void svdm_exit_dp_mode(int port)
{
- const struct usb_mux *mux = &usb_muxes[port];
+ const struct usb_mux * const mux = &usb_muxes[port];
svdm_safe_dp_mode(port);
+ gpio_set_level(GPIO_USB_C0_HPD_OD, 0);
+ gpio_set_level(GPIO_USB_C0_DP_OE_L, 1);
mux->hpd_update(port, 0, 0);
}