Loading drivers/usb/pd/policy_engine.c +109 −51 Original line number Diff line number Diff line Loading @@ -233,6 +233,7 @@ static void *usbpd_ipc_log; #define FIRST_SOURCE_CAP_TIME 100 #define VDM_BUSY_TIME 50 #define VCONN_ON_TIME 100 #define SINK_TX_TIME 16 /* tPSHardReset + tSafe0V */ #define SNK_HARD_RESET_VBUS_OFF_TIME (35 + 650) Loading Loading @@ -843,10 +844,6 @@ static int pd_eval_src_caps(struct usbpd *pd) break; } } /* downgrade to 2.0 if no PPS */ if (!pps_found) pd->spec_rev = USBPD_REV_20; } val.intval = pps_found ? Loading Loading @@ -1199,6 +1196,39 @@ static void log_decoded_request(struct usbpd *pd, u32 rdo) } } static bool in_src_ams(struct usbpd *pd) { union power_supply_propval val = {0}; if (pd->current_pr != PR_SRC) return false; if (pd->spec_rev != USBPD_REV_30) return true; power_supply_get_property(pd->usb_psy, POWER_SUPPLY_PROP_TYPEC_SRC_RP, &val); return val.intval == 1; } static void start_src_ams(struct usbpd *pd, bool ams) { union power_supply_propval val = {0}; if (pd->current_pr != PR_SRC || pd->spec_rev < USBPD_REV_30) return; usbpd_dbg(&pd->dev, "Set Rp to %s\n", ams ? "1.5A" : "3A"); val.intval = ams ? 1 : 2; /* SinkTxNG / SinkTxOK */ power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_TYPEC_SRC_RP, &val); if (ams) kick_sm(pd, SINK_TX_TIME); } int usbpd_register_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr) { if (find_svid_handler(pd, hdlr->svid)) { Loading Loading @@ -1510,11 +1540,26 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) static void handle_vdm_tx(struct usbpd *pd, enum pd_sop_type sop_type) { u32 vdm_hdr; int ret; if (!pd->vdm_tx) return; /* only send one VDM at a time */ if (pd->vdm_tx) { u32 vdm_hdr = pd->vdm_tx->data[0]; vdm_hdr = pd->vdm_tx->data[0]; /* * PD 3.0: For initiated SVDMs, source must first ensure Rp is set * to SinkTxNG to indicate the start of an AMS */ if (VDM_IS_SVDM(vdm_hdr) && SVDM_HDR_CMD_TYPE(vdm_hdr) == SVDM_CMD_TYPE_INITIATOR && pd->current_pr == PR_SRC && !in_src_ams(pd)) { /* Set SinkTxNG and reschedule sm_work to send again */ start_src_ams(pd, true); return; } ret = pd_send_msg(pd, MSG_VDM, pd->vdm_tx->data, pd->vdm_tx->size, sop_type); Loading Loading @@ -1549,7 +1594,6 @@ static void handle_vdm_tx(struct usbpd *pd, enum pd_sop_type sop_type) pd->vdm_tx = NULL; } } static void reset_vdm_state(struct usbpd *pd) { Loading Loading @@ -1785,6 +1829,12 @@ static int usbpd_startup_common(struct usbpd *pd, pd_reset_protocol(pd); if (!pd->in_pr_swap) { /* * support up to PD 3.0; if peer is 2.0 * phy_msg_received() will handle the downgrade. */ pd->spec_rev = USBPD_REV_30; if (pd->pd_phy_opened) { pd_phy_close(); pd->pd_phy_opened = false; Loading Loading @@ -1830,14 +1880,15 @@ static void enter_state_src_startup(struct usbpd *pd) dual_role_instance_changed(pd->dual_role); val.intval = 1; /* Rp-1.5A; SinkTxNG for PD 3.0 */ power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_TYPEC_SRC_RP, &val); /* Set CC back to DRP toggle for the next disconnect */ val.intval = POWER_SUPPLY_TYPEC_PR_DUAL; power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &val); /* support only PD 2.0 as a source */ pd->spec_rev = USBPD_REV_20; if (usbpd_startup_common(pd, &phy_params)) return; Loading Loading @@ -1897,6 +1948,12 @@ static void handle_state_src_startup_wait_for_vdm_resp(struct usbpd *pd, if (!rx_msg) ms -= SENDER_RESPONSE_TIME; /* * Emarker may have negotiated down to rev 2.0. * Reset to 3.0 to begin SOP communication with sink */ pd->spec_rev = USBPD_REV_30; pd->current_state = PE_SRC_SEND_CAPABILITIES; kick_sm(pd, ms); } Loading Loading @@ -2043,6 +2100,8 @@ static void enter_state_src_ready(struct usbpd *pd) usbpd_send_svdm(pd, USBPD_SID, USBPD_SVDM_DISCOVER_IDENTITY, SVDM_CMD_TYPE_INITIATOR, 0, NULL, 0); else start_src_ams(pd, false); kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); complete(&pd->is_ready); Loading Loading @@ -2096,6 +2155,8 @@ static void handle_state_src_ready(struct usbpd *pd, struct rx_msg *rx_msg) } vconn_swap(pd); if (!pd->vdm_tx) start_src_ams(pd, false); } else if (IS_DATA(rx_msg, MSG_VDM)) { handle_vdm_rx(pd, rx_msg); } else if (rx_msg && pd->spec_rev == USBPD_REV_30) { Loading Loading @@ -2125,8 +2186,10 @@ static void handle_state_src_ready(struct usbpd *pd, struct rx_msg *rx_msg) pd->current_state = PE_DRS_SEND_DR_SWAP; kick_sm(pd, SENDER_RESPONSE_TIME); } else { } else if (pd->vdm_tx) { handle_vdm_tx(pd, SOP_MSG); } else { start_src_ams(pd, false); } } Loading Loading @@ -2227,12 +2290,6 @@ static void enter_state_snk_startup(struct usbpd *pd) dual_role_instance_changed(pd->dual_role); /* * support up to PD 3.0 as a sink; if source is 2.0 * phy_msg_received() will handle the downgrade. */ pd->spec_rev = USBPD_REV_30; if (usbpd_startup_common(pd, &phy_params)) return; Loading Loading @@ -2488,8 +2545,7 @@ static void handle_ctrl_snk_ready(struct usbpd *pd, struct rx_msg *rx_msg) SOP_MSG); if (ret) usbpd_set_state(pd, PE_SEND_SOFT_RESET); } else if (IS_CTRL(rx_msg, MSG_GET_SOURCE_CAP) && pd->spec_rev == USBPD_REV_20) { } else if (IS_CTRL(rx_msg, MSG_GET_SOURCE_CAP)) { ret = pd_send_msg(pd, MSG_SOURCE_CAPABILITIES, default_src_caps, ARRAY_SIZE(default_src_caps), SOP_MSG); Loading @@ -2510,8 +2566,7 @@ static void handle_ctrl_snk_ready(struct usbpd *pd, struct rx_msg *rx_msg) } dr_swap(pd); } else if (IS_CTRL(rx_msg, MSG_PR_SWAP) && pd->spec_rev == USBPD_REV_20) { } else if (IS_CTRL(rx_msg, MSG_PR_SWAP)) { /* TODO: should we Reject in certain circumstances? */ ret = pd_send_msg(pd, MSG_ACCEPT, NULL, 0, SOP_MSG); if (ret) { Loading @@ -2521,8 +2576,7 @@ static void handle_ctrl_snk_ready(struct usbpd *pd, struct rx_msg *rx_msg) usbpd_set_state(pd, PE_PRS_SNK_SRC_TRANSITION_TO_OFF); return; } else if (IS_CTRL(rx_msg, MSG_VCONN_SWAP) && pd->spec_rev == USBPD_REV_20) { } else if (IS_CTRL(rx_msg, MSG_VCONN_SWAP)) { /* * if VCONN is connected to VBUS, make sure we are * not in high voltage contract, otherwise reject. Loading Loading @@ -3494,6 +3548,10 @@ static int usbpd_do_swap(struct usbpd *pd, bool dr_swap, pd->send_dr_swap = true; else pd->send_pr_swap = true; if (pd->current_state == PE_SRC_READY && !in_src_ams(pd)) start_src_ams(pd, true); else kick_sm(pd, 0); /* wait for operation to complete */ Loading drivers/usb/pd/qpnp-pdphy.c +1 −1 Original line number Diff line number Diff line Loading @@ -734,7 +734,7 @@ static irqreturn_t pdphy_msg_rx_irq(int irq, void *data) /* ack to change ownership of rx buffer back to PDPHY RX HW */ pdphy_reg_write(pdphy, USB_PDPHY_RX_ACKNOWLEDGE, 0); if (((buf[0] & 0xf) == PD_MSG_BIST) && size >= 5) { /* BIST */ if (((buf[0] & 0xf) == PD_MSG_BIST) && !(buf[1] & 0x80) && size >= 5) { u8 mode = buf[5] >> 4; /* [31:28] of 1st data object */ pd_phy_bist_mode(mode); Loading Loading
drivers/usb/pd/policy_engine.c +109 −51 Original line number Diff line number Diff line Loading @@ -233,6 +233,7 @@ static void *usbpd_ipc_log; #define FIRST_SOURCE_CAP_TIME 100 #define VDM_BUSY_TIME 50 #define VCONN_ON_TIME 100 #define SINK_TX_TIME 16 /* tPSHardReset + tSafe0V */ #define SNK_HARD_RESET_VBUS_OFF_TIME (35 + 650) Loading Loading @@ -843,10 +844,6 @@ static int pd_eval_src_caps(struct usbpd *pd) break; } } /* downgrade to 2.0 if no PPS */ if (!pps_found) pd->spec_rev = USBPD_REV_20; } val.intval = pps_found ? Loading Loading @@ -1199,6 +1196,39 @@ static void log_decoded_request(struct usbpd *pd, u32 rdo) } } static bool in_src_ams(struct usbpd *pd) { union power_supply_propval val = {0}; if (pd->current_pr != PR_SRC) return false; if (pd->spec_rev != USBPD_REV_30) return true; power_supply_get_property(pd->usb_psy, POWER_SUPPLY_PROP_TYPEC_SRC_RP, &val); return val.intval == 1; } static void start_src_ams(struct usbpd *pd, bool ams) { union power_supply_propval val = {0}; if (pd->current_pr != PR_SRC || pd->spec_rev < USBPD_REV_30) return; usbpd_dbg(&pd->dev, "Set Rp to %s\n", ams ? "1.5A" : "3A"); val.intval = ams ? 1 : 2; /* SinkTxNG / SinkTxOK */ power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_TYPEC_SRC_RP, &val); if (ams) kick_sm(pd, SINK_TX_TIME); } int usbpd_register_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr) { if (find_svid_handler(pd, hdlr->svid)) { Loading Loading @@ -1510,11 +1540,26 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) static void handle_vdm_tx(struct usbpd *pd, enum pd_sop_type sop_type) { u32 vdm_hdr; int ret; if (!pd->vdm_tx) return; /* only send one VDM at a time */ if (pd->vdm_tx) { u32 vdm_hdr = pd->vdm_tx->data[0]; vdm_hdr = pd->vdm_tx->data[0]; /* * PD 3.0: For initiated SVDMs, source must first ensure Rp is set * to SinkTxNG to indicate the start of an AMS */ if (VDM_IS_SVDM(vdm_hdr) && SVDM_HDR_CMD_TYPE(vdm_hdr) == SVDM_CMD_TYPE_INITIATOR && pd->current_pr == PR_SRC && !in_src_ams(pd)) { /* Set SinkTxNG and reschedule sm_work to send again */ start_src_ams(pd, true); return; } ret = pd_send_msg(pd, MSG_VDM, pd->vdm_tx->data, pd->vdm_tx->size, sop_type); Loading Loading @@ -1549,7 +1594,6 @@ static void handle_vdm_tx(struct usbpd *pd, enum pd_sop_type sop_type) pd->vdm_tx = NULL; } } static void reset_vdm_state(struct usbpd *pd) { Loading Loading @@ -1785,6 +1829,12 @@ static int usbpd_startup_common(struct usbpd *pd, pd_reset_protocol(pd); if (!pd->in_pr_swap) { /* * support up to PD 3.0; if peer is 2.0 * phy_msg_received() will handle the downgrade. */ pd->spec_rev = USBPD_REV_30; if (pd->pd_phy_opened) { pd_phy_close(); pd->pd_phy_opened = false; Loading Loading @@ -1830,14 +1880,15 @@ static void enter_state_src_startup(struct usbpd *pd) dual_role_instance_changed(pd->dual_role); val.intval = 1; /* Rp-1.5A; SinkTxNG for PD 3.0 */ power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_TYPEC_SRC_RP, &val); /* Set CC back to DRP toggle for the next disconnect */ val.intval = POWER_SUPPLY_TYPEC_PR_DUAL; power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &val); /* support only PD 2.0 as a source */ pd->spec_rev = USBPD_REV_20; if (usbpd_startup_common(pd, &phy_params)) return; Loading Loading @@ -1897,6 +1948,12 @@ static void handle_state_src_startup_wait_for_vdm_resp(struct usbpd *pd, if (!rx_msg) ms -= SENDER_RESPONSE_TIME; /* * Emarker may have negotiated down to rev 2.0. * Reset to 3.0 to begin SOP communication with sink */ pd->spec_rev = USBPD_REV_30; pd->current_state = PE_SRC_SEND_CAPABILITIES; kick_sm(pd, ms); } Loading Loading @@ -2043,6 +2100,8 @@ static void enter_state_src_ready(struct usbpd *pd) usbpd_send_svdm(pd, USBPD_SID, USBPD_SVDM_DISCOVER_IDENTITY, SVDM_CMD_TYPE_INITIATOR, 0, NULL, 0); else start_src_ams(pd, false); kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); complete(&pd->is_ready); Loading Loading @@ -2096,6 +2155,8 @@ static void handle_state_src_ready(struct usbpd *pd, struct rx_msg *rx_msg) } vconn_swap(pd); if (!pd->vdm_tx) start_src_ams(pd, false); } else if (IS_DATA(rx_msg, MSG_VDM)) { handle_vdm_rx(pd, rx_msg); } else if (rx_msg && pd->spec_rev == USBPD_REV_30) { Loading Loading @@ -2125,8 +2186,10 @@ static void handle_state_src_ready(struct usbpd *pd, struct rx_msg *rx_msg) pd->current_state = PE_DRS_SEND_DR_SWAP; kick_sm(pd, SENDER_RESPONSE_TIME); } else { } else if (pd->vdm_tx) { handle_vdm_tx(pd, SOP_MSG); } else { start_src_ams(pd, false); } } Loading Loading @@ -2227,12 +2290,6 @@ static void enter_state_snk_startup(struct usbpd *pd) dual_role_instance_changed(pd->dual_role); /* * support up to PD 3.0 as a sink; if source is 2.0 * phy_msg_received() will handle the downgrade. */ pd->spec_rev = USBPD_REV_30; if (usbpd_startup_common(pd, &phy_params)) return; Loading Loading @@ -2488,8 +2545,7 @@ static void handle_ctrl_snk_ready(struct usbpd *pd, struct rx_msg *rx_msg) SOP_MSG); if (ret) usbpd_set_state(pd, PE_SEND_SOFT_RESET); } else if (IS_CTRL(rx_msg, MSG_GET_SOURCE_CAP) && pd->spec_rev == USBPD_REV_20) { } else if (IS_CTRL(rx_msg, MSG_GET_SOURCE_CAP)) { ret = pd_send_msg(pd, MSG_SOURCE_CAPABILITIES, default_src_caps, ARRAY_SIZE(default_src_caps), SOP_MSG); Loading @@ -2510,8 +2566,7 @@ static void handle_ctrl_snk_ready(struct usbpd *pd, struct rx_msg *rx_msg) } dr_swap(pd); } else if (IS_CTRL(rx_msg, MSG_PR_SWAP) && pd->spec_rev == USBPD_REV_20) { } else if (IS_CTRL(rx_msg, MSG_PR_SWAP)) { /* TODO: should we Reject in certain circumstances? */ ret = pd_send_msg(pd, MSG_ACCEPT, NULL, 0, SOP_MSG); if (ret) { Loading @@ -2521,8 +2576,7 @@ static void handle_ctrl_snk_ready(struct usbpd *pd, struct rx_msg *rx_msg) usbpd_set_state(pd, PE_PRS_SNK_SRC_TRANSITION_TO_OFF); return; } else if (IS_CTRL(rx_msg, MSG_VCONN_SWAP) && pd->spec_rev == USBPD_REV_20) { } else if (IS_CTRL(rx_msg, MSG_VCONN_SWAP)) { /* * if VCONN is connected to VBUS, make sure we are * not in high voltage contract, otherwise reject. Loading Loading @@ -3494,6 +3548,10 @@ static int usbpd_do_swap(struct usbpd *pd, bool dr_swap, pd->send_dr_swap = true; else pd->send_pr_swap = true; if (pd->current_state == PE_SRC_READY && !in_src_ams(pd)) start_src_ams(pd, true); else kick_sm(pd, 0); /* wait for operation to complete */ Loading
drivers/usb/pd/qpnp-pdphy.c +1 −1 Original line number Diff line number Diff line Loading @@ -734,7 +734,7 @@ static irqreturn_t pdphy_msg_rx_irq(int irq, void *data) /* ack to change ownership of rx buffer back to PDPHY RX HW */ pdphy_reg_write(pdphy, USB_PDPHY_RX_ACKNOWLEDGE, 0); if (((buf[0] & 0xf) == PD_MSG_BIST) && size >= 5) { /* BIST */ if (((buf[0] & 0xf) == PD_MSG_BIST) && !(buf[1] & 0x80) && size >= 5) { u8 mode = buf[5] >> 4; /* [31:28] of 1st data object */ pd_phy_bist_mode(mode); Loading