From 06d89b033065d9c96f4a6e53129b22b912fae224 Mon Sep 17 00:00:00 2001 From: Parth Malkan Date: Tue, 10 Aug 2021 21:54:59 +0000 Subject: SSFC: Framework to support two charger sources Many platforms have requirements to support more than one charge source (eg. pirika). It can't be supported by just enabling two different CONFIGS as that can lead to conflicts. Eg.USD_PD_VBUS_DETECT_TCPC vs USB_PD_VBUS_DETECT_DISCHARGE. This change provides a framework that supports two different charger sources in the same build. Please see the CL for relevant logs. BRANCH=None BUG=b:194375840 TEST=make -j buildall Signed-off-by: Parth Malkan Change-Id: I309cc5930233983e615d90a4290fc749abf7aa2d Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3088232 Reviewed-by: Aseda Aboagye --- common/build.mk | 1 + common/usb_charger.c | 11 +++--- common/usb_common.c | 20 ++++++++--- common/usb_pd_flags.c | 65 +++++++++++++++++++++++++++++++++++ common/usb_pd_protocol.c | 76 ++++++++++++++++++++++------------------- driver/tcpm/tcpci.c | 35 +++++++++++-------- include/config.h | 7 ++++ include/usb_pd_flags.h | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ zephyr/CMakeLists.txt | 3 +- 9 files changed, 248 insertions(+), 58 deletions(-) create mode 100644 common/usb_pd_flags.c create mode 100644 include/usb_pd_flags.h diff --git a/common/build.mk b/common/build.mk index 867dcf465f..a1a956f9ab 100644 --- a/common/build.mk +++ b/common/build.mk @@ -52,6 +52,7 @@ common-$(CONFIG_BODY_DETECTION)+=body_detection.o common-$(CONFIG_CAPSENSE)+=capsense.o common-$(CONFIG_CEC)+=cec.o common-$(CONFIG_CBI_EEPROM)+=cbi.o cbi_eeprom.o +common-$(CONFIG_USB_PD_FLAGS)+=usb_pd_flags.o common-$(CONFIG_CBI_GPIO)+=cbi.o cbi_gpio.o ifeq ($(HAS_MOCK_CHARGE_MANAGER),) common-$(CONFIG_CHARGE_MANAGER)+=charge_manager.o diff --git a/common/usb_charger.c b/common/usb_charger.c index 20031a9469..b8e8038811 100644 --- a/common/usb_charger.c +++ b/common/usb_charger.c @@ -22,6 +22,7 @@ #include "task.h" #include "usb_charge.h" #include "usb_pd.h" +#include "usb_pd_flags.h" #include "usbc_ppc.h" #include "util.h" @@ -81,11 +82,11 @@ void usb_charger_vbus_change(int port, int vbus_level) usb_charger_reset_charge(port); #endif -#if (defined(CONFIG_USB_PD_VBUS_DETECT_CHARGER) \ - || defined(CONFIG_USB_PD_VBUS_DETECT_PPC)) - /* USB PD task */ - task_wake(PD_PORT_TO_TASK_ID(port)); -#endif + if ((get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_CHARGER) || + (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_PPC)) { + /* USB PD task */ + task_wake(PD_PORT_TO_TASK_ID(port)); + } } void usb_charger_reset_charge(int port) diff --git a/common/usb_common.c b/common/usb_common.c index 2515caf287..786bd118cf 100644 --- a/common/usb_common.c +++ b/common/usb_common.c @@ -25,6 +25,7 @@ #include "usb_mux.h" #include "usb_pd.h" #include "usb_pd_dpm.h" +#include "usb_pd_flags.h" #include "usb_pd_tcpm.h" #include "usbc_ocp.h" #include "usbc_ppc.h" @@ -851,12 +852,17 @@ void pd_set_vbus_discharge(int port, int enable) mutex_lock(&discharge_lock[port]); enable &= !board_vbus_source_enabled(port); - if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_GPIO)) + if (get_usb_pd_discharge() == USB_PD_DISCHARGE_GPIO) { gpio_discharge_vbus(port, enable); - else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_TCPC)) + } else if (get_usb_pd_discharge() == USB_PD_DISCHARGE_TCPC) { +#ifdef CONFIG_USB_PD_DISCHARGE_PPC tcpc_discharge_vbus(port, enable); - else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_PPC)) +#endif + } else if (get_usb_pd_discharge() == USB_PD_DISCHARGE_PPC) { +#ifdef CONFIG_USB_PD_DISCHARGE_PPC ppc_discharge_vbus(port, enable); +#endif + } mutex_unlock(&discharge_lock[port]); } @@ -884,6 +890,10 @@ void pd_deferred_resume(int port) } #endif /* CONFIG_USB_PD_TCPM_TCPCI */ +__overridable int pd_snk_is_vbus_provided(int port) +{ + return EC_SUCCESS; +} /* * Check the specified Vbus level @@ -893,8 +903,10 @@ void pd_deferred_resume(int port) */ __overridable bool pd_check_vbus_level(int port, enum vbus_level level) { - if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_TCPC)) + if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_TCPC) && + (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_TCPC)) { return tcpm_check_vbus_level(port, level); + } else if (level == VBUS_PRESENT) return pd_snk_is_vbus_provided(port); else diff --git a/common/usb_pd_flags.c b/common/usb_pd_flags.c new file mode 100644 index 0000000000..9328c03346 --- /dev/null +++ b/common/usb_pd_flags.c @@ -0,0 +1,65 @@ +/* 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. + */ + +/* + * Contains USB PD accessors definition + */ + +#include "common.h" +#include "config.h" +#include "usb_pd_flags.h" + +static union usb_pd_runtime_flags usb_pd_flags; +BUILD_ASSERT(sizeof(usb_pd_flags) == sizeof(uint32_t)); + +enum usb_pd_vbus_detect get_usb_pd_vbus_detect(void) +{ + if (IS_ENABLED(CONFIG_USB_PD_RUNTIME_FLAGS)) + return (enum usb_pd_vbus_detect) usb_pd_flags.vbus_detect; + else if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_TCPC)) + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_TCPC; + else if (IS_ENABLED(CONFIG_USD_PD_VBUS_DETECT_GPIO)) + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_GPIO; + else if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_PPC)) + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_PPC; + else if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_CHARGER)) + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_CHARGER; + else + return (enum usb_pd_vbus_detect)USB_PD_VBUS_DETECT_NONE; +} + +enum usb_pd_discharge get_usb_pd_discharge(void) +{ + if (IS_ENABLED(CONFIG_USB_PD_RUNTIME_FLAGS)) + return (enum usb_pd_discharge)usb_pd_flags.discharge; + else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_TCPC)) + return (enum usb_pd_discharge)USB_PD_DISCHARGE_TCPC; + else if (IS_ENABLED(CONFIG_USD_PD_DISCHARGE_GPIO)) + return (enum usb_pd_discharge)USB_PD_DISCHARGE_GPIO; + else if (IS_ENABLED(CONFIG_USB_PD_DISCHARGE_PPC)) + return (enum usb_pd_discharge)USB_PD_DISCHARGE_PPC; + else + return (enum usb_pd_discharge)USB_PD_DISCHARGE_NONE; +} + +enum usb_pd_charger_otg get_usb_pd_charger_otg(void) +{ + return usb_pd_flags.charger_otg; +} + +void set_usb_pd_vbus_detect(enum usb_pd_vbus_detect vbus_detect) +{ + usb_pd_flags.vbus_detect = vbus_detect; +} + +void set_usb_pd_discharge(enum usb_pd_discharge discharge) +{ + usb_pd_flags.discharge = discharge; +} + +void set_usb_pd_charger_otg(enum usb_pd_charger_otg charger_otg) +{ + usb_pd_flags.charger_otg = charger_otg; +} diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 07b50363b9..abf75e8004 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -29,6 +29,7 @@ #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_flags.h" #include "usb_pd_tcpm.h" #include "usb_pd_tcpc.h" #include "usbc_ocp.h" @@ -1570,10 +1571,10 @@ static void handle_data_request(int port, uint32_t head, if ((pd[port].task_state == PD_STATE_SNK_DISCOVERY) || (pd[port].task_state == PD_STATE_SNK_TRANSITION) || (pd[port].task_state == PD_STATE_SNK_REQUESTED) -#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE - || (pd[port].task_state == - PD_STATE_SNK_HARD_RESET_RECOVER) -#endif + || ((get_usb_pd_vbus_detect() == + USB_PD_VBUS_DETECT_NONE) + && (pd[port].task_state == + PD_STATE_SNK_HARD_RESET_RECOVER)) || (pd[port].task_state == PD_STATE_SNK_READY)) { #ifdef CONFIG_USB_PD_REV30 /* @@ -4098,52 +4099,58 @@ void pd_task(void *u) case PD_STATE_SNK_HARD_RESET_RECOVER: if (pd[port].last_state != pd[port].task_state) pd[port].flags |= PD_FLAGS_CHECK_IDENTITY; -#ifdef CONFIG_USB_PD_VBUS_DETECT_NONE - /* - * Can't measure vbus state so this is the maximum - * recovery time for the source. - */ - if (pd[port].last_state != pd[port].task_state) - set_state_timeout(port, get_time().val + + + if (get_usb_pd_vbus_detect() == + USB_PD_VBUS_DETECT_NONE) { + /* + * Can't measure vbus state so this is the + * maximum recovery time for the source. + */ + if (pd[port].last_state != pd[port].task_state) + set_state_timeout(port, get_time().val + PD_T_SAFE_0V + PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON, PD_STATE_SNK_DISCONNECTED); -#else - /* Wait for VBUS to go low and then high*/ - if (pd[port].last_state != pd[port].task_state) { - snk_hard_reset_vbus_off = 0; - set_state_timeout(port, + } else { +#ifndef CONFIG_USB_PD_VBUS_DETECT_NONE + /* Wait for VBUS to go low and then high*/ + if (pd[port].last_state != + pd[port].task_state) { + snk_hard_reset_vbus_off = 0; + set_state_timeout(port, get_time().val + PD_T_SAFE_0V, hard_reset_count < PD_HARD_RESET_COUNT ? PD_STATE_HARD_RESET_SEND : PD_STATE_SNK_DISCOVERY); - } + } - if (!pd_is_vbus_present(port) && - !snk_hard_reset_vbus_off) { - /* VBUS has gone low, reset timeout */ - snk_hard_reset_vbus_off = 1; - set_state_timeout(port, + if (!pd_is_vbus_present(port) && + !snk_hard_reset_vbus_off) { + /* VBUS has gone low, reset timeout */ + snk_hard_reset_vbus_off = 1; + set_state_timeout(port, get_time().val + PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON, PD_STATE_SNK_DISCONNECTED); - } - if (pd_is_vbus_present(port) && - snk_hard_reset_vbus_off) { - /* VBUS went high again */ - set_state(port, PD_STATE_SNK_DISCOVERY); - timeout = 10*MSEC; - } + } + if (pd_is_vbus_present(port) && + snk_hard_reset_vbus_off) { + /* VBUS went high again */ + set_state(port, PD_STATE_SNK_DISCOVERY); + timeout = 10*MSEC; + } - /* - * Don't need to set timeout because VBUS changing - * will trigger an interrupt and wake us up. - */ + /* + * Don't need to set timeout because VBUS + * changing will trigger an interrupt and + * wake us up. + */ #endif + } break; case PD_STATE_SNK_DISCOVERY: /* Wait for source cap expired only if we are enabled */ @@ -4172,7 +4179,8 @@ void pd_task(void *u) int batt_soc = usb_get_battery_soc(); if (batt_soc < CONFIG_USB_PD_RESET_MIN_BATT_SOC || - battery_get_disconnect_state() != BATTERY_NOT_DISCONNECTED) + battery_get_disconnect_state() != + BATTERY_NOT_DISCONNECTED) pd[port].flags |= PD_FLAGS_SNK_WAITING_BATT; else diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index 73a4b68295..1e08e0967d 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -21,6 +21,7 @@ #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" +#include "usb_pd_flags.h" #include "usb_pd_tcpc.h" #include "usb_pd_tcpm.h" #include "util.h" @@ -321,14 +322,20 @@ static int init_alert_mask(int port) * Create mask of alert events that will cause the TCPC to * signal the TCPM via the Alert# gpio line. */ - mask = TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED | - TCPC_REG_ALERT_TX_DISCARDED | TCPC_REG_ALERT_RX_STATUS | - TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS | - TCPC_REG_ALERT_FAULT -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - | TCPC_REG_ALERT_POWER_STATUS -#endif - ; + if (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_TCPC) { + mask = TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED | + TCPC_REG_ALERT_TX_DISCARDED | TCPC_REG_ALERT_RX_STATUS | + TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS | + TCPC_REG_ALERT_FAULT + | TCPC_REG_ALERT_POWER_STATUS + ; + } else { + mask = TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED | + TCPC_REG_ALERT_TX_DISCARDED | TCPC_REG_ALERT_RX_STATUS | + TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS | + TCPC_REG_ALERT_FAULT + ; + } /* TCPCI Rev2 includes SAFE0V alerts */ if (TCPC_FLAGS_VSAFE0V(tcpc_config[port].flags)) @@ -361,11 +368,11 @@ static int init_power_status_mask(int port) uint8_t mask; int rv; -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - mask = TCPC_REG_POWER_STATUS_VBUS_PRES; -#else - mask = 0; -#endif + if (get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_TCPC) + mask = TCPC_REG_POWER_STATUS_VBUS_PRES; + else + mask = 0; + rv = tcpc_write(port, TCPC_REG_POWER_STATUS_MASK , mask); return rv; @@ -1142,7 +1149,7 @@ static void tcpci_check_vbus_changed(int port, int alert, uint32_t *pd_event) tcpc_vbus[port] = BIT(VBUS_SAFE0V); } - if (IS_ENABLED(CONFIG_USB_PD_VBUS_DETECT_TCPC) && + if ((get_usb_pd_vbus_detect() == USB_PD_VBUS_DETECT_TCPC) && IS_ENABLED(CONFIG_USB_CHARGER)) { /* Update charge manager with new VBUS state */ usb_charger_vbus_change(port, diff --git a/include/config.h b/include/config.h index f74c9f82c9..5c0975c713 100644 --- a/include/config.h +++ b/include/config.h @@ -4235,6 +4235,13 @@ */ #undef CONFIG_USB_PD_DEBUG_LEVEL +/* + * Define if this board is using runtime flags instead of build time configs + * to control USB PD properties. + */ +#define CONFIG_USB_PD_FLAGS +#undef CONFIG_USB_PD_RUNTIME_FLAGS + /* * Define if this board can enable VBUS discharge (eg. through a GPIO-controlled * discharge circuit, or through port controller registers) to discharge VBUS diff --git a/include/usb_pd_flags.h b/include/usb_pd_flags.h new file mode 100644 index 0000000000..71932de885 --- /dev/null +++ b/include/usb_pd_flags.h @@ -0,0 +1,88 @@ +/* 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. + */ + +/* + * Contains USB PD flags definition and accessors + */ +#ifndef __CROS_EC_USB_PD_FLAGS_H +#define __CROS_EC_USB_PD_FLAGS_H + +#include "stdint.h" + +/* + * USB PD VBUS detect (0-2) + */ +enum usb_pd_vbus_detect { + USB_PD_VBUS_DETECT_NONE = 0, + USB_PD_VBUS_DETECT_TCPC = 1, + USB_PD_VBUS_DETECT_GPIO = 2, + USB_PD_VBUS_DETECT_PPC = 3, + USB_PD_VBUS_DETECT_CHARGER = 4 +}; + +/* + * USB PD DISCHARGE (Bits 3-4) + */ +enum usb_pd_discharge { + USB_PD_DISCHARGE_NONE = 0, + USB_PD_DISCHARGE_TCPC = 1, + USB_PD_DISCHARGE_GPIO = 2, + USB_PD_DISCHARGE_PPC = 3 +}; + +/* + * USB PD Charger OTG (Bit 5) + */ +enum usb_pd_charger_otg { + USB_PD_CHARGER_OTG_DISABLED = 0, + USB_PD_CHARGER_OTG_ENABLED = 1 +}; + +union usb_pd_runtime_flags { + struct { + enum usb_pd_vbus_detect vbus_detect : 3; + enum usb_pd_discharge discharge : 2; + enum usb_pd_charger_otg charger_otg : 1; + uint32_t reserved : 26; + }; + uint32_t raw_value; +}; + +/** + * Set VBUS detect type from USB_PD_FLAGS. + */ +void set_usb_pd_vbus_detect(enum usb_pd_vbus_detect vbus_detect); + +/** + * Get VBUS detect type from USB_PD_FLAGS. + * + * @return the VBUS detect type. + */ +enum usb_pd_vbus_detect get_usb_pd_vbus_detect(void); + +/** + * Set USB PD discharge type from USB_PD_FLAGS. + */ +void set_usb_pd_discharge(enum usb_pd_discharge discharge); + +/** + * Get USB PD discharge type from USB_PD_FLAGS. + * + * @return the USB PD discharge type. + */ +enum usb_pd_discharge get_usb_pd_discharge(void); + +/** + * Set USB PD charger OTG from USB_PD_FLAGS. + */ +void set_usb_pd_charger_otg(enum usb_pd_charger_otg charger_otg); + +/** + * Get USB PD charger OTG from USB_PD_FLAGS. + * + * @return the USB PD charger OTG. + */ +enum usb_pd_charger_otg get_usb_pd_charger_otg(void); +#endif /* __CROS_EC_USB_PD_FLAGS_H */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index cb85bf2154..e896f6d841 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -308,7 +308,8 @@ zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USB_POWER_DELIVERY "${PLATFORM_EC}/common/usbc/usbc_task.c" "${PLATFORM_EC}/common/usbc/usb_pd_timer.c" "${PLATFORM_EC}/common/usbc/usb_sm.c" - "${PLATFORM_EC}/common/usbc_intr_task.c") + "${PLATFORM_EC}/common/usbc_intr_task.c" + "${PLATFORM_EC}/common/usb_pd_flags.c") zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_CONSOLE_CMD_CHARGEN "${PLATFORM_EC}/common/chargen.c") -- cgit v1.2.1