mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 01:21:49 +00:00
grunt: Set USB-C DP HPD GPIOs correctly.
Change the EC to drive the Hotplug Detect (HPD) GPIOs. Grunt HW has these driven from EC to SOC, unlike coral which had the TCPCs drive the HPD signals to SOC. BUG=b:71810897 BRANCH=none TEST=external display works using USB-C to DP adapter on both ports Change-Id: I22ec9eecc5bdf9c6463dd3ce208d051faf15c57a Signed-off-by: Edward Hill <ecgh@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/892099 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org>
This commit is contained in:
@@ -313,39 +313,81 @@ 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)
|
||||
{
|
||||
const struct usb_mux *mux = &usb_muxes[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(PORT_TO_HPD(port), 1);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int cur_lvl;
|
||||
int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]);
|
||||
int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]);
|
||||
const struct usb_mux *mux = &usb_muxes[port];
|
||||
enum gpio_signal hpd = PORT_TO_HPD(port);
|
||||
const struct usb_mux * const mux = &usb_muxes[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;
|
||||
return 1; /* ack */
|
||||
}
|
||||
|
||||
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);
|
||||
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) {
|
||||
/*
|
||||
* IRQ can only be generated when the level is high, because
|
||||
* the IRQ is signaled by a short low pulse from the high level.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
mux->hpd_update(port, lvl, irq);
|
||||
|
||||
/* ack */
|
||||
return 1;
|
||||
return 1; /* ack */
|
||||
}
|
||||
|
||||
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(PORT_TO_HPD(port), 0);
|
||||
mux->hpd_update(port, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user