From 482a0811d65d91ca3c030f577d07f4f674058419 Mon Sep 17 00:00:00 2001 From: Alec Berg Date: Wed, 15 Jul 2015 10:23:10 -0700 Subject: [PATCH] glados: add HPD handling to policy layer Add setting HPD gpio to glados USB PD policy layer BUG=chrome-os-partner:42321 BRANCH=none TEST=make -j buildall Change-Id: I293224fa5189c8827f1837877ffb791fddc7fb77 Signed-off-by: Alec Berg Reviewed-on: https://chromium-review.googlesource.com/285743 Reviewed-by: Todd Broch --- board/glados/board.h | 2 +- board/glados/usb_pd_policy.c | 58 ++++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/board/glados/board.h b/board/glados/board.h index 76302791d4..8bbd240c6e 100644 --- a/board/glados/board.h +++ b/board/glados/board.h @@ -88,7 +88,7 @@ #define I2C_PORT_USB_CHARGER_2 MEC1322_I2C3 #undef DEFERRABLE_MAX_COUNT -#define DEFERRABLE_MAX_COUNT 11 +#define DEFERRABLE_MAX_COUNT 13 #ifndef __ASSEMBLER__ diff --git a/board/glados/usb_pd_policy.c b/board/glados/usb_pd_policy.c index bb6df0202b..3ff8a76c53 100644 --- a/board/glados/usb_pd_policy.c +++ b/board/glados/usb_pd_policy.c @@ -243,11 +243,14 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload, #ifdef CONFIG_USB_PD_ALT_MODE_DFP static int dp_flags[CONFIG_USB_PD_PORT_COUNT]; +/* DP Status VDM as returned by UFP */ +static uint32_t dp_status[CONFIG_USB_PD_PORT_COUNT]; static void svdm_safe_dp_mode(int port) { /* make DP interface safe until configure */ dp_flags[port] = 0; + dp_status[port] = 0; usb_mux_set(port, TYPEC_MUX_NONE, USB_SWITCH_CONNECT, pd_get_polarity(port)); } @@ -282,26 +285,75 @@ static int svdm_dp_status(int port, uint32_t *payload) static int svdm_dp_config(int port, uint32_t *payload) { int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); + int pin_mode = pd_dfp_dp_get_pin_mode(port, dp_status[port]); - usb_mux_set(port, TYPEC_MUX_DP, + if (!pin_mode) + return 0; + + usb_mux_set(port, mf_pref ? TYPEC_MUX_DOCK : TYPEC_MUX_DP, USB_SWITCH_CONNECT, pd_get_polarity(port)); + payload[0] = VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); - payload[1] = VDO_DP_CFG(MODE_DP_PIN_E, /* pin mode */ + payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ 1, /* DPv1.3 signaling */ 2); /* UFP connected */ return 2; }; +#define PORT_TO_HPD(port) ((port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD) 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); } +static void hpd0_irq_deferred(void) +{ + gpio_set_level(GPIO_USB_C0_DP_HPD, 1); +} + +static void hpd1_irq_deferred(void) +{ + gpio_set_level(GPIO_USB_C1_DP_HPD, 1); +} + +DECLARE_DEFERRED(hpd0_irq_deferred); +DECLARE_DEFERRED(hpd1_irq_deferred); +#define PORT_TO_HPD_IRQ_DEFERRED(port) ((port) ? hpd1_irq_deferred : \ + hpd0_irq_deferred) + 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); + 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; + } + + if (irq & cur_lvl) { + gpio_set_level(hpd, 0); + hook_call_deferred(PORT_TO_HPD_IRQ_DEFERRED(port), + HPD_DSTREAM_DEBOUNCE_IRQ); + } else if (irq & !cur_lvl) { + CPRINTF("ERR:HPD:IRQ&LOW\n"); + return 0; /* nak */ + } else { + gpio_set_level(hpd, lvl); + } /* ack */ return 1; } @@ -309,7 +361,7 @@ static int svdm_dp_attention(int port, uint32_t *payload) static void svdm_exit_dp_mode(int port) { svdm_safe_dp_mode(port); - /* gpio_set_level(PORT_TO_HPD(port), 0); */ + gpio_set_level(PORT_TO_HPD(port), 0); } static int svdm_enter_gfu_mode(int port, uint32_t mode_caps)