servo_v4/usb_pd_policy: Reject SNK->SRC power swap if CC_ALLOW_SRC not set

When ServoV4 acts as sink ('cc snk' issued), and we issue 'cc pdsnk'
there are following state transitions (starting from C1 SNK_READY):

 C1 st8 SNK_READY          <--- From this point DUT acts as source
                                DUT's PE is in PE_SRC_Ready state
 C1 RECV 196f/1 [0]ff008001
 C1 RECV 0b67/0            <--- DUT asks for source capabilities
 C1 srcCAP>1               <--- ServoV4 sends its capabilities
 C1 RECV 0d6a/0            <--- DUT requests power swap
 C1 CTRL[3]>1              <--- ServoV4 accepts
 C1 st10 SNK_SWAP_SNK_DISABLE
 C1 st11 SNK_SWAP_SRC_DISABLE
 C1 RECV 0e66/0            <--- DUT sends PS_RDY to inform that it
                                disabled power
 C1 st12 SNK_SWAP_STANDBY  <--- ServoV4 enables power supply and waits
                                PD_POWER_SUPPLY_TURN_ON_DELAY to ensure
                                that it is turned on, before switching
                                to SNK_SWAP_COMPLETE
 C1 st13 SNK_SWAP_COMPLETE <--- Power swap completed successfully
 C1 CTRL[6]>1              <--- ServoV4 sends PS_RDY to inform that
                                power was enabled.
 C1 st18 SRC_DISCOVERY
 C1 srcCAP>1               <--- ServoV4 sends its capabilities
 C1 st19 SRC_NEGOCIATE
 C1 RECV 1062/1 [0]4304b12c
 Requested 15000 mV 3000 mA (for 3000/3000 mA)
 C1 CTRL[3]>1              <--- ServoV4 accepts
 C1 st20 SRC_ACCEPTED
 C1 st21 SRC_POWERED       <--- Switching to requested voltage. This
                                calls pd_transition_voltage() from
                                servo_v4/usb_pd_policy which requests
                                charger to change its voltage.
 [570.815776 Waiting for CHG port transition]
                           <--- Here we are changing active task to
                                PD_C0. This task changes dual role
                                for C1 (DUT port), because CC_ALLOW_SRC
                                is not set. Appropriate event is set too
 C0 Req [4] 15000mV 3000mA
 C0 REQ>1
 C0 st6 SNK_REQUESTED
 [570.822679 CL: p0 s0 i500 v5000]
 C0 RECV 0763/0
 C0 st7 SNK_TRANSITION
 C0 RECV 0966/0
 C0 st8 SNK_READY          <--- Charger voltage changed successfully
 [570.991969 CL: p0 s0 i3000 v15000]
                           <--- Context switch to PD_C1 task
 [571.001981 CHG transitioned]
                           <--- Check event and call
                                update_dual_role_config() which
                                changes state to SNK_DISCONNECTED
 C1 st2 SNK_DISCONNECTED

Port 1 switches to SNK_DISCONNECTED state because PD_C0 task calls
pd_send_request_msg() (reaction for voltage change request), which
limits maximum current by calling charge_manager_force_ceil().

Charge manager calls board_set_charge_limit() to limit current, which
calls update_ports() which calls board_manage_dut_port()
unconditionally. This function checks if charge through is allowed. It
turns out that it is not allowed, because CC_ALLOW_SRC bit is not set
in cc_config (see is_charge_through_allowed()), then
board_manage_dut_port() changes dual role of port 1 to force sink.

Fix for this issue is simple. Function is_charge_through_allowed()
actually tells us that we are not able to source power when 'cc snk' or
'cc pdsnk' was issued. So fix is just to reject power swap when our
power role is sink, and CC_ALLOW_SRC is not set.

BUG=b:162254118
BRANCH=none
TEST=Issue 'cc snk' from ServoV4 console and wait until state gets
     stable. Issue 'cc pdsnk' from ServoV4 console and check if port 1
     reaches SNK_READY state.

Signed-off-by: Patryk Duda <pdk@semihalf.com>
Change-Id: Idf89c0f79a60275345d23aca4705811b1acba98a
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2563682
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-by: Sam Hurst <shurst@google.com>
Reviewed-by: Diana Z <dzigterman@chromium.org>
This commit is contained in:
Patryk Duda 2020-11-27 15:24:06 +01:00 committed by Commit Bot
parent 8150f11ccf
commit a2390f3c50
1 changed files with 3 additions and 0 deletions

View File

@ -710,6 +710,9 @@ __override int pd_check_power_swap(int port)
if (port == CHG)
return 0;
if (pd_get_power_role(port) == PD_ROLE_SINK && !(cc_config & CC_ALLOW_SRC))
return 0;
if (pd_snk_is_vbus_provided(CHG))
return allow_pr_swap;