From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751544AbeABPvE (ORCPT + 1 other); Tue, 2 Jan 2018 10:51:04 -0500 Received: from mail1.bemta6.messagelabs.com ([193.109.254.111]:17732 "EHLO mail1.bemta6.messagelabs.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751459AbeABPu7 (ORCPT ); Tue, 2 Jan 2018 10:50:59 -0500 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprAKsWRWlGSWpSXmKPExsUSt3OpsW7CKu8 og2WPBSyaF69ns3hzfDqTRdfqnSwWl3fNYbP43HuE0WLRslZmiycLzzBZNC54z2JxeneJxZ/n t9gcuDx2zrrL7rFpVSebx7yTgR77565h93i/7yqbx87vDewenzfJBbBHsWbmJeVXJLBmtD/hK FhiVfH8xGnGBsZ2wy5GLg4hgXWMEj1XNzF3MXICORUSs49tY+ti5ODgFciUaNipBGJyCrhLbP 3EDGIKCbhJzHpbB1LMJmAhMfnEAzYQm0VARWLNpU4WkBJhAT+Jp58cQYaLCMxjkni14S5YDbN AnUTv77csIDavgKDEyZlPWCDiEhIHX7yAOsBA4vSCRrC4hIC9xPT3V8HWSgjoSzQei4UIG0p8 n/UNqsRcYsftG6wTGAVnIZk6C8nUBYxMqxjVi1OLylKLdC30kooy0zNKchMzc3QNDcz0clOLi xPTU3MSk4r1kvNzNzECY4QBCHYwzr7sf4hRkoNJSZQ3J9U7SogvKT+lMiOxOCO+qDQntfgQow YHh0DLxZMHmaRY8vLzUpUkeMVWAtUJFqWmp1akZeYAoximVIKDR0mE990KoDRvcUFibnFmOkT qFKMux7OZrxuYhcBmSInz8oDMEAApyijNgxsBSyiXGGWlhHkZgQ4U4ilILcrNLEGVf8UozsGo JMy7DWQVT2ZeCdymV0BHMAEd8ee8J8gRJYkIKakGxrjyk9u+6DSL8x/eWbbF7rdE5Zr+X2WlM 7sPSu260REVoy7e7GqeqcV5XchMU23y2usPuI1MFy9+ZVPDJO2yS8NIp2Hn7/lX7/k3Kz77vG +L6N91/N8CDT/lOq+0utA0rzZhyaGwJw9PWr9YbdZeOu+g3toHUj02Zy6y/OgsmO9x5OfFg1O iOJVYijMSDbWYi4oTAZ6RAPUjAwAA X-Env-Sender: Adam.Thomson.Opensource@diasemi.com X-Msg-Ref: server-15.tower-193.messagelabs.com!1514908256!117673836!1 X-Originating-IP: [94.185.165.51] X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Message-ID: In-Reply-To: References: From: Adam Thomson Date: Tue, 2 Jan 2018 15:50:55 +0000 Subject: [PATCH v4 7/7] typec: tcpm: Add support for sink PPS related messages To: Heikki Krogerus , Guenter Roeck , Greg Kroah-Hartman , Sebastian Reichel , Hans de Goede , Yueyao Zhu , Rui Miguel Silva CC: , , , MIME-Version: 1.0 Content-Type: text/plain X-KSE-AttachmentFiltering-Interceptor-Info: protection disabled X-KSE-ServerInfo: sw-ex-cashub01.diasemi.com, 9 X-KSE-Antivirus-Interceptor-Info: scan successful X-KSE-Antivirus-Info: Clean, bases: 02/01/2018 11:56:00 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: This commit adds sink side support for Get_Status, Status, Get_PPS_Status and PPS_Status handling. As there's the potential for a partner to respond with Not_Supported handling of this message is also added. Sending of Not_Supported is added is added to handle messages received but not yet handled. Signed-off-by: Adam Thomson --- drivers/usb/typec/tcpm.c | 152 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 143 insertions(+), 9 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index b86a51c..54d17d7 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -113,6 +115,11 @@ S(SNK_TRYWAIT_VBUS), \ S(BIST_RX), \ \ + S(GET_STATUS_SEND), \ + S(GET_STATUS_SEND_TIMEOUT), \ + S(GET_PPS_STATUS_SEND), \ + S(GET_PPS_STATUS_SEND_TIMEOUT), \ + \ S(ERROR_RECOVERY), \ S(PORT_RESET), \ S(PORT_RESET_WAIT_OFF) @@ -143,6 +150,7 @@ enum pd_msg_request { PD_MSG_NONE = 0, PD_MSG_CTRL_REJECT, PD_MSG_CTRL_WAIT, + PD_MSG_CTRL_NOT_SUPP, PD_MSG_DATA_SINK_CAP, PD_MSG_DATA_SOURCE_CAP, }; @@ -1413,10 +1421,42 @@ static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo, /* * PD (data, control) command handling functions */ +static inline enum tcpm_state ready_state(struct tcpm_port *port) +{ + if (port->pwr_role == TYPEC_SOURCE) + return SRC_READY; + else + return SNK_READY; +} static int tcpm_pd_send_control(struct tcpm_port *port, enum pd_ctrl_msg_type type); +static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, + int cnt) +{ + u32 p0 = le32_to_cpu(payload[0]); + unsigned int type = usb_pd_ado_type(p0); + + if (!type) { + tcpm_log(port, "Alert message received with no type"); + return; + } + + /* Just handling non-battery alerts for now */ + if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) { + switch (port->state) { + case SRC_READY: + case SNK_READY: + tcpm_set_state(port, GET_STATUS_SEND, 0); + break; + default: + tcpm_queue_message(port, PD_MSG_CTRL_WAIT); + break; + } + } +} + static void tcpm_pd_data_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1502,6 +1542,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port, tcpm_set_state(port, BIST_RX, 0); } break; + case PD_DATA_ALERT: + tcpm_handle_alert(port, msg->payload, cnt); + break; + case PD_DATA_BATT_STATUS: + case PD_DATA_GET_COUNTRY_INFO: + /* Currently unsupported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled data message type %#x", type); break; @@ -1584,6 +1632,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; case PD_CTRL_REJECT: case PD_CTRL_WAIT: + case PD_CTRL_NOT_SUPP: switch (port->state) { case SNK_NEGOTIATE_CAPABILITIES: /* USB PD specification, Figure 8-43 */ @@ -1703,12 +1752,84 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; } break; + case PD_CTRL_GET_SOURCE_CAP_EXT: + case PD_CTRL_GET_STATUS: + case PD_CTRL_FR_SWAP: + case PD_CTRL_GET_PPS_STATUS: + case PD_CTRL_GET_COUNTRY_CODES: + /* Currently not supported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled ctrl message type %#x", type); break; } } +static void tcpm_pd_ext_msg_request(struct tcpm_port *port, + const struct pd_message *msg) +{ + enum pd_ext_msg_type type = pd_header_type_le(msg->header); + unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); + u8 *data; + + if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) { + tcpm_log(port, "Unchunked extended messages unsupported"); + return; + } + + if (data_size > (PD_EXT_MAX_CHUNK_DATA)) { + tcpm_log(port, "Chunk handling not yet supported"); + return; + } + + data = kzalloc(data_size, GFP_KERNEL); + if (!data) { + tcpm_log(port, "Failed to allocate memory for ext msg data"); + return; + } + memcpy(data, msg->ext_msg.data, data_size); + + switch (type) { + case PD_EXT_STATUS: + /* + * If PPS related events raised then get PPS status to clear + * (see USB PD 3.0 Spec, 6.5.2.4) + */ + if (data[USB_PD_EXT_SDB_EVENT_FLAGS] & USB_PD_EXT_SDB_PPS_EVENTS) + tcpm_set_state(port, GET_PPS_STATUS_SEND, 0); + else + tcpm_set_state(port, ready_state(port), 0); + break; + case PD_EXT_PPS_STATUS: + /* + * For now the PPS status message is used to clear events + * and nothing more. + */ + tcpm_set_state(port, ready_state(port), 0); + break; + case PD_EXT_SOURCE_CAP_EXT: + case PD_EXT_GET_BATT_CAP: + case PD_EXT_GET_BATT_STATUS: + case PD_EXT_BATT_CAP: + case PD_EXT_GET_MANUFACTURER_INFO: + case PD_EXT_MANUFACTURER_INFO: + case PD_EXT_SECURITY_REQUEST: + case PD_EXT_SECURITY_RESPONSE: + case PD_EXT_FW_UPDATE_REQUEST: + case PD_EXT_FW_UPDATE_RESPONSE: + case PD_EXT_COUNTRY_INFO: + case PD_EXT_COUNTRY_CODES: + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; + default: + tcpm_log(port, "Unhandle extended message type %#x", type); + break; + } + + kfree(data); +} + static void tcpm_pd_rx_handler(struct work_struct *work) { struct pd_rx_event *event = container_of(work, @@ -1749,7 +1870,9 @@ static void tcpm_pd_rx_handler(struct work_struct *work) "Data role mismatch, initiating error recovery"); tcpm_set_state(port, ERROR_RECOVERY, 0); } else { - if (cnt) + if (msg->header & PD_HEADER_EXT_HDR) + tcpm_pd_ext_msg_request(port, msg); + else if (cnt) tcpm_pd_data_request(port, msg); else tcpm_pd_ctrl_request(port, msg); @@ -1810,6 +1933,9 @@ static bool tcpm_send_queued_message(struct tcpm_port *port) case PD_MSG_CTRL_REJECT: tcpm_pd_send_control(port, PD_CTRL_REJECT); break; + case PD_MSG_CTRL_NOT_SUPP: + tcpm_pd_send_control(port, PD_CTRL_NOT_SUPP); + break; case PD_MSG_DATA_SINK_CAP: tcpm_pd_send_sink_caps(port); break; @@ -2561,14 +2687,6 @@ static inline enum tcpm_state hard_reset_state(struct tcpm_port *port) return SNK_UNATTACHED; } -static inline enum tcpm_state ready_state(struct tcpm_port *port) -{ - if (port->pwr_role == TYPEC_SOURCE) - return SRC_READY; - else - return SNK_READY; -} - static inline enum tcpm_state unattached_state(struct tcpm_port *port) { if (port->port_type == TYPEC_PORT_DRP) { @@ -3271,6 +3389,22 @@ static void run_state_machine(struct tcpm_port *port) /* Always switch to unattached state */ tcpm_set_state(port, unattached_state(port), 0); break; + case GET_STATUS_SEND: + tcpm_pd_send_control(port, PD_CTRL_GET_STATUS); + tcpm_set_state(port, GET_STATUS_SEND_TIMEOUT, + PD_T_SENDER_RESPONSE); + break; + case GET_STATUS_SEND_TIMEOUT: + tcpm_set_state(port, ready_state(port), 0); + break; + case GET_PPS_STATUS_SEND: + tcpm_pd_send_control(port, PD_CTRL_GET_PPS_STATUS); + tcpm_set_state(port, GET_PPS_STATUS_SEND_TIMEOUT, + PD_T_SENDER_RESPONSE); + break; + case GET_PPS_STATUS_SEND_TIMEOUT: + tcpm_set_state(port, ready_state(port), 0); + break; case ERROR_RECOVERY: tcpm_swap_complete(port, -EPROTO); tcpm_pps_complete(port, -EPROTO); -- 1.9.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [v4,7/7] typec: tcpm: Add support for sink PPS related messages From: "Opensource \[Adam Thomson\]" Message-Id: Date: Tue, 2 Jan 2018 15:50:55 +0000 To: Heikki Krogerus , Guenter Roeck , Greg Kroah-Hartman , Sebastian Reichel , Hans de Goede , Yueyao Zhu , Rui Miguel Silva Cc: linux-usb@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, support.opensource@diasemi.com List-ID: VGhpcyBjb21taXQgYWRkcyBzaW5rIHNpZGUgc3VwcG9ydCBmb3IgR2V0X1N0YXR1cywgU3RhdHVz LApHZXRfUFBTX1N0YXR1cyBhbmQgUFBTX1N0YXR1cyBoYW5kbGluZy4gQXMgdGhlcmUncyB0aGUK cG90ZW50aWFsIGZvciBhIHBhcnRuZXIgdG8gcmVzcG9uZCB3aXRoIE5vdF9TdXBwb3J0ZWQKaGFu ZGxpbmcgb2YgdGhpcyBtZXNzYWdlIGlzIGFsc28gYWRkZWQuIFNlbmRpbmcgb2YKTm90X1N1cHBv cnRlZCBpcyBhZGRlZCBpcyBhZGRlZCB0byBoYW5kbGUgbWVzc2FnZXMKcmVjZWl2ZWQgYnV0IG5v dCB5ZXQgaGFuZGxlZC4KClNpZ25lZC1vZmYtYnk6IEFkYW0gVGhvbXNvbiA8QWRhbS5UaG9tc29u Lk9wZW5zb3VyY2VAZGlhc2VtaS5jb20+Ci0tLQogZHJpdmVycy91c2IvdHlwZWMvdGNwbS5jIHwg MTUyICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrLS0tCiAxIGZp bGUgY2hhbmdlZCwgMTQzIGluc2VydGlvbnMoKyksIDkgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0 IGEvZHJpdmVycy91c2IvdHlwZWMvdGNwbS5jIGIvZHJpdmVycy91c2IvdHlwZWMvdGNwbS5jCmlu ZGV4IGI4NmE1MWMuLjU0ZDE3ZDcgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvdXNiL3R5cGVjL3RjcG0u YworKysgYi9kcml2ZXJzL3VzYi90eXBlYy90Y3BtLmMKQEAgLTE5LDcgKzE5LDkgQEAKICNpbmNs dWRlIDxsaW51eC9zbGFiLmg+CiAjaW5jbHVkZSA8bGludXgvc3BpbmxvY2suaD4KICNpbmNsdWRl IDxsaW51eC91c2IvcGQuaD4KKyNpbmNsdWRlIDxsaW51eC91c2IvcGRfYWRvLmg+CiAjaW5jbHVk ZSA8bGludXgvdXNiL3BkX2Jkby5oPgorI2luY2x1ZGUgPGxpbnV4L3VzYi9wZF9leHRfc2RiLmg+ CiAjaW5jbHVkZSA8bGludXgvdXNiL3BkX3Zkby5oPgogI2luY2x1ZGUgPGxpbnV4L3VzYi90Y3Bt Lmg+CiAjaW5jbHVkZSA8bGludXgvdXNiL3R5cGVjLmg+CkBAIC0xMTMsNiArMTE1LDExIEBACiAJ UyhTTktfVFJZV0FJVF9WQlVTKSwJCQlcCiAJUyhCSVNUX1JYKSwJCQkJXAogCQkJCQkJXAorCVMo R0VUX1NUQVRVU19TRU5EKSwJCQlcCisJUyhHRVRfU1RBVFVTX1NFTkRfVElNRU9VVCksCQlcCisJ UyhHRVRfUFBTX1NUQVRVU19TRU5EKSwJCQlcCisJUyhHRVRfUFBTX1NUQVRVU19TRU5EX1RJTUVP VVQpLAkJXAorCQkJCQkJXAogCVMoRVJST1JfUkVDT1ZFUlkpLAkJCVwKIAlTKFBPUlRfUkVTRVQp LAkJCQlcCiAJUyhQT1JUX1JFU0VUX1dBSVRfT0ZGKQpAQCAtMTQzLDYgKzE1MCw3IEBAIGVudW0g cGRfbXNnX3JlcXVlc3QgewogCVBEX01TR19OT05FID0gMCwKIAlQRF9NU0dfQ1RSTF9SRUpFQ1Qs CiAJUERfTVNHX0NUUkxfV0FJVCwKKwlQRF9NU0dfQ1RSTF9OT1RfU1VQUCwKIAlQRF9NU0dfREFU QV9TSU5LX0NBUCwKIAlQRF9NU0dfREFUQV9TT1VSQ0VfQ0FQLAogfTsKQEAgLTE0MTMsMTAgKzE0 MjEsNDIgQEAgc3RhdGljIGludCB0Y3BtX3ZhbGlkYXRlX2NhcHMoc3RydWN0IHRjcG1fcG9ydCAq cG9ydCwgY29uc3QgdTMyICpwZG8sCiAvKgogICogUEQgKGRhdGEsIGNvbnRyb2wpIGNvbW1hbmQg aGFuZGxpbmcgZnVuY3Rpb25zCiAgKi8KK3N0YXRpYyBpbmxpbmUgZW51bSB0Y3BtX3N0YXRlIHJl YWR5X3N0YXRlKHN0cnVjdCB0Y3BtX3BvcnQgKnBvcnQpCit7CisJaWYgKHBvcnQtPnB3cl9yb2xl ID09IFRZUEVDX1NPVVJDRSkKKwkJcmV0dXJuIFNSQ19SRUFEWTsKKwllbHNlCisJCXJldHVybiBT TktfUkVBRFk7Cit9CiAKIHN0YXRpYyBpbnQgdGNwbV9wZF9zZW5kX2NvbnRyb2woc3RydWN0IHRj cG1fcG9ydCAqcG9ydCwKIAkJCQllbnVtIHBkX2N0cmxfbXNnX3R5cGUgdHlwZSk7CiAKK3N0YXRp YyB2b2lkIHRjcG1faGFuZGxlX2FsZXJ0KHN0cnVjdCB0Y3BtX3BvcnQgKnBvcnQsIGNvbnN0IF9f bGUzMiAqcGF5bG9hZCwKKwkJCSAgICAgIGludCBjbnQpCit7CisJdTMyIHAwID0gbGUzMl90b19j cHUocGF5bG9hZFswXSk7CisJdW5zaWduZWQgaW50IHR5cGUgPSB1c2JfcGRfYWRvX3R5cGUocDAp OworCisJaWYgKCF0eXBlKSB7CisJCXRjcG1fbG9nKHBvcnQsICJBbGVydCBtZXNzYWdlIHJlY2Vp dmVkIHdpdGggbm8gdHlwZSIpOworCQlyZXR1cm47CisJfQorCisJLyogSnVzdCBoYW5kbGluZyBu b24tYmF0dGVyeSBhbGVydHMgZm9yIG5vdyAqLworCWlmICghKHR5cGUgJiBVU0JfUERfQURPX1RZ UEVfQkFUVF9TVEFUVVNfQ0hBTkdFKSkgeworCQlzd2l0Y2ggKHBvcnQtPnN0YXRlKSB7CisJCWNh c2UgU1JDX1JFQURZOgorCQljYXNlIFNOS19SRUFEWToKKwkJCXRjcG1fc2V0X3N0YXRlKHBvcnQs IEdFVF9TVEFUVVNfU0VORCwgMCk7CisJCQlicmVhazsKKwkJZGVmYXVsdDoKKwkJCXRjcG1fcXVl dWVfbWVzc2FnZShwb3J0LCBQRF9NU0dfQ1RSTF9XQUlUKTsKKwkJCWJyZWFrOworCQl9CisJfQor fQorCiBzdGF0aWMgdm9pZCB0Y3BtX3BkX2RhdGFfcmVxdWVzdChzdHJ1Y3QgdGNwbV9wb3J0ICpw b3J0LAogCQkJCSBjb25zdCBzdHJ1Y3QgcGRfbWVzc2FnZSAqbXNnKQogewpAQCAtMTUwMiw2ICsx NTQyLDE0IEBAIHN0YXRpYyB2b2lkIHRjcG1fcGRfZGF0YV9yZXF1ZXN0KHN0cnVjdCB0Y3BtX3Bv cnQgKnBvcnQsCiAJCQl0Y3BtX3NldF9zdGF0ZShwb3J0LCBCSVNUX1JYLCAwKTsKIAkJfQogCQli cmVhazsKKwljYXNlIFBEX0RBVEFfQUxFUlQ6CisJCXRjcG1faGFuZGxlX2FsZXJ0KHBvcnQsIG1z Zy0+cGF5bG9hZCwgY250KTsKKwkJYnJlYWs7CisJY2FzZSBQRF9EQVRBX0JBVFRfU1RBVFVTOgor CWNhc2UgUERfREFUQV9HRVRfQ09VTlRSWV9JTkZPOgorCQkvKiBDdXJyZW50bHkgdW5zdXBwb3J0 ZWQgKi8KKwkJdGNwbV9xdWV1ZV9tZXNzYWdlKHBvcnQsIFBEX01TR19DVFJMX05PVF9TVVBQKTsK KwkJYnJlYWs7CiAJZGVmYXVsdDoKIAkJdGNwbV9sb2cocG9ydCwgIlVuaGFuZGxlZCBkYXRhIG1l c3NhZ2UgdHlwZSAlI3giLCB0eXBlKTsKIAkJYnJlYWs7CkBAIC0xNTg0LDYgKzE2MzIsNyBAQCBz dGF0aWMgdm9pZCB0Y3BtX3BkX2N0cmxfcmVxdWVzdChzdHJ1Y3QgdGNwbV9wb3J0ICpwb3J0LAog CQlicmVhazsKIAljYXNlIFBEX0NUUkxfUkVKRUNUOgogCWNhc2UgUERfQ1RSTF9XQUlUOgorCWNh c2UgUERfQ1RSTF9OT1RfU1VQUDoKIAkJc3dpdGNoIChwb3J0LT5zdGF0ZSkgewogCQljYXNlIFNO S19ORUdPVElBVEVfQ0FQQUJJTElUSUVTOgogCQkJLyogVVNCIFBEIHNwZWNpZmljYXRpb24sIEZp Z3VyZSA4LTQzICovCkBAIC0xNzAzLDEyICsxNzUyLDg0IEBAIHN0YXRpYyB2b2lkIHRjcG1fcGRf Y3RybF9yZXF1ZXN0KHN0cnVjdCB0Y3BtX3BvcnQgKnBvcnQsCiAJCQlicmVhazsKIAkJfQogCQli cmVhazsKKwljYXNlIFBEX0NUUkxfR0VUX1NPVVJDRV9DQVBfRVhUOgorCWNhc2UgUERfQ1RSTF9H RVRfU1RBVFVTOgorCWNhc2UgUERfQ1RSTF9GUl9TV0FQOgorCWNhc2UgUERfQ1RSTF9HRVRfUFBT X1NUQVRVUzoKKwljYXNlIFBEX0NUUkxfR0VUX0NPVU5UUllfQ09ERVM6CisJCS8qIEN1cnJlbnRs eSBub3Qgc3VwcG9ydGVkICovCisJCXRjcG1fcXVldWVfbWVzc2FnZShwb3J0LCBQRF9NU0dfQ1RS TF9OT1RfU1VQUCk7CisJCWJyZWFrOwogCWRlZmF1bHQ6CiAJCXRjcG1fbG9nKHBvcnQsICJVbmhh bmRsZWQgY3RybCBtZXNzYWdlIHR5cGUgJSN4IiwgdHlwZSk7CiAJCWJyZWFrOwogCX0KIH0KIAor c3RhdGljIHZvaWQgdGNwbV9wZF9leHRfbXNnX3JlcXVlc3Qoc3RydWN0IHRjcG1fcG9ydCAqcG9y dCwKKwkJCQkgICAgY29uc3Qgc3RydWN0IHBkX21lc3NhZ2UgKm1zZykKK3sKKwllbnVtIHBkX2V4 dF9tc2dfdHlwZSB0eXBlID0gcGRfaGVhZGVyX3R5cGVfbGUobXNnLT5oZWFkZXIpOworCXVuc2ln bmVkIGludCBkYXRhX3NpemUgPSBwZF9leHRfaGVhZGVyX2RhdGFfc2l6ZV9sZShtc2ctPmV4dF9t c2cuaGVhZGVyKTsKKwl1OCAqZGF0YTsKKworCWlmICghKG1zZy0+ZXh0X21zZy5oZWFkZXIgJiYg UERfRVhUX0hEUl9DSFVOS0VEKSkgeworCQl0Y3BtX2xvZyhwb3J0LCAiVW5jaHVua2VkIGV4dGVu ZGVkIG1lc3NhZ2VzIHVuc3VwcG9ydGVkIik7CisJCXJldHVybjsKKwl9CisKKwlpZiAoZGF0YV9z aXplID4gKFBEX0VYVF9NQVhfQ0hVTktfREFUQSkpIHsKKwkJdGNwbV9sb2cocG9ydCwgIkNodW5r IGhhbmRsaW5nIG5vdCB5ZXQgc3VwcG9ydGVkIik7CisJCXJldHVybjsKKwl9CisKKwlkYXRhID0g a3phbGxvYyhkYXRhX3NpemUsIEdGUF9LRVJORUwpOworCWlmICghZGF0YSkgeworCQl0Y3BtX2xv Zyhwb3J0LCAiRmFpbGVkIHRvIGFsbG9jYXRlIG1lbW9yeSBmb3IgZXh0IG1zZyBkYXRhIik7CisJ CXJldHVybjsKKwl9CisJbWVtY3B5KGRhdGEsIG1zZy0+ZXh0X21zZy5kYXRhLCBkYXRhX3NpemUp OworCisJc3dpdGNoICh0eXBlKSB7CisJY2FzZSBQRF9FWFRfU1RBVFVTOgorCQkvKgorCQkgKiBJ ZiBQUFMgcmVsYXRlZCBldmVudHMgcmFpc2VkIHRoZW4gZ2V0IFBQUyBzdGF0dXMgdG8gY2xlYXIK KwkJICogKHNlZSBVU0IgUEQgMy4wIFNwZWMsIDYuNS4yLjQpCisJCSAqLworCQlpZiAoZGF0YVtV U0JfUERfRVhUX1NEQl9FVkVOVF9GTEFHU10gJiBVU0JfUERfRVhUX1NEQl9QUFNfRVZFTlRTKQor CQkJdGNwbV9zZXRfc3RhdGUocG9ydCwgR0VUX1BQU19TVEFUVVNfU0VORCwgMCk7CisJCWVsc2UK KwkJCXRjcG1fc2V0X3N0YXRlKHBvcnQsIHJlYWR5X3N0YXRlKHBvcnQpLCAwKTsKKwkJYnJlYWs7 CisJY2FzZSBQRF9FWFRfUFBTX1NUQVRVUzoKKwkJLyoKKwkJICogRm9yIG5vdyB0aGUgUFBTIHN0 YXR1cyBtZXNzYWdlIGlzIHVzZWQgdG8gY2xlYXIgZXZlbnRzCisJCSAqIGFuZCBub3RoaW5nIG1v cmUuCisJCSAqLworCQl0Y3BtX3NldF9zdGF0ZShwb3J0LCByZWFkeV9zdGF0ZShwb3J0KSwgMCk7 CisJCWJyZWFrOworCWNhc2UgUERfRVhUX1NPVVJDRV9DQVBfRVhUOgorCWNhc2UgUERfRVhUX0dF VF9CQVRUX0NBUDoKKwljYXNlIFBEX0VYVF9HRVRfQkFUVF9TVEFUVVM6CisJY2FzZSBQRF9FWFRf QkFUVF9DQVA6CisJY2FzZSBQRF9FWFRfR0VUX01BTlVGQUNUVVJFUl9JTkZPOgorCWNhc2UgUERf RVhUX01BTlVGQUNUVVJFUl9JTkZPOgorCWNhc2UgUERfRVhUX1NFQ1VSSVRZX1JFUVVFU1Q6CisJ Y2FzZSBQRF9FWFRfU0VDVVJJVFlfUkVTUE9OU0U6CisJY2FzZSBQRF9FWFRfRldfVVBEQVRFX1JF UVVFU1Q6CisJY2FzZSBQRF9FWFRfRldfVVBEQVRFX1JFU1BPTlNFOgorCWNhc2UgUERfRVhUX0NP VU5UUllfSU5GTzoKKwljYXNlIFBEX0VYVF9DT1VOVFJZX0NPREVTOgorCQl0Y3BtX3F1ZXVlX21l c3NhZ2UocG9ydCwgUERfTVNHX0NUUkxfTk9UX1NVUFApOworCQlicmVhazsKKwlkZWZhdWx0Ogor CQl0Y3BtX2xvZyhwb3J0LCAiVW5oYW5kbGUgZXh0ZW5kZWQgbWVzc2FnZSB0eXBlICUjeCIsIHR5 cGUpOworCQlicmVhazsKKwl9CisKKwlrZnJlZShkYXRhKTsKK30KKwogc3RhdGljIHZvaWQgdGNw bV9wZF9yeF9oYW5kbGVyKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKIHsKIAlzdHJ1Y3QgcGRf cnhfZXZlbnQgKmV2ZW50ID0gY29udGFpbmVyX29mKHdvcmssCkBAIC0xNzQ5LDcgKzE4NzAsOSBA QCBzdGF0aWMgdm9pZCB0Y3BtX3BkX3J4X2hhbmRsZXIoc3RydWN0IHdvcmtfc3RydWN0ICp3b3Jr KQogCQkJCSAiRGF0YSByb2xlIG1pc21hdGNoLCBpbml0aWF0aW5nIGVycm9yIHJlY292ZXJ5Iik7 CiAJCQl0Y3BtX3NldF9zdGF0ZShwb3J0LCBFUlJPUl9SRUNPVkVSWSwgMCk7CiAJCX0gZWxzZSB7 Ci0JCQlpZiAoY250KQorCQkJaWYgKG1zZy0+aGVhZGVyICYgUERfSEVBREVSX0VYVF9IRFIpCisJ CQkJdGNwbV9wZF9leHRfbXNnX3JlcXVlc3QocG9ydCwgbXNnKTsKKwkJCWVsc2UgaWYgKGNudCkK IAkJCQl0Y3BtX3BkX2RhdGFfcmVxdWVzdChwb3J0LCBtc2cpOwogCQkJZWxzZQogCQkJCXRjcG1f cGRfY3RybF9yZXF1ZXN0KHBvcnQsIG1zZyk7CkBAIC0xODEwLDYgKzE5MzMsOSBAQCBzdGF0aWMg Ym9vbCB0Y3BtX3NlbmRfcXVldWVkX21lc3NhZ2Uoc3RydWN0IHRjcG1fcG9ydCAqcG9ydCkKIAkJ Y2FzZSBQRF9NU0dfQ1RSTF9SRUpFQ1Q6CiAJCQl0Y3BtX3BkX3NlbmRfY29udHJvbChwb3J0LCBQ RF9DVFJMX1JFSkVDVCk7CiAJCQlicmVhazsKKwkJY2FzZSBQRF9NU0dfQ1RSTF9OT1RfU1VQUDoK KwkJCXRjcG1fcGRfc2VuZF9jb250cm9sKHBvcnQsIFBEX0NUUkxfTk9UX1NVUFApOworCQkJYnJl YWs7CiAJCWNhc2UgUERfTVNHX0RBVEFfU0lOS19DQVA6CiAJCQl0Y3BtX3BkX3NlbmRfc2lua19j YXBzKHBvcnQpOwogCQkJYnJlYWs7CkBAIC0yNTYxLDE0ICsyNjg3LDYgQEAgc3RhdGljIGlubGlu ZSBlbnVtIHRjcG1fc3RhdGUgaGFyZF9yZXNldF9zdGF0ZShzdHJ1Y3QgdGNwbV9wb3J0ICpwb3J0 KQogCXJldHVybiBTTktfVU5BVFRBQ0hFRDsKIH0KIAotc3RhdGljIGlubGluZSBlbnVtIHRjcG1f c3RhdGUgcmVhZHlfc3RhdGUoc3RydWN0IHRjcG1fcG9ydCAqcG9ydCkKLXsKLQlpZiAocG9ydC0+ cHdyX3JvbGUgPT0gVFlQRUNfU09VUkNFKQotCQlyZXR1cm4gU1JDX1JFQURZOwotCWVsc2UKLQkJ cmV0dXJuIFNOS19SRUFEWTsKLX0KLQogc3RhdGljIGlubGluZSBlbnVtIHRjcG1fc3RhdGUgdW5h dHRhY2hlZF9zdGF0ZShzdHJ1Y3QgdGNwbV9wb3J0ICpwb3J0KQogewogCWlmIChwb3J0LT5wb3J0 X3R5cGUgPT0gVFlQRUNfUE9SVF9EUlApIHsKQEAgLTMyNzEsNiArMzM4OSwyMiBAQCBzdGF0aWMg dm9pZCBydW5fc3RhdGVfbWFjaGluZShzdHJ1Y3QgdGNwbV9wb3J0ICpwb3J0KQogCQkvKiBBbHdh eXMgc3dpdGNoIHRvIHVuYXR0YWNoZWQgc3RhdGUgKi8KIAkJdGNwbV9zZXRfc3RhdGUocG9ydCwg dW5hdHRhY2hlZF9zdGF0ZShwb3J0KSwgMCk7CiAJCWJyZWFrOworCWNhc2UgR0VUX1NUQVRVU19T RU5EOgorCQl0Y3BtX3BkX3NlbmRfY29udHJvbChwb3J0LCBQRF9DVFJMX0dFVF9TVEFUVVMpOwor CQl0Y3BtX3NldF9zdGF0ZShwb3J0LCBHRVRfU1RBVFVTX1NFTkRfVElNRU9VVCwKKwkJCSAgICAg ICBQRF9UX1NFTkRFUl9SRVNQT05TRSk7CisJCWJyZWFrOworCWNhc2UgR0VUX1NUQVRVU19TRU5E X1RJTUVPVVQ6CisJCXRjcG1fc2V0X3N0YXRlKHBvcnQsIHJlYWR5X3N0YXRlKHBvcnQpLCAwKTsK KwkJYnJlYWs7CisJY2FzZSBHRVRfUFBTX1NUQVRVU19TRU5EOgorCQl0Y3BtX3BkX3NlbmRfY29u dHJvbChwb3J0LCBQRF9DVFJMX0dFVF9QUFNfU1RBVFVTKTsKKwkJdGNwbV9zZXRfc3RhdGUocG9y dCwgR0VUX1BQU19TVEFUVVNfU0VORF9USU1FT1VULAorCQkJICAgICAgIFBEX1RfU0VOREVSX1JF U1BPTlNFKTsKKwkJYnJlYWs7CisJY2FzZSBHRVRfUFBTX1NUQVRVU19TRU5EX1RJTUVPVVQ6CisJ CXRjcG1fc2V0X3N0YXRlKHBvcnQsIHJlYWR5X3N0YXRlKHBvcnQpLCAwKTsKKwkJYnJlYWs7CiAJ Y2FzZSBFUlJPUl9SRUNPVkVSWToKIAkJdGNwbV9zd2FwX2NvbXBsZXRlKHBvcnQsIC1FUFJPVE8p OwogCQl0Y3BtX3Bwc19jb21wbGV0ZShwb3J0LCAtRVBST1RPKTsK From mboxrd@z Thu Jan 1 00:00:00 1970 From: Adam Thomson Subject: [PATCH v4 7/7] typec: tcpm: Add support for sink PPS related messages Date: Tue, 2 Jan 2018 15:50:55 +0000 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain Return-path: In-Reply-To: Sender: linux-kernel-owner@vger.kernel.org To: Heikki Krogerus , Guenter Roeck , Greg Kroah-Hartman , Sebastian Reichel , Hans de Goede , Yueyao Zhu , Rui Miguel Silva Cc: linux-usb@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, support.opensource@diasemi.com List-Id: linux-pm@vger.kernel.org This commit adds sink side support for Get_Status, Status, Get_PPS_Status and PPS_Status handling. As there's the potential for a partner to respond with Not_Supported handling of this message is also added. Sending of Not_Supported is added is added to handle messages received but not yet handled. Signed-off-by: Adam Thomson --- drivers/usb/typec/tcpm.c | 152 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 143 insertions(+), 9 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index b86a51c..54d17d7 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -113,6 +115,11 @@ S(SNK_TRYWAIT_VBUS), \ S(BIST_RX), \ \ + S(GET_STATUS_SEND), \ + S(GET_STATUS_SEND_TIMEOUT), \ + S(GET_PPS_STATUS_SEND), \ + S(GET_PPS_STATUS_SEND_TIMEOUT), \ + \ S(ERROR_RECOVERY), \ S(PORT_RESET), \ S(PORT_RESET_WAIT_OFF) @@ -143,6 +150,7 @@ enum pd_msg_request { PD_MSG_NONE = 0, PD_MSG_CTRL_REJECT, PD_MSG_CTRL_WAIT, + PD_MSG_CTRL_NOT_SUPP, PD_MSG_DATA_SINK_CAP, PD_MSG_DATA_SOURCE_CAP, }; @@ -1413,10 +1421,42 @@ static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo, /* * PD (data, control) command handling functions */ +static inline enum tcpm_state ready_state(struct tcpm_port *port) +{ + if (port->pwr_role == TYPEC_SOURCE) + return SRC_READY; + else + return SNK_READY; +} static int tcpm_pd_send_control(struct tcpm_port *port, enum pd_ctrl_msg_type type); +static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, + int cnt) +{ + u32 p0 = le32_to_cpu(payload[0]); + unsigned int type = usb_pd_ado_type(p0); + + if (!type) { + tcpm_log(port, "Alert message received with no type"); + return; + } + + /* Just handling non-battery alerts for now */ + if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) { + switch (port->state) { + case SRC_READY: + case SNK_READY: + tcpm_set_state(port, GET_STATUS_SEND, 0); + break; + default: + tcpm_queue_message(port, PD_MSG_CTRL_WAIT); + break; + } + } +} + static void tcpm_pd_data_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1502,6 +1542,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port, tcpm_set_state(port, BIST_RX, 0); } break; + case PD_DATA_ALERT: + tcpm_handle_alert(port, msg->payload, cnt); + break; + case PD_DATA_BATT_STATUS: + case PD_DATA_GET_COUNTRY_INFO: + /* Currently unsupported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled data message type %#x", type); break; @@ -1584,6 +1632,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; case PD_CTRL_REJECT: case PD_CTRL_WAIT: + case PD_CTRL_NOT_SUPP: switch (port->state) { case SNK_NEGOTIATE_CAPABILITIES: /* USB PD specification, Figure 8-43 */ @@ -1703,12 +1752,84 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; } break; + case PD_CTRL_GET_SOURCE_CAP_EXT: + case PD_CTRL_GET_STATUS: + case PD_CTRL_FR_SWAP: + case PD_CTRL_GET_PPS_STATUS: + case PD_CTRL_GET_COUNTRY_CODES: + /* Currently not supported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled ctrl message type %#x", type); break; } } +static void tcpm_pd_ext_msg_request(struct tcpm_port *port, + const struct pd_message *msg) +{ + enum pd_ext_msg_type type = pd_header_type_le(msg->header); + unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); + u8 *data; + + if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) { + tcpm_log(port, "Unchunked extended messages unsupported"); + return; + } + + if (data_size > (PD_EXT_MAX_CHUNK_DATA)) { + tcpm_log(port, "Chunk handling not yet supported"); + return; + } + + data = kzalloc(data_size, GFP_KERNEL); + if (!data) { + tcpm_log(port, "Failed to allocate memory for ext msg data"); + return; + } + memcpy(data, msg->ext_msg.data, data_size); + + switch (type) { + case PD_EXT_STATUS: + /* + * If PPS related events raised then get PPS status to clear + * (see USB PD 3.0 Spec, 6.5.2.4) + */ + if (data[USB_PD_EXT_SDB_EVENT_FLAGS] & USB_PD_EXT_SDB_PPS_EVENTS) + tcpm_set_state(port, GET_PPS_STATUS_SEND, 0); + else + tcpm_set_state(port, ready_state(port), 0); + break; + case PD_EXT_PPS_STATUS: + /* + * For now the PPS status message is used to clear events + * and nothing more. + */ + tcpm_set_state(port, ready_state(port), 0); + break; + case PD_EXT_SOURCE_CAP_EXT: + case PD_EXT_GET_BATT_CAP: + case PD_EXT_GET_BATT_STATUS: + case PD_EXT_BATT_CAP: + case PD_EXT_GET_MANUFACTURER_INFO: + case PD_EXT_MANUFACTURER_INFO: + case PD_EXT_SECURITY_REQUEST: + case PD_EXT_SECURITY_RESPONSE: + case PD_EXT_FW_UPDATE_REQUEST: + case PD_EXT_FW_UPDATE_RESPONSE: + case PD_EXT_COUNTRY_INFO: + case PD_EXT_COUNTRY_CODES: + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; + default: + tcpm_log(port, "Unhandle extended message type %#x", type); + break; + } + + kfree(data); +} + static void tcpm_pd_rx_handler(struct work_struct *work) { struct pd_rx_event *event = container_of(work, @@ -1749,7 +1870,9 @@ static void tcpm_pd_rx_handler(struct work_struct *work) "Data role mismatch, initiating error recovery"); tcpm_set_state(port, ERROR_RECOVERY, 0); } else { - if (cnt) + if (msg->header & PD_HEADER_EXT_HDR) + tcpm_pd_ext_msg_request(port, msg); + else if (cnt) tcpm_pd_data_request(port, msg); else tcpm_pd_ctrl_request(port, msg); @@ -1810,6 +1933,9 @@ static bool tcpm_send_queued_message(struct tcpm_port *port) case PD_MSG_CTRL_REJECT: tcpm_pd_send_control(port, PD_CTRL_REJECT); break; + case PD_MSG_CTRL_NOT_SUPP: + tcpm_pd_send_control(port, PD_CTRL_NOT_SUPP); + break; case PD_MSG_DATA_SINK_CAP: tcpm_pd_send_sink_caps(port); break; @@ -2561,14 +2687,6 @@ static inline enum tcpm_state hard_reset_state(struct tcpm_port *port) return SNK_UNATTACHED; } -static inline enum tcpm_state ready_state(struct tcpm_port *port) -{ - if (port->pwr_role == TYPEC_SOURCE) - return SRC_READY; - else - return SNK_READY; -} - static inline enum tcpm_state unattached_state(struct tcpm_port *port) { if (port->port_type == TYPEC_PORT_DRP) { @@ -3271,6 +3389,22 @@ static void run_state_machine(struct tcpm_port *port) /* Always switch to unattached state */ tcpm_set_state(port, unattached_state(port), 0); break; + case GET_STATUS_SEND: + tcpm_pd_send_control(port, PD_CTRL_GET_STATUS); + tcpm_set_state(port, GET_STATUS_SEND_TIMEOUT, + PD_T_SENDER_RESPONSE); + break; + case GET_STATUS_SEND_TIMEOUT: + tcpm_set_state(port, ready_state(port), 0); + break; + case GET_PPS_STATUS_SEND: + tcpm_pd_send_control(port, PD_CTRL_GET_PPS_STATUS); + tcpm_set_state(port, GET_PPS_STATUS_SEND_TIMEOUT, + PD_T_SENDER_RESPONSE); + break; + case GET_PPS_STATUS_SEND_TIMEOUT: + tcpm_set_state(port, ready_state(port), 0); + break; case ERROR_RECOVERY: tcpm_swap_complete(port, -EPROTO); tcpm_pps_complete(port, -EPROTO); -- 1.9.1