| /* |
| * USB PD Driver - Policy Engine |
| */ |
| |
| #include <linux/device.h> |
| #include <linux/workqueue.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| #include <linux/ccic/usbpd.h> |
| #include <linux/delay.h> |
| #include <linux/completion.h> |
| #include <linux/ccic/usbpd.h> |
| |
| #include <linux/power_supply.h> |
| #if defined(CONFIG_BATTERY_SAMSUNG_V2) |
| #include "../battery_v2/include/sec_charging_common.h" |
| #endif |
| |
| #include <linux/muic/muic.h> |
| #if defined(CONFIG_MUIC_NOTIFIER) |
| #include <linux/muic/muic_notifier.h> |
| #endif /* CONFIG_MUIC_NOTIFIER */ |
| |
| #include <linux/usb_notify.h> |
| |
| #if (defined CONFIG_CCIC_NOTIFIER || defined CONFIG_DUAL_ROLE_USB_INTF) |
| #include <linux/ccic/usbpd_ext.h> |
| #endif |
| |
| #define CHECK_MSG(pd, msg, ret) do {\ |
| if (pd->phy_ops.get_status(pd, msg))\ |
| return ret;\ |
| } while (0); |
| |
| #define CHECK_CMD(pd, event, ret) do {\ |
| if (pd->manager.cmd & event) {\ |
| pd->manager.cmd &= ~event; \ |
| return ret;\ |
| } \ |
| } while (0); |
| |
| policy_state usbpd_policy_src_startup(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Send_Capabilities; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Reset CapsCounter |
| Reset Protocol Layer |
| Start SwapSourceStartTimer (only after Swap) |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* CapsCounter Reset */ |
| pd_data->counter.caps_counter = 0; |
| |
| /* PD Protocol Initialization */ |
| usbpd_init_protocol(pd_data); |
| pd_data->phy_ops.soft_reset(pd_data); |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP80); |
| |
| /* Fro tSrcrecover after PE_SRC_Transition_to_default */ |
| if (policy->txhardresetflag == 1) { |
| policy->txhardresetflag = 0; |
| |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Startup; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= 200) |
| break; |
| } |
| } |
| |
| /* Configuration Channel On */ |
| pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_ON); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_discovery(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Initialize and run SourceCapabilityTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Delay*/ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Discovery; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= tTypeCSendSourceCap) |
| break; |
| } |
| |
| if (ret == PE_SRC_Discovery) |
| return ret; |
| /* Caps Counter Check */ |
| if (pd_data->counter.caps_counter <= USBPD_nCapsCount) |
| return PE_SRC_Send_Capabilities; |
| else |
| return PE_SRC_Disabled; |
| } |
| |
| policy_state usbpd_policy_src_send_capabilities(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| bool received_goodcrc = 0; |
| int ret = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Request present source capabilities from Device Policy Manager |
| Send PD Capabilities message |
| Increment CapsCounter (optional) |
| If GoodCRC received: |
| - stop NoResponseTimer |
| - reset HardResetCounter and CapsCounter |
| - initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Source Capabilities PDO Read & Write */ |
| policy->tx_msg_header.word = pd_data->source_msg_header.word; |
| policy->tx_data_obj[0].object = pd_data->source_data_obj.object; |
| |
| /* Interrupt Status Bit Clear */ |
| pd_data->phy_ops.get_status(pd_data, MSG_ERROR ); |
| pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC); |
| pd_data->phy_ops.get_status(pd_data, MSG_REQUEST); |
| pd_data->phy_ops.get_status(pd_data, MSG_GET_SNK_CAP); |
| |
| /* Add Caps Counter */ |
| pd_data->counter.caps_counter++; |
| |
| /* Send Message */ |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); // Setting 25ms is actual 25 ~ 29ms |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Send_Capabilities; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_REQUEST)) { |
| pd_data->counter.hard_reset_counter = 0; |
| pd_data->counter.caps_counter = 0; |
| pd_data->source_request_obj.object |
| = policy->rx_data_obj[0].object; |
| dev_info(pd_data->dev, "got Request.\n"); |
| ret = PE_SRC_Negotiate_Capability; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) |
| received_goodcrc = 1; |
| |
| if (policy->rx_hardreset) { |
| ret = 0; |
| break; |
| } |
| |
| /* TD.PD.SRC.E14 Atomic Message Sequence */ |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GET_SNK_CAP)) { |
| ret = PE_SRC_Send_Soft_Reset; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| ret = PE_SRC_Discovery; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_PING)) { |
| ret = PE_SRC_Send_Soft_Reset; |
| break; |
| } |
| |
| if (ms >= tSenderResponse) { |
| if (received_goodcrc) { |
| ret = PE_SRC_Hard_Reset; |
| |
| if (pd_data->counter.hard_reset_counter > USBPD_nHardResetCount) |
| ret = Error_Recovery; |
| |
| break; |
| } |
| } |
| |
| if (ms >= 100) { |
| ret = PE_SRC_Discovery; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_negotiate_capability(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Negotiate_Capability; |
| int data_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Get Device Policy Manager evaluation of sink request: |
| - Can be met |
| - Can??t be met |
| - Could be met later from Power Reserve |
| If the sink request for Operating Current or Operating Power can be met, |
| but the sink still requires more power Capability Mismatch this |
| information will be passed to Device Policy Manager |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* Check Specification Revision */ |
| if(pd_data->protocol_rx.msg_header.spec_revision >= USBPD_PD3_0) |
| pd_data->specification_revision = USBPD_PD3_0; |
| else |
| pd_data->specification_revision = USBPD_PD2_0; |
| #endif |
| |
| |
| /* Get Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| mutex_lock(&pd_data->accept_mutex); |
| /* Analysis Received Request Message */ |
| if (usbpd_manager_match_request(pd_data) == 0) { |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, |
| data_role, USBPD_SOURCE); |
| dev_info(pd_data->dev, "%s sended accept\n", __func__); |
| ret = PE_SRC_Transition_Supply; /* Accept */ |
| } else { |
| ret = PE_SRC_Capability_Response; /* Reject */ |
| } |
| mutex_unlock(&pd_data->accept_mutex); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_transition_supply(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Ready; |
| int ms1 = 0, ms2 = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Initialize and run SourceActivityTimer (see Section 8.3.3.5) |
| If GotoMin send GotoMin message |
| Else send Accept message (within tReceiverResponse) |
| Wait tSrcTransition and request Device Policy Manager to transition Power Supply |
| |
| Actions on exit: |
| Send PS_RDY message |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Send Message */ |
| // Move to PE_SRC_Nego |
| //usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, USBPD_DFP, USBPD_SOURCE); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Transition_Supply; |
| break; |
| } |
| ms1 = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { |
| |
| usbpd_timer2_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Transition_Supply; |
| break; |
| } |
| ms2 = usbpd_check_time2(pd_data); |
| if (ms2 > tSrcTransition) |
| break; |
| } |
| |
| if (ret == PE_SRC_Transition_Supply) |
| return ret; |
| |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_PS_RDY, USBPD_DFP, USBPD_SOURCE); |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP180); |
| |
| ret = PE_SRC_Ready; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| ret = PE_SRC_Send_Soft_Reset; |
| break; |
| } |
| |
| if (ms1 >= 8) { |
| ret = PE_SRC_Hard_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_ready(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Initialize and run SourceActivityTimer (see Section 8.3.3.5) |
| Initialize and run DiscoverIdentityTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| if (pd_data->pd_nego == false) |
| pd_data->pd_nego = true; |
| |
| #if defined (CONFIG_TYPEC) && defined (CONFIG_CCIC_TYPEC_PRSWAP) |
| if (policy->pd_support == 0) { |
| policy->pd_support = 1; |
| if (pd_data->phy_ops.set_pwr_opmode) |
| pd_data->phy_ops.set_pwr_opmode(pd_data, TYPEC_PWR_MODE_PD); |
| } |
| #else |
| #if defined(CONFIG_USB_NOTIFY_LAYER) |
| if (policy->pd_support == 0 && policy->otgnotify_sent == 0) { |
| struct otg_notify *o_notify = get_otg_notify(); |
| |
| policy->otgnotify_sent = 1; |
| if (o_notify) |
| send_otg_notify(o_notify, NOTIFY_EVENT_PD_CONTRACT, 1); |
| } |
| #endif |
| #endif |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* when PD3.0, set sink Tx Ok(RP 330uA) */ |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP330); |
| else |
| #endif |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP180); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| while(1){ |
| if (policy->plug_valid == 0) |
| return PE_SRC_Ready; |
| |
| if (policy->rx_hardreset) { |
| policy->rx_hardreset = 0; |
| return PE_SRC_Hard_Reset_Received; |
| } |
| |
| ms = usbpd_check_time1(pd_data); |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* Specification Revision */ |
| if(pd_data->specification_revision == USBPD_PD3_0){ |
| /* PD 3.0 : Control Message */ |
| CHECK_MSG(pd_data, MSG_GET_SOURCE_CAP_EXTENDED, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_STATUS, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_FR_SWAP, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_PPS_STATUS, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_COUNTRY_CODES, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_SINK_CAP_EXTENDED, PE_SRC_Send_Not_Supported); |
| |
| /* PD 3.0 : Data Message */ |
| CHECK_MSG(pd_data, MSG_BATTERY_STATUS, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_ALERT, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_COUNTRY_INFO, PE_SRC_Send_Not_Supported); |
| |
| /* PD 3.0 : Extended Message */ |
| CHECK_MSG(pd_data, MSG_SOURCE_CAPABILITIES_EXTENDED, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_STATUS, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_BATTERY_CAP, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_BATTERY_STATUS, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_BATTERY_CAPABILITIES, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_MANUFACTURER_INFO, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_MANUFACTURER_INFO, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_SECURITY_REQUEST, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_SECURITY_RESPONSE, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_FIRMWARE_UPDATE_REQUEST, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_FIRMWARE_UPDATE_RESPONSE, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_PPS_STATUS, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_COUNTRY_INFO, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_COUNTRY_CODES, PE_SRC_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_SINK_CAPABILITIES_EXTENDED, PE_SRC_Send_Not_Supported); |
| |
| /* When PD3.0 state, NOT_SUPPORT message is transmitted instead of REJECT. */ |
| CHECK_MSG(pd_data, MSG_VCONN_SWAP, PE_SRC_Send_Not_Supported); |
| |
| /* Unrecognized Message Received in Ready State */ |
| CHECK_MSG(pd_data, MSG_RESERVED, PE_SRC_Send_Not_Supported); |
| } |
| #endif |
| |
| /* Wait Message or State */ |
| CHECK_MSG(pd_data, MSG_GET_SRC_CAP, PE_SRC_Give_Source_Cap); |
| CHECK_MSG(pd_data, MSG_REQUEST, PE_SRC_Negotiate_Capability); |
| CHECK_MSG(pd_data, MSG_PR_SWAP, PE_PRS_SRC_SNK_Evaluate_Swap); |
| CHECK_MSG(pd_data, MSG_DR_SWAP, PE_DRS_Evaluate_Port); |
| CHECK_MSG(pd_data, MSG_VCONN_SWAP, PE_VCS_Evaluate_Swap); |
| CHECK_MSG(pd_data, MSG_GET_SNK_CAP, PE_DR_SRC_Give_Sink_Cap); |
| CHECK_MSG(pd_data, MSG_SOFTRESET, PE_SRC_Soft_Reset); |
| //CHECK_MSG(pd_data, MSG_ERROR, PE_SRC_Send_Soft_Reset); |
| CHECK_MSG(pd_data, MSG_BIST, PE_BIST_Carrier_Mode); |
| CHECK_MSG(pd_data, MSG_ACCEPT, PE_SRC_Send_Soft_Reset); |
| CHECK_MSG(pd_data, MSG_SOFTRESET, PE_SRC_Soft_Reset); |
| |
| /* Wait VDM */ |
| CHECK_MSG(pd_data, VDM_DISCOVER_IDENTITY, PE_UFP_VDM_Get_Identity); |
| CHECK_MSG(pd_data, VDM_DISCOVER_SVID, PE_UFP_VDM_Get_SVIDs); |
| CHECK_MSG(pd_data, VDM_DISCOVER_MODE, PE_UFP_VDM_Get_Modes); |
| CHECK_MSG(pd_data, VDM_ENTER_MODE, PE_UFP_VDM_Evaluate_Mode_Entry); |
| CHECK_MSG(pd_data, VDM_EXIT_MODE, PE_UFP_VDM_Mode_Exit); |
| CHECK_MSG(pd_data, VDM_ATTENTION, PE_DFP_VDM_Attention_Request); |
| CHECK_MSG(pd_data, VDM_DP_STATUS_UPDATE, PE_UFP_VDM_Evaluate_Status); |
| CHECK_MSG(pd_data, VDM_DP_CONFIGURE, PE_UFP_VDM_Evaluate_Configure); |
| CHECK_MSG(pd_data, UVDM_MSG, PE_DFP_UVDM_Receive_Message); |
| |
| /* Command Check from AP */ |
| CHECK_CMD(pd_data, MANAGER_REQ_GET_SNKCAP, PE_SRC_Get_Sink_Cap); |
| CHECK_CMD(pd_data, MANAGER_REQ_GOTOMIN, PE_SRC_Transition_Supply); |
| CHECK_CMD(pd_data, MANAGER_REQ_SRCCAP_CHANGE, PE_SRC_Send_Capabilities); |
| CHECK_CMD(pd_data, MANAGER_REQ_PR_SWAP, PE_PRS_SRC_SNK_Send_Swap); |
| CHECK_CMD(pd_data, MANAGER_REQ_DR_SWAP, PE_DRS_Evaluate_Send_Port); |
| CHECK_CMD(pd_data, MANAGER_REQ_VCONN_SWAP, PE_VCS_Send_Swap); |
| |
| CHECK_CMD(pd_data, MANAGER_REQ_UVDM_SEND_MESSAGE, PE_DFP_UVDM_Send_Message); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_DISCOVER_IDENTITY, PE_DFP_VDM_Identity_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_DISCOVER_SVID, PE_DFP_VDM_SVIDs_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_DISCOVER_MODE, PE_DFP_VDM_Modes_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_ENTER_MODE, PE_DFP_VDM_Mode_Entry_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_EXIT_MODE, PE_DFP_VDM_Mode_Exit_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_STATUS_UPDATE, PE_DFP_VDM_Status_Update); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_DisplayPort_Configure, PE_DFP_VDM_DisplayPort_Configure); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_ATTENTION, PE_UFP_VDM_Attention_Request); |
| |
| if (ms >= 2000) |
| break; |
| } |
| |
| /* Data Role Check */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| if ((data_role == USBPD_DFP) && (ms >= 30)) |
| usbpd_manager_vdm_request_enabled(pd_data); |
| |
| return PE_SRC_Ready; |
| } |
| |
| policy_state usbpd_policy_src_disabled(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Disable Power Delivery |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return PE_SRC_Disabled; |
| } |
| |
| policy_state usbpd_policy_src_capability_response(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = 0; |
| int data_role = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Reject message if request can't be met |
| Send Wait message if request could be met later from the Power |
| Reserve and present Contract is still valid |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Send Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Reject, |
| data_role, USBPD_SOURCE); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Capability_Response; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { |
| ret = PE_SRC_Ready; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| ret = PE_SRC_Send_Soft_Reset; |
| break; |
| } |
| if (ms >= 10) { |
| ret = PE_SRC_Hard_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_hard_reset(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Transition_to_default; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Generate Hard Reset signalling |
| Start PSHardResetTimer |
| Increment HardResetCounter |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Message ID Clear */ |
| usbpd_init_counters(pd_data); |
| |
| /* Policy Initialization */ |
| usbpd_init_policy(pd_data); |
| |
| /* Send Hardreset */ |
| pd_data->phy_ops.hard_reset(pd_data); |
| |
| /* Configuration Channel On */ |
| pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_OFF); |
| |
| /* Delay : Setting 25 is actual 57.3ms */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Hard_Reset; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= tPSHardReset) |
| break; |
| } |
| |
| if (ret == PE_SRC_Hard_Reset) |
| return ret; |
| |
| /* Add Hardreset Counter */ |
| pd_data->counter.hard_reset_counter++; |
| |
| /* Set Tx HardReset Flag After SRC_HADRESET */ |
| policy->txhardresetflag = 1; |
| |
| return PE_SRC_Transition_to_default; |
| } |
| |
| policy_state usbpd_policy_src_hard_reset_received(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Transition_to_default; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Start PSHardResetTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Message ID Clear */ |
| usbpd_init_counters(pd_data); |
| |
| /* Policy Initialization */ |
| usbpd_init_policy(pd_data); |
| |
| /* Delay */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Hard_Reset_Received; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= tPSHardReset) |
| break; |
| } |
| |
| if (ret == PE_SRC_Hard_Reset_Received) |
| return ret; |
| |
| /* Set Tx HardReset Flag After SRC_HADRESET */ |
| policy->txhardresetflag = 1; |
| |
| return PE_SRC_Transition_to_default; |
| } |
| |
| policy_state usbpd_policy_src_transition_to_default(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Startup; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Request Device Policy Manager to request power |
| supply Hard Resets to vSafe5V via vSafe0V |
| Reset local HW |
| If Type-C request Device Policy Manager to set |
| Port Data Role to DFP and turn off VCONN |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* VBUS Turn off */ |
| pd_data->phy_ops.set_otg_control(pd_data, 0); |
| |
| /* Delay */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Transition_to_default; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= tSrcRecover) |
| break; |
| } |
| |
| if (ret == PE_SRC_Transition_to_default) |
| return ret; |
| |
| /* initial reset */ |
| pd_data->phy_ops.driver_reset(pd_data); |
| |
| pd_data->phy_ops.set_otg_control(pd_data, 1); |
| /* |
| Request Device Policy Manager to request power |
| supply Hard Resets to vSafe5V via vSafe0V |
| |
| If(Type-C request Device Policy Manager to set Port Data Role to DFP) |
| turn off VCONN |
| */ |
| |
| /* |
| Request Device Policy Manager to turn on VCONN |
| Initialize and start NoResponseTimer |
| Inform Protocol Layer Hard Reset complete |
| */ |
| |
| /* confirm VBUS ON : done by set_otg_control */ |
| return PE_SRC_Startup; |
| } |
| |
| policy_state usbpd_policy_src_give_source_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Give_Source_Cap; |
| int data_role = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Action on entry : |
| Request source capabilities from Device Policy Manager |
| Send Capabilities message |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Message Setting */ |
| policy->tx_msg_header.msg_type = USBPD_Source_Capabilities; |
| policy->tx_msg_header.port_data_role = data_role; |
| policy->tx_msg_header.port_power_role = USBPD_SOURCE; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].power_data_obj.max_current = 500 / 10; |
| policy->tx_data_obj[0].power_data_obj.voltage = 5000 / 50; |
| policy->tx_data_obj[0].power_data_obj.peak_current = 0; |
| policy->tx_data_obj[0].power_data_obj.unchunked_extended_message_supported = 0; |
| policy->tx_data_obj[0].power_data_obj.data_role_swap = 1; |
| policy->tx_data_obj[0].power_data_obj.usb_comm_capable = 1; |
| policy->tx_data_obj[0].power_data_obj.externally_powered = 0; |
| policy->tx_data_obj[0].power_data_obj.usb_suspend_support = 1; |
| policy->tx_data_obj[0].power_data_obj.dual_role_power = 1; |
| policy->tx_data_obj[0].power_data_obj.supply = 0; |
| |
| /* Send Message */ |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Give_Source_Cap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_REQUEST)) { |
| ret = PE_SRC_Negotiate_Capability; |
| break; |
| } |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| ret = PE_SRC_Send_Soft_Reset; |
| break; |
| } |
| if (ms >= tSenderResponse) { |
| ret = PE_SRC_Hard_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_get_sink_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int ret = PE_SRC_Get_Sink_Cap; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_Sink_Cap message |
| Initialize and run |
| SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Send Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Get_Sink_Cap, data_role, USBPD_SOURCE); |
| |
| /* Wait Message */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) |
| break; |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_SNK_CAP)) { |
| dev_info(pd_data->dev, "got SinkCap.\n"); |
| ret = PE_SRC_Ready; |
| break; |
| } |
| if (ms >= tSenderResponse) { |
| ret = PE_SRC_Ready; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_wait_new_capabilities(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Wait for new Source Capabilities |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return PE_SRC_Send_Capabilities; |
| } |
| |
| policy_state usbpd_policy_src_send_soft_reset(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Send_Soft_Reset; |
| int data_role = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Reset Protocol Layer |
| Send Soft Reset message |
| Initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| |
| /* USB PD Protocol Initialization */ |
| usbpd_init_protocol(pd_data); |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Message ID Clear */ |
| usbpd_init_counters(pd_data); |
| pd_data->counter.hard_reset_counter = 0; |
| |
| /* Send Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Soft_Reset, |
| data_role, USBPD_SOURCE); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Send_Soft_Reset; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { |
| ret = PE_SRC_Send_Capabilities; |
| break; |
| } |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| ret = PE_SRC_Hard_Reset; |
| break; |
| } |
| if (ms >= tSenderResponse) { |
| ret = PE_SRC_Hard_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_soft_reset(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Soft_Reset; |
| int data_role = 0; |
| int ms = 0; |
| /********************************************** |
| Actions on entry: |
| Reset Protocol Layer |
| Send Accept message |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* USB PD Counters Initialization */ |
| usbpd_init_counters(pd_data); |
| pd_data->counter.hard_reset_counter = 0; |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Send Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, data_role, USBPD_SOURCE); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SRC_Soft_Reset; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { |
| ret = PE_SRC_Send_Capabilities; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| ret = PE_SRC_Hard_Reset; |
| break; |
| } |
| if (ms >= 10) { |
| ret = PE_SRC_Ready; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_startup(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Reset Protocol Layer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* PD Protocol Initialization */ |
| usbpd_init_protocol(pd_data); |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP80); |
| |
| /* Configuration Channel On */ |
| //pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_ON); |
| //Move to PE_SNK_Wait_for_Capabilities |
| |
| return PE_SNK_Discovery; |
| } |
| |
| policy_state usbpd_policy_snk_discovery(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = 0; |
| int vbus_check = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Wait for VBUS |
| **********************************************/ |
| |
| /* TODO: wait vbus */ |
| /* if coming from HardReset |
| && NoResponseTimer timeout |
| && HardResetCounter <= nHardResetCount, |
| return(PE_SNK_Hard_Reset) */ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SNK_Discovery; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| |
| vbus_check = pd_data->phy_ops.vbus_on_check(pd_data); |
| if (vbus_check < 0 || vbus_check > 0) { |
| ret = PE_SNK_Wait_for_Capabilities; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= tNoResponse) { |
| /* HardReset Count Check */ |
| if (pd_data->counter.hard_reset_counter <= USBPD_nHardResetCount) { |
| ret = PE_SNK_Hard_Reset; |
| break; |
| } else { |
| ret = Error_Recovery; |
| break; |
| } |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_wait_for_capabilities(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Wait_for_Capabilities; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Initialize and run SinkWaitCapTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Configuration Channel On */ |
| pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_ON); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SNK_Wait_for_Capabilities; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| /* Rx Source Capabilities */ |
| if (pd_data->phy_ops.get_status(pd_data, MSG_SRC_CAP)) { |
| ret = PE_SNK_Evaluate_Capability; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= tTypeCSinkWaitCap) { |
| #if !defined(CONFIG_SEC_FACTORY) |
| /* HardReset Count Check */ |
| if (pd_data->counter.hard_reset_counter <= USBPD_nHardResetCount) { |
| ret = PE_SNK_Hard_Reset; |
| break; |
| } else { |
| ret = Error_Recovery; |
| break; |
| } |
| #else |
| ret = Error_Recovery; |
| break; |
| #endif |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_evaluate_capability(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int sink_request_obj_num = 0; |
| int ret = PE_SNK_Evaluate_Capability; |
| union power_supply_propval val; |
| struct power_supply *psy; |
| |
| /********************************************** |
| Actions on entry: |
| Reset HardResetCounter to zero. |
| Ask Device Policy Manager to evaluate the options based on supplied |
| capabilities, any Power Reserve that it needs, and respond indicating |
| the selected capability and, optionally, a Capability Mismatch |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| psy = power_supply_get_by_name("battery"); |
| if (psy) { |
| val.intval = 1; |
| psy_do_property("battery", set, POWER_SUPPLY_EXT_PROP_SRCCAP, val); |
| } else { |
| pr_err("%s: Fail to get psy battery\n", __func__); |
| } |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* Check Specification Revision */ |
| if(pd_data->protocol_rx.msg_header.spec_revision >= USBPD_PD3_0) |
| pd_data->specification_revision = USBPD_PD3_0; |
| else |
| pd_data->specification_revision = USBPD_PD2_0; |
| #endif |
| |
| |
| /* Select PDO */ |
| #ifdef CONFIG_BATTERY_SAMSUNG |
| #ifdef CONFIG_USB_TYPEC_MANAGER_NOTIFIER |
| if (pd_noti.sink_status.selected_pdo_num == 0) { |
| pd_noti.sink_status.selected_pdo_num = 1; |
| if (policy->sink_cap_received) { |
| policy->send_sink_cap = 1; |
| policy->sink_cap_received = 0; |
| } |
| } |
| #endif |
| #endif |
| |
| /* Select Object Position */ |
| sink_request_obj_num = usbpd_manager_evaluate_capability(pd_data); |
| |
| /* Branch */ |
| if (sink_request_obj_num > 0) |
| ret = PE_SNK_Select_Capability; |
| else |
| ret = PE_SNK_Hard_Reset; |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_select_capability(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Select_Capability; |
| int data_role = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Request based on Device Policy Manager response: |
| - Request from present capabilities |
| - Optionally Indicate that other capabilities would be preferred (Capability Mismatch) |
| Initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Message Header Setting */ |
| policy->tx_msg_header.msg_type = USBPD_Request; |
| policy->tx_msg_header.port_data_role = data_role; |
| policy->tx_msg_header.port_power_role = USBPD_SINK; |
| policy->tx_msg_header.num_data_objs = 1; /* Initial Select PDO = 1 */ |
| |
| /* Select PDO */ |
| policy->tx_data_obj[0] = usbpd_manager_select_capability(pd_data); |
| |
| /* Send Message*/ |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer*/ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SNK_Select_Capability; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GET_SNK_CAP)) { |
| ret = PE_SNK_Send_Soft_Reset; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { |
| ret = PE_SNK_Transition_Sink; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT) | |
| pd_data->phy_ops.get_status(pd_data, MSG_WAIT)) { |
| /* 1st Power Negotiation Check */ |
| if (pd_noti.sink_status.selected_pdo_num == 0) |
| ret = PE_SNK_Wait_for_Capabilities; |
| else |
| ret = PE_SNK_Ready; |
| |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= tSenderResponse) { |
| ret = PE_SNK_Hard_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_transition_sink(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| struct usbpd_manager_data *manager = &pd_data->manager; |
| int ret = PE_SNK_Transition_Sink; |
| int ms = 0; |
| bool vbus_short = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Initialize and run PSTransitionTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Policy Engine State Setting */ |
| policy->state = PE_SNK_Transition_Sink; |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SNK_Transition_Sink; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { |
| /* Device Information */ |
| dev_info(pd_data->dev, "got PS_READY.\n"); |
| |
| pd_data->phy_ops.pd_vbus_short_check(pd_data); |
| pd_data->phy_ops.get_vbus_short_check(pd_data, &vbus_short); |
| |
| #ifdef CONFIG_BATTERY_SAMSUNG |
| #ifdef CONFIG_USB_TYPEC_MANAGER_NOTIFIER |
| if (vbus_short) { |
| pd_noti.sink_status.available_pdo_num = 1; |
| if (pd_noti.sink_status.power_list[1].max_current > manager->vb_cc_short_max_input_current) |
| pd_noti.sink_status.power_list[1].max_current = manager->vb_cc_short_max_input_current; |
| } |
| pd_noti.sink_status.current_pdo_num = pd_noti.sink_status.selected_pdo_num; |
| #endif |
| #endif |
| /* Notify Plug Attach */ |
| usbpd_manager_plug_attach(pd_data->dev, ATTACHED_DEV_TYPE3_CHARGER_MUIC); |
| |
| /* Check CC instead of vbus */ |
| pd_data->phy_ops.cc_instead_of_vbus(pd_data, 1); |
| |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| /* PD Certification(Ellisys) : TD.PD.SNK.E10 GetSinkCap in place of PS_RDY */ |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GET_SNK_CAP)) { |
| ret = PE_SNK_Hard_Reset; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= tPSTransition) { |
| ret = PE_SNK_Hard_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_ready(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Initialize and run SinkActivityTimer2 |
| Initialize and run SinkRequestTimer3 (on receiving Wait) |
| Initialize and run DiscoverIdentityTimer5 |
| **********************************************/ |
| |
| CHECK_MSG(pd_data, VDM_DISCOVER_IDENTITY, PE_UFP_VDM_Get_Identity); |
| CHECK_MSG(pd_data, VDM_DISCOVER_SVID, PE_UFP_VDM_Get_SVIDs); |
| CHECK_MSG(pd_data, VDM_DISCOVER_MODE, PE_UFP_VDM_Get_Modes); |
| CHECK_MSG(pd_data, VDM_ENTER_MODE, PE_UFP_VDM_Evaluate_Mode_Entry); |
| CHECK_MSG(pd_data, VDM_EXIT_MODE, PE_UFP_VDM_Mode_Exit); |
| |
| /* PD State Inform to AP */ |
| if(pd_data->protocol_rx.msg_header.msg_type != USBPD_Vendor_Defined){ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| } |
| |
| if (pd_data->pd_nego == false) |
| pd_data->pd_nego = true; |
| |
| #if defined (CONFIG_TYPEC) && defined (CONFIG_CCIC_TYPEC_PRSWAP) |
| if (policy->pd_support == 0) { |
| policy->pd_support = 1; |
| if (pd_data->phy_ops.set_pwr_opmode) |
| pd_data->phy_ops.set_pwr_opmode(pd_data, TYPEC_PWR_MODE_PD); |
| } |
| #else |
| #if defined(CONFIG_USB_NOTIFY_LAYER) |
| if (policy->pd_support == 0 && policy->otgnotify_sent == 0) { |
| struct otg_notify *o_notify = get_otg_notify(); |
| |
| policy->otgnotify_sent = 1; |
| if (o_notify) |
| send_otg_notify(o_notify, NOTIFY_EVENT_PD_CONTRACT, 1); |
| } |
| #endif |
| #endif |
| |
| /* Data Role Check */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| while (1) { |
| if (policy->plug_valid == 0) |
| return PE_SNK_Ready; |
| |
| if (policy->rx_hardreset) { |
| policy->rx_hardreset = 0; |
| return PE_SNK_Transition_to_default; |
| } |
| |
| |
| ms = usbpd_check_time1(pd_data); |
| #if defined(CONFIG_PDIC_PD30) |
| /* Specification Revision */ |
| if(pd_data->specification_revision == USBPD_PD3_0){ |
| /* PD 3.0 : Control Message */ |
| CHECK_MSG(pd_data, MSG_GET_SOURCE_CAP_EXTENDED, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_STATUS, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_FR_SWAP, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_PPS_STATUS, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_COUNTRY_CODES, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_SINK_CAP_EXTENDED, PE_SNK_Send_Not_Supported); |
| |
| /* PD 3.0 : Data Message */ |
| CHECK_MSG(pd_data, MSG_BATTERY_STATUS, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_ALERT, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_COUNTRY_INFO, PE_SNK_Send_Not_Supported); |
| |
| /* PD 3.0 : Extended Message */ |
| CHECK_MSG(pd_data, MSG_SOURCE_CAPABILITIES_EXTENDED, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_STATUS, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_BATTERY_CAP, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_BATTERY_STATUS, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_BATTERY_CAPABILITIES, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_GET_MANUFACTURER_INFO, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_MANUFACTURER_INFO, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_SECURITY_REQUEST, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_SECURITY_RESPONSE, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_FIRMWARE_UPDATE_REQUEST, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_FIRMWARE_UPDATE_RESPONSE, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_PPS_STATUS, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_COUNTRY_INFO, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_COUNTRY_CODES, PE_SNK_Send_Not_Supported); |
| CHECK_MSG(pd_data, MSG_SINK_CAPABILITIES_EXTENDED, PE_SNK_Send_Not_Supported); |
| |
| /* When PD3.0 state, NOT_SUPPORT message is transmitted instead of REJECT. */ |
| CHECK_MSG(pd_data, MSG_VCONN_SWAP, PE_SNK_Send_Not_Supported); |
| |
| /* Unrecognized Message Received in Ready State */ |
| CHECK_MSG(pd_data, MSG_RESERVED, PE_SNK_Send_Not_Supported); |
| } |
| #endif |
| |
| /* Message Check */ |
| CHECK_MSG(pd_data, MSG_GET_SNK_CAP, PE_SNK_Give_Sink_Cap); |
| CHECK_MSG(pd_data, MSG_PR_SWAP, PE_PRS_SNK_SRC_Evaluate_Swap); |
| CHECK_MSG(pd_data, MSG_DR_SWAP, PE_DRS_Evaluate_Port); |
| CHECK_MSG(pd_data, MSG_VCONN_SWAP, PE_VCS_Evaluate_Swap); |
| CHECK_MSG(pd_data, MSG_GET_SRC_CAP, PE_DR_SNK_Give_Source_Cap); |
| CHECK_MSG(pd_data, MSG_BIST, PE_BIST_Carrier_Mode); |
| CHECK_MSG(pd_data, MSG_ACCEPT, PE_SNK_Send_Soft_Reset); |
| CHECK_MSG(pd_data, MSG_SOFTRESET, PE_SNK_Soft_Reset); |
| CHECK_MSG(pd_data, MSG_SRC_CAP, PE_SNK_Evaluate_Capability); |
| |
| /* Wait VDM */ |
| CHECK_MSG(pd_data, VDM_DISCOVER_IDENTITY, PE_UFP_VDM_Get_Identity); |
| CHECK_MSG(pd_data, VDM_DISCOVER_SVID, PE_UFP_VDM_Get_SVIDs); |
| CHECK_MSG(pd_data, VDM_DISCOVER_MODE, PE_UFP_VDM_Get_Modes); |
| CHECK_MSG(pd_data, VDM_ENTER_MODE, PE_UFP_VDM_Evaluate_Mode_Entry); |
| CHECK_MSG(pd_data, VDM_EXIT_MODE, PE_UFP_VDM_Mode_Exit); |
| CHECK_MSG(pd_data, VDM_ATTENTION, PE_DFP_VDM_Attention_Request); |
| CHECK_MSG(pd_data, VDM_DP_STATUS_UPDATE, PE_UFP_VDM_Evaluate_Status); |
| CHECK_MSG(pd_data, VDM_DP_CONFIGURE, PE_UFP_VDM_Evaluate_Configure); |
| CHECK_MSG(pd_data, UVDM_MSG, PE_DFP_UVDM_Receive_Message); |
| |
| /* Command Check from AP */ |
| CHECK_CMD(pd_data, MANAGER_REQ_NEW_POWER_SRC, PE_SNK_Select_Capability); |
| CHECK_CMD(pd_data, MANAGER_REQ_GET_SRC_CAP, PE_SNK_Get_Source_Cap); |
| CHECK_CMD(pd_data, MANAGER_REQ_PR_SWAP, PE_PRS_SNK_SRC_Send_Swap); |
| CHECK_CMD(pd_data, MANAGER_REQ_DR_SWAP, PE_DRS_Evaluate_Send_Port); |
| CHECK_CMD(pd_data, MANAGER_REQ_VCONN_SWAP, PE_VCS_Send_Swap); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_DISCOVER_IDENTITY, PE_DFP_VDM_Identity_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_DISCOVER_SVID, PE_DFP_VDM_SVIDs_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_DISCOVER_MODE, PE_DFP_VDM_Modes_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_ATTENTION, PE_UFP_VDM_Attention_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_ENTER_MODE, PE_DFP_VDM_Mode_Entry_Request); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_STATUS_UPDATE, PE_DFP_VDM_Status_Update); |
| CHECK_CMD(pd_data, MANAGER_REQ_VDM_DisplayPort_Configure, PE_DFP_VDM_DisplayPort_Configure); |
| CHECK_CMD(pd_data, MANAGER_REQ_UVDM_SEND_MESSAGE, PE_DFP_UVDM_Send_Message); |
| |
| if (ms >= 2000) |
| break; |
| } |
| |
| if (data_role == USBPD_DFP) |
| usbpd_manager_vdm_request_enabled(pd_data); |
| |
| /* TD.PD.VDMU.E17 Interruption by VDM Command */ |
| if(pd_data->protocol_rx.msg_header.msg_type == USBPD_Vendor_Defined){ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| CHECK_MSG(pd_data, VDM_DISCOVER_IDENTITY, PE_UFP_VDM_Get_Identity); |
| CHECK_MSG(pd_data, VDM_DISCOVER_SVID, PE_UFP_VDM_Get_SVIDs); |
| CHECK_MSG(pd_data, VDM_DISCOVER_MODE, PE_UFP_VDM_Get_Modes); |
| CHECK_MSG(pd_data, VDM_ENTER_MODE, PE_UFP_VDM_Evaluate_Mode_Entry); |
| CHECK_MSG(pd_data, VDM_EXIT_MODE, PE_UFP_VDM_Mode_Exit); |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= 1) |
| break; |
| } |
| } |
| |
| return PE_SNK_Ready; |
| } |
| |
| policy_state usbpd_policy_snk_hard_reset(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Generate Hard Reset signalling. |
| Increment HardResetCounter. |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.hard_reset(pd_data); |
| pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_OFF); |
| /* increase hard reset counter */ |
| pd_data->counter.hard_reset_counter++; |
| |
| return PE_SNK_Transition_to_default; |
| } |
| |
| policy_state usbpd_policy_snk_transition_to_default(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Startup; |
| int ms = 0; |
| |
| /********************************************** |
| Hard reset signalling received |
| |
| Actions on entry: |
| Request Device Policy Manager to request power sink transition to default |
| Reset local HW |
| If Type-C set Port Data Role to UFP and turn off VCONN |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Message ID Clear */ |
| usbpd_init_counters(pd_data); |
| |
| /* Policy Initialization */ |
| usbpd_init_policy(pd_data); |
| |
| /* Driver Reset */ |
| pd_data->phy_ops.driver_reset(pd_data); |
| |
| /* Vconn Off */ |
| usbpd_manager_turn_off_vconn(pd_data); |
| |
| /* Wait 200ms */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SNK_Transition_to_default; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= 200) |
| break; |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_give_sink_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Give_Sink_Cap; |
| int data_role = 0; |
| int ms = 0; |
| /********************************************** |
| Get Sink Cap Message received |
| |
| Actions on entry: |
| Get present sink capabilities from Device Policy Manager |
| Send Capabilities message (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| #ifdef CONFIG_BATTERY_SAMSUNG |
| #ifdef CONFIG_USB_TYPEC_MANAGER_NOTIFIER |
| pd_noti.sink_status.selected_pdo_num = 0; |
| #endif |
| #endif |
| |
| /* Sink Cap Message Setting */ |
| policy->tx_msg_header.word = pd_data->sink_msg_header.word; |
| policy->tx_msg_header.port_data_role = data_role; |
| policy->tx_data_obj[0].object = pd_data->sink_data_obj[0].object; |
| policy->tx_data_obj[1].object = pd_data->sink_data_obj[1].object; |
| policy->sink_cap_received = 1; |
| |
| /* Clear Interrupt Status */ |
| pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC); |
| pd_data->phy_ops.get_status(pd_data, MSG_ERROR); |
| |
| /* Send Message */ |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SNK_Give_Sink_Cap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| dev_info(pd_data->dev, "got MSG_ERROR. -> PE_SNK_Send_Soft_Reset\n"); |
| ret = PE_SNK_Send_Soft_Reset; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { |
| dev_info(pd_data->dev, "got MSG_GOODCRC -> PE_SNK_Ready.\n"); |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= 10) { |
| dev_info(pd_data->dev, "got Timer1_overflag -> PE_SNK_Send_Soft_Reset\n"); |
| ret = PE_SNK_Send_Soft_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_get_source_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Get_Source_Cap; |
| int data_role = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_Source_Cap message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Send Message*/ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Get_Source_Cap, data_role, USBPD_SINK); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SNK_Get_Source_Cap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= 10) { |
| ret = PE_SNK_Get_Source_Cap; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_send_soft_reset(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Send_Soft_Reset; |
| int data_role = 0; |
| int ms = 0; |
| /********************************************** |
| Actions on entry: |
| Reset Protocol Layer |
| Send Soft Reset message |
| Initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* USB PD Protocol Initialization */ |
| usbpd_init_protocol(pd_data); |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Message ID Clear */ |
| usbpd_init_counters(pd_data); |
| pd_data->counter.hard_reset_counter = 0; |
| |
| /* Send Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Soft_Reset, |
| data_role, USBPD_SINK); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SNK_Send_Soft_Reset; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { |
| ret = PE_SNK_Wait_for_Capabilities; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= tSenderResponse) { |
| ret = PE_SNK_Hard_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_soft_reset(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int ret = PE_SNK_Soft_Reset; |
| int ms = 0; |
| |
| /********************************************** |
| Soft Reset message received |
| |
| Actions on entry: |
| Reset Protocol Layer |
| Send Accept message |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* USB PD Counters Initialization */ |
| usbpd_init_counters(pd_data); |
| pd_data->counter.hard_reset_counter = 0; |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Send Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, data_role, USBPD_SINK); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_SNK_Soft_Reset; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { |
| ret = PE_SNK_Wait_for_Capabilities; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| ret = PE_SNK_Hard_Reset; |
| break; |
| } |
| |
| if (ms >= 10) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_drs_evaluate_port(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int power_role = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| if (policy->modal_operation) { |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Hard_Reset; |
| else |
| return PE_SNK_Hard_Reset; |
| } |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| if (data_role == USBPD_DFP) |
| return PE_DRS_DFP_UFP_Evaluate_DR_Swap; |
| else |
| return PE_DRS_UFP_DFP_Evaluate_DR_Swap; |
| } |
| |
| policy_state usbpd_policy_drs_evaluate_send_port(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int power_role = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| if (policy->modal_operation) { |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Hard_Reset; |
| else |
| return PE_SNK_Hard_Reset; |
| } |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| if (data_role == USBPD_DFP) |
| return PE_DRS_DFP_UFP_Send_DR_Swap; |
| else |
| return PE_DRS_UFP_DFP_Send_DR_Swap; |
| } |
| |
| policy_state usbpd_policy_drs_dfp_ufp_evaluate_dr_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| bool drs_ok; |
| |
| /********************************************** |
| DR_Swap message received & not in Modal Operation |
| |
| Actions on entry: |
| Get evaluation of Data Role Swap |
| request from Device Policy Manager |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| drs_ok = usbpd_manager_data_role_swap(pd_data); |
| |
| if (drs_ok) |
| return PE_DRS_DFP_UFP_Accept_DR_Swap; |
| else |
| return PE_DRS_DFP_UFP_Reject_DR_Swap; |
| } |
| |
| policy_state usbpd_policy_drs_dfp_ufp_accept_dr_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Accept message |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| mutex_lock(&pd_data->accept_mutex); |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Accept, USBPD_DFP, power_role); |
| |
| pd_data->phy_ops.set_data_role(pd_data, USBPD_UFP); |
| mutex_unlock(&pd_data->accept_mutex); |
| |
| return PE_DRS_DFP_UFP_Change_to_UFP; |
| } |
| |
| policy_state usbpd_policy_drs_dfp_ufp_change_to_ufp(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Request Device Policy Manager to |
| change port to UFP |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| policy_state usbpd_policy_drs_dfp_ufp_send_dr_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int ret = 0; |
| int ms = 0; |
| /********************************************** |
| Actions on entry: |
| Send Swap DR message |
| Initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_DR_Swap, USBPD_DFP, power_role)) { |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DRS_DFP_UFP_Send_DR_Swap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { |
| dev_info(pd_data->dev, "%s, got Accept\n", __func__); |
| ret = PE_DRS_DFP_UFP_Change_to_UFP; |
| #if defined (CONFIG_TYPEC) && defined (CONFIG_CCIC_TYPEC_PRSWAP) |
| pd_data->phy_ops.set_data_role(pd_data, USBPD_UFP); |
| #endif |
| break; |
| } |
| if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { |
| dev_info(pd_data->dev, "%s, got Reject\n", __func__); |
| break; |
| } |
| if (pd_data->phy_ops.get_status(pd_data, MSG_WAIT)) { |
| dev_info(pd_data->dev, "%s, got Wait\n", __func__); |
| break; |
| } |
| if (ms >= tSenderResponse) |
| break; |
| } |
| if (ret > 0) |
| return ret; |
| } |
| |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| policy_state usbpd_policy_drs_dfp_ufp_reject_dr_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Reject or Wait message as appropriate |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Reject, USBPD_DFP, power_role)) { |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| return PE_DRS_DFP_UFP_Reject_DR_Swap; |
| } |
| |
| policy_state usbpd_policy_drs_ufp_dfp_evaluate_dr_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| bool drs_ok; |
| |
| /********************************************** |
| Actions on entry: |
| Get evaluation of Data Role Swap |
| request from Device Policy Manager |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| drs_ok = usbpd_manager_data_role_swap(pd_data); |
| |
| if (drs_ok) |
| return PE_DRS_UFP_DFP_Accept_DR_Swap; |
| else |
| return PE_DRS_UFP_DFP_Reject_DR_Swap; |
| } |
| |
| policy_state usbpd_policy_drs_ufp_dfp_accept_dr_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Accept message |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| mutex_lock(&pd_data->accept_mutex); |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Accept, USBPD_UFP, power_role); |
| pd_data->phy_ops.set_data_role(pd_data, USBPD_DFP); |
| mutex_unlock(&pd_data->accept_mutex); |
| return PE_DRS_UFP_DFP_Change_to_DFP; |
| } |
| |
| policy_state usbpd_policy_drs_ufp_dfp_change_to_dfp(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Request Device Policy Manager to change port to DFP |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| policy_state usbpd_policy_drs_ufp_dfp_send_dr_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int ret = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Swap DR message |
| Initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_DR_Swap, USBPD_UFP, power_role)) { |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DRS_UFP_DFP_Send_DR_Swap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { |
| dev_info(pd_data->dev, "%s, got Accept\n", __func__); |
| ret = PE_DRS_UFP_DFP_Change_to_DFP; |
| #if defined (CONFIG_TYPEC) && defined (CONFIG_CCIC_TYPEC_PRSWAP) |
| pd_data->phy_ops.set_data_role(pd_data, USBPD_DFP); |
| #endif |
| break; |
| } |
| if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { |
| dev_info(pd_data->dev, "%s, got Reject\n", __func__); |
| break; |
| } |
| if (pd_data->phy_ops.get_status(pd_data, MSG_WAIT)) { |
| dev_info(pd_data->dev, "%s, got Wait\n", __func__); |
| break; |
| } |
| if (ms > tSenderResponse) |
| break; |
| } |
| if (ret > 0) |
| return ret; |
| } |
| |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| policy_state usbpd_policy_drs_ufp_dfp_reject_dr_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int data_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Reject or Wait message as appropriate |
| **********************************************/ |
| |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Reject, data_role, USBPD_SINK)) { |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| return PE_DRS_UFP_DFP_Reject_DR_Swap; |
| } |
| |
| policy_state usbpd_policy_prs_src_snk_reject_pr_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| /********************************************** |
| Actions on entry: |
| Send Reject or Wait message as appropriate |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Reject, data_role, USBPD_SOURCE)) |
| return PE_SRC_Ready; |
| |
| return PE_PRS_SRC_SNK_Reject_PR_Swap; |
| } |
| |
| policy_state usbpd_policy_prs_src_snk_evaluate_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| bool prs_ok; |
| |
| /********************************************** |
| Actions on entry: |
| Get evaluation of swap request from Device Policy Manager |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* DPM Check to support roleswap */ |
| prs_ok = usbpd_manager_power_role_swap(pd_data); |
| |
| /* Branch */ |
| if (prs_ok) |
| return PE_PRS_SRC_SNK_Accept_Swap; |
| else |
| return PE_PRS_SRC_SNK_Reject_PR_Swap; |
| } |
| |
| policy_state usbpd_policy_prs_src_snk_send_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int ret = PE_SRC_Ready; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send PR_Swap message |
| Initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_PR_Swap, data_role, USBPD_SOURCE); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_PRS_SRC_SNK_Send_Swap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { |
| ret = PE_PRS_SRC_SNK_Transition_off; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { |
| ret = PE_SRC_Ready; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_WAIT)) { |
| ret = PE_SRC_Ready; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= tSenderResponse + 5) { |
| ret = PE_SRC_Ready; |
| break; |
| } |
| |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_prs_src_snk_accept_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /********************************************** |
| Actions on entry: |
| Send Accept message |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Accept, data_role, USBPD_SOURCE); |
| |
| return PE_PRS_SRC_SNK_Transition_off; |
| |
| } |
| |
| policy_state usbpd_policy_prs_src_snk_transition_to_off(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| struct usbpd_manager_data *manager = &pd_data->manager; |
| int ret = PE_PRS_SRC_SNK_Assert_Rd; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Tell Device Policy Manager to turn off power supply |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Delay */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_PRS_SRC_SNK_Transition_off; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= tSrcTransition) |
| break; |
| } |
| |
| if (ret == PE_PRS_SRC_SNK_Transition_off) |
| return ret; |
| |
| #if defined CONFIG_CCIC_S2MU004 |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_SOURCE); |
| #endif |
| pd_data->phy_ops.pr_swap(pd_data, USBPD_SOURCE_OFF); |
| |
| /* VBUS off */ |
| pd_data->phy_ops.set_otg_control(pd_data, 0); |
| |
| pr_info("%s, %d\n", __func__, manager->acc_type); |
| |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_PRS_SRC_SNK_Transition_off; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= 600) |
| break; |
| } |
| #if 0 |
| /* TODO: svid_0 == 0 confition check? |
| * based on 004 code 600ms no condition vs here 150ms w/ condition */ |
| /* skip delay when GEARVR is attached */ |
| if (manager->acc_type != CCIC_DOCK_HMT || manager->SVID_0 == 0) |
| msleep(600); |
| #endif |
| #if defined CONFIG_CCIC_S2MU004 |
| if (ret == PE_PRS_SRC_SNK_Transition_off) |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); |
| #endif |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_prs_src_snk_assert_rd(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Request DPM to assert Rd |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Asserted Rd */ |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_SINK); |
| |
| return PE_PRS_SRC_SNK_Wait_Source_on; |
| } |
| |
| policy_state usbpd_policy_prs_src_snk_wait_source_on(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = 0; |
| int data_role = 0; |
| int ms = 0; |
| /********************************************** |
| Actions on entry: |
| Send PS_RDY message |
| Initialize and run PSSourceOnTimer |
| **********************************************/ |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Send Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_PS_RDY, data_role, USBPD_SINK); |
| usbpd_timer1_start(pd_data); |
| |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_PRS_SRC_SNK_Wait_Source_on; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { |
| dev_info(pd_data->dev, "got PSRDY.\n"); |
| pd_data->counter.swap_hard_reset_counter = 0; |
| |
| /* Message ID Clear */ |
| usbpd_init_counters(pd_data); |
| pd_data->counter.hard_reset_counter = 0; |
| pd_data->phy_ops.soft_reset(pd_data); |
| |
| mdelay(15); |
| ret = PE_SNK_Startup; |
| break; |
| } |
| if (ms >= tPSSourceOn) { |
| ret = PE_SNK_Hard_Reset; |
| if (pd_data->counter.hard_reset_counter > USBPD_nHardResetCount) |
| ret = Error_Recovery; |
| break; |
| } |
| } |
| |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_prs_snk_src_reject_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Reject or Wait message as appropriate |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Reject, data_role, USBPD_SINK)) |
| return PE_SNK_Ready; |
| |
| return PE_PRS_SNK_SRC_Reject_Swap; |
| } |
| |
| policy_state usbpd_policy_prs_snk_src_evaluate_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| bool prs_ok; |
| int ret = PE_PRS_SNK_SRC_Evaluate_Swap; |
| |
| /********************************************** |
| Actions on entry: |
| Get evaluation of swap request from Device Policy Manager |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Power Role Swap Check */ |
| prs_ok = usbpd_manager_power_role_swap(pd_data); |
| |
| if (prs_ok) |
| ret = PE_PRS_SNK_SRC_Accept_Swap; |
| else |
| ret = PE_PRS_SNK_SRC_Reject_Swap; |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_prs_snk_src_send_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int ret = PE_SNK_Ready; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send PR_Swap message |
| Initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_PR_Swap, data_role, USBPD_SINK); |
| |
| usbpd_timer1_start(pd_data); |
| |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_PRS_SNK_SRC_Send_Swap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ACCEPT)) { |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_SINK); |
| ret = PE_PRS_SNK_SRC_Transition_off; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_WAIT)) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= tSenderResponse) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_prs_snk_src_accept_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Accept message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Send Accept Message */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| #if defined CONFIG_CCIC_S2MU004 |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_SINK); |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, |
| data_role, USBPD_SINK); |
| #else |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Accept, |
| data_role, USBPD_SINK); |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_SINK); |
| #endif |
| |
| return PE_PRS_SNK_SRC_Transition_off; |
| } |
| |
| policy_state usbpd_policy_prs_snk_src_transition_to_off(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = 0; |
| int ms = 0; |
| /********************************************** |
| Actions on entry: |
| Initialize and run PSSourceOffTimer |
| Tell Device Policy Manager to turn off Power Sink. |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| msleep(50); |
| |
| pd_data->phy_ops.pr_swap(pd_data, USBPD_SINK_OFF); |
| |
| /* Start Timer 750ms */ |
| usbpd_timer1_start(pd_data); |
| |
| while (1) { |
| if (policy->plug_valid == 0) { |
| pr_info("%s, plug_valid == 0\n", __func__); |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); |
| ret = PE_PRS_SNK_SRC_Transition_off; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { |
| dev_info(pd_data->dev, "got PSRDY.\n"); |
| ret = PE_PRS_SNK_SRC_Assert_Rp; |
| break; |
| } |
| if (ms >= tPSSourceOff) { |
| ret = PE_SRC_Hard_Reset; |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); |
| if (pd_data->counter.hard_reset_counter > USBPD_nHardResetCount) |
| ret = Error_Recovery; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_prs_snk_src_assert_rp(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Request DPM to assert Rp |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_SOURCE); |
| |
| return PE_PRS_SNK_SRC_Source_on; |
| } |
| |
| policy_state usbpd_policy_prs_snk_src_source_on(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int ret = 0; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Tell Device Policy Manager to turn on Source |
| Initialize and run SourceActivityTimer (see Section 8.3.3.6.1.2)1 |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| pd_data->phy_ops.pr_swap(pd_data, USBPD_SOURCE_ON); |
| |
| /* VBUS on */ |
| pd_data->phy_ops.set_otg_control(pd_data, 1); |
| |
| /* Dealy */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_PRS_SNK_SRC_Source_on; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= 200) |
| break; |
| } |
| |
| if (ret == PE_PRS_SNK_SRC_Source_on) |
| return ret; |
| |
| /* send PS_RDY */ |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_PS_RDY, data_role, USBPD_SOURCE)) { |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_PRS_SNK_SRC_Source_on; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (ms >= tSwapSourceStart) |
| break; |
| } |
| |
| if (ret == PE_PRS_SNK_SRC_Source_on) |
| return ret; |
| /* TODO: 4) check GoodCRC : may need to be added for certification */ |
| |
| /* Message ID Clear */ |
| usbpd_init_counters(pd_data); |
| pd_data->counter.hard_reset_counter = 0; |
| |
| return PE_SRC_Startup; |
| } |
| |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); |
| |
| return PE_PRS_SNK_SRC_Source_on; |
| } |
| |
| policy_state usbpd_policy_vcs_evaluate_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| bool vcs_ok; |
| |
| /********************************************** |
| Actions on entry: |
| Get evaluation of VCONN swap |
| request from Device Policy Manager |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Request from DPM */ |
| vcs_ok = usbpd_manager_vconn_source_swap(pd_data); |
| |
| if (vcs_ok) |
| return PE_VCS_Accept_Swap; |
| else |
| return PE_VCS_Reject_VCONN_Swap; |
| } |
| |
| policy_state usbpd_policy_vcs_accept_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int vconn_source = 0; |
| int power_role = 0; |
| int data_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Accept message |
| **********************************************/ |
| |
| pd_data->phy_ops.get_vconn_source(pd_data, &vconn_source); |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Accept, data_role, power_role)) { |
| if (vconn_source) |
| return PE_VCS_Wait_for_VCONN; |
| else |
| return PE_VCS_Turn_On_VCONN; |
| } |
| |
| return PE_VCS_Accept_Swap; |
| } |
| |
| policy_state usbpd_policy_vcs_send_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int vconn_source = 0; |
| int power_role = 0; |
| int ret = PE_VCS_Send_Swap; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send VCONN_Swap message |
| Initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| |
| /* PD State Inform for AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Get Vconn Source */ |
| pd_data->phy_ops.get_vconn_source(pd_data, &vconn_source); |
| |
| /* Get Power Role */ |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| /* Send Vconn Swap */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_VCONN_Swap, USBPD_DFP, power_role); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_VCS_Send_Swap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { |
| if (vconn_source) |
| ret = PE_VCS_Wait_for_VCONN; |
| else |
| ret = PE_VCS_Turn_On_VCONN; |
| break; |
| } |
| /* TimeOver Check */ |
| if (ms >= 10) { |
| if (power_role == USBPD_SINK) |
| ret = PE_SNK_Hard_Reset; |
| else |
| ret = PE_SRC_Hard_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_vcs_wait_for_vconn(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_VCS_Wait_for_VCONN; |
| int ms = 0; |
| /********************************************** |
| Actions on entry: |
| Start VCONNOnTimer |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_VCS_Wait_for_VCONN; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_PSRDY)) { |
| pd_data->counter.swap_hard_reset_counter = 0; |
| ret = PE_VCS_Turn_Off_VCONN; |
| break; |
| } |
| /* TimeOver Check */ |
| if (ms >= tVCONNSourceOn) { |
| if (pd_data->counter.swap_hard_reset_counter > USBPD_nHardResetCount) |
| ret = Error_Recovery; |
| else |
| ret = PE_SNK_Hard_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_vcs_turn_off_vconn(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Tell Device Policy Manager to turn off VCONN |
| **********************************************/ |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.set_vconn_source(pd_data, USBPD_VCONN_OFF); |
| |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| policy_state usbpd_policy_vcs_turn_on_vconn(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Tell Device Policy Manager to turn on VCONN |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.set_vconn_source(pd_data, USBPD_VCONN_ON); |
| |
| return PE_VCS_Send_PS_RDY; |
| } |
| |
| policy_state usbpd_policy_vcs_send_ps_rdy(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int data_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send PS_RDY message |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| mdelay(5); |
| |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_PS_RDY, data_role, data_role)) { |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| return PE_VCS_Send_PS_RDY; |
| } |
| |
| policy_state usbpd_policy_vcs_reject_vconn_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Reject or Wait message as appropriate |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Reject, USBPD_DFP, power_role)) { |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| return PE_VCS_Reject_VCONN_Swap; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_get_identity(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_UFP_VDM_Get_Identity; |
| int rx_svid = 0; |
| int rx_command_type = 0; |
| int data_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Request Identity information from DPM |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Get Device Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Read SVID */ |
| rx_svid = pd_data->protocol_rx.data_obj[0].structured_vdm.svid; |
| |
| /* rx_command_type */ |
| rx_command_type = pd_data->protocol_rx.data_obj[0].structured_vdm.command_type; |
| |
| switch (rx_svid) { |
| case PD_SID: |
| case PD_SID_1: |
| if (data_role == USBPD_DFP) { |
| switch (rx_command_type) { |
| case Initiator: |
| ret = PE_UFP_VDM_Get_Identity_NAK; |
| break; |
| |
| case Responder_NAK: |
| case Responder_BUSY: |
| ret = PE_DFP_VDM_Identity_NAKed; |
| break; |
| default: |
| break; |
| } |
| } else |
| ret = PE_UFP_VDM_Send_Identity; |
| |
| break; |
| default: |
| ret = PE_UFP_VDM_Get_Identity_NAK; |
| break; |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_send_identity(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Discover Identity ACK |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 4; |
| |
| /* VDM Header */ |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 0; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_ACK; |
| policy->tx_data_obj[0].structured_vdm.command = Discover_Identity; |
| |
| /* ID Header */ |
| policy->tx_data_obj[1].object = 0; |
| policy->tx_data_obj[1].id_header_vdo.Data_Capable_USB_Host = 1; |
| policy->tx_data_obj[1].id_header_vdo.Data_Capable_USB_Device = 1; |
| policy->tx_data_obj[1].id_header_vdo.Product_Type = UFP_PDUSB_Peripheral; |
| policy->tx_data_obj[1].id_header_vdo.modal_op_supported = 0; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[1].id_header_vdo.product_type_dfp = DFP_PDUSB_Host; |
| else |
| #endif |
| policy->tx_data_obj[1].id_header_vdo.product_type_dfp = 0; //PD2.0 Reserved Bit |
| policy->tx_data_obj[1].id_header_vdo.USB_Vendor_ID = SAMSUNG_VENDOR_ID; |
| |
| /* Cert Stat */ |
| policy->tx_data_obj[2].object = 0; |
| policy->tx_data_obj[2].cert_stat_vdo.xid = 0; |
| |
| /* Product VDO */ |
| policy->tx_data_obj[3].object = 0; |
| policy->tx_data_obj[3].product_vdo.USB_Product_ID = 0x6860; /* Samsung Phone */ |
| policy->tx_data_obj[3].product_vdo.Device_Version = 0x0400; /* BCD Device */ |
| |
| /* TODO: data object should be prepared from device manager */ |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Send_Identity; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_get_identity_nak(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int data_role = 0; |
| int rx_svid = 0; |
| |
| /********************************************** |
| Actions on entry: NAK |
| Send Discover Identity NAK/BUSY Command |
| response as requested |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| rx_svid = pd_data->protocol_rx.data_obj[0].structured_vdm.svid; |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = data_role; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = rx_svid; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 0; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_NAK; |
| policy->tx_data_obj[0].structured_vdm.command = Discover_Identity; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Get_Identity_NAK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_get_svids(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Request SVIDs information from DPM |
| **********************************************/ |
| |
| if (usbpd_manager_get_svids(pd_data) == MANAGER_SUPPORT) |
| return PE_UFP_VDM_Send_SVIDs; |
| else |
| return PE_UFP_VDM_Get_SVIDs_NAK; |
| |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_send_svids(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Discover SVIDs ACK |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 2; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 0; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_ACK; |
| policy->tx_data_obj[0].structured_vdm.command = Discover_SVIDs; |
| |
| policy->tx_data_obj[1].vdm_svid.svid_0 = PD_SID; |
| policy->tx_data_obj[1].vdm_svid.svid_1 = 0xFF01; |
| |
| /* TODO: data object should be prepared from device manager */ |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| |
| return PE_UFP_VDM_Send_SVIDs; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_get_svids_nak(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int rx_svid = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Discover SVIDs NAK/BUSY Command |
| response as requested |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| rx_svid = pd_data->protocol_rx.data_obj[0].structured_vdm.svid; |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = rx_svid; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 0; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_NAK; |
| policy->tx_data_obj[0].structured_vdm.command = Discover_SVIDs; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Get_SVIDs_NAK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_get_modes(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Request Modes information from DPM |
| **********************************************/ |
| |
| if (usbpd_manager_get_modes(pd_data) == MANAGER_SUPPORT) |
| return PE_UFP_VDM_Send_Modes; |
| else |
| return PE_UFP_VDM_Get_Modes_NAK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_send_modes(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Discover Modes ACK |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 2; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 0; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_ACK; |
| policy->tx_data_obj[0].structured_vdm.command = Discover_Modes; |
| |
| /* TODO: data object should be prepared from device manager */ |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Send_Modes; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_get_modes_nak(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int rx_svid = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Discover Modes NAK/BUSY Command |
| response as requested |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| rx_svid = pd_data->protocol_rx.data_obj[0].structured_vdm.svid; |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = rx_svid; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 0; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_NAK; |
| policy->tx_data_obj[0].structured_vdm.command = Discover_Modes; |
| |
| /* TODO: data object should be prepared from device manager */ |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Get_Modes_NAK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_evaluate_mode_entry(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Request DPM to evaluate request to enter a Mode |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Certification: Ellisys: TD.PD.VDMU.E15.Applicability */ |
| if (usbpd_manager_get_svids(pd_data) == MANAGER_SUPPORT) |
| return PE_UFP_VDM_Mode_Entry_ACK; |
| else |
| return PE_UFP_VDM_Mode_Entry_NAK; |
| |
| /* Todo |
| check DPM evaluate request to enter a mode |
| */ |
| /* |
| if (usbpd_manager_enter_mode(pd_data, mode_pos, |
| mode_vdo) == 0) |
| return PE_UFP_VDM_Mode_Entry_ACK; |
| else |
| return PE_UFP_VDM_Mode_Entry_NAK; |
| */ |
| return PE_UFP_VDM_Evaluate_Mode_Entry; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_mode_entry_ack(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Enter Mode ACK Command |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_ACK; |
| policy->tx_data_obj[0].structured_vdm.command = Enter_Mode; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| /* TODO: may need to wait a while(5ms) and send status_update */ |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Mode_Entry_ACK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_mode_entry_nak(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int rx_svid = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Enter Mode NAK Command response as requested |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| rx_svid = pd_data->protocol_rx.data_obj[0].structured_vdm.svid; |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = rx_svid; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_NAK; |
| policy->tx_data_obj[0].structured_vdm.command = Enter_Mode; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Mode_Entry_NAK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_mode_exit(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| unsigned mode_pos; |
| int ret = PE_UFP_VDM_Mode_Exit; |
| |
| /********************************************** |
| Actions on entry: |
| Request DPM to evaluate request to exit the requested Mode |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* get mode to exit */ |
| mode_pos = policy->rx_data_obj[0].structured_vdm.obj_pos; |
| if (usbpd_manager_exit_mode(pd_data, mode_pos) == MANAGER_SUPPORT) |
| ret = PE_UFP_VDM_Mode_Exit_ACK; |
| |
| ret = PE_UFP_VDM_Mode_Exit_NAK; |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_mode_exit_ack(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Exit Mode ACK Command |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_ACK; |
| policy->tx_data_obj[0].structured_vdm.command = Exit_Mode; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Mode_Exit_NAK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_mode_exit_nak(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int rx_svid = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Exit Mode NAK Command |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| rx_svid = pd_data->protocol_rx.data_obj[0].structured_vdm.svid; |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = rx_svid; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_NAK; |
| policy->tx_data_obj[0].structured_vdm.command = Exit_Mode; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Mode_Exit_NAK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_attention_request(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Attention Command request |
| **********************************************/ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| /* policy->tx_msg_header.num_data_objs = 1; number of objects*/ |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Initiator; |
| policy->tx_data_obj[0].structured_vdm.command = Attention; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Attention_Request; |
| |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_evaluate_status(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| |
| /* Todo |
| check DPM evaluate request to inform status |
| */ |
| /* |
| if (usbpd_manager_enter_mode(pd_data, mode_pos, |
| mode_vdo) == 0) |
| return PE_UFP_VDM_Mode_Entry_ACK; |
| else |
| return PE_UFP_VDM_Mode_Entry_NAK; |
| */ |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_status_ack(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_ACK; |
| policy->tx_data_obj[0].structured_vdm.command = DisplayPort_Status_Update; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Status_ACK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_status_nak(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int rx_svid = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| rx_svid = pd_data->protocol_rx.data_obj[0].structured_vdm.svid; |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = rx_svid; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_NAK; |
| policy->tx_data_obj[0].structured_vdm.command = DisplayPort_Status_Update; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Status_NAK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_evaluate_configure(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| |
| /* Todo |
| check DPM evaluate request to inform status |
| */ |
| /* |
| if (usbpd_manager_enter_mode(pd_data, mode_pos, |
| mode_vdo) == 0) |
| return PE_UFP_VDM_Mode_Entry_ACK; |
| else |
| return PE_UFP_VDM_Mode_Entry_NAK; |
| */ |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_configure_ack(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_ACK; |
| policy->tx_data_obj[0].structured_vdm.command = DisplayPort_Configure; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Configure_ACK; |
| } |
| |
| policy_state usbpd_policy_ufp_vdm_configure_nak(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int rx_svid = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| rx_svid = pd_data->protocol_rx.data_obj[0].structured_vdm.svid; |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_UFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = rx_svid; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Responder_NAK; |
| policy->tx_data_obj[0].structured_vdm.command = DisplayPort_Configure; |
| |
| if (usbpd_send_msg(pd_data, &policy->tx_msg_header, |
| policy->tx_data_obj)) { |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| return PE_UFP_VDM_Configure_NAK; |
| } |
| |
| /* the end ufp */ |
| |
| policy_state usbpd_policy_dfp_vdm_identity_request(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int ms = 0; |
| int ret = PE_DFP_VDM_Identity_Request; |
| |
| /********************************************** |
| Actions on entry: |
| Send Discover Identity request |
| Start VDMResponseTimer |
| **********************************************/ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* when PD3.0, set sink Tx NG(RP 180uA) for Send Request Message */ |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP180); |
| #endif |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_DFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 0; |
| policy->tx_data_obj[0].structured_vdm.command_type = Initiator; |
| policy->tx_data_obj[0].structured_vdm.command = Discover_Identity; |
| |
| pd_data->counter.discover_identity_counter++; |
| |
| /* Send Message */ |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, VDM_DISCOVER_IDENTITY)) { |
| pd_data->counter.discover_identity_counter = 0; |
| dev_info(pd_data->dev, "RX_DIS_ID_ACK\n"); |
| |
| if (pd_data->protocol_rx.data_obj[0].structured_vdm.command_type == Responder_ACK) { |
| dev_info(pd_data->dev, "Responder_ACK\n"); |
| ret = PE_DFP_VDM_Identity_ACKed; |
| } else if (pd_data->protocol_rx.data_obj[0].structured_vdm.command_type == Responder_NAK |
| || pd_data->protocol_rx.data_obj[0].structured_vdm.command_type == Responder_BUSY) { |
| dev_info(pd_data->dev, "Responder_NAK or BUSY\n"); |
| ret = PE_DFP_VDM_Identity_NAKed; |
| |
| /* IF PD2.0, selfsoft reset for BIST Carrier 2 Test */ |
| if(pd_data->specification_revision == USBPD_PD2_0) |
| pd_data->phy_ops.soft_reset(pd_data); |
| } |
| break; |
| } |
| |
| if (ms >= tVDMSenderResponse) { |
| dev_info(pd_data->dev, "tVDMSenderResponse over\n"); |
| ret = PE_DFP_VDM_Identity_NAKed; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| static policy_state usbpd_policy_dfp_vdm_response(struct policy_data *policy, |
| usbpd_manager_event_type event) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| usbpd_manager_inform_event(pd_data, event); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (power_role == USBPD_SINK) |
| return PE_SNK_Ready; |
| else |
| return PE_SRC_Ready; |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_identity_acked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of identity |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, |
| MANAGER_DISCOVER_IDENTITY_ACKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_identity_naked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of result |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Interrupt Status Bit Clear */ |
| pd_data->phy_ops.get_status(pd_data, MSG_ERROR ); |
| |
| /* Clear Message Bit */ |
| pd_data->phy_ops.get_status(pd_data, VDM_DISCOVER_IDENTITY); |
| |
| return usbpd_policy_dfp_vdm_response(policy, |
| MANAGER_DISCOVER_IDENTITY_NAKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_svids_request(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int ret = PE_DFP_VDM_SVIDs_NAKed; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Discover SVIDs request |
| Start VDMResponseTimer |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* when PD3.0, set sink Tx NG(RP 180uA) for Send Request Message */ |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP180); |
| #endif |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_DFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 0; |
| policy->tx_data_obj[0].structured_vdm.command_type = Initiator; |
| policy->tx_data_obj[0].structured_vdm.command = Discover_SVIDs; |
| |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DFP_VDM_SVIDs_Request; |
| break; |
| } |
| |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, VDM_DISCOVER_SVID)) { |
| if (policy->rx_data_obj[0].structured_vdm.command_type |
| == Responder_ACK) |
| ret = PE_DFP_VDM_SVIDs_ACKed; |
| break; |
| } |
| if (ms >= tVDMSenderResponse) |
| break; |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_svids_acked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of SVIDs |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, |
| MANAGER_DISCOVER_SVID_ACKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_svids_naked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of result |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, |
| MANAGER_DISCOVER_SVID_NAKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_modes_request(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| struct usbpd_manager_data *manager = &pd_data->manager; |
| int power_role = 0; |
| int ret = PE_DFP_VDM_Modes_NAKed; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Discover Modes request |
| Start VDMResponseTimer |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* when PD3.0, set sink Tx NG(RP 180uA) for Send Request Message */ |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP180); |
| #endif |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_DFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = manager->SVID_0; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 0; |
| policy->tx_data_obj[0].structured_vdm.command_type = Initiator; |
| policy->tx_data_obj[0].structured_vdm.command = Discover_Modes; |
| |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DFP_VDM_Modes_Request; |
| break; |
| } |
| |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, VDM_DISCOVER_MODE)) { |
| if (policy->rx_data_obj[0].structured_vdm.command_type |
| == Responder_ACK) |
| ret = PE_DFP_VDM_Modes_ACKed; |
| break; |
| } |
| if (ms >= tVDMSenderResponse) |
| break; |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_modes_acked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of Modes |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, |
| MANAGER_DISCOVER_MODE_ACKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_modes_naked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of result |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, |
| MANAGER_DISCOVER_MODE_NAKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_entry_request(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| struct usbpd_manager_data *manager = &pd_data->manager; |
| int power_role = 0; |
| int ret = PE_DFP_VDM_Mode_Entry_NAKed; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Mode Entry request |
| Start VDMModeEntryTimer |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* when PD3.0, set sink Tx NG(RP 180uA) for Send Request Message */ |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP180); |
| #endif |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_DFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = manager->SVID_0; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Initiator; |
| policy->tx_data_obj[0].structured_vdm.command = Enter_Mode; |
| |
| /* TODO: obj_pos , vdo should be set by device manager */ |
| |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DFP_VDM_Mode_Entry_Request; |
| break; |
| } |
| |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, VDM_ENTER_MODE)) { |
| if (policy->rx_data_obj[0].structured_vdm.command_type |
| == Responder_ACK) |
| ret = PE_DFP_VDM_Mode_Entry_ACKed; |
| break; |
| } |
| if (ms >= tVDMWaitModeEntry) |
| break; |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_entry_acked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Request DPM to enter the mode |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, MANAGER_ENTER_MODE_ACKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_entry_naked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of reason for failure |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, MANAGER_ENTER_MODE_NAKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_exit_request(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int ret = PE_DFP_VDM_Mode_Exit_NAKed; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Exit Mode request |
| Start VDMModeExitTimer |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* when PD3.0, set sink Tx NG(RP 180uA) for Send Request Message */ |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP180); |
| #endif |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_DFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Initiator; |
| policy->tx_data_obj[0].structured_vdm.command = Exit_Mode; |
| |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DFP_VDM_Mode_Exit_Request; |
| break; |
| } |
| |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, VDM_EXIT_MODE)) { |
| if (policy->rx_data_obj[0].structured_vdm.command_type |
| == Responder_ACK) |
| ret = PE_DFP_VDM_Mode_Exit_ACKed; |
| break; |
| } |
| if (ms >= tVDMWaitModeExit) |
| break; |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_exit_acked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of ACK |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, MANAGER_EXIT_MODE_ACKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_exit_naked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of NAK |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, MANAGER_EXIT_MODE_NAKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_attention_request(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| Actions on entry: |
| Inform Device Policy Manager of Attention Command request |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, MANAGER_ATTENTION_REQUEST); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_status_update(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int ret = PE_DFP_VDM_Status_Update_NAKed; |
| int ms = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* when PD3.0, set sink Tx NG(RP 180uA) for Send Request Message */ |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP180); |
| #endif |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_DFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 2; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID_1; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Initiator; |
| policy->tx_data_obj[0].structured_vdm.command = DisplayPort_Status_Update; |
| |
| /* second object for vdo */ |
| policy->tx_data_obj[1].object = 0; |
| policy->tx_data_obj[1].displayport_status.port_connected = 1; |
| |
| /* TODO: obj_pos , vdo should be set by device manager */ |
| |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DFP_VDM_Status_Update; |
| break; |
| } |
| |
| ms = usbpd_check_time1(pd_data); |
| |
| if (pd_data->phy_ops.get_status(pd_data, VDM_DP_STATUS_UPDATE)) { |
| pr_info("%s : command(%d), command_type(%d), obj_pos(%d), version(%d), vdm_type(%d)\n", |
| __func__, policy->rx_data_obj[0].structured_vdm.command, |
| policy->rx_data_obj[0].structured_vdm.command_type, |
| policy->rx_data_obj[0].structured_vdm.obj_pos, |
| policy->rx_data_obj[0].structured_vdm.version, |
| policy->rx_data_obj[0].structured_vdm.vdm_type); |
| if (policy->rx_data_obj[0].structured_vdm.command_type |
| == Responder_ACK) |
| ret = PE_DFP_VDM_Status_Update_ACKed; |
| break; |
| } |
| |
| if (ms >= tVDMWaitModeEntry) |
| break; |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_status_update_acked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, MANAGER_STATUS_UPDATE_ACKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_status_update_naked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, MANAGER_STATUS_UPDATE_NAKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_displayport_configure(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| int ret = PE_DFP_VDM_DisplayPort_Configure_NAKed; |
| int ms = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| #if defined(CONFIG_PDIC_PD30) |
| /* when PD3.0, set sink Tx NG(RP 180uA) for Send Request Message */ |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP180); |
| #endif |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| policy->tx_msg_header.msg_type = USBPD_Vendor_Defined; |
| policy->tx_msg_header.port_data_role = USBPD_DFP; |
| policy->tx_msg_header.port_power_role = power_role; |
| policy->tx_msg_header.num_data_objs = 2; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].structured_vdm.svid = PD_SID_1; |
| policy->tx_data_obj[0].structured_vdm.vdm_type = Structured_VDM; |
| #if defined(CONFIG_PDIC_PD30) |
| if(pd_data->specification_revision >= USBPD_PD3_0) |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version2; |
| else |
| #endif |
| policy->tx_data_obj[0].structured_vdm.version = VDM_Version1; |
| policy->tx_data_obj[0].structured_vdm.obj_pos = 1; |
| policy->tx_data_obj[0].structured_vdm.command_type = Initiator; |
| policy->tx_data_obj[0].structured_vdm.command = DisplayPort_Configure; |
| |
| /* second object for vdo */ |
| policy->tx_data_obj[1].object = 0; |
| policy->tx_data_obj[1].displayport_configurations.select_configuration = USB_U_AS_UFP_D; |
| policy->tx_data_obj[1].displayport_configurations.displayport_protocol = DP_V_1_3; |
| policy->tx_data_obj[1].displayport_configurations.ufp_u_pin_assignment = PIN_ASSIGNMENT_D; |
| |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DFP_VDM_DisplayPort_Configure; |
| break; |
| } |
| |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, VDM_DP_CONFIGURE)) { |
| if (policy->rx_data_obj[0].structured_vdm.command_type |
| == Responder_ACK) |
| ret = PE_DFP_VDM_DisplayPort_Configure_ACKed; |
| break; |
| } |
| if (ms >= tVDMWaitModeEntry) |
| break; |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_displayport_configure_acked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, MANAGER_DisplayPort_Configure_ACKED); |
| } |
| |
| policy_state usbpd_policy_dfp_vdm_displayport_configure_naked(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return usbpd_policy_dfp_vdm_response(policy, MANAGER_DisplayPort_Configure_NACKED); |
| } |
| |
| policy_state usbpd_policy_dfp_uvdm_send_message(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| struct usbpd_manager_data *manager = &pd_data->manager; |
| int power_role = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| usbpd_send_msg(pd_data, &manager->uvdm_msg_header, manager->uvdm_data_obj); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| policy_state usbpd_policy_dfp_uvdm_receive_message(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int power_role = 0; |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| usbpd_manager_inform_event(pd_data, MANAGER_UVDM_RECEIVE_MESSAGE); |
| |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| |
| if (power_role == USBPD_SOURCE) |
| return PE_SRC_Ready; |
| else |
| return PE_SNK_Ready; |
| } |
| |
| policy_state usbpd_policy_dr_src_get_source_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_DR_SRC_Get_Source_Cap; |
| int data_role = 0; |
| int ms = 0; |
| |
| /********************************************** |
| get source capabilities request from Device Policy Manager |
| |
| Actions on entry: |
| Send Get_Source_Cap message |
| Initialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Send Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Get_Source_Cap, data_role, USBPD_SOURCE); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DR_SRC_Get_Source_Cap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| ret = PE_SRC_Send_Soft_Reset; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_SRC_CAP)) { |
| ret = PE_SRC_Ready; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { |
| ret = PE_SRC_Ready; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= tSenderResponse) { |
| ret = PE_SRC_Ready; |
| break; |
| } |
| } |
| |
| /********************************************** |
| Actions on exit: |
| Pass source capabilities/outcome to Device Policy Manager |
| |
| Source capabilities message received |
| | SenderResponseTimer Timeout | Reject message received |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_dr_src_give_sink_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int data_role = 0; |
| int ret = PE_DR_SRC_Give_Sink_Cap; |
| int ms = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Get present sink capabilities from Device Policy Manager |
| Send Capabilities message (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Sink Cap Message Setting */ |
| policy->tx_msg_header.word = pd_data->sink_msg_header.word; |
| policy->tx_msg_header.port_data_role = data_role; |
| policy->tx_data_obj[0].object = pd_data->sink_data_obj[0].object; |
| policy->tx_data_obj[1].object = pd_data->sink_data_obj[1].object; |
| |
| /* Clear Interrupt Status */ |
| pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC); |
| pd_data->phy_ops.get_status(pd_data, MSG_ERROR); |
| |
| /* Send Message */ |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DR_SRC_Give_Sink_Cap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { |
| dev_info(pd_data->dev, "got dr_src_give_sink_cap MSG_GOODCRC.\n"); |
| ret = PE_SRC_Ready; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| dev_info(pd_data->dev, "got dr_src_give_sink_cap MSG_ERROR.\n"); |
| ret = PE_SRC_Send_Soft_Reset; |
| break; |
| } |
| |
| if (ms >= 10) { |
| ret = PE_SRC_Ready; |
| dev_info(pd_data->dev, "got dr_src_give_sink_cap Timer1_overflag.\n"); |
| break; |
| } |
| } |
| |
| /* Sink Capabilities message sent */ |
| return ret; |
| } |
| |
| policy_state usbpd_policy_dr_snk_get_sink_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_DR_SNK_Get_Sink_Cap; |
| int data_role = 0; |
| int ms = 0; |
| |
| /********************************************** |
| get sink capabilities request from Device Policy Manager |
| |
| Actions on entry: |
| Send Get_Sink_Cap message |
| Initialize and run |
| SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Send Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, |
| USBPD_Get_Sink_Cap, data_role, USBPD_SINK); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) { |
| ret = PE_DR_SNK_Get_Sink_Cap; |
| break; |
| } |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_ERROR)) { |
| ret = PE_SNK_Send_Soft_Reset; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_SNK_CAP)) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| if (pd_data->phy_ops.get_status(pd_data, MSG_REJECT)) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| /* TimeOver Check */ |
| if (ms >= tSenderResponse) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| } |
| |
| /********************************************** |
| Actions on exit: |
| Pass sink capabilities/outcome to |
| Device Policy Manager |
| |
| Sink capabilities message received |
| | SenderResponseTimer Timeout | Reject message received |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_dr_snk_give_source_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_DR_SNK_Give_Source_Cap; |
| int data_role = 0; |
| int ms = 0; |
| /********************************************** |
| Actions on entry: |
| Request source capabilities from |
| Device Policy Manager |
| Send Capabilities message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Read Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* Message Setting */ |
| policy->tx_msg_header.msg_type = USBPD_Source_Capabilities; |
| policy->tx_msg_header.port_data_role = data_role; |
| policy->tx_msg_header.port_power_role = USBPD_SINK; |
| policy->tx_msg_header.num_data_objs = 1; |
| |
| policy->tx_data_obj[0].object = 0; |
| policy->tx_data_obj[0].power_data_obj.max_current = 500 / 10; |
| policy->tx_data_obj[0].power_data_obj.voltage = 5000 / 50; |
| policy->tx_data_obj[0].power_data_obj.peak_current = 0; |
| policy->tx_data_obj[0].power_data_obj.rsvd = 0; |
| policy->tx_data_obj[0].power_data_obj.unchunked_extended_message_supported = 0; |
| policy->tx_data_obj[0].power_data_obj.data_role_swap = 1; |
| policy->tx_data_obj[0].power_data_obj.usb_comm_capable = 1; |
| policy->tx_data_obj[0].power_data_obj.externally_powered = 0; |
| policy->tx_data_obj[0].power_data_obj.usb_suspend_support = 1; |
| policy->tx_data_obj[0].power_data_obj.dual_role_power = 1; |
| policy->tx_data_obj[0].power_data_obj.supply = 0; |
| |
| /* Send Message */ |
| usbpd_send_msg(pd_data, &policy->tx_msg_header, policy->tx_data_obj); |
| |
| /* Start Timer */ |
| usbpd_timer1_start(pd_data); |
| |
| /* Wait Message or State */ |
| while (1) { |
| if (policy->plug_valid == 0) |
| break; |
| ms = usbpd_check_time1(pd_data); |
| if (pd_data->phy_ops.get_status(pd_data, MSG_GOODCRC)) { |
| ret = PE_SNK_Ready; |
| break; |
| } |
| |
| if (ms >= 10) { |
| ret = PE_SNK_Send_Soft_Reset; |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_bist_carrier_mode(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_BIST_Carrier_Mode; |
| |
| /********************************************** |
| Actions on entry: |
| Consume Frame |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /********************************************** |
| Actions on exit: |
| Detach |
| or Hard Reset signaling received |
| **********************************************/ |
| |
| return ret; |
| |
| } |
| |
| policy_state usbpd_policy_src_send_not_supported(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Send_Not_Supported; |
| int data_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Not_Supported MessagePower |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Get Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* tChunkingNotSupported 40~50ms */ |
| if((pd_data->protocol_rx.msg_header.extended) |
| && (pd_data->protocol_rx.data_obj[0].extended_msg_header_type.chunked) |
| && (pd_data->protocol_rx.data_obj[0].extended_msg_header_type.data_size >= 26)) { |
| mdelay(30); |
| } |
| |
| /* Send Not_Supported Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Not_Supported, data_role, USBPD_SOURCE); |
| |
| ret = PE_SRC_Ready; |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_not_supported_received(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Not_Supported_Received; |
| |
| /********************************************** |
| Actions on entry: |
| Inform Device Policy Manager of Not_Supported Message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_chunk_received(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Chunk_Received; |
| |
| /********************************************** |
| Actions on entry: |
| Start ChunkingNotSupportedTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_send_not_supported(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Send_Not_Supported; |
| int data_role = 0; |
| |
| /********************************************** |
| Actions on entry: |
| Send Not_Supported Message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| //dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /* Get Data Role */ |
| pd_data->phy_ops.get_data_role(pd_data, &data_role); |
| |
| /* tChunkingNotSupported 40~50ms */ |
| if((pd_data->protocol_rx.msg_header.extended) |
| && (pd_data->protocol_rx.data_obj[0].extended_msg_header_type.chunked) |
| && (pd_data->protocol_rx.data_obj[0].extended_msg_header_type.data_size >= 26)) { |
| mdelay(30); |
| } |
| |
| /* Send Not_Supported Message */ |
| usbpd_send_ctrl_msg(pd_data, &policy->tx_msg_header, USBPD_Not_Supported, data_role, USBPD_SINK); |
| |
| ret = PE_SNK_Ready; |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_not_supported_received(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Not_Supported_Received; |
| |
| /********************************************** |
| Actions on entry: |
| Inform Device Policy Manager of Not_Supported Message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_chunk_received(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Chunk_Received; |
| |
| /********************************************** |
| Actions on entry: |
| Start ChunkingNotSupportedTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_send_source_alert(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Send_Source_Alert; |
| |
| /********************************************** |
| Actions on entry: |
| Send Alert Message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_source_alert_received(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Source_Alert_Received; |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of the detail of the alert |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_send_sink_alert(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Send_Sink_Alert; |
| |
| /********************************************** |
| Actions on entry: |
| Send Alert Message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_sink_alert_received(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Sink_Alert_Received; |
| |
| /********************************************** |
| Actions on entry: |
| Inform DPM of the detail of the alert |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_get_source_cap_ext(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Get_Source_Cap_Ext; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_Source_Cap_Extended MessageInitialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /********************************************** |
| Actions on exit: |
| Pass source extended capabilities/outcome to Device Policy Manager |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_give_source_cap_ext(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Give_Source_Cap_Ext; |
| |
| /********************************************** |
| Actions on entry: |
| Get present extended source capabilities |
| from Device Policy ManagerSend Source_Capabilities_Extended message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_get_source_status(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Get_Source_Status; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_Status MessageInitialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /********************************************** |
| Actions on exit: |
| Pass Source status/outcome to Device Policy Manager |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_give_source_status(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Give_Source_Status; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Source status from Device Policy ManagerSend Status message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_get_sink_status(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Get_Sink_Status; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_Status MessageInitialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /********************************************** |
| Actions on exit: |
| Pass Sink status/outcome to Device Policy Manager |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_give_sink_status(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Give_Sink_Status; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Sink status from Device Policy ManagerSend Status message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_snk_get_pps_status(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SNK_Get_PPS_Status; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_PPS_Status MessageInitialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /********************************************** |
| Actions on exit: |
| Pass Source status/outcome to Device Policy Manager |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_src_give_pps_status(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_SRC_Give_PPS_Status; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Source PPS status from Device Policy ManagerSend PPS_Status message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_get_battery_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Get_Battery_Cap; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_Battery_Cap MessageInitialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /********************************************** |
| Actions on exit: |
| Pass Battery capabilities/outcome to Device Policy Manager |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_give_battery_cap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Give_Battery_Cap; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Battery capabilities from Device Policy ManagerSend Battery_Capabilities Message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_get_battery_status(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Get_Battery_Status; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_Battery_Status MessageInitialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /********************************************** |
| Actions on exit: |
| Pass Battery status/outcome to Device Policy Manager |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_give_battery_status(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Give_Battery_Status; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Battery status from Device Policy ManagerSend Battery_Status Message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_get_manufacturer_info(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Get_Manufacturer_Info; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Manufacturer Information from Device Policy ManagerSend Manufacturer_Info Message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_give_manufacturer_info(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Give_Manufacturer_Info; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Manufacturer Information from Device Policy ManagerSend Manufacturer_Info Message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_get_country_codes(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Get_Country_Codes; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_Country_Codes MessageInitialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /********************************************** |
| Actions on exit: |
| Pass Country Codes/outcome to Device Policy Manager |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_give_country_codes(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Give_Country_Codes; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Country Codes from Device Policy ManagerSend Country_Codes Message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_get_country_info(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Get_Country_Info; |
| |
| /********************************************** |
| Actions on entry: |
| Send Get_Country_Info MessageInitialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| /********************************************** |
| Actions on exit: |
| Pass Country Information/outcome to Device Policy Manager |
| **********************************************/ |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_give_country_info(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Give_Country_Info; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Country Information from Device Policy ManagerSend Country_Info Message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_send_security_request(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Send_Security_Request; |
| |
| /********************************************** |
| Actions on entry: |
| Send Security_Request Message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_send_security_response(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Send_Security_Response; |
| |
| /********************************************** |
| Actions on entry: |
| Get present Security response from Device Policy ManagerSend Security_Response Message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_security_response_received(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Security_Response_Received; |
| |
| /********************************************** |
| Actions on entry: |
| Inform Device Policy Manager of the security response details. |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_send_firmware_update_request(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Send_Firmware_Update_Request; |
| |
| /********************************************** |
| Actions on entry: |
| Send Firmware_Update_Request Message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_send_firmware_update_response(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Send_Firmware_Update_Response; |
| |
| /********************************************** |
| Actions on entry: |
| Get present firmware update response from Device Policy ManagerSend Firmware_Update_Response Message |
| (based on Device Policy Manager response) |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_firmware_update_response_received(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_Firmware_Update_Response_Received; |
| |
| /********************************************** |
| Actions on entry: |
| Inform Device Policy Manager of the firmware update response details. |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_src_snk_evaluate_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SRC_SNK_Evaluate_Swap; |
| |
| /********************************************** |
| Actions on entry: |
| Ask Device Policy Manager if Fast Role Swap signaled on CC wire |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_src_snk_accept_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SRC_SNK_Accept_Swap; |
| |
| /********************************************** |
| Actions on entry: |
| Send Accept Message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_src_snk_transition_to_off(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SRC_SNK_Transition_to_off; |
| |
| /********************************************** |
| Actions on entry: |
| Wait for VBUS to reach vSafe5V |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_src_snk_assert_rd(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SRC_SNK_Assert_Rd; |
| |
| /********************************************** |
| Actions on entry: |
| Request DPM to assert Rd |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_src_snk_wait_source_on(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SRC_SNK_Wait_Source_on; |
| |
| /********************************************** |
| Actions on entry: |
| Send PS_RDY MessageInitialize and run PSSourceOnTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_snk_src_start_ams(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SNK_SRC_Start_AMS; |
| |
| /********************************************** |
| Actions on entry: |
| Notify the Protocol Layer that the first Message in the AMS will follow. |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_snk_src_send_swap(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SNK_SRC_Send_Swap; |
| |
| /********************************************** |
| Actions on entry: |
| Send FR_Swap messageInitialize and run SenderResponseTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_snk_src_transition_to_off(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SNK_SRC_Transition_to_off; |
| |
| /********************************************** |
| Actions on entry: |
| Initialize and run PSSourceOffTimer |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_snk_src_vbus_applied(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SNK_SRC_Vbus_Applied; |
| |
| /********************************************** |
| Actions on entry: |
| Request Device Policy Manager to notify when vSafe5v is being applied by the local power source. |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_snk_src_assert_rp(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SNK_SRC_Assert_Rp; |
| |
| /********************************************** |
| Actions on entry: |
| Request DPM to assert Rp |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_policy_frs_snk_src_source_on(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| int ret = PE_FRS_SNK_SRC_Source_on; |
| |
| /********************************************** |
| Actions on entry: |
| Send PS_RDY Message |
| **********************************************/ |
| |
| /* PD State Inform to AP */ |
| dev_info(pd_data->dev, "%s\n", __func__); |
| |
| return ret; |
| } |
| |
| policy_state usbpd_error_recovery(struct policy_data *policy) |
| { |
| struct usbpd_data *pd_data = policy_to_usbpd(policy); |
| |
| /********************************************** |
| **********************************************/ |
| |
| dev_err(pd_data->dev, "%s\n", __func__); |
| |
| return Error_Recovery; |
| } |
| |
| void usbpd_policy_work(struct work_struct *work) |
| { |
| struct usbpd_data *pd_data = container_of(work, struct usbpd_data, |
| worker); |
| struct policy_data *policy = &pd_data->policy; |
| int power_role = 0; |
| policy_state next_state = policy->state; |
| policy_state saved_state; |
| |
| do { |
| if (!policy->plug_valid) { |
| pr_info("%s : usbpd cable is empty\n", __func__); |
| break; |
| } |
| |
| if (policy->rx_hardreset || policy->rx_softreset |
| || policy->plug) { |
| saved_state = 0; |
| next_state = 0; /* default */ |
| } |
| saved_state = next_state; |
| switch (next_state) { |
| case PE_SRC_Startup: |
| next_state = usbpd_policy_src_startup(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SRC_Discovery: |
| next_state = usbpd_policy_src_discovery(policy); |
| break; |
| case PE_SRC_Send_Capabilities: |
| next_state = usbpd_policy_src_send_capabilities(policy); |
| break; |
| case PE_SRC_Negotiate_Capability: |
| next_state = usbpd_policy_src_negotiate_capability(policy); |
| break; |
| case PE_SRC_Transition_Supply: |
| next_state = usbpd_policy_src_transition_supply(policy); |
| break; |
| case PE_SRC_Ready: |
| next_state = usbpd_policy_src_ready(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SRC_Disabled: |
| next_state = usbpd_policy_src_disabled(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SRC_Capability_Response: |
| next_state = usbpd_policy_src_capability_response(policy); |
| break; |
| case PE_SRC_Hard_Reset: |
| next_state = usbpd_policy_src_hard_reset(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SRC_Hard_Reset_Received: |
| next_state = usbpd_policy_src_hard_reset_received(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SRC_Transition_to_default: |
| next_state = usbpd_policy_src_transition_to_default(policy); |
| break; |
| case PE_SRC_Give_Source_Cap: |
| next_state = usbpd_policy_src_give_source_cap(policy); |
| break; |
| case PE_SRC_Get_Sink_Cap: |
| next_state = usbpd_policy_src_get_sink_cap(policy); |
| break; |
| case PE_SRC_Wait_New_Capabilities: |
| next_state = usbpd_policy_src_wait_new_capabilities(policy); |
| break; |
| case PE_SRC_Send_Soft_Reset: |
| next_state = usbpd_policy_src_send_soft_reset(policy); |
| break; |
| case PE_SRC_Soft_Reset: |
| next_state = usbpd_policy_src_soft_reset(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| |
| case PE_SNK_Startup: |
| next_state = usbpd_policy_snk_startup(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SNK_Discovery: |
| next_state = usbpd_policy_snk_discovery(policy); |
| break; |
| case PE_SNK_Wait_for_Capabilities: |
| next_state = usbpd_policy_snk_wait_for_capabilities(policy); |
| break; |
| case PE_SNK_Evaluate_Capability: |
| next_state = usbpd_policy_snk_evaluate_capability(policy); |
| break; |
| case PE_SNK_Select_Capability: |
| next_state = usbpd_policy_snk_select_capability(policy); |
| break; |
| case PE_SNK_Transition_Sink: |
| next_state = usbpd_policy_snk_transition_sink(policy); |
| break; |
| case PE_SNK_Ready: |
| next_state = usbpd_policy_snk_ready(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SNK_Hard_Reset: |
| next_state = usbpd_policy_snk_hard_reset(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SNK_Transition_to_default: |
| next_state = usbpd_policy_snk_transition_to_default(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SNK_Give_Sink_Cap: |
| next_state = usbpd_policy_snk_give_sink_cap(policy); |
| break; |
| case PE_SNK_Get_Source_Cap: |
| next_state = usbpd_policy_snk_get_source_cap(policy); |
| break; |
| case PE_SNK_Send_Soft_Reset: |
| next_state = usbpd_policy_snk_send_soft_reset(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_SNK_Soft_Reset: |
| next_state = usbpd_policy_snk_soft_reset(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_DRS_Evaluate_Port: |
| next_state = usbpd_policy_drs_evaluate_port(policy); |
| break; |
| case PE_DRS_Evaluate_Send_Port: |
| next_state = usbpd_policy_drs_evaluate_send_port(policy); |
| break; |
| case PE_DRS_DFP_UFP_Evaluate_DR_Swap: |
| next_state = usbpd_policy_drs_dfp_ufp_evaluate_dr_swap(policy); |
| break; |
| case PE_DRS_DFP_UFP_Accept_DR_Swap: |
| next_state = usbpd_policy_drs_dfp_ufp_accept_dr_swap(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_DRS_DFP_UFP_Change_to_UFP: |
| next_state = usbpd_policy_drs_dfp_ufp_change_to_ufp(policy); |
| break; |
| case PE_DRS_DFP_UFP_Send_DR_Swap: |
| next_state = usbpd_policy_drs_dfp_ufp_send_dr_swap(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_DRS_DFP_UFP_Reject_DR_Swap: |
| next_state = usbpd_policy_drs_dfp_ufp_reject_dr_swap(policy); |
| break; |
| case PE_DRS_UFP_DFP_Evaluate_DR_Swap: |
| next_state = usbpd_policy_drs_ufp_dfp_evaluate_dr_swap(policy); |
| break; |
| case PE_DRS_UFP_DFP_Accept_DR_Swap: |
| next_state = usbpd_policy_drs_ufp_dfp_accept_dr_swap(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_DRS_UFP_DFP_Change_to_DFP: |
| next_state = usbpd_policy_drs_ufp_dfp_change_to_dfp(policy); |
| break; |
| case PE_DRS_UFP_DFP_Send_DR_Swap: |
| next_state = usbpd_policy_drs_ufp_dfp_send_dr_swap(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_DRS_UFP_DFP_Reject_DR_Swap: |
| next_state = usbpd_policy_drs_ufp_dfp_reject_dr_swap(policy); |
| break; |
| |
| case PE_PRS_SRC_SNK_Reject_PR_Swap: |
| next_state = usbpd_policy_prs_src_snk_reject_pr_swap(policy); |
| break; |
| case PE_PRS_SRC_SNK_Evaluate_Swap: |
| next_state = usbpd_policy_prs_src_snk_evaluate_swap(policy); |
| break; |
| case PE_PRS_SRC_SNK_Send_Swap: |
| next_state = usbpd_policy_prs_src_snk_send_swap(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_PRS_SRC_SNK_Accept_Swap: |
| next_state = usbpd_policy_prs_src_snk_accept_swap(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_PRS_SRC_SNK_Transition_off: |
| next_state = usbpd_policy_prs_src_snk_transition_to_off(policy); |
| break; |
| case PE_PRS_SRC_SNK_Assert_Rd: |
| next_state = usbpd_policy_prs_src_snk_assert_rd(policy); |
| break; |
| case PE_PRS_SRC_SNK_Wait_Source_on: |
| next_state = usbpd_policy_prs_src_snk_wait_source_on(policy); |
| break; |
| case PE_PRS_SNK_SRC_Reject_Swap: |
| next_state = usbpd_policy_prs_snk_src_reject_swap(policy); |
| break; |
| case PE_PRS_SNK_SRC_Evaluate_Swap: |
| next_state = usbpd_policy_prs_snk_src_evaluate_swap(policy); |
| break; |
| case PE_PRS_SNK_SRC_Send_Swap: |
| next_state = usbpd_policy_prs_snk_src_send_swap(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_PRS_SNK_SRC_Accept_Swap: |
| next_state = usbpd_policy_prs_snk_src_accept_swap(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| case PE_PRS_SNK_SRC_Transition_off: |
| next_state = usbpd_policy_prs_snk_src_transition_to_off(policy); |
| break; |
| case PE_PRS_SNK_SRC_Assert_Rp: |
| next_state = usbpd_policy_prs_snk_src_assert_rp(policy); |
| break; |
| case PE_PRS_SNK_SRC_Source_on: |
| next_state = usbpd_policy_prs_snk_src_source_on(policy); |
| break; |
| case PE_VCS_Evaluate_Swap: |
| next_state = usbpd_policy_vcs_evaluate_swap(policy); |
| break; |
| case PE_VCS_Accept_Swap: |
| next_state = usbpd_policy_vcs_accept_swap(policy); |
| break; |
| case PE_VCS_Wait_for_VCONN: |
| next_state = usbpd_policy_vcs_wait_for_vconn(policy); |
| break; |
| case PE_VCS_Turn_Off_VCONN: |
| next_state = usbpd_policy_vcs_turn_off_vconn(policy); |
| break; |
| case PE_VCS_Turn_On_VCONN: |
| next_state = usbpd_policy_vcs_turn_on_vconn(policy); |
| break; |
| case PE_VCS_Send_PS_RDY: |
| next_state = usbpd_policy_vcs_send_ps_rdy(policy); |
| break; |
| case PE_VCS_Send_Swap: |
| next_state = usbpd_policy_vcs_send_swap(policy); |
| break; |
| case PE_VCS_Reject_VCONN_Swap: |
| next_state = usbpd_policy_vcs_reject_vconn_swap(policy); |
| break; |
| |
| case PE_UFP_VDM_Get_Identity: |
| next_state = usbpd_policy_ufp_vdm_get_identity(policy); |
| break; |
| case PE_UFP_VDM_Send_Identity: |
| next_state = usbpd_policy_ufp_vdm_send_identity(policy); |
| break; |
| case PE_UFP_VDM_Get_Identity_NAK: |
| next_state = usbpd_policy_ufp_vdm_get_identity_nak(policy); |
| break; |
| case PE_UFP_VDM_Get_SVIDs: |
| next_state = usbpd_policy_ufp_vdm_get_svids(policy); |
| break; |
| case PE_UFP_VDM_Send_SVIDs: |
| next_state = usbpd_policy_ufp_vdm_send_svids(policy); |
| break; |
| case PE_UFP_VDM_Get_SVIDs_NAK: |
| next_state = usbpd_policy_ufp_vdm_get_svids_nak(policy); |
| break; |
| case PE_UFP_VDM_Get_Modes: |
| next_state = usbpd_policy_ufp_vdm_get_modes(policy); |
| break; |
| case PE_UFP_VDM_Send_Modes: |
| next_state = usbpd_policy_ufp_vdm_send_modes(policy); |
| break; |
| case PE_UFP_VDM_Get_Modes_NAK: |
| next_state = usbpd_policy_ufp_vdm_get_modes_nak(policy); |
| break; |
| case PE_UFP_VDM_Evaluate_Mode_Entry: |
| next_state = usbpd_policy_ufp_vdm_evaluate_mode_entry(policy); |
| break; |
| case PE_UFP_VDM_Mode_Entry_ACK: |
| next_state = usbpd_policy_ufp_vdm_mode_entry_ack(policy); |
| break; |
| case PE_UFP_VDM_Mode_Entry_NAK: |
| next_state = usbpd_policy_ufp_vdm_mode_entry_nak(policy); |
| break; |
| case PE_UFP_VDM_Mode_Exit: |
| next_state = usbpd_policy_ufp_vdm_mode_exit(policy); |
| break; |
| case PE_UFP_VDM_Mode_Exit_ACK: |
| next_state = usbpd_policy_ufp_vdm_mode_exit_ack(policy); |
| break; |
| case PE_UFP_VDM_Mode_Exit_NAK: |
| next_state = usbpd_policy_ufp_vdm_mode_exit_nak(policy); |
| break; |
| case PE_UFP_VDM_Attention_Request: |
| next_state = usbpd_policy_ufp_vdm_attention_request(policy); |
| break; |
| case PE_UFP_VDM_Evaluate_Status: |
| next_state = usbpd_policy_ufp_vdm_evaluate_status(policy); |
| break; |
| case PE_UFP_VDM_Status_ACK: |
| next_state = usbpd_policy_ufp_vdm_status_ack(policy); |
| break; |
| case PE_UFP_VDM_Status_NAK: |
| next_state = usbpd_policy_ufp_vdm_status_nak(policy); |
| break; |
| case PE_UFP_VDM_Evaluate_Configure: |
| next_state = usbpd_policy_ufp_vdm_evaluate_configure(policy); |
| break; |
| case PE_UFP_VDM_Configure_ACK: |
| next_state = usbpd_policy_ufp_vdm_configure_ack(policy); |
| break; |
| case PE_UFP_VDM_Configure_NAK: |
| next_state = usbpd_policy_ufp_vdm_configure_nak(policy); |
| break; |
| case PE_DFP_VDM_Identity_Request: |
| next_state = usbpd_policy_dfp_vdm_identity_request(policy); |
| break; |
| case PE_DFP_VDM_Identity_ACKed: |
| next_state = usbpd_policy_dfp_vdm_identity_acked(policy); |
| break; |
| case PE_DFP_VDM_Identity_NAKed: |
| next_state = usbpd_policy_dfp_vdm_identity_naked(policy); |
| break; |
| case PE_DFP_VDM_SVIDs_Request: |
| next_state = usbpd_policy_dfp_vdm_svids_request(policy); |
| break; |
| case PE_DFP_VDM_SVIDs_ACKed: |
| next_state = usbpd_policy_dfp_vdm_svids_acked(policy); |
| break; |
| case PE_DFP_VDM_SVIDs_NAKed: |
| next_state = usbpd_policy_dfp_vdm_svids_naked(policy); |
| break; |
| case PE_DFP_VDM_Modes_Request: |
| next_state = usbpd_policy_dfp_vdm_modes_request(policy); |
| break; |
| case PE_DFP_VDM_Modes_ACKed: |
| next_state = usbpd_policy_dfp_vdm_modes_acked(policy); |
| break; |
| case PE_DFP_VDM_Modes_NAKed: |
| next_state = usbpd_policy_dfp_vdm_modes_naked(policy); |
| break; |
| case PE_DFP_VDM_Mode_Entry_Request: |
| next_state = usbpd_policy_dfp_vdm_entry_request(policy); |
| break; |
| case PE_DFP_VDM_Mode_Entry_ACKed: |
| next_state = usbpd_policy_dfp_vdm_entry_acked(policy); |
| break; |
| case PE_DFP_VDM_Mode_Entry_NAKed: |
| next_state = usbpd_policy_dfp_vdm_entry_naked(policy); |
| break; |
| case PE_DFP_VDM_Mode_Exit_Request: |
| next_state = usbpd_policy_dfp_vdm_exit_request(policy); |
| break; |
| case PE_DFP_VDM_Mode_Exit_ACKed: |
| next_state = usbpd_policy_dfp_vdm_exit_acked(policy); |
| break; |
| case PE_DFP_VDM_Mode_Exit_NAKed: |
| next_state = usbpd_policy_dfp_vdm_exit_naked(policy); |
| break; |
| case PE_DFP_VDM_Attention_Request: |
| next_state = usbpd_policy_dfp_vdm_attention_request(policy); |
| break; |
| case PE_DFP_VDM_Status_Update: |
| next_state = usbpd_policy_dfp_vdm_status_update(policy); |
| break; |
| case PE_DFP_VDM_Status_Update_ACKed: |
| next_state = usbpd_policy_dfp_vdm_status_update_acked(policy); |
| break; |
| case PE_DFP_VDM_Status_Update_NAKed: |
| next_state = usbpd_policy_dfp_vdm_status_update_naked(policy); |
| break; |
| case PE_DFP_VDM_DisplayPort_Configure: |
| next_state = usbpd_policy_dfp_vdm_displayport_configure(policy); |
| break; |
| case PE_DFP_VDM_DisplayPort_Configure_ACKed: |
| next_state = usbpd_policy_dfp_vdm_displayport_configure_acked(policy); |
| break; |
| case PE_DFP_VDM_DisplayPort_Configure_NAKed: |
| next_state = usbpd_policy_dfp_vdm_displayport_configure_naked(policy); |
| break; |
| case PE_DFP_UVDM_Send_Message: |
| next_state = usbpd_policy_dfp_uvdm_send_message(policy); |
| break; |
| case PE_DFP_UVDM_Receive_Message: |
| next_state = usbpd_policy_dfp_uvdm_receive_message(policy); |
| break; |
| case PE_DR_SRC_Get_Source_Cap: |
| next_state = usbpd_policy_dr_src_get_source_cap(policy); |
| break; |
| case PE_DR_SRC_Give_Sink_Cap: |
| next_state = usbpd_policy_dr_src_give_sink_cap(policy); |
| break; |
| case PE_DR_SNK_Get_Sink_Cap: |
| next_state = usbpd_policy_dr_snk_get_sink_cap(policy); |
| break; |
| case PE_DR_SNK_Give_Source_Cap: |
| next_state = usbpd_policy_dr_snk_give_source_cap(policy); |
| break; |
| case PE_BIST_Carrier_Mode: |
| next_state = usbpd_policy_bist_carrier_mode(policy); |
| break; |
| |
| /* PD 3.0 */ |
| case PE_SRC_Send_Not_Supported: |
| next_state = usbpd_policy_src_send_not_supported(policy); |
| break; |
| case PE_SRC_Not_Supported_Received: |
| next_state = usbpd_policy_src_not_supported_received(policy); |
| break; |
| case PE_SRC_Chunk_Received: |
| next_state = usbpd_policy_src_chunk_received(policy); |
| break; |
| |
| case PE_SNK_Send_Not_Supported: |
| next_state = usbpd_policy_snk_send_not_supported(policy); |
| break; |
| case PE_SNK_Not_Supported_Received: |
| next_state = usbpd_policy_snk_not_supported_received(policy); |
| break; |
| case PE_SNK_Chunk_Received : |
| next_state = usbpd_policy_snk_chunk_received(policy); |
| break; |
| |
| case PE_SRC_Send_Source_Alert: |
| next_state = usbpd_policy_src_send_source_alert(policy); |
| break; |
| case PE_SNK_Source_Alert_Received: |
| next_state = usbpd_policy_snk_source_alert_received(policy); |
| break; |
| case PE_SNK_Send_Sink_Alert: |
| next_state = usbpd_policy_snk_send_sink_alert(policy); |
| break; |
| case PE_SRC_Sink_Alert_Received: |
| next_state = usbpd_policy_src_sink_alert_received(policy); |
| break; |
| |
| case PE_SNK_Get_Source_Cap_Ext: |
| next_state = usbpd_policy_snk_get_source_cap_ext(policy); |
| break; |
| case PE_SRC_Give_Source_Cap_Ext: |
| next_state = usbpd_policy_src_give_source_cap_ext(policy); |
| break; |
| case PE_SNK_Get_Source_Status: |
| next_state = usbpd_policy_snk_get_source_status(policy); |
| break; |
| case PE_SRC_Give_Source_Status: |
| next_state = usbpd_policy_src_give_source_status(policy); |
| break; |
| case PE_SRC_Get_Sink_Status: |
| next_state = usbpd_policy_src_get_sink_status(policy); |
| break; |
| case PE_SNK_Give_Sink_Status: |
| next_state = usbpd_policy_snk_give_sink_status(policy); |
| break; |
| case PE_SNK_Get_PPS_Status: |
| next_state = usbpd_policy_snk_get_pps_status(policy); |
| break; |
| case PE_SRC_Give_PPS_Status: |
| next_state = usbpd_policy_src_give_pps_status(policy); |
| break; |
| case PE_Get_Battery_Cap: |
| next_state = usbpd_policy_get_battery_cap(policy); |
| break; |
| case PE_Give_Battery_Cap: |
| next_state = usbpd_policy_give_battery_cap(policy); |
| break; |
| case PE_Get_Battery_Status: |
| next_state = usbpd_policy_get_battery_status(policy); |
| break; |
| case PE_Give_Battery_Status: |
| next_state = usbpd_policy_give_battery_status(policy); |
| break; |
| case PE_Get_Manufacturer_Info: |
| next_state = usbpd_policy_get_manufacturer_info(policy); |
| break; |
| case PE_Give_Manufacturer_Info: |
| next_state = usbpd_policy_give_manufacturer_info(policy); |
| break; |
| case PE_Get_Country_Codes: |
| next_state = usbpd_policy_get_country_codes(policy); |
| break; |
| case PE_Give_Country_Codes: |
| next_state = usbpd_policy_give_country_codes(policy); |
| break; |
| case PE_Get_Country_Info: |
| next_state = usbpd_policy_get_country_info(policy); |
| break; |
| case PE_Give_Country_Info: |
| next_state = usbpd_policy_give_country_info(policy); |
| break; |
| case PE_Send_Security_Request: |
| next_state = usbpd_policy_send_security_request(policy); |
| break; |
| case PE_Send_Security_Response: |
| next_state = usbpd_policy_send_security_response(policy); |
| break; |
| case PE_Security_Response_Received: |
| next_state = usbpd_policy_security_response_received(policy); |
| break; |
| case PE_Send_Firmware_Update_Request: |
| next_state = usbpd_policy_send_firmware_update_request(policy); |
| break; |
| case PE_Send_Firmware_Update_Response: |
| next_state = usbpd_policy_send_firmware_update_response(policy); |
| break; |
| case PE_Firmware_Update_Response_Received: |
| next_state = usbpd_policy_firmware_update_response_received(policy); |
| break; |
| case PE_FRS_SRC_SNK_Evaluate_Swap: |
| next_state = usbpd_policy_frs_src_snk_evaluate_swap(policy); |
| break; |
| case PE_FRS_SRC_SNK_Accept_Swap: |
| next_state = usbpd_policy_frs_src_snk_accept_swap(policy); |
| break; |
| case PE_FRS_SRC_SNK_Transition_to_off: |
| next_state = usbpd_policy_frs_src_snk_transition_to_off(policy); |
| break; |
| case PE_FRS_SRC_SNK_Assert_Rd: |
| next_state = usbpd_policy_frs_src_snk_assert_rd(policy); |
| break; |
| case PE_FRS_SRC_SNK_Wait_Source_on: |
| next_state = usbpd_policy_frs_src_snk_wait_source_on(policy); |
| break; |
| case PE_FRS_SNK_SRC_Start_AMS: |
| next_state = usbpd_policy_frs_snk_src_start_ams(policy); |
| break; |
| case PE_FRS_SNK_SRC_Send_Swap: |
| next_state = usbpd_policy_frs_snk_src_send_swap(policy); |
| break; |
| case PE_FRS_SNK_SRC_Transition_to_off: |
| next_state = usbpd_policy_frs_snk_src_transition_to_off(policy); |
| break; |
| case PE_FRS_SNK_SRC_Vbus_Applied: |
| next_state = usbpd_policy_frs_snk_src_vbus_applied(policy); |
| break; |
| case PE_FRS_SNK_SRC_Assert_Rp: |
| next_state = usbpd_policy_frs_snk_src_assert_rp(policy); |
| break; |
| case PE_FRS_SNK_SRC_Source_on: |
| next_state = usbpd_policy_frs_snk_src_source_on(policy); |
| break; |
| |
| case Error_Recovery: |
| next_state = usbpd_error_recovery(policy); |
| store_usblog_notify(NOTIFY_FUNCSTATE, (void *)&next_state, NULL); |
| break; |
| |
| default: |
| pd_data->phy_ops.get_power_role(pd_data, &power_role); |
| pr_info("%s, %d\n", __func__, power_role); |
| |
| if (power_role == USBPD_SINK) { |
| pr_info("%s, SINK\n", __func__); |
| if (policy->rx_hardreset) { |
| policy->rx_hardreset = 0; |
| next_state = PE_SNK_Transition_to_default; |
| } else if (policy->rx_softreset) { |
| policy->rx_softreset = 0; |
| next_state = PE_SNK_Soft_Reset; |
| } else if (policy->plug) { |
| policy->plug = 0; |
| next_state = PE_SNK_Startup; |
| } else { |
| next_state = PE_SNK_Startup; |
| } |
| } else { |
| pr_info("%s, SOURCE\n", __func__); |
| if (policy->rx_hardreset) { |
| policy->rx_hardreset = 0; |
| next_state = PE_SRC_Hard_Reset_Received; |
| } else if (policy->rx_softreset) { |
| policy->rx_softreset = 0; |
| next_state = PE_SRC_Soft_Reset; |
| } else if (policy->plug) { |
| policy->plug = 0; |
| next_state = PE_SRC_Startup; |
| } else { |
| next_state = PE_SRC_Startup; |
| } |
| } |
| |
| break; |
| } |
| dev_info(pd_data->dev, "%s saved state %x next_state %x \n", __func__, saved_state, next_state); |
| } while (saved_state != next_state); |
| |
| #if defined CONFIG_CCIC_S2MU004 |
| if (pd_data->is_prswap) |
| pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP); |
| #endif |
| |
| policy->state = next_state; |
| dev_info(pd_data->dev, "%s Finished\n", __func__); |
| } |
| |
| void usbpd_init_policy(struct usbpd_data *pd_data) |
| { |
| int i; |
| struct policy_data *policy = &pd_data->policy; |
| |
| policy->state = 0; |
| policy->rx_hardreset = 0; |
| policy->rx_softreset = 0; |
| policy->plug = 0; |
| policy->rx_msg_header.word = 0; |
| policy->tx_msg_header.word = 0; |
| policy->modal_operation = 0; |
| policy->sink_cap_received = 0; |
| policy->send_sink_cap = 0; |
| policy->txhardresetflag = 0; |
| policy->pd_support = 0; |
| policy->otgnotify_sent = 0; |
| #if defined(CONFIG_PDIC_PD30) |
| pd_data->specification_revision = USBPD_PD3_0; |
| #else |
| pd_data->specification_revision = USBPD_PD2_0; |
| #endif |
| |
| for (i = 0; i < USBPD_MAX_COUNT_MSG_OBJECT; i++) { |
| policy->rx_data_obj[i].object = 0; |
| policy->tx_data_obj[i].object = 0; |
| } |
| } |
| |
| void usbpd_kick_policy_work(struct device *dev) |
| { |
| struct usbpd_data *pd_data = dev_get_drvdata(dev); |
| |
| if (pd_data->policy_wqueue) |
| queue_work(pd_data->policy_wqueue, &pd_data->worker); |
| else |
| schedule_work(&pd_data->worker); |
| } |
| |
| void usbpd_cancel_policy_work(struct device *dev) |
| { |
| struct usbpd_data *pd_data = dev_get_drvdata(dev); |
| |
| if (pd_data->policy_wqueue) |
| flush_workqueue(pd_data->policy_wqueue); |
| } |
| |