diff options
author | Vijay Hiremath <vijay.p.hiremath@intel.com> | 2015-07-16 19:18:07 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-07-22 05:02:48 +0000 |
commit | 2302647f574852f3a76813dc8adf2a9dc7d81235 (patch) | |
tree | 606478b650d82200b9b9be9f5979cdf38f3f1837 /board | |
parent | dfcb1dc9e16a0e0f1bdf95033d60663ce5b76f93 (diff) | |
download | chrome-ec-2302647f574852f3a76813dc8adf2a9dc7d81235.tar.gz |
kunimitsu: add HPD handling to policy layer
Ported the HPD handling to policy from Glados
Change-Id: I293224fa5189c8827f1837877ffb791fddc7fb77
Reviewed-on: https://chromium-review.googlesource.com/285743
BUG=none
TEST=make buildall -j
BRANCH=none
Change-Id: I72e2f0853902bfa3536ba083f8ece5785be625c4
Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/287410
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Diffstat (limited to 'board')
-rw-r--r-- | board/kunimitsu/board.h | 3 | ||||
-rw-r--r-- | board/kunimitsu/gpio.inc | 4 | ||||
-rw-r--r-- | board/kunimitsu/usb_pd_policy.c | 84 |
3 files changed, 78 insertions, 13 deletions
diff --git a/board/kunimitsu/board.h b/board/kunimitsu/board.h index 87af8b45c1..788559d558 100644 --- a/board/kunimitsu/board.h +++ b/board/kunimitsu/board.h @@ -52,6 +52,7 @@ #define CONFIG_USB_SWITCH_PI3USB9281 #define CONFIG_USB_SWITCH_PI3USB9281_CHIP_COUNT 2 #define CONFIG_USBC_SS_MUX +#define CONFIG_USBC_VCONN #define CONFIG_SCI_GPIO GPIO_PCH_SCI_L #define CONFIG_SPI_PORT 1 @@ -84,7 +85,7 @@ #define I2C_PORT_USB_CHARGER_2 MEC1322_I2C3 #undef DEFERRABLE_MAX_COUNT -#define DEFERRABLE_MAX_COUNT 11 +#define DEFERRABLE_MAX_COUNT 13 #define CONFIG_ALS #define CONFIG_ALS_OPT3001 diff --git a/board/kunimitsu/gpio.inc b/board/kunimitsu/gpio.inc index e578cbd9bb..7c9e9e8ecb 100644 --- a/board/kunimitsu/gpio.inc +++ b/board/kunimitsu/gpio.inc @@ -48,8 +48,8 @@ GPIO(USB2_ENABLE, PIN(67), GPIO_OUT_HIGH) GPIO(ENTERING_RW, PIN(41), GPIO_OUT_LOW) GPIO(PCH_SMI_L, PIN(44), GPIO_ODR_HIGH) GPIO(PCH_PWRBTN_L, PIN(45), GPIO_OUT_HIGH) -GPIO(USB_C0_DP_HPD, PIN(46), GPIO_OUT_HIGH) -GPIO(USB_C1_DP_HPD, PIN(51), GPIO_OUT_HIGH) +GPIO(USB_C0_DP_HPD, PIN(46), GPIO_OUT_LOW) +GPIO(USB_C1_DP_HPD, PIN(51), GPIO_OUT_LOW) GPIO(CPU_PROCHOT, PIN(52), GPIO_OUT_LOW) GPIO(ENABLE_TOUCHPAD, PIN(53), GPIO_OUT_HIGH) GPIO(BAT_PRESENT_L, PIN(56), GPIO_INPUT) diff --git a/board/kunimitsu/usb_pd_policy.c b/board/kunimitsu/usb_pd_policy.c index 304b809994..3ff8a76c53 100644 --- a/board/kunimitsu/usb_pd_policy.c +++ b/board/kunimitsu/usb_pd_policy.c @@ -157,18 +157,30 @@ void pd_execute_data_swap(int port, int data_role) /* TODO: need to open/close D+/D- switch based on role */ } -void pd_check_pr_role(int port, int pr_role, int partner_pr_swap) +void pd_check_pr_role(int port, int pr_role, int flags) { - /* If sink, and dual role toggling is on, then switch to source */ - if (partner_pr_swap && pr_role == PD_ROLE_SINK && - pd_get_dual_role() == PD_DRP_TOGGLE_ON) - pd_request_power_swap(port); + /* + * If partner is dual-role power and dualrole toggling is on, consider + * if a power swap is necessary. + */ + if ((flags & PD_FLAGS_PARTNER_DR_POWER) && + pd_get_dual_role() == PD_DRP_TOGGLE_ON) { + /* + * If we are a sink and partner is not externally powered, then + * swap to become a source. If we are source and partner is + * externally powered, swap to become a sink. + */ + int partner_extpower = flags & PD_FLAGS_PARTNER_EXTPOWER; + if ((!partner_extpower && pr_role == PD_ROLE_SINK) || + (partner_extpower && pr_role == PD_ROLE_SOURCE)) + pd_request_power_swap(port); + } } -void pd_check_dr_role(int port, int dr_role, int partner_dr_swap) +void pd_check_dr_role(int port, int dr_role, int flags) { /* If UFP, try to switch to DFP */ - if (partner_dr_swap && dr_role == PD_ROLE_UFP) + if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP) pd_request_data_swap(port); } /* ----------------- Vendor Defined Messages ------------------ */ @@ -231,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)); } @@ -270,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]); + + if (!pin_mode) + return 0; - usb_mux_set(port, TYPEC_MUX_DP, + 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; } @@ -297,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) |