summaryrefslogtreecommitdiff
path: root/board/chell
diff options
context:
space:
mode:
authorKevin K Wong <kevin.k.wong@intel.com>2017-04-06 22:39:01 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-05-29 03:28:25 -0700
commit03a665939f8adef0f8fd5a170f859210f65d2c54 (patch)
treeb9da51dc9bdecefebc13ffae238de8a895a60cf4 /board/chell
parent6bbcf5b3f8fac6c6d4f8ea9edef470cf4887f1a7 (diff)
downloadchrome-ec-03a665939f8adef0f8fd5a170f859210f65d2c54.tar.gz
pd: ensure tighter timings for IRQ_HPD pulse
In order to ensure we are always meeting the deadlines for the IRQ_HPD pulse, increase the priority of the processing by moving the rising edge from the low-priority HOOK task (in a deferred function) to the caller task (which is the high-priority PD task). The downside is we are now sleeping in the PD task blocking the processing of the PD messages during this time. Changed HPD_DSTREAM_DEBOUNCE_IRQ to 500us instead of 750us. According to DP spec, the IRQ_HPD pulse width is between 500us and 1000us. Ensure there is a minimum of 2ms delay in between each IRQ_HPD as specified by the DP spec, by sleeping before sending the next pulse if needed. (in practice, this should not wait if we are not too off processing the messages) BUG=chromium:711334 BRANCH=glados strago reef oak TEST=manual, on SKL platform with kernel 3.18 and MST, verify display is functional on USB-C dock. Change-Id: Ib2e9dd608c5f1c671cc5a0fd979a5742101375ff Signed-off-by: Kevin K Wong <kevin.k.wong@intel.com> Signed-off-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/508629 Reviewed-by: Todd Broch <tbroch@chromium.org>
Diffstat (limited to 'board/chell')
-rw-r--r--board/chell/usb_pd_policy.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/board/chell/usb_pd_policy.c b/board/chell/usb_pd_policy.c
index efe2b953c5..9c2218dd5a 100644
--- a/board/chell/usb_pd_policy.c
+++ b/board/chell/usb_pd_policy.c
@@ -281,6 +281,12 @@ 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];
+
#define PORT_TO_HPD(port) ((port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD)
static void svdm_dp_post_config(int port)
{
@@ -289,24 +295,11 @@ static void svdm_dp_post_config(int port)
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);
+ /* set the minimum time delay (2ms) for the next HPD IRQ */
+ hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL;
}
-DECLARE_DEFERRED(hpd0_irq_deferred);
-DECLARE_DEFERRED(hpd1_irq_deferred);
-#define PORT_TO_HPD_IRQ_DEFERRED(port) ((port) ? \
- &hpd1_irq_deferred_data : \
- &hpd0_irq_deferred_data)
-
static int svdm_dp_attention(int port, uint32_t *payload)
{
int cur_lvl;
@@ -325,14 +318,25 @@ static int svdm_dp_attention(int port, uint32_t *payload)
}
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);
- hook_call_deferred(PORT_TO_HPD_IRQ_DEFERRED(port),
- HPD_DSTREAM_DEBOUNCE_IRQ);
+ 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;
}
/* ack */
return 1;