diff options
Diffstat (limited to 'baseboard/cherry/usb_pd_policy.c')
-rw-r--r-- | baseboard/cherry/usb_pd_policy.c | 260 |
1 files changed, 0 insertions, 260 deletions
diff --git a/baseboard/cherry/usb_pd_policy.c b/baseboard/cherry/usb_pd_policy.c deleted file mode 100644 index 0c7f4dcee5..0000000000 --- a/baseboard/cherry/usb_pd_policy.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "adc.h" -#include "atomic.h" -#include "charge_manager.h" -#include "chipset.h" -#include "driver/tcpm/rt1718s.h" -#include "driver/tcpm/tcpci.h" -#include "timer.h" -#include "usb_dp_alt_mode.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usbc_ppc.h" - -#if CONFIG_USB_PD_3A_PORTS != 1 -#error Cherry reference must have at least one 3.0 A port -#endif - -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) - -/* The port that the aux channel is on. */ -static enum { - AUX_PORT_NONE = -1, - AUX_PORT_C0 = 0, - AUX_PORT_C1HDMI = 1, -} aux_port = AUX_PORT_NONE; - -int svdm_get_hpd_gpio(int port) -{ - /* HPD is low active, inverse the result */ - return !gpio_get_level(GPIO_EC_AP_DP_HPD_ODL); -} - -void svdm_set_hpd_gpio(int port, int en) -{ - /* - * HPD is low active, inverse the en - * TODO: C0&C1 shares the same HPD, implement FCFS policy. - */ - gpio_set_level(GPIO_EC_AP_DP_HPD_ODL, !en); -} - -static void aux_switch_port(int port) -{ - if (port != AUX_PORT_NONE) - gpio_set_level_verbose(CC_USBPD, GPIO_DP_PATH_SEL, !port); - aux_port = port; -} - -static void aux_display_disconnected(int port) -{ - /* Gets the other port. C0 -> C1, C1 -> C0. */ - int other_port = !port; - - /* If the current port is not the aux port, nothing needs to be done. */ - if (aux_port != port) - return; - - /* If the other port is connected to a external display, switch aux. */ - if (dp_status[other_port] & DP_FLAGS_DP_ON) - aux_switch_port(other_port); - else - aux_switch_port(AUX_PORT_NONE); -} - -__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 (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); - - /* 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; - } - -#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); - } - - /* - * Cherry can only output to 1 display port at a time. - * This implements FCFS policy by changing the aux channel. If a - * display is connected to the either port (says A), and the port A - * will be served until the display is disconnected from port A. - * It won't output to the other display which connects to port B. - */ - if (lvl && aux_port == AUX_PORT_NONE) - /* - * A display is connected, and no display was plugged on either - * port. - */ - aux_switch_port(port); - else if (!lvl) - aux_display_disconnected(port); - - - /* 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; -} - -__override void svdm_exit_dp_mode(int port) -{ -#ifdef CONFIG_USB_PD_DP_HPD_GPIO - svdm_set_hpd_gpio(port, 0); -#endif /* CONFIG_USB_PD_DP_HPD_GPIO */ - usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | - USB_PD_MUX_HPD_IRQ_DEASSERTED); - - aux_display_disconnected(port); - -#ifdef USB_PD_PORT_TCPC_MST - if (port == USB_PD_PORT_TCPC_MST) - baseboard_mst_enable_control(port, 0); -#endif -} - -int pd_snk_is_vbus_provided(int port) -{ - static atomic_t vbus_prev[CONFIG_USB_PD_PORT_MAX_COUNT]; - int vbus; - - /* - * Use ppc_is_vbus_present for all ports on Cherry, and - * port 1 on other devices. - */ - if (IS_ENABLED(BOARD_CHERRY) || port == 1) - return ppc_is_vbus_present(port); - - /* b/181203590: use ADC for port 0 (syv682x) */ - vbus = (adc_read_channel(ADC_VBUS) >= PD_V_SINK_DISCONNECT_MAX); - -#ifdef CONFIG_USB_CHARGER - /* - * There's no PPC to inform VBUS change for usb_charger, so inform - * the usb_charger now. - */ - if (!!(vbus_prev[port] != vbus)) - usb_charger_vbus_change(port, vbus); - - if (vbus) - atomic_or(&vbus_prev[port], 1); - else - atomic_clear(&vbus_prev[port]); -#endif - return vbus; -} - -void pd_power_supply_reset(int port) -{ - int prev_en; - - prev_en = ppc_is_sourcing_vbus(port); - - /* Disable VBUS. */ - ppc_vbus_source_enable(port, 0); - - /* Enable discharge if we were previously sourcing 5V */ - if (prev_en) - pd_set_vbus_discharge(port, 1); - - if (port == 1) - rt1718s_gpio_set_level(port, GPIO_EN_USB_C1_5V_OUT, 0); - - /* Notify host of power info change. */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -int pd_check_vconn_swap(int port) -{ - /* Allow Vconn swap if AP is on. */ - return chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_ON); -} - -int pd_set_power_supply_ready(int port) -{ - int rv; - - /* Disable charging. */ - rv = ppc_vbus_sink_enable(port, 0); - if (rv) - return rv; - - pd_set_vbus_discharge(port, 0); - - /* Provide Vbus. */ - rv = ppc_vbus_source_enable(port, 1); - if (rv) - return rv; - - if (port == 1) - rt1718s_gpio_set_level(port, GPIO_EN_USB_C1_5V_OUT, 1); - - /* Notify host of power info change. */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; -} - -int board_vbus_source_enabled(int port) -{ - return ppc_is_sourcing_vbus(port); -} |