diff options
-rw-r--r-- | common/system.c | 9 | ||||
-rw-r--r-- | common/usb_pd_protocol.c | 36 | ||||
-rw-r--r-- | include/usb_pd.h | 2 |
3 files changed, 31 insertions, 16 deletions
diff --git a/common/system.c b/common/system.c index 5db3681c26..268e393b1b 100644 --- a/common/system.c +++ b/common/system.c @@ -402,13 +402,10 @@ static void jump_to_image(uintptr_t init_addr) #ifdef CONFIG_USB_POWER_DELIVERY /* - * On sysjump, we are most definitely going to drop pings (if any) - * and lose all of our PD state. Instead of trying to remember all - * the states and deal with on-going transmission, let's send soft - * reset here so that the communication starts over without dropping - * power. + * Notify USB PD module that we are about to sysjump and give it time + * to do what it needs. */ - pd_soft_reset(); + pd_prepare_sysjump(); usleep(5*MSEC); #endif diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 131a441913..b9ed705d65 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -240,6 +240,7 @@ static int pd_src_cap_cnt[PD_PORT_COUNT]; #define PD_FLAGS_GET_SNK_CAP_SENT (1 << 5) /* get sink cap sent */ #define PD_FLAGS_NEW_CONTRACT (1 << 6) /* new power contract established */ #define PD_FLAGS_EXPLICIT_CONTRACT (1 << 7) /* explicit pwr contract in place */ +#define PD_FLAGS_SFT_RST_DIS_COMM (1 << 8) /* disable comms after soft reset */ /* Flags to clear on a disconnect */ #define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \ PD_FLAGS_PARTNER_DR_DATA | \ @@ -255,7 +256,7 @@ static struct pd_protocol { /* current port data role (DFP or UFP) */ uint8_t data_role; /* port flags, see PD_FLAGS_* */ - uint8_t flags; + uint16_t flags; /* 3-bit rolling message ID counter */ uint8_t msg_id; /* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */ @@ -751,6 +752,10 @@ static void execute_soft_reset(int port) #else set_state(port, PD_STATE_SRC_DISCOVERY); #endif + /* if flag to disable PD comms after soft reset, then disable comms */ + if (pd[port].flags & PD_FLAGS_SFT_RST_DIS_COMM) + pd_comm_enable(0); + CPRINTF("Soft Reset\n"); } @@ -765,6 +770,25 @@ void pd_soft_reset(void) } } +void pd_prepare_sysjump(void) +{ + int i; + + /* + * On sysjump, we are most definitely going to drop pings (if any) + * and lose all of our PD state. Instead of trying to remember all + * the states and deal with on-going transmission, let's send soft + * reset here and then disable PD communication until after sysjump + * is complete so that the communication starts over without dropping + * power. + */ + for (i = 0; i < PD_PORT_COUNT; ++i) + if (pd_is_connected(i)) + pd[i].flags |= PD_FLAGS_SFT_RST_DIS_COMM; + + pd_soft_reset(); +} + #ifdef CONFIG_USB_PD_DUAL_ROLE static void pd_store_src_cap(int port, int cnt, uint32_t *src_caps) { @@ -982,13 +1006,7 @@ static void handle_ctrl_request(int port, uint16_t head, break; case PD_CTRL_ACCEPT: if (pd[port].task_state == PD_STATE_SOFT_RESET) { -#ifdef CONFIG_USB_PD_DUAL_ROLE - set_state(port, pd[port].power_role == PD_ROLE_SINK ? - PD_STATE_SNK_DISCOVERY : - PD_STATE_SRC_DISCOVERY); -#else - set_state(port, PD_STATE_SRC_DISCOVERY); -#endif + execute_soft_reset(port); } else if (pd[port].task_state == PD_STATE_SRC_DR_SWAP) { /* switch data role */ pd_dr_swap(port); @@ -1402,7 +1420,6 @@ int pd_get_partner_data_swap_capable(int port) void pd_comm_enable(int enable) { pd_comm_enabled = enable; - #ifdef CONFIG_USB_PD_DUAL_ROLE /* * If communications are enabled, start hard reset timer for @@ -2139,7 +2156,6 @@ void pd_task(void) #endif /* CONFIG_USB_PD_DUAL_ROLE */ case PD_STATE_SOFT_RESET: if (pd[port].last_state != pd[port].task_state) { - execute_soft_reset(port); res = send_control(port, PD_CTRL_SOFT_RESET); /* if soft reset failed, try hard reset. */ diff --git a/include/usb_pd.h b/include/usb_pd.h index 7418988236..7c7532d08f 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -1168,6 +1168,8 @@ void pd_ping_enable(int port, int enable); /* Issue PD soft reset */ void pd_soft_reset(void); +/* Prepare PD communication for sysjump */ +void pd_prepare_sysjump(void); /** * Signal power request to indicate a charger update that affects the port. |