A little hack to make pd negotiation fininsh earlier

patch used:

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index bf84a1ef4a3d..c832392ed012 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -4159,7 +4159,7 @@ static void run_state_machine(struct tcpm_port *port)
                break;
        case SNK_ATTACH_WAIT:
                port->debouncing = true;
-               timer_val_msecs = PD_T_CC_DEBOUNCE;
+               timer_val_msecs = 100;
                trace_android_vh_typec_tcpm_get_timer(tcpm_states[SNK_ATTACH_WAIT],
                                                      CC_DEBOUNCE, &timer_val_msecs);
                if ((port->cc1 == TYPEC_CC_OPEN &&
@@ -4317,7 +4317,7 @@ static void run_state_machine(struct tcpm_port *port)
                if (port->vbus_never_low) {
                        port->vbus_never_low = false;
                        tcpm_set_state(port, SNK_SOFT_RESET,
-                                      timer_val_msecs);
+                                      100);
                } else {
                        tcpm_set_state(port, hard_reset_state(port),
                                       timer_val_msecs);
@@ -4874,7 +4874,7 @@ static void run_state_machine(struct tcpm_port *port)
                               PD_T_ERROR_RECOVERY);
                break;
        case PORT_RESET_WAIT_OFF:
-               timer_val_msecs = PD_T_PS_SOURCE_OFF;
+               timer_val_msecs = 100;
                trace_android_vh_typec_tcpm_get_timer(tcpm_states[PORT_RESET_WAIT_OFF],
                                                      SOURCE_OFF, &timer_val_msecs);
                tcpm_set_state(port,

When the state of tcpm state machine changes, there will be a delay time waiting for cc signal from the source. I find three delays which will never get signals from the pd source and end up with useless waiting time:
state change PORT_RESET_WAIT_OFF -> SNK_UNATTACHED [delayed 920 ms]
state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED [delayed 200 ms]
state change SNK_WAIT_CAPABILITIES -> SNK_SOFT_RESET [delayed 310 ms]
My patch changes all these three delay time to 100ms, saving 1130ms of pd negotiation time.
Now I can finish the pd negotiation just 3 seconds after kernel boots up:

[    2.630455] sw reset
[    2.634210] fusb302 device ID: 0x91
[    2.638865] pd := off
[    2.638867] vbus is already Off
[    2.638869] charge is already Off
[    2.638871] vconn is already Off
[    2.639725] pd header := Sink, Device
[    2.639755] cc1=Open, cc2=Open
[    2.644415] pd := off
[    2.644417] vbus is already Off
[    2.644419] charge is already Off
[    2.644421] vconn is already Off
[    2.645230] pd header := Sink, Device
[    2.645237] cc := Rd
[    2.757137] start drp toggling
[    2.759480] IRQ: 0x80, a: 0x00, b: 0x00, status0: 0x83
[    2.759493] IRQ: VBUS_OK, vbus=On
[    2.763328] IRQ: 0x00, a: 0x40, b: 0x00, status0: 0x83
[    2.763341] IRQ: TOGDONE
[    2.769927] detected cc1=Rp-3.0, cc2=Open
[    2.769954] cc1=Rp-3.0, cc2=Open
[    2.871101] pd header := Sink, Device
[    2.871167] vbus is already Off
[    2.876083] pd := on
[    2.978427] sending PD message header: 8d
[    2.978433] sending PD message len: 0
[    2.980476] IRQ: 0x41, a: 0x00, b: 0x00, status0: 0x93
[    2.980491] IRQ: BC_LVL, handler pending
[    2.982381] IRQ: 0x51, a: 0x04, b: 0x01, status0: 0x93
[    2.982389] IRQ: BC_LVL, handler pending
[    2.982394] IRQ: PD tx success
[    2.984112] PD message header: 1a1
[    2.984112] PD message len: 0
[    2.984116] IRQ: PD sent good CRC
[    2.985808] PD message header: 1a3
[    2.985809] PD message len: 0
[    2.987625] IRQ: 0x51, a: 0x00, b: 0x01, status0: 0x93
[    2.987631] IRQ: BC_LVL, handler pending
[    2.987637] IRQ: PD sent good CRC
[    2.991939] PD message header: 63a1
[    2.991943] PD message len: 24
[    2.998153] pd := on
[    3.000751] sending PD message header: 1282
[    3.000758] sending PD message len: 4
[    3.002687] IRQ: 0x41, a: 0x00, b: 0x00, status0: 0x93
[    3.002702] IRQ: BC_LVL, handler pending
[    3.004528] IRQ: 0x51, a: 0x04, b: 0x00, status0: 0x93
[    3.004529] IRQ: BC_LVL, handler pending
[    3.004530] IRQ: PD tx success
[    3.006228] PD message header: 3a1
[    3.006229] PD message len: 0
[    3.008049] IRQ: 0x51, a: 0x00, b: 0x01, status0: 0x93
[    3.008055] IRQ: BC_LVL, handler pending
[    3.008060] IRQ: PD sent good CRC
[    3.009804] PD message header: 5a3
[    3.009809] PD message len: 0
[    3.040518] IRQ: 0x51, a: 0x00, b: 0x01, status0: 0x93
[    3.040533] IRQ: BC_LVL, handler pending
[    3.040543] IRQ: PD sent good CRC
[    3.042284] PD message header: 7a6
[    3.042290] PD message len: 0
[    3.044147] IRQ: 0x41, a: 0x00, b: 0x00, status0: 0x93
[    3.044154] IRQ: BC_LVL, handler pending
[    3.046578] sending PD message header: 148f
[    3.046580] sending PD message len: 4
[    3.048430] IRQ: 0x41, a: 0x00, b: 0x00, status0: 0x93
[    3.048432] IRQ: BC_LVL, handler pending
[    3.050245] IRQ: 0x51, a: 0x04, b: 0x00, status0: 0x93
[    3.050251] IRQ: BC_LVL, handler pending
[    3.050257] IRQ: PD tx success
[    3.051991] PD message header: 5a1
[    3.051995] PD message len: 0
[    3.055386] IRQ: 0x41, a: 0x00, b: 0x00, status0: 0x93
[    3.055392] IRQ: BC_LVL, handler pending
[    3.057237] IRQ: 0x51, a: 0x00, b: 0x01, status0: 0x93
[    3.057243] IRQ: BC_LVL, handler pending
[    3.057248] IRQ: PD sent good CRC
[    3.060983] PD message header: 49af
[    3.060994] PD message len: 16
[    3.063548] sending PD message header: 168f
[    3.063554] sending PD message len: 4
[    3.065443] IRQ: 0x41, a: 0x00, b: 0x00, status0: 0x93
[    3.065453] IRQ: BC_LVL, handler pending
[    3.067268] IRQ: 0x51, a: 0x04, b: 0x00, status0: 0x93
[    3.067269] IRQ: BC_LVL, handler pending
[    3.067270] IRQ: PD tx success
[    3.068960] PD message header: 7a1
[    3.068961] PD message len: 0
[    3.072429] IRQ: 0x41, a: 0x00, b: 0x01, status0: 0x93
[    3.072436] IRQ: BC_LVL, handler pending
[    3.072442] IRQ: PD sent good CRC
[    3.074180] PD message header: bb0
[    3.074184] PD message len: 0
[    3.076041] IRQ: 0x51, a: 0x00, b: 0x00, status0: 0x93
[    3.076048] IRQ: BC_LVL, handler pending
[    3.109416] BC_LVL handler, status0=0x93
[    2.634214] Setting usb_comm capable false
[    2.638872] Setting voltage/current limit 0 mV 0 mA
[    2.638878] polarity 0
[    2.638898] Requesting mux state 0, usb-role 0, orientation 0
[    2.639747] state change INVALID_STATE -> SNK_UNATTACHED [rev1 NONE_AMS]
[    2.639757] CC1: 0 -> 0, CC2: 0 -> 0 [state SNK_UNATTACHED, polarity 0, disconnected]
[    2.639762] 4-0022: registered
[    2.639763] Setting usb_comm capable false
[    2.644422] Setting voltage/current limit 0 mV 0 mA
[    2.644429] polarity 0
[    2.644430] Requesting mux state 0, usb-role 0, orientation 0
[    2.645236] cc:=2
[    2.650651] pending state change PORT_RESET -> PORT_RESET_WAIT_OFF @ 100 ms [rev1 NONE_AMS]
[    2.650657] state change PORT_RESET -> PORT_RESET_WAIT_OFF [delayed 100 ms]
[    2.650660] pending state change PORT_RESET_WAIT_OFF -> SNK_UNATTACHED @ 100 ms [rev1 NONE_AMS]
[    2.750704] state change PORT_RESET_WAIT_OFF -> SNK_UNATTACHED [delayed 100 ms]
[    2.750719] Start toggling
[    2.769965] CC1: 0 -> 5, CC2: 0 -> 0 [state TOGGLING, polarity 0, connected]
[    2.769976] state change TOGGLING -> SNK_ATTACH_WAIT [rev1 NONE_AMS]
[    2.769986] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @ 100 ms [rev1 NONE_AMS]
[    2.870168] state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED [delayed 100 ms]
[    2.870187] state change SNK_DEBOUNCED -> SNK_ATTACHED [rev1 NONE_AMS]
[    2.870196] polarity 0
[    2.870202] Requesting mux state 1, usb-role 2, orientation 1
[    2.871110] state change SNK_ATTACHED -> SNK_STARTUP [rev1 NONE_AMS]
[    2.871141] state change SNK_STARTUP -> SNK_DISCOVERY [rev3 NONE_AMS]
[    2.871148] Setting voltage/current limit 5000 mV 3000 mA
[    2.871162] vbus=0 charge:=1
[    2.871172] state change SNK_DISCOVERY -> SNK_WAIT_CAPABILITIES [rev3 NONE_AMS]
[    2.876089] pending state change SNK_WAIT_CAPABILITIES -> SNK_SOFT_RESET @ 100 ms [rev3 NONE_AMS]
[    2.976250] state change SNK_WAIT_CAPABILITIES -> SNK_SOFT_RESET [delayed 100 ms]
[    2.976266] AMS SOFT_RESET_AMS start
[    2.976273] state change SNK_SOFT_RESET -> AMS_START [rev3 SOFT_RESET_AMS]
[    2.976281] state change AMS_START -> SOFT_RESET_SEND [rev3 SOFT_RESET_AMS]
[    2.976288] PD TX, header: 0x8d
[    2.984113] PD TX complete, status: 0
[    2.984119] pending state change SOFT_RESET_SEND -> HARD_RESET_SEND @ 60 ms [rev3 SOFT_RESET_AMS]
[    2.985814] PD RX, header: 0x1a3 [1]
[    2.985817] AMS SOFT_RESET_AMS finished
[    2.985819] state change SOFT_RESET_SEND -> SNK_WAIT_CAPABILITIES [rev3 NONE_AMS]
[    2.998166] pending state change SNK_WAIT_CAPABILITIES -> HARD_RESET_SEND @ 310 ms [rev3 NONE_AMS]
[    2.998182] PD RX, header: 0x63a1 [1]
[    2.998195]  PDO 0: type 0, 5000 mV, 3000 mA [E]
[    2.998204]  PDO 1: type 0, 9000 mV, 3000 mA []
[    2.998211]  PDO 2: type 0, 12000 mV, 3000 mA []
[    2.998219]  PDO 3: type 0, 15000 mV, 3000 mA []
[    2.998229]  PDO 4: type 0, 20000 mV, 2250 mA []
[    2.998237]  PDO 5: type 3, 3300-16000 mV, 3000 mA
[    2.998242] state change SNK_WAIT_CAPABILITIES -> SNK_NEGOTIATE_CAPABILITIES [rev3 POWER_NEGOTIATION]
[    2.998256] Setting usb_comm capable false
[    2.998282] cc=2 cc1=5 cc2=0 vbus=0 vconn=sink polarity=0
[    2.998291] Requesting PDO 4: 20000 mV, 2250 mA
[    2.998299] PD TX, header: 0x1282
[    3.006230] PD TX complete, status: 0
[    3.006236] pending state change SNK_NEGOTIATE_CAPABILITIES -> HARD_RESET_SEND @ 60 ms [rev3 POWER_NEGOTIATION]
[    3.009830] PD RX, header: 0x5a3 [1]
[    3.009837] state change SNK_NEGOTIATE_CAPABILITIES -> SNK_TRANSITION_SINK [rev3 POWER_NEGOTIATION]
[    3.009848] Setting standby current 5000 mV @ 500 mA
[    3.009853] Setting voltage/current limit 5000 mV 500 mA
[    3.009869] pending state change SNK_TRANSITION_SINK -> HARD_RESET_SEND @ 500 ms [rev3 POWER_NEGOTIATION]
[    3.042313] PD RX, header: 0x7a6 [1]
[    3.042329] Setting voltage/current limit 20000 mV 2250 mA
[    3.042355] state change SNK_TRANSITION_SINK -> SNK_READY [rev3 POWER_NEGOTIATION]
[    3.042653] AMS POWER_NEGOTIATION finished
[    3.042667] AMS DISCOVER_IDENTITY start
[    3.042674] PD TX, header: 0x148f
[    3.052000] PD TX complete, status: 0
[    3.061017] PD RX, header: 0x49af [1]
[    3.061028] Rx VDM cmd 0xff00a041 type 1 cmd 1 len 4
[    3.061038] AMS DISCOVER_IDENTITY finished
[    3.061117] Identity: 22d9:0002.0002
[    3.061128] AMS DISCOVER_SVIDS start
[    3.061133] PD TX, header: 0x168f
[    3.068963] PD TX complete, status: 0
[    3.074202] PD RX, header: 0xbb0 [1]
[    3.074211] AMS DISCOVER_SVIDS finished
1 Like

Does it mean the bootloop issue is fixed with this patch ?

It may make it better.

2 Likes

Are the original delays per USB standard or arbitrary per IC manufacturer?

Those original delay timings are defined in include/linux/usb/pd.h. I just tested one pd power. You can see the delayed time using command cat /sys/kernel/debug/usb/*-4-0022|grep delayed on your side.

2 Likes

I’m asking because if it doesn’t follow spec then it’s unlikely that it will be incorporated into the main kernel branch.

Spec is just a standard. If everything follows the spec we will have less pain on the pd negotiation. But now at least rock5b is doing pd negotiation with a pd power which seems not following the spec.
Maybe we can define a property in device tree to let driver wait shorter on some specific devices.

Don’t get me wrong, I appreciate the PD negotiation performance update, I’m just worried it won’t get into the main kernel branch and users will have to constantly compile their own kernel or depend on a 3rd party precompiled images.

2 Likes