diff options
Diffstat (limited to 'common/usb_common.c')
-rw-r--r-- | common/usb_common.c | 381 |
1 files changed, 0 insertions, 381 deletions
diff --git a/common/usb_common.c b/common/usb_common.c deleted file mode 100644 index a068142ae5..0000000000 --- a/common/usb_common.c +++ /dev/null @@ -1,381 +0,0 @@ -/* Copyright 2019 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 common USB functions shared between the old (i.e. usb_pd_protocol) - * and the new (i.e. usb_sm_*) USB-C PD stacks. - */ - -#include "common.h" -#include "charge_state.h" -#include "task.h" -#include "usb_common.h" -#include "usb_pd.h" -#include "usb_pd_tcpm.h" -#include "util.h" - -int usb_get_battery_soc(void) -{ -#if defined(CONFIG_CHARGER) - return charge_get_percent(); -#elif defined(CONFIG_BATTERY) - return board_get_battery_soc(); -#else - return 0; -#endif -} - -/* - * CC values for regular sources and Debug sources (aka DTS) - * - * Source type Mode of Operation CC1 CC2 - * --------------------------------------------- - * Regular Default USB Power RpUSB Open - * Regular USB-C @ 1.5 A Rp1A5 Open - * Regular USB-C @ 3 A Rp3A0 Open - * DTS Default USB Power Rp3A0 Rp1A5 - * DTS USB-C @ 1.5 A Rp1A5 RpUSB - * DTS USB-C @ 3 A Rp3A0 RpUSB - */ - -typec_current_t usb_get_typec_current_limit(enum pd_cc_polarity_type polarity, - enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2) -{ - typec_current_t charge = 0; - enum tcpc_cc_voltage_status cc = polarity ? cc2 : cc1; - enum tcpc_cc_voltage_status cc_alt = polarity ? cc1 : cc2; - - switch (cc) { - case TYPEC_CC_VOLT_RP_3_0: - if (!cc_is_rp(cc_alt) || cc_alt == TYPEC_CC_VOLT_RP_DEF) - charge = 3000; - else if (cc_alt == TYPEC_CC_VOLT_RP_1_5) - charge = 500; - break; - case TYPEC_CC_VOLT_RP_1_5: - charge = 1500; - break; - case TYPEC_CC_VOLT_RP_DEF: - charge = 500; - break; - default: - break; - } - - if (IS_ENABLED(CONFIG_USBC_DISABLE_CHARGE_FROM_RP_DEF) && charge == 500) - charge = 0; - - if (cc_is_rp(cc_alt)) - charge |= TYPEC_CURRENT_DTS_MASK; - - return charge; -} - -enum pd_cc_polarity_type get_snk_polarity(enum tcpc_cc_voltage_status cc1, - enum tcpc_cc_voltage_status cc2) -{ - /* The following assumes: - * - * TYPEC_CC_VOLT_RP_3_0 > TYPEC_CC_VOLT_RP_1_5 - * TYPEC_CC_VOLT_RP_1_5 > TYPEC_CC_VOLT_RP_DEF - * TYPEC_CC_VOLT_RP_DEF > TYPEC_CC_VOLT_OPEN - */ - return cc2 > cc1; -} - -enum pd_cc_states pd_get_cc_state( - enum tcpc_cc_voltage_status cc1, enum tcpc_cc_voltage_status cc2) -{ - /* Port partner is a SNK */ - if (cc_is_snk_dbg_acc(cc1, cc2)) - return PD_CC_UFP_DEBUG_ACC; - if (cc_is_at_least_one_rd(cc1, cc2)) - return PD_CC_UFP_ATTACHED; - if (cc_is_audio_acc(cc1, cc2)) - return PD_CC_UFP_AUDIO_ACC; - - /* Port partner is a SRC */ - if (cc_is_rp(cc1) && cc_is_rp(cc2)) - return PD_CC_DFP_DEBUG_ACC; - if (cc_is_rp(cc1) || cc_is_rp(cc2)) - return PD_CC_DFP_ATTACHED; - - /* - * 1) Both lines are Vopen or - * 2) Only an e-marked cabled without a partner on the other side - */ - return PD_CC_NONE; -} -/* - * Zinger implements a board specific usb policy that does not define - * PD_MAX_VOLTAGE_MV and PD_OPERATING_POWER_MW. And in turn, does not - * use the following functions. - */ -#if defined(PD_MAX_VOLTAGE_MV) && defined(PD_OPERATING_POWER_MW) -int pd_find_pdo_index(uint32_t src_cap_cnt, const uint32_t * const src_caps, - int max_mv, uint32_t *selected_pdo) -{ - int i, uw, mv; - int ret = 0; - int cur_uw = 0; - int prefer_cur; - - int __attribute__((unused)) cur_mv = 0; - - /* max voltage is always limited by this boards max request */ - max_mv = MIN(max_mv, PD_MAX_VOLTAGE_MV); - - /* Get max power that is under our max voltage input */ - for (i = 0; i < src_cap_cnt; i++) { - /* its an unsupported Augmented PDO (PD3.0) */ - if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_AUGMENTED) - continue; - - mv = ((src_caps[i] >> 10) & 0x3FF) * 50; - /* Skip invalid voltage */ - if (!mv) - continue; - /* Skip any voltage not supported by this board */ - if (!pd_is_valid_input_voltage(mv)) - continue; - - if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { - uw = 250000 * (src_caps[i] & 0x3FF); - } else { - int ma = (src_caps[i] & 0x3FF) * 10; - - ma = MIN(ma, PD_MAX_CURRENT_MA); - uw = ma * mv; - } - - if (mv > max_mv) - continue; - uw = MIN(uw, PD_MAX_POWER_MW * 1000); - prefer_cur = 0; - - /* Apply special rules in case of 'tie' */ - if (IS_ENABLED(PD_PREFER_LOW_VOLTAGE)) { - if (uw == cur_uw && mv < cur_mv) - prefer_cur = 1; - } else if (IS_ENABLED(PD_PREFER_HIGH_VOLTAGE)) { - if (uw == cur_uw && mv > cur_mv) - prefer_cur = 1; - } - - /* Prefer higher power, except for tiebreaker */ - if (uw > cur_uw || prefer_cur) { - ret = i; - cur_uw = uw; - cur_mv = mv; - } - } - - if (selected_pdo) - *selected_pdo = src_caps[ret]; - - return ret; -} - -void pd_extract_pdo_power(uint32_t pdo, uint32_t *ma, uint32_t *mv) -{ - int max_ma, uw; - - *mv = ((pdo >> 10) & 0x3FF) * 50; - - if (*mv == 0) { - *ma = 0; - return; - } - - if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { - uw = 250000 * (pdo & 0x3FF); - max_ma = 1000 * MIN(1000 * uw, PD_MAX_POWER_MW) / *mv; - } else { - max_ma = 10 * (pdo & 0x3FF); - max_ma = MIN(max_ma, PD_MAX_POWER_MW * 1000 / *mv); - } - - *ma = MIN(max_ma, PD_MAX_CURRENT_MA); -} - -void pd_build_request(uint32_t src_cap_cnt, const uint32_t * const src_caps, - int32_t vpd_vdo, uint32_t *rdo, uint32_t *ma, - uint32_t *mv, enum pd_request_type req_type, - uint32_t max_request_mv) -{ - uint32_t pdo; - int pdo_index, flags = 0; - int uw; - int max_or_min_ma; - int max_or_min_mw; - int max_vbus; - int vpd_vbus_dcr; - int vpd_gnd_dcr; - - if (req_type == PD_REQUEST_VSAFE5V) { - /* src cap 0 should be vSafe5V */ - pdo_index = 0; - pdo = src_caps[0]; - } else { - /* find pdo index for max voltage we can request */ - pdo_index = pd_find_pdo_index(src_cap_cnt, src_caps, - max_request_mv, &pdo); - } - - pd_extract_pdo_power(pdo, ma, mv); - - /* - * Adjust VBUS current if CTVPD device was detected. - */ - if (vpd_vdo > 0) { - max_vbus = VPD_VDO_MAX_VBUS(vpd_vdo); - vpd_vbus_dcr = VPD_VDO_VBUS_IMP(vpd_vdo) << 1; - vpd_gnd_dcr = VPD_VDO_GND_IMP(vpd_vdo); - - /* - * Valid max_vbus values: - * 00b - 20000 mV - * 01b - 30000 mV - * 10b - 40000 mV - * 11b - 50000 mV - */ - max_vbus = 20000 + max_vbus * 10000; - if (*mv > max_vbus) - *mv = max_vbus; - - /* - * 5000 mA cable: 150 = 750000 / 50000 - * 3000 mA cable: 250 = 750000 / 30000 - */ - if (*ma > 3000) - *ma = 750000 / (150 + vpd_vbus_dcr + vpd_gnd_dcr); - else - *ma = 750000 / (250 + vpd_vbus_dcr + vpd_gnd_dcr); - } - - uw = *ma * *mv; - /* Mismatch bit set if less power offered than the operating power */ - if (uw < (1000 * PD_OPERATING_POWER_MW)) - flags |= RDO_CAP_MISMATCH; - -#ifdef CONFIG_USB_PD_GIVE_BACK - /* Tell source we are give back capable. */ - flags |= RDO_GIVE_BACK; - - /* - * BATTERY PDO: Inform the source that the sink will reduce - * power to this minimum level on receipt of a GotoMin Request. - */ - max_or_min_mw = PD_MIN_POWER_MW; - - /* - * FIXED or VARIABLE PDO: Inform the source that the sink will - * reduce current to this minimum level on receipt of a GotoMin - * Request. - */ - max_or_min_ma = PD_MIN_CURRENT_MA; -#else - /* - * Can't give back, so set maximum current and power to - * operating level. - */ - max_or_min_ma = *ma; - max_or_min_mw = uw / 1000; -#endif - - if ((pdo & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { - int mw = uw / 1000; - *rdo = RDO_BATT(pdo_index + 1, mw, max_or_min_mw, flags); - } else { - *rdo = RDO_FIXED(pdo_index + 1, *ma, max_or_min_ma, flags); - } -} -#endif - -#ifdef CONFIG_USB_PD_ALT_MODE_DFP -void notify_sysjump_ready(volatile const task_id_t * const sysjump_task_waiting) -{ - /* - * If event was set from pd_prepare_sysjump, wake the - * task waiting on us to complete. - */ - if (*sysjump_task_waiting != TASK_ID_INVALID) - task_set_event(*sysjump_task_waiting, - TASK_EVENT_SYSJUMP_READY, 0); -} -#endif - -__attribute__((weak)) uint8_t board_get_usb_pd_port_count(void) -{ - return CONFIG_USB_PD_PORT_MAX_COUNT; -} - -enum pd_drp_next_states drp_auto_toggle_next_state( - uint64_t *drp_sink_time, - enum pd_power_role power_role, - enum pd_dual_role_states drp_state, - enum tcpc_cc_voltage_status cc1, - enum tcpc_cc_voltage_status cc2) -{ - /* Set to appropriate port state */ - if (cc_is_open(cc1, cc2)) { - /* - * If nothing is attached then use drp_state to determine next - * state. If DRP auto toggle is still on, then remain in the - * DRP_AUTO_TOGGLE state. Otherwise, stop dual role toggling - * and go to a disconnected state. - */ - switch (drp_state) { - case PD_DRP_TOGGLE_OFF: - return DRP_TC_DEFAULT; - case PD_DRP_FREEZE: - if (power_role == PD_ROLE_SINK) - return DRP_TC_UNATTACHED_SNK; - else - return DRP_TC_UNATTACHED_SRC; - case PD_DRP_FORCE_SINK: - return DRP_TC_UNATTACHED_SNK; - case PD_DRP_FORCE_SOURCE: - return DRP_TC_UNATTACHED_SRC; - case PD_DRP_TOGGLE_ON: - default: - return DRP_TC_DRP_AUTO_TOGGLE; - } - } else if ((cc_is_rp(cc1) || cc_is_rp(cc2)) && - drp_state != PD_DRP_FORCE_SOURCE) { - /* SNK allowed unless ForceSRC */ - return DRP_TC_UNATTACHED_SNK; - } else if (cc_is_at_least_one_rd(cc1, cc2) || - cc_is_audio_acc(cc1, cc2)) { - /* - * SRC allowed unless ForceSNK or Toggle Off - * - * Ideally we wouldn't use auto-toggle when drp_state is - * TOGGLE_OFF/FORCE_SINK, but for some TCPCs, auto-toggle can't - * be prevented in low power mode. Try being a sink in case the - * connected device is dual-role (this ensures reliable charging - * from a hub, b/72007056). 100 ms is enough time for a - * dual-role partner to switch from sink to source. If the - * connected device is sink-only, then we will attempt - * TC_UNATTACHED_SNK twice (due to debounce time), then return - * to low power mode (and stay there). After 200 ms, reset - * ready for a new connection. - */ - if (drp_state == PD_DRP_TOGGLE_OFF || - drp_state == PD_DRP_FORCE_SINK) { - if (get_time().val > *drp_sink_time + 200*MSEC) - *drp_sink_time = get_time().val; - if (get_time().val < *drp_sink_time + 100*MSEC) - return DRP_TC_UNATTACHED_SNK; - else - return DRP_TC_DRP_AUTO_TOGGLE; - } else { - return DRP_TC_UNATTACHED_SRC; - } - } else { - /* Anything else, keep toggling */ - return DRP_TC_DRP_AUTO_TOGGLE; - } -} |