diff options
author | YH Lin <yueherngl@chromium.org> | 2022-12-03 00:17:55 +0000 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-12-05 17:43:18 +0000 |
commit | dd732876495ed4942d00b9f9ca8dd3b01bad7120 (patch) | |
tree | bdff671e5ad3e71e30ab56f4f084f34a2fd72e28 /zephyr/projects/corsola/src/usb_pd_policy.c | |
parent | 184d13e77614be3be5374d3fef9d1edf66ec8687 (diff) | |
download | chrome-ec-dd732876495ed4942d00b9f9ca8dd3b01bad7120.tar.gz |
Revert "Merge remote-tracking branch cros/main into factory-brya-14909.124.B-main"factory-brya-14909.124.B-main
This reverts commit 184d13e77614be3be5374d3fef9d1edf66ec8687.
Reason for revert: broken build due to ec-utils.
Original change's description:
> Merge remote-tracking branch cros/main into factory-brya-14909.124.B-main
>
> Generated by: util/update_release_branch.py --baseboard brya --relevant_paths_file
> baseboard/brya/relevant-paths.txt factory-brya-14909.124.B-main
>
> Relevant changes:
>
> git log --oneline 19d4d68ffa..aa40b859b3 -- baseboard/brya board/agah
> board/anahera board/banshee board/brya board/crota board/felwinter
> board/gimble board/kano board/mithrax board/osiris board/primus
> board/redrix board/taeko board/taniks board/vell board/volmar
> driver/bc12/pi3usb9201_public.* driver/charger/bq25710.*
> driver/ppc/nx20p348x.* driver/ppc/syv682x_public.*
> driver/retimer/bb_retimer_public.* driver/tcpm/nct38xx.*
> driver/tcpm/ps8xxx_public.* driver/tcpm/tcpci.* include/power/alderlake*
> include/intel_x86.h power/alderlake* power/intel_x86.c
> util/getversion.sh
>
> e6da633c38 driver: Sort header files
> 234a87ae2d tcpci: Add FRS enable to driver structure
> a56be59ccd tcpm_header: add test for tcpm_dump_registers
> 57b3256963 Rename CONFIG_CHARGER_INPUT_CURRENT to _CHARGER_DEFAULT_CURRENT_LIMIT
> e420c8ff9a marasov: Modify TypeC and TypeA configuration.
> 43b53e0045 Add default implementation of board_set_charge_limit
> b75dc90677 Add CONFIG_CHARGER_MIN_INPUT_CURRENT_LIMIT
> f1b563c350 baseboard: Sort header files
> 7d01b1e58d driver/retimer/ps8818.h: Add I2C ADDR FLAGS 0x30, 0x58, 0x70
> ec31407993 Add CONFIG_CHARGER_INPUT_CURRENT_DERATE_PCT
> 8f89f69a5b crota: disable lid angle sensor for clamshell
>
> BRANCH=None
> BUG=b:260630630 b:163093572 b:259002141 b:255184961 b:259354679
> BUG=b:247100970 b:254328661
> TEST=`emerge-brya chromeos-ec`
>
> Force-Relevant-Builds: all
> Change-Id: I0ecfa0e6af68631283c7a9e8f1afb9d827176c62
> Signed-off-by: YH Lin <yueherngl@google.com>
Bug: b:260630630 b:163093572 b:259002141 b:255184961 b:259354679
Bug: b:247100970 b:254328661
Change-Id: Ia14942d1bd6a502062399d77cb59d1f4b549b2c9
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4077247
Auto-Submit: YH Lin <yueherngl@chromium.org>
Tested-by: YH Lin <yueherngl@chromium.org>
Reviewed-by: Boris Mittelberg <bmbm@google.com>
Commit-Queue: YH Lin <yueherngl@chromium.org>
Diffstat (limited to 'zephyr/projects/corsola/src/usb_pd_policy.c')
-rw-r--r-- | zephyr/projects/corsola/src/usb_pd_policy.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/zephyr/projects/corsola/src/usb_pd_policy.c b/zephyr/projects/corsola/src/usb_pd_policy.c new file mode 100644 index 0000000000..a885362c61 --- /dev/null +++ b/zephyr/projects/corsola/src/usb_pd_policy.c @@ -0,0 +1,226 @@ +/* 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 "console.h" +#include "chipset.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" + +#include "baseboard_usbc_config.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; +} |