Skip to content

Commit 15e2d78

Browse files
JohnWC-Yehamstan
authored andcommitted
fwk: pd: fix profile restore when port role is swapped to source
When a port performs a Power Role Swap (PR_SWAP) and becomes a source, previously, the code skipped profile evaluation for all Source ports. It may keep the other port limited to 1.5A output because the previous logic only reduced the current on sink detection and never restored it after a role change. Behavior summary: - [source, sink] → no change profile - [source, nothing] → restore profile to default - [source, source] → skip evaluation This ensures correct power negotiation after PR_SWAP and prevents the sink port from being stuck at 1.5A limit. BRANCH=fwk-tulip-29169 BUG=https://app.clickup.com/t/86ev324ut TEST= [Port1 (A device), Port2 (B device)] 1. Connect two pd device -> [3A, 1.5A] 2. A device connect AC [3A + AC, 1.5A] -> [SRC, keep 1.5A] 3. A device remove AC [SRC remove AC, 1.5A] -> [3A, keep 1.5A] 4. B device connect AC [3A, 1.5A + AC] -> [keep 3A, SRC] 5. B device remove AC [3A, SRC remove AC] -> [keep 3A, 1.5A] 6. A device disconnect [3A remove device, 1.5A] -> [Nothing, keep 1.5A] 7. A device connect [Nothing, 1.5A] -> [3A, 1.5A] 8. B device disconnect [3A, 1.5A remove device] -> [keep 3A, Nothing] 9. B device connect [3A, Nothing] -> [3A, 1.5A] TEST=Connect the PD device (max operating current less than 1500mA) to port 0. This device gets the 5V/3A PDO; And then connect the PD device (max operating current is 3000mA) to port 1, the first device do the re-negotiation to 5V/1.5A and the second device do the re-negotiation to 5V/3A. Signed-off-by: johnwc_yeh <JohnWC_Yeh@compal.com>
1 parent 283a549 commit 15e2d78

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

zephyr/program/framework/src/cypress_pd_common.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -474,9 +474,10 @@ void cypd_evaluate_port_profile(int controller, int port, int ccg_event)
474474
int pd_port = PDPORT(controller, port);
475475
int shared_pd_port = PDPORT(controller, (port ? 0 : 1));
476476
bool first_port = false;
477-
bool all_ports_disconnect = false;
477+
bool restore_profile = false;
478478
bool profile_is_changed = false;
479479
static uint8_t ignore_evaluate_reason;
480+
bool allow_profile_swap = true;
480481

481482
#ifndef CONFIG_SELECT_3A_TYPEC_OUTPUT_CURRENT
482483
return
@@ -486,18 +487,23 @@ void cypd_evaluate_port_profile(int controller, int port, int ccg_event)
486487
if (pd_chip_config[controller].support_max_port < 2)
487488
return;
488489

489-
/* Skip to evaluate the port profile if the port is a source */
490-
if (pd_port_states[pd_port].c_state == CCG_STATUS_SOURCE)
491-
return;
492-
493490
/* Skip to evaluate the port profile if the safety level is 2 or more */
494491
if (pre_safety_level >= TYPEC_SAFETY_LEVEL_2)
495492
return;
496493

497-
if ((ccg_event == CCG_RESPONSE_PORT_DISCONNECT) &&
498-
(pd_port_states[shared_pd_port].c_state == CCG_STATUS_NOTHING))
499-
all_ports_disconnect = true;
500-
else {
494+
/* Skip to evaluate the port profile if both are source ports */
495+
if (pd_port_states[pd_port].c_state == CCG_STATUS_SOURCE &&
496+
pd_port_states[shared_pd_port].c_state == CCG_STATUS_SOURCE)
497+
return;
498+
499+
if (ccg_event == CCG_RESPONSE_PORT_DISCONNECT ||
500+
pd_port_states[pd_port].c_state == CCG_STATUS_SOURCE) {
501+
if (pd_port_states[shared_pd_port].c_state == CCG_STATUS_NOTHING)
502+
restore_profile = true;
503+
504+
/* Only allow swapping profiles when both ports sink devices */
505+
allow_profile_swap = false;
506+
} else {
501507
/* Avoid the infinite loop if the ports reset or exchange profile */
502508
if (ignore_evaluate_reason & BIT(controller))
503509
return;
@@ -539,7 +545,7 @@ void cypd_evaluate_port_profile(int controller, int port, int ccg_event)
539545

540546
cypd_select_pdo(controller, (port ? 0 : 1), CCG_PD_CMD_SET_TYPEC_1_5A);
541547
}
542-
} else if (all_ports_disconnect) {
548+
} else if (restore_profile) {
543549

544550
for (int idx = 0; idx < pd_chip_config[controller].support_max_port; idx++) {
545551
int port_idx = PDPORT(controller, idx);
@@ -586,10 +592,12 @@ void cypd_evaluate_port_profile(int controller, int port, int ccg_event)
586592
}
587593
} else if ((pre_safety_level < TYPEC_SAFETY_LEVEL_2) &&
588594
((pd_port_states[shared_pd_port].pd_state) &&
589-
(pd_port_states[shared_pd_port].current <= 1500)) &&
595+
(pd_port_states[shared_pd_port].current <= 1500) &&
596+
(pd_port_states[shared_pd_port].safety_table[pre_safety_level] ==
597+
CCG_PD_CMD_SET_TYPEC_3A)) &&
590598
(((pd_port_states[pd_port].pd_state) &&
591599
(pd_port_states[pd_port].max_operating_current > 1500)) ||
592-
pd_port_states[pd_port].rdo_mismatch)) {
600+
pd_port_states[pd_port].rdo_mismatch) && allow_profile_swap) {
593601
/**
594602
* Another port maximum operating current less than 1.5A
595603
* EC allows PD chip provide more current if the RDO capabilities mismatch

0 commit comments

Comments
 (0)