diff options
Diffstat (limited to 'zephyr/program/corsola/src/usb_pd_policy.c')
-rw-r--r-- | zephyr/program/corsola/src/usb_pd_policy.c | 225 |
1 files changed, 0 insertions, 225 deletions
diff --git a/zephyr/program/corsola/src/usb_pd_policy.c b/zephyr/program/corsola/src/usb_pd_policy.c deleted file mode 100644 index a5f3f11134..0000000000 --- a/zephyr/program/corsola/src/usb_pd_policy.c +++ /dev/null @@ -1,225 +0,0 @@ -/* Copyright 2021 The ChromiumOS Authors - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "atomic.h" -#include "baseboard_usbc_config.h" -#include "chipset.h" -#include "console.h" -#include "hooks.h" -#include "timer.h" -#include "typec_control.h" -#include "usb_dp_alt_mode.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usbc_ppc.h" - -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) - -static int active_aux_port = -1; - -int pd_check_vconn_swap(int port) -{ - /* Allow Vconn swap if AP is on. */ - return chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_ON); -} - -static void set_dp_aux_path_sel(int port) -{ - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(dp_aux_path_sel), port); - CPRINTS("Set DP_AUX_PATH_SEL: %d", port); -} - -int svdm_get_hpd_gpio(int port) -{ - /* HPD is low active, inverse the result */ - return !gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(ec_ap_dp_hpd_odl)); -} - -static void reset_aux_deferred(void) -{ - if (active_aux_port == -1) - /* reset to 1 for lower power consumption. */ - set_dp_aux_path_sel(1); -} -DECLARE_DEFERRED(reset_aux_deferred); - -void svdm_set_hpd_gpio(int port, int en) -{ - /* - * HPD is low active, inverse the en. - * - * Implement FCFS policy: - * 1) Enable hpd if no active port. - * 2) Disable hpd if active port is the given port. - */ - if (en && active_aux_port < 0) { - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(ec_ap_dp_hpd_odl), 0); - active_aux_port = port; - hook_call_deferred(&reset_aux_deferred_data, -1); - } - - if (!en && active_aux_port == port) { - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(ec_ap_dp_hpd_odl), 1); - active_aux_port = -1; - /* - * This might be a HPD debounce to send a HPD IRQ (500us), so - * do not reset the aux path immediately. Defer this call and - * re-check if this is a real disable. - */ - hook_call_deferred(&reset_aux_deferred_data, 1 * MSEC); - } -} - -__override int svdm_dp_config(int port, uint32_t *payload) -{ - int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); - uint8_t pin_mode = get_dp_pin_mode(port); - mux_state_t mux_mode = svdm_dp_get_mux_mode(port); - int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); - - if (!pin_mode) { - return 0; - } - - CPRINTS("pin_mode: %x, mf: %d, mux: %d", pin_mode, mf_pref, mux_mode); - /* - * Defer setting the usb_mux until HPD goes high, svdm_dp_attention(). - * The AP only supports one DP phy. An external DP mux switches between - * the two ports. Should switch those muxes when it is really used, - * i.e. HPD high; otherwise, the real use case is preempted, like: - * (1) plug a dongle without monitor connected to port-0, - * (2) plug a dongle without monitor connected to port-1, - * (3) plug a monitor to the port-1 dongle. - */ - - payload[0] = - VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); - payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ - 1, /* DPv1.3 signaling */ - 2); /* UFP connected */ - return 2; -}; - -__override void svdm_dp_post_config(int port) -{ - mux_state_t mux_mode = svdm_dp_get_mux_mode(port); - - typec_set_sbu(port, true); - - /* - * Prior to post-config, the mux will be reset to safe mode, and this - * will break mux config and aux path config we did in the first DP - * status command. Only enable this if the port is the current aux-port. - */ - if (port == active_aux_port) { - usb_mux_set(port, mux_mode, USB_SWITCH_CONNECT, - polarity_rm_dts(pd_get_polarity(port))); - usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL | - USB_PD_MUX_HPD_IRQ_DEASSERTED); - } - - dp_flags[port] |= DP_FLAGS_DP_ON; -} - -int corsola_is_dp_muxable(int port) -{ - int i; - - for (i = 0; i < board_get_usb_pd_port_count(); i++) { - if (i != port) { - if (usb_mux_get(i) & USB_PD_MUX_DP_ENABLED) { - return 0; - } - } - } - - return 1; -} - -__override int svdm_dp_attention(int port, uint32_t *payload) -{ - int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); - int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - int cur_lvl = svdm_get_hpd_gpio(port); -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - mux_state_t mux_state; - - dp_status[port] = payload[1]; - - if (!corsola_is_dp_muxable(port)) { - /* TODO(waihong): Info user? */ - CPRINTS("p%d: The other port is already muxed.", port); - return 0; /* nak */ - } - - if (lvl) { - set_dp_aux_path_sel(port); - - usb_mux_set(port, USB_PD_MUX_DOCK, USB_SWITCH_CONNECT, - polarity_rm_dts(pd_get_polarity(port))); - } else { - usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT, - polarity_rm_dts(pd_get_polarity(port))); - } - - if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && (irq || lvl)) { - /* - * Wake up the AP. IRQ or level high indicates a DP sink is now - * present. - */ - if (IS_ENABLED(CONFIG_MKBP_EVENT)) { - pd_notify_dp_alt_mode_entry(port); - } - } - -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - if (irq && !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 */ - } - - if (irq && cur_lvl) { - uint64_t now = get_time().val; - /* wait for the minimum spacing between IRQ_HPD if needed */ - if (now < svdm_hpd_deadline[port]) { - usleep(svdm_hpd_deadline[port] - now); - } - - /* generate IRQ_HPD pulse */ - svdm_set_hpd_gpio(port, 0); - /* - * b/171172053#comment14: since the HPD_DSTREAM_DEBOUNCE_IRQ is - * very short (500us), we can use udelay instead of usleep for - * more stable pulse period. - */ - udelay(HPD_DSTREAM_DEBOUNCE_IRQ); - svdm_set_hpd_gpio(port, 1); - } else { - svdm_set_hpd_gpio(port, lvl); - } - - /* set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - - mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | - (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); - usb_mux_hpd_update(port, mux_state); - -#ifdef USB_PD_PORT_TCPC_MST - if (port == USB_PD_PORT_TCPC_MST) { - baseboard_mst_enable_control(port, lvl); - } -#endif - - /* ack */ - return 1; -} |