diff options
author | Todd Broch <tbroch@chromium.org> | 2014-10-13 17:50:33 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-10-25 08:14:10 +0000 |
commit | cadce20c1ac866833d15ad7d8360cda17ea344e2 (patch) | |
tree | e9d27e61d9bb1583f7768a2c11da041cfbced5a2 /board | |
parent | bf8335a0a329f8d40fe3c4e911c9f9bb144ca2ad (diff) | |
download | chrome-ec-cadce20c1ac866833d15ad7d8360cda17ea344e2.tar.gz |
pd: Add DFP parsing for alternate mode status & attention.
Once alternate mode is entered the DFP will make an initial status
request to the UFP. Future status changes on the UFP are then sent to
the DFP via the attention command. This VDM consists of the VDM
header plus another VDO containing mode specific information.
CL adds ability of DFP to consume the attention VDMs status message
and in the case of DisplayPort SID toggle the necessary HPD gpio
accordingly.
BRANCH=samus
BUG=chrome-os-partner:30645
TEST=manual, for DFP w/ HPD over CC see HPD toggle correctly without
manually driving it providing cable connected when AMA is inserted.
Change-Id: Ifef60b5d0170cbcc1b518e3b13e84bac99a17e32
Signed-off-by: Todd Broch <tbroch@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/224769
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'board')
-rw-r--r-- | board/dingdong/usb_pd_policy.c | 46 | ||||
-rw-r--r-- | board/fruitpie/usb_pd_policy.c | 7 | ||||
-rw-r--r-- | board/hoho/usb_pd_policy.c | 46 | ||||
-rw-r--r-- | board/samus_pd/usb_pd_policy.c | 42 |
4 files changed, 92 insertions, 49 deletions
diff --git a/board/dingdong/usb_pd_policy.c b/board/dingdong/usb_pd_policy.c index fa0894e509..97504a1cbf 100644 --- a/board/dingdong/usb_pd_policy.c +++ b/board/dingdong/usb_pd_policy.c @@ -124,7 +124,14 @@ static int svdm_response_svids(int port, uint32_t *payload) return 2; } -const uint32_t vdo_dp_mode[1] = { +/* Will only ever be a single mode for this UFP_D device as it has no USB + * support (2.0 or 3.0) making it only PIN_E configureable nor does it have any + * source functionality. + */ +#define MODE_CNT 1 +#define OPOS 1 + +const uint32_t vdo_dp_mode[MODE_CNT] = { VDO_MODE_DP(0, /* UFP pin cfg supported : none */ MODE_DP_PIN_E, /* DFP pin cfg supported */ 1, /* no usb2.0 signalling in AMode */ @@ -135,57 +142,46 @@ const uint32_t vdo_dp_mode[1] = { static int svdm_response_modes(int port, uint32_t *payload) { - int mode_cnt = ARRAY_SIZE(vdo_dp_mode); - if (PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) { /* TODO(tbroch) USB billboard enabled here then */ return 1; /* will generate a NAK */ } memcpy(payload + 1, vdo_dp_mode, sizeof(vdo_dp_mode)); - return mode_cnt + 1; -} - -static int hpd_get_irq(int port) -{ - /* TODO(tbroch) FIXME */ - return 0; -} - -static enum hpd_level hpd_get_level(int port) -{ - /* TODO(tbroch) FIXME: needs debounce */ - return gpio_get_level(GPIO_DP_HPD); + return MODE_CNT + 1; } static int dp_status(int port, uint32_t *payload) { - uint32_t ufp_dp_sts = payload[1] & 0x3; - payload[1] = VDO_DP_STATUS(hpd_get_irq(port), /* IRQ_HPD */ - hpd_get_level(port), /* HPD_HI|LOW */ + int opos = PD_VDO_OPOS(payload[0]); + int hpd = gpio_get_level(GPIO_DP_HPD); + if (opos != OPOS) + return 0; /* nak */ + + payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + (hpd == 1), /* HPD_HI|LOW */ 0, /* request exit DP */ 0, /* request exit USB */ 0, /* MF pref */ gpio_get_level(GPIO_PD_SBU_ENABLE), 0, /* power low */ - (ufp_dp_sts | 0x2)); + 0x2); return 2; } static int dp_config(int port, uint32_t *payload) { - if (PD_DP_CFG_DPON(payload[1])) { + if (PD_DP_CFG_DPON(payload[1])) gpio_set_level(GPIO_PD_SBU_ENABLE, 1); - payload[1] = 0; - } - return 2; + + return 1; } static int svdm_enter_mode(int port, uint32_t *payload) { /* SID & mode request is valid */ if ((PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) || - (PD_VDO_OPOS(payload[0]) != 1)) + (PD_VDO_OPOS(payload[0]) != OPOS)) return 0; /* will generate NAK */ return 1; } diff --git a/board/fruitpie/usb_pd_policy.c b/board/fruitpie/usb_pd_policy.c index 6caea5692f..aa63911cc9 100644 --- a/board/fruitpie/usb_pd_policy.c +++ b/board/fruitpie/usb_pd_policy.c @@ -224,6 +224,12 @@ static int svdm_dp_config(int port, uint32_t *payload) return 2; }; +static int svdm_dp_attention(int port, uint32_t *payload) +{ + CPRINTF("dp sts:%08x\n", payload[1]); + return 1; /* ack */ +} + static void svdm_exit_dp_mode(int port) { CPRINTF("Exiting mode\n"); @@ -236,6 +242,7 @@ const struct svdm_amode_fx supported_modes[] = { .enter = &svdm_enter_dp_mode, .status = &svdm_dp_status, .config = &svdm_dp_config, + .attention = &svdm_dp_attention, .exit = &svdm_exit_dp_mode, }, }; diff --git a/board/hoho/usb_pd_policy.c b/board/hoho/usb_pd_policy.c index 61457d3d6c..b747766aa9 100644 --- a/board/hoho/usb_pd_policy.c +++ b/board/hoho/usb_pd_policy.c @@ -124,7 +124,14 @@ static int svdm_response_svids(int port, uint32_t *payload) return 2; } -const uint32_t vdo_dp_mode[1] = { +/* Will only ever be a single mode for this UFP_D device as it has no USB + * support (2.0 or 3.0) making it only PIN_E configureable nor does it have any + * source functionality. + */ +#define MODE_CNT 1 +#define OPOS 1 + +const uint32_t vdo_dp_mode[MODE_CNT] = { VDO_MODE_DP(0, /* UFP pin cfg supported : none */ MODE_DP_PIN_C, /* DFP pin cfg supported */ 1, /* no usb2.0 signalling in AMode */ @@ -135,39 +142,30 @@ const uint32_t vdo_dp_mode[1] = { static int svdm_response_modes(int port, uint32_t *payload) { - int mode_cnt = ARRAY_SIZE(vdo_dp_mode); - if (PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) { /* TODO(tbroch) USB billboard enabled here then */ return 1; /* will generate a NAK */ } memcpy(payload + 1, vdo_dp_mode, sizeof(vdo_dp_mode)); - return mode_cnt + 1; -} - -static int hpd_get_irq(int port) -{ - /* TODO(tbroch) FIXME */ - return 0; -} - -static enum hpd_level hpd_get_level(int port) -{ - return gpio_get_level(GPIO_DP_HPD); + return MODE_CNT + 1; } static int dp_status(int port, uint32_t *payload) { - uint32_t ufp_dp_sts = payload[1] & 0x3; - payload[1] = VDO_DP_STATUS(hpd_get_irq(port), /* IRQ_HPD */ - hpd_get_level(port), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - 0, /* MF pref */ + int opos = PD_VDO_OPOS(payload[0]); + int hpd = gpio_get_level(GPIO_DP_HPD); + if (opos != OPOS) + return 0; /* nak */ + + payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + (hpd == 1), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ gpio_get_level(GPIO_PD_SBU_ENABLE), - 0, /* power low */ - (ufp_dp_sts | 0x2)); + 0, /* power low */ + 0x2); return 2; } @@ -182,7 +180,7 @@ static int svdm_enter_mode(int port, uint32_t *payload) { /* SID & mode request is valid */ if ((PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) || - (PD_VDO_OPOS(payload[0]) != 1)) + (PD_VDO_OPOS(payload[0]) != OPOS)) return 0; /* will generate a NAK */ return 1; } diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c index e8ffd2a886..507c6d3bce 100644 --- a/board/samus_pd/usb_pd_policy.c +++ b/board/samus_pd/usb_pd_policy.c @@ -7,6 +7,7 @@ #include "common.h" #include "console.h" #include "gpio.h" +#include "hooks.h" #include "host_command.h" #include "registers.h" #include "task.h" @@ -275,9 +276,49 @@ static int svdm_dp_config(int port, uint32_t *payload) return 2; }; +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(port) ((port) ? GPIO_USB_C1_DP_HPD : GPIO_USB_C0_DP_HPD) + +static int svdm_dp_attention(int port, uint32_t *payload) +{ + int cur_lvl; + int lvl = PD_VDO_HPD_LVL(payload[1]); + int irq = PD_VDO_HPD_IRQ(payload[1]); + enum gpio_signal hpd = PORT_TO_HPD(port); + cur_lvl = gpio_get_level(hpd); + if (irq & cur_lvl) { + gpio_set_level(hpd, 0); + /* 250 usecs is minimum, 2msec is max */ + if (port) + hook_call_deferred(hpd1_irq_deferred, 300); + else + hook_call_deferred(hpd0_irq_deferred, 300); + } else if (irq & !cur_lvl) { + CPRINTF("PE ERR: IRQ_HPD w/ HPD_LOW\n"); + return 0; /* nak */ + } else { + gpio_set_level(hpd, lvl); + } + /* ack */ + return 1; +} + static void svdm_exit_dp_mode(int port) { svdm_safe_dp_mode(port); + gpio_set_level(PORT_TO_HPD(port), 0); } const struct svdm_amode_fx supported_modes[] = { @@ -286,6 +327,7 @@ const struct svdm_amode_fx supported_modes[] = { .enter = &svdm_enter_dp_mode, .status = &svdm_dp_status, .config = &svdm_dp_config, + .attention = &svdm_dp_attention, .exit = &svdm_exit_dp_mode, }, }; |