From patchwork Tue Aug 25 04:21:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734819 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B4EC8739 for ; Tue, 25 Aug 2020 04:22:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9BF8020737 for ; Tue, 25 Aug 2020 04:22:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="jkhAZg0i" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728405AbgHYEW1 (ORCPT ); Tue, 25 Aug 2020 00:22:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50828 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725970AbgHYEW0 (ORCPT ); Tue, 25 Aug 2020 00:22:26 -0400 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B8A3AC061574 for ; Mon, 24 Aug 2020 21:22:25 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id 78so1902088pgf.5 for ; Mon, 24 Aug 2020 21:22:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=JEUp//OgrqIdq4oBTWKdSUH95jBvEG8vdsM1vuPs8Tc=; b=jkhAZg0iMscEcFm/RUujA72vXdC5gOQalIMPfd5KOkCgy0trvRgRNN31LwH8axbb7i xOLx4FM+xYzv2EGDoGafREwUQoWb2M+/oQkPRZlswGJnaPNb8tdZwjkBj1fnwNhV576/ R0y80iV4KLLDO566lEoAvw6xLv1BQdZffvioxrcRTOZVQMglHb96tE6o9Xjskbs7rhkf ApskSMLxthNLqOY1aRI+2ijCMAJLe5FnQYOcxBmE0yrHJfckDTTYByGE5JXdgtLrQw3I nUpd3w8XVA8y4JfSuoVObQcUCdk71hZLCS2c00zANEgCy3TZ0y47FfmqCp4xPp8G1mQo iu3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=JEUp//OgrqIdq4oBTWKdSUH95jBvEG8vdsM1vuPs8Tc=; b=N06ihSy2WR2S2HYPsA7wSvNRXQCJ1q7FBWQk4G8CbRrEbSJNR2qtIVBl8qHrspwZRA pfQCr6zbFj4pGzTqOvPaogarpoBZYhJGunpffGcFllt66jOPgjyKmgwfMLQavZHVnxKv 3QJPrAS9L9SCMl2VnBzftjk/awvOqsO13bULyXMm6tWOXbmFKlLKPuo5VI6PARxv8okk riRsuuNLXyn0R/WMhWF3wFj5h/JbwncGDNc8RiYQuiZZkQka9GVQnIpquljV1rTnZ9qv OCl14lokS2Mh20PKpJpgUW1Dkz9vQqzmNM6mb/iZZ4layhlCzJvw2fgz6i/7RbzqHiq9 JK/Q== X-Gm-Message-State: AOAM533bgYjc3HTVMt1211NMt3qsayAZNWZJoNACvPZIBlMFNQQ9qE68 FWJFwqakND4nOHc/410OchKuZTxysIg= X-Google-Smtp-Source: ABdhPJyqxUn6kmdMRMpi7HMnXOCyU5kHwFBq5l3bMwOsEy7jvpoqAEAyF30GuaZPav1y862SjZOY2YhBsHQ= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a17:90a:bd8a:: with SMTP id z10mr72361pjr.12.1598329345209; Mon, 24 Aug 2020 21:22:25 -0700 (PDT) Date: Mon, 24 Aug 2020 21:21:57 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-2-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 01/14 v1] usb: typec: tcpci: Add register definitions to tcpci From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Add register definitions to trap extended alerts. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/tcpci.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h index 11c36d086c86..fd26ca35814c 100644 --- a/drivers/usb/typec/tcpm/tcpci.h +++ b/drivers/usb/typec/tcpm/tcpci.h @@ -16,6 +16,7 @@ #define TCPC_PD_INT_REV 0xa #define TCPC_ALERT 0x10 +#define TCPC_ALERT_EXTENDED_STATUS BIT(13) #define TCPC_ALERT_VBUS_DISCNCT BIT(11) #define TCPC_ALERT_RX_BUF_OVF BIT(10) #define TCPC_ALERT_FAULT BIT(9) @@ -32,6 +33,10 @@ #define TCPC_ALERT_MASK 0x12 #define TCPC_POWER_STATUS_MASK 0x14 #define TCPC_FAULT_STATUS_MASK 0x15 + +#define TCPC_EXTENDED_STATUS_MASK 0x16 +#define TCPC_EXTENDED_STATUS_MASK_VSAFE0V BIT(0) + #define TCPC_CONFIG_STD_OUTPUT 0x18 #define TCPC_TCPC_CTRL 0x19 From patchwork Tue Aug 25 04:21:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734821 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8AABA138A for ; Tue, 25 Aug 2020 04:22:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6EBEA20738 for ; Tue, 25 Aug 2020 04:22:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="kLvgRy07" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726471AbgHYEWb (ORCPT ); Tue, 25 Aug 2020 00:22:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50842 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725265AbgHYEWa (ORCPT ); Tue, 25 Aug 2020 00:22:30 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 15383C061574 for ; Mon, 24 Aug 2020 21:22:30 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id lx6so889975pjb.9 for ; Mon, 24 Aug 2020 21:22:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=uNM7HP/LHsK3vi9PvtdHxJ86dOAfeYqmzrZ0qZRLxlA=; b=kLvgRy07hQY2lFzW8fHlfXXMd+Cdx+25eTP3d2GAQaRmvrpEvr0iAFVsIyM6tdQzUG fEUK0gzn46C7cz3lOCBOpJEG17FJ/QjLLf1910ETwwZs1q9K767pm1R1eH6rypa3PQEp a0r1Sys7b8s83UyKlk8Gq4MWl2gJQVX8QPRPxlghpMYrA6BiO8cB4uolJpWH4hx036mY +mKRGeRc8gRUBQhgtQP7i1Bp8UK+GWO0/69lxHNwRpsvcRrom/zeJLCKBTCnADIxDPF+ rm/iLdkxbk2V2xnx5aaRVvF8mZ2p9pwsE+LP5fRI1EHlZYZqbL9MDeALfyugt3HmeRTa rKcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=uNM7HP/LHsK3vi9PvtdHxJ86dOAfeYqmzrZ0qZRLxlA=; b=UuoqX4en2i0i/NcQ7zdLGK5u2RbH1sERpvEvJowDgsfzMrQWOrC8BWurirQMwAMdzc Awmw7EcLk5PGxd1BHv61N/8RWaL4EiDgBE8IOMVGHVQXbQG6VjdvQbGDUeOSxguyo/u2 mlb4L6tvMOHxIz6Q9FH8EbQH539FMex7C0/Vu8/C2Wc+xBf7JW5qKfeOIvcz5mFeGmPX 8QxnsOd///PKVcSCCkQkv0boN0rZeepmQzgQ1ayQqfKtlTNixMBwrtqO7OUZotTtCE6M 8UqySMIcR5OoysOPUXVa8ysyD00+VR8tOV5n325dE0ndbNFQtm+JkgCj27PXZXh5p7cO IWKw== X-Gm-Message-State: AOAM531m90+tDabDbSS3h7N6QL0HGU+QqJ9fCCndntXDXVB83gmO3tXU WbRfPsEcnLSpZKmNekzOx3W43L6CYTI= X-Google-Smtp-Source: ABdhPJwgrbZbyUxmLVv4z18yXQbs+H+ZgJyhIt2GSckwXachV3QFr36xqqieA4TJVkGjje0KVF56fSqFqOQ= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a63:cd54:: with SMTP id a20mr5362196pgj.228.1598329349509; Mon, 24 Aug 2020 21:22:29 -0700 (PDT) Date: Mon, 24 Aug 2020 21:21:58 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-3-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 02/14 v2] usb: typec: tcpci: Add support when hidden tx registers are inaccessible From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org TCPCI spec forbids direct access of TX_BUF_BYTE_x register. The existing version of tcpci driver assumes that those registers are directly addressible. Add support for tcpci chips which do not support direct access to TX_BUF_BYTE_x registers. TX_BUF_BYTE_x can only be accessed by I2C_WRITE_BYTE_COUNT. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/tcpci.c | 49 +++++++++++++++++++++++++--------- drivers/usb/typec/tcpm/tcpci.h | 8 ++++++ 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index f57d91fd0e09..90d348caa6a8 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -320,8 +320,7 @@ static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink) return 0; } -static int tcpci_pd_transmit(struct tcpc_dev *tcpc, - enum tcpm_transmit_type type, +static int tcpci_pd_transmit(struct tcpc_dev *tcpc, enum tcpm_transmit_type type, const struct pd_message *msg) { struct tcpci *tcpci = tcpc_to_tcpci(tcpc); @@ -330,23 +329,47 @@ static int tcpci_pd_transmit(struct tcpc_dev *tcpc, int ret; cnt = msg ? pd_header_cnt(header) * 4 : 0; - ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2); - if (ret < 0) - return ret; + /** + * TCPCI spec forbids direct access of TCPC_TX_DATA. + * But, since some of the chipsets offer this capability, + * it's fair to support both. + */ + if (!tcpci->data->TX_BUF_BYTE_x_hidden) { + ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2); + if (ret < 0) + return ret; - ret = tcpci_write16(tcpci, TCPC_TX_HDR, header); - if (ret < 0) - return ret; + ret = tcpci_write16(tcpci, TCPC_TX_HDR, header); + if (ret < 0) + return ret; + + if (cnt > 0) { + ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA, &msg->payload, cnt); + if (ret < 0) + return ret; + } + } else { + u8 buf[TCPC_TRANSMIT_BUFFER_MAX_LEN] = {0,}; + u8 pos = 0; + + /* Payload + header + TCPC_TX_BYTE_CNT */ + buf[pos++] = cnt + 2; + + if (msg) + memcpy(&buf[pos], &msg->header, sizeof(msg->header)); + + pos += sizeof(header); + + if (cnt > 0) + memcpy(&buf[pos], msg->payload, cnt); - if (cnt > 0) { - ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA, - &msg->payload, cnt); + pos += cnt; + ret = regmap_raw_write(tcpci->regmap, TCPC_TX_BYTE_CNT, buf, pos); if (ret < 0) return ret; } - reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) | - (type << TCPC_TRANSMIT_TYPE_SHIFT); + reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) | (type << TCPC_TRANSMIT_TYPE_SHIFT); ret = regmap_write(tcpci->regmap, TCPC_TRANSMIT, reg); if (ret < 0) return ret; diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h index fd26ca35814c..cf9d8b63adcb 100644 --- a/drivers/usb/typec/tcpm/tcpci.h +++ b/drivers/usb/typec/tcpm/tcpci.h @@ -128,9 +128,17 @@ #define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76 #define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78 +/* I2C_WRITE_BYTE_COUNT + 1 when TX_BUF_BYTE_x is only accessible I2C_WRITE_BYTE_COUNT */ +#define TCPC_TRANSMIT_BUFFER_MAX_LEN 31 + +/* + * @TX_BUF_BYTE_x_hidden + * optional; Set when TX_BUF_BYTE_x can only be accessed through I2C_WRITE_BYTE_COUNT. + */ struct tcpci; struct tcpci_data { struct regmap *regmap; + unsigned char TX_BUF_BYTE_x_hidden:1; int (*init)(struct tcpci *tcpci, struct tcpci_data *data); int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data, bool enable); From patchwork Tue Aug 25 04:21:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734823 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 66CD0739 for ; Tue, 25 Aug 2020 04:22:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 498B620737 for ; Tue, 25 Aug 2020 04:22:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="n72OI6Mo" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728520AbgHYEWf (ORCPT ); Tue, 25 Aug 2020 00:22:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50856 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728483AbgHYEWe (ORCPT ); Tue, 25 Aug 2020 00:22:34 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 654F2C061574 for ; Mon, 24 Aug 2020 21:22:34 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id t13so924463pjd.0 for ; Mon, 24 Aug 2020 21:22:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=F8R7yB/uW413X5BedlVvfs1XP30S/Fpzu0dI0Wqxoxc=; b=n72OI6MoEkQhfKUwJdHzWFQo0b8hAvkNDSD1jmWoyZQ0V8OJBU2zf9TYkIjQYpXtCo dUStaSep5gflMaYcmcL10S6XR/DnqRv7amQsr9GxaBe2MnDAxILEhPQWW3VG5ABPS2vh gDTLW7GGp0hfHW1TCkZJkfAAwPALmBk/VDLkGb6JSOt8XzTD1AjuqshMjX8wseVt5E8S RY6f27PWDyrpbj01THKYTfJ5h+K5UhMQJSGDLhuErTYtZvRFeFQGkDh7vmu1PbxIrVWT SBPc9z1H4Ln+WHTzwN1F8WXvd1I+1D7wnSbQtdxyTo2Gbffbf9SRmBA2yLbXStxxNNxR C0yQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=F8R7yB/uW413X5BedlVvfs1XP30S/Fpzu0dI0Wqxoxc=; b=mmHY8U/qv22uZV8LlP0qbhhyoNWoG2rQ7PDnVspff7i0ngne7/oB5H3sdiGMKZEQmU baLkp0oHL3iwrxnbuttjeGB0sD3jsk/heMSrnfri0pLYhBdPpE6tBX/ey5/I7uTjLlQB WahUg2zY+Tf53j08bhoc3gwD2OOOAt/6W3j+b33TvtQ2Hwv8ACLBIXq3Jxk6fd3AJoyV daTcbOThRlfAkVu1qT/oQCCnZXmNFR/WQ7S1UR/oix4ba46mtxh/ci2j4eMujqMyt/PS 95vKmRXUyISq2bIWi75AkU0uVXF7bhyazO9n2zmnbLz38+O0BWIIThr6mdJnK6QQAzHi A9ew== X-Gm-Message-State: AOAM530pCEIKHBiDEBVqi4y+x5v1A1en0RHALXiuGZDpP+Q1iMCrDJ7u kxtSQDvQaOTN/RfwonzaJXheGBDUxuk= X-Google-Smtp-Source: ABdhPJzj5NrEqS6R/E/pway38JrzWHE+PYmAiWI5fTlEcegdm6POulaQfy5AaYM7tiD79DhVVquGuO7tQkA= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a17:90a:638c:: with SMTP id f12mr249425pjj.1.1598329353549; Mon, 24 Aug 2020 21:22:33 -0700 (PDT) Date: Mon, 24 Aug 2020 21:21:59 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-4-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 03/14 v1] usb: typec: tcpci: update ROLE_CONTROL for DRP From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org ROLE_CONTROL register would not have the actual CC terminations unless the port does not set ROLE_CONTROL.DRP. For DRP ports, CC_STATUS.cc1/cc2 indicates the final terminations applied when TCPC enters potential_connect_as_source/_sink. For DRP ports, infer port role from CC_STATUS and set corresponding CC terminations before setting the orientation. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/tcpci.c | 37 +++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 90d348caa6a8..9e814d454d14 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -191,12 +191,47 @@ static int tcpci_set_polarity(struct tcpc_dev *tcpc, struct tcpci *tcpci = tcpc_to_tcpci(tcpc); unsigned int reg; int ret; + enum typec_cc_status cc1, cc2; - /* Keep the disconnect cc line open */ + /* Obtain Rp setting from role control */ ret = regmap_read(tcpci->regmap, TCPC_ROLE_CTRL, ®); if (ret < 0) return ret; + ret = tcpci_get_cc(tcpc, &cc1, &cc2); + if (ret < 0) + return ret; + + /* + * When port has drp toggling enabled, ROLE_CONTROL would only have the initial + * terminations for the toggling and does not indicate the final cc + * terminations when ConnectionResult is 0 i.e. drp toggling stops and + * the connection is resolbed. Infer port role from TCPC_CC_STATUS based on the + * terminations seen. The port role is then used to set the cc terminations. + */ + if (reg & TCPC_ROLE_CTRL_DRP) { + /* Disable DRP for the OPEN setting to take effect */ + reg = reg & ~TCPC_ROLE_CTRL_DRP; + + if (polarity == TYPEC_POLARITY_CC2) { + reg &= ~(TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT); + /* Local port is source */ + if (cc2 == TYPEC_CC_RD) + /* Role control would have the Rp setting when DRP was enabled */ + reg |= TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT; + else + reg |= TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT; + } else { + reg &= ~(TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT); + /* Local port is source */ + if (cc1 == TYPEC_CC_RD) + /* Role control would have the Rp setting when DRP was enabled */ + reg |= TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT; + else + reg |= TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT; + } + } + if (polarity == TYPEC_POLARITY_CC2) reg |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT; else From patchwork Tue Aug 25 04:22:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734843 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A509016B1 for ; Tue, 25 Aug 2020 04:23:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8DD6420738 for ; Tue, 25 Aug 2020 04:23:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="qEp6lskp" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728559AbgHYEWl (ORCPT ); Tue, 25 Aug 2020 00:22:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50874 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728555AbgHYEWj (ORCPT ); Tue, 25 Aug 2020 00:22:39 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 978D9C061574 for ; Mon, 24 Aug 2020 21:22:38 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 36so6864343pgz.18 for ; Mon, 24 Aug 2020 21:22:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=nWeRgBg8Ta0JRUMqjnIe2WAINWblXQ1/8Tod3psP/Qw=; b=qEp6lskpZWqC4EQJ85EobO2qxMlWdWKJb/ThqSCHe/SvBlUmgrda0L1rykQdI+/aNF EfYKonzOKbyEeGAECfW4HAra3tDodTSOaX8EsUVhsIVDw9tLH52IRWcF5slGHj5OVpMN ryNRSK6ZdR4dEC0zxZnHyzopX2OzuLFI3H6cjSKVjLml3qRbrBgMUd0f2VnGN4YtpTqo PzQgm+/4yr/yegRzzmru3yOZ4grnL7NC+1ctWiv15hFwxJdKUXcDEUXAUdJekQE8BKx9 QHNJcfxwXHrxZ95ROVp7JovwMhp2ds9PkiGKheTQw5c5+A/jd/cntR5yW8YOmdH7PxVg w0hA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=nWeRgBg8Ta0JRUMqjnIe2WAINWblXQ1/8Tod3psP/Qw=; b=qqeFEai9ABsXCAJQRNwZfJeVSVN1qOdnrr7gPU8FxrDYm4fA0aCvPa4MmaMG+nBl7P fNb3+tBAX4aoNbGJBlG2fzjd3uOKlDXccF5/nzZohQARJVK4gPWkU+9mHb1P4CffmW0N N/SrMtafQTMZS+zZLxcHR9SXCt8L34AID6K1qlHve9K6YyNQZe4i3UiPX9YXu8YNbsQ+ Vm0vVmUJne+uxlwCD+bJtOPa4D/qt30qUJZAQ+9Px55fKZPUWyE1UzkI06EX3mNJezFo CRQWjsvjf6Ud19D8C8mnTFasio5oEss+XmF/4GRVAZO9YUsY9yJycVsE7LSwMaTjL8mD iG/A== X-Gm-Message-State: AOAM530x3YdN5kEusJEXCpLIHf8Y0NjJZscR2H270vX7KkZxpXaRo4Bc RQOIHnoe/P+TMz0IDP1XbMvhch7sURY= X-Google-Smtp-Source: ABdhPJzgqZaIyM+aghkM5fFsP3zxDfJ+c5ExAt1tqg5VtdJqpTDO9F7xYLnF4n9fsWs0V1GJ/nfPbAbWH48= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a17:90a:5aa2:: with SMTP id n31mr48366pji.33.1598329358088; Mon, 24 Aug 2020 21:22:38 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:00 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-5-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 04/14 v1] usb: typec: tcpci: Add a getter method to retrieve tcpm_port reference From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Allow chip level drivers to retrieve reference to tcpm_port. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/tcpci.c | 6 ++++++ drivers/usb/typec/tcpm/tcpci.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 9e814d454d14..7b7991c8ac87 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -38,6 +38,12 @@ struct tcpci_chip { struct tcpci_data data; }; +struct tcpm_port *tcpci_get_tcpm_port(struct tcpci *tcpci) +{ + return tcpci->port; +} +EXPORT_SYMBOL_GPL(tcpci_get_tcpm_port); + static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc) { return container_of(tcpc, struct tcpci, tcpc); diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h index cf9d8b63adcb..04c49a0b0368 100644 --- a/drivers/usb/typec/tcpm/tcpci.h +++ b/drivers/usb/typec/tcpm/tcpci.h @@ -150,4 +150,6 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data); void tcpci_unregister_port(struct tcpci *tcpci); irqreturn_t tcpci_irq(struct tcpci *tcpci); +struct tcpm_port; +struct tcpm_port *tcpci_get_tcpm_port(struct tcpci *tcpci); #endif /* __LINUX_USB_TCPCI_H */ From patchwork Tue Aug 25 04:22:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734845 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 104AC138A for ; Tue, 25 Aug 2020 04:23:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EBE2F2072D for ; Tue, 25 Aug 2020 04:23:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="SR8bV9aH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728603AbgHYEXr (ORCPT ); Tue, 25 Aug 2020 00:23:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728498AbgHYEWl (ORCPT ); Tue, 25 Aug 2020 00:22:41 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BD17EC0613ED for ; Mon, 24 Aug 2020 21:22:40 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id a5so13305939ybh.3 for ; Mon, 24 Aug 2020 21:22:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=0dZapQdAtC5VdVTKkYzxbs06O/e7miNf9pUPYlnZYxc=; b=SR8bV9aHZi3LpVJCd3ZaaayHE1IvEYoeHSSh+5U7zZema8WmAIRsED0y24i357zAh3 x9UEJGz4n1Yl85yVLI/oPIO3LA2OhftrkwEpxD0blcFkHq/dCnxoCGWGoC0Cski5gPrM waJUe+sZQGL/9Azz8RVGiN0xhrrONi/jqrjlLdolRNlLm97fSkeEmyXU/7MvoQ1kjRon UPFjJ9068cz656Xzr92H71s/XfRmEE2rs2YpZNQv5xzVlPM9HzhmMe+1HnnpB21shOqQ vj4FQzKODvOCbt0UifK7Qmt1EN7PRVwkVVBh5DEuou/Dm6e6DZWKTWEtIKzeEwkWiI+r L01w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=0dZapQdAtC5VdVTKkYzxbs06O/e7miNf9pUPYlnZYxc=; b=ikpMlC76uu0Zl/Vt6lVbUwGBzt/ZKWBbAKC3hihOHn+Q3AJyBZF0LiQPyoDAGTe/LR AyjjKiME9gVBzex4XbKCCaB6Mc6ch3e+K5W4x3P4jQPTMnCyL/+T16HPyAVqiAkzJIKW cVTBXB+jJyxU9I5REiUjMvVrgLYl+fTHgI6majK5tjzYJs16XvSTZTkJD9DynT1UnyoQ /wkMsKkxd4vtkOZh/425BvNCb3XSlJQpP2DeI8AlB+r/jfyTJd42iKSRDR99FxSC4pRX uqJFCzysv1KNBUeukYioQg6AJ0JZHobviFIQZp9mjHBRB585E26xKyBZYeU2gi24hzur LKhA== X-Gm-Message-State: AOAM533/2DPiYsa4z2uy66lGmgaJXNHj799HPAswTvykNi4W6e04kLS4 i4TWKDfk2bJIHyYQ3SBAdbdayIBRwVE= X-Google-Smtp-Source: ABdhPJxEJTTEQnr7/U15XqRjhIF5ahbOmYBlRNAKXqXmejuNOHs/wA6XsbCZhbPFLzBLltmwJQRygS4SHho= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a25:d8d4:: with SMTP id p203mr11208201ybg.289.1598329360044; Mon, 24 Aug 2020 21:22:40 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:01 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-6-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 05/14 v5] usb: typec: tcpci: Add set_vbus tcpci callback From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org set_vbus callback allows TCPC which are TCPCI based, however, does not support turning on sink and source mode through Command.SinkVbus and Command.SourceVbusDefaultVoltage. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/tcpci.c | 7 +++++++ drivers/usb/typec/tcpm/tcpci.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 7b7991c8ac87..89d28e3fbee8 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -328,6 +328,13 @@ static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink) struct tcpci *tcpci = tcpc_to_tcpci(tcpc); int ret; + if (tcpci->data->set_vbus) { + ret = tcpci->data->set_vbus(tcpci, tcpci->data, source, sink); + /* Bypass when ret > 0 */ + if (ret != 0) + return ret < 0 ? ret : 0; + } + /* Disable both source and sink first before enabling anything */ if (!source) { diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h index 04c49a0b0368..4d441bdf24d5 100644 --- a/drivers/usb/typec/tcpm/tcpci.h +++ b/drivers/usb/typec/tcpm/tcpci.h @@ -144,6 +144,7 @@ struct tcpci_data { bool enable); int (*start_drp_toggling)(struct tcpci *tcpci, struct tcpci_data *data, enum typec_cc_status cc); + int (*set_vbus)(struct tcpci *tcpci, struct tcpci_data *data, bool source, bool sink); }; struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data); From patchwork Tue Aug 25 04:22:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734835 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A8C87138A for ; Tue, 25 Aug 2020 04:23:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8E65E20738 for ; Tue, 25 Aug 2020 04:23:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="B42heZaf" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726163AbgHYEWq (ORCPT ); Tue, 25 Aug 2020 00:22:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50892 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728598AbgHYEWn (ORCPT ); Tue, 25 Aug 2020 00:22:43 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3AFDAC061574 for ; Mon, 24 Aug 2020 21:22:43 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id w17so13264177ybl.9 for ; Mon, 24 Aug 2020 21:22:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=LaXEwiyj3MgKPctp60ipXsQUebEP+5mdaxvo+R2WRtw=; b=B42heZafxHivLXm0aOGdLVibiLm0qF8L3IvB4FKYWSdfzVeQcw8YAoeM3uGV1iASBk QStfkWVxSFPTJbJeD+It4FOLb8AjJ6vzLOe/RMg5JAwfkLpFm5XN3y5xQ4gwduYKMZ+2 vWdM3FW1wS9yUociub30p+hdr04vhK5WAMaVU8lDzlMMy2NnH7lFDgTo8bhkinl8MzJF zoCrgkEXwTmjv1GHk59JMRF8DZ233ezppxpssME2uLw+CUQySOth4LrkUA7PLVcxjk7s UP+7OdA2NtD/Lupell9hj0Q35a70qWkW9PZdrQXvC3bqXphEGo4779HmR5NuOEPnBPly lOiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=LaXEwiyj3MgKPctp60ipXsQUebEP+5mdaxvo+R2WRtw=; b=joYVCdyq6I5svNBh+xVEUWOVMfnJECmvYuDjE3ozJhishQbS70ehmRspNjuuel1JWE BqBp6/im3u8AlCfRB6oi0Q+ySE2z7haKIiIZ9mxjHssi/xQq9RCmpGXZSlWi+IB0iXD4 D+6p2c97wSS67n8QAmGMUX2GOkhno8JsjtQllh69BtygXX6nAao2zDJJJQWxDkZdmKbh zQXXu4SP/46NHO9KNL6kQkvBL4M5kj1EPv8R0alfb4CP1vA5mVXgK+XjGEJTN9p+dfFS Yjd5laZ5d0VVMTkvhPgwvmfLZZ1APPtczeayFho/Ts7Slp0rQFaYkwOam7XiT5rQywaf sxew== X-Gm-Message-State: AOAM530xOSn3nfu05TeFMYuAJuiAg9H4YWhOxtLbFvm5zrstzMc+APzM dxDd3Sv7TqBcQkGvXVidCpn5TMT2rNc= X-Google-Smtp-Source: ABdhPJxFkE/6S2bXb/DiC+7xpTwEG+Px60JIceRAjFDtnoEnF2XgbQDbE3vGU5rXuA/vyLvl2tJtvpOXlRs= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a25:3b0d:: with SMTP id i13mr11726889yba.314.1598329362488; Mon, 24 Aug 2020 21:22:42 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:02 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-7-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 06/14 v1] dt-bindings: usb: Maxim type-c controller device tree binding document From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Add device tree binding document for Maxim TCPCI based Type-C chip driver Signed-off-by: Badhri Jagan Sridharan --- .../devicetree/bindings/usb/maxim,tcpci.txt | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/maxim,tcpci.txt diff --git a/Documentation/devicetree/bindings/usb/maxim,tcpci.txt b/Documentation/devicetree/bindings/usb/maxim,tcpci.txt new file mode 100644 index 000000000000..8a5b08e57b2d --- /dev/null +++ b/Documentation/devicetree/bindings/usb/maxim,tcpci.txt @@ -0,0 +1,44 @@ +Maxim TCPCI Type-C PD controller: +--------------------------------- + +Required properties: +- compatible: should be set maxim,tcpci: + +- reg: 0x25:the i2c slave address of typec port controller device. +- interrupt-parent: the phandle to the interrupt controller which provides + the interrupt. +- usbpd,usbpd_int: interrupt specification for tcpci alert. + +Required sub-node: +- connector: The "usb-c-connector" attached to the tcpci chip, the bindings + of connector node are specified in + Documentation/devicetree/bindings/connector/usb-connector.txt + +maxtcpc: maxtcpc@25 { + status = "okay"; + compatible = "maxim,tcpc"; + reg = <0x25>; + interrupt-parent = <&gpa8>; + usbpd,usbpd_int = <&gpa8 2 GPIO_ACTIVE_LOW>; + + connector { + compatible = "usb-c-connector"; + label = "USB-C"; + data-role = "dual"; + power-role = "dual"; + try-power-role = "sink"; + self-powered; + op-sink-microwatt = <2600000>; + source-pdos = ; + sink-pdos = ; + }; +}; From patchwork Tue Aug 25 04:22:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734841 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 43A3C739 for ; Tue, 25 Aug 2020 04:23:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1A1E620737 for ; Tue, 25 Aug 2020 04:23:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="dX5uz47r" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728543AbgHYEXh (ORCPT ); Tue, 25 Aug 2020 00:23:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50902 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728548AbgHYEWp (ORCPT ); Tue, 25 Aug 2020 00:22:45 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2FFA3C061574 for ; Mon, 24 Aug 2020 21:22:45 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id x6so13375119ybp.10 for ; Mon, 24 Aug 2020 21:22:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=sFdYqBQlTSkB+FFqFlpawTx7xM2r9WYQ3mb5WM7+TDQ=; b=dX5uz47rOdNS32QHVSWJzNCzMTPaSaOMrw2hwaJLtbyBStRFrCNExIdSuqI2aBsbka HHM6794Ikzpr4ubevzqkxqj5nERllwBBabxaFdvdaH2qbOdhvzfFjezAg0GbZqfeq52f t0nNIdyaDkQN2z6Jf/uj/xzlLC+Y1rbNHuXHOsfxnvA7znqHu2PIMUa8g+HxCJCyL77+ EMePiPFP4uTQWPB3UAOsH2G/fpIVM9O5dDbqnZWFm7cJigQA1fmkfRVmk6XO/2f/UsYE gYLmC2D0HAth92diZQZ8czf8O4KCgkH4bPCv/nhrEqI+iUT60Qx7/trveJqst5Xmz5CR 5dPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=sFdYqBQlTSkB+FFqFlpawTx7xM2r9WYQ3mb5WM7+TDQ=; b=kiHlZQYeG388oDnanbIy3WNWkn5qsXv4zi9N2fV9xHAgaFZeYYT5v1uL2I1FqP4Rpv M4wXfcs586lr+tCPRU3fG6kiP3jZWwmCsBV7a3mKSJtx1SYD66I+Xsj5367yp1W7FQxt JZTRRx2F5pQiuIozYPxBYvepZyJZSdCpIRiTzF4dQEgMfd8V3eZQVXqzRj+aN/2bTIFH 5hS2hw5c4kIVj/9VlRiufKk0GnSEHvLNrsbMWalTSg3cfyOmYSQWdl5PKa26ZYCVPTkF da7oh7Oq42tBohb1eFWKmXdz/AcIL6t4rP6MfOe7YEMPyC2GT08ptqunI1BuDU2rwBRu 5bQg== X-Gm-Message-State: AOAM533gXb+lqewzgQKK6RD3TA9j4OZSloDhv7UrTG7AUCEng3DJydJs a0+So6p2Wsy8GoLJvfortXAawTm9tmw= X-Google-Smtp-Source: ABdhPJyhAYrZP4syB+/LfKRsjiHSevArYgDQeEQwJ784AAKb9XLYH3OQm2uDpxYkuL+OQ7f8RrFPtNkYJWk= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a25:ca83:: with SMTP id a125mr12717448ybg.513.1598329364377; Mon, 24 Aug 2020 21:22:44 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:03 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-8-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 07/14 v1] usb: typec: tcpci_maxim: Chip level TCPC driver From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Chip level TCPC driver for Maxim's TCPCI implementation. This TCPC implementation does not support the following commands: COMMAND.SinkVbus, COMMAND.SourceVbusDefaultVoltage, COMMAND.SourceVbusHighVoltage. Instead the sinking and sourcing from vbus is supported by writes to custom registers. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/Kconfig | 6 + drivers/usb/typec/tcpm/Makefile | 13 +- drivers/usb/typec/tcpm/tcpci.h | 1 + drivers/usb/typec/tcpm/tcpci_maxim.c | 474 +++++++++++++++++++++++++++ 4 files changed, 488 insertions(+), 6 deletions(-) create mode 100644 drivers/usb/typec/tcpm/tcpci_maxim.c diff --git a/drivers/usb/typec/tcpm/Kconfig b/drivers/usb/typec/tcpm/Kconfig index fa3f39336246..7c9722b02afe 100644 --- a/drivers/usb/typec/tcpm/Kconfig +++ b/drivers/usb/typec/tcpm/Kconfig @@ -27,6 +27,12 @@ config TYPEC_RT1711H Type-C Port Controller Manager to provide USB PD and USB Type-C functionalities. +config TYPEC_TCPCI_MAXIM + tristate "Maxim TCPCI based Type-C chip driver" + select USB_PSY + help + MAXIM TCPCI based Type-C chip driver + endif # TYPEC_TCPCI config TYPEC_FUSB302 diff --git a/drivers/usb/typec/tcpm/Makefile b/drivers/usb/typec/tcpm/Makefile index a5ff6c8eb892..58d001cf0dd2 100644 --- a/drivers/usb/typec/tcpm/Makefile +++ b/drivers/usb/typec/tcpm/Makefile @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_TYPEC_TCPM) += tcpm.o -obj-$(CONFIG_TYPEC_FUSB302) += fusb302.o -obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o -typec_wcove-y := wcove.o -obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o -obj-$(CONFIG_TYPEC_RT1711H) += tcpci_rt1711h.o +obj-$(CONFIG_TYPEC_TCPM) += tcpm.o +obj-$(CONFIG_TYPEC_FUSB302) += fusb302.o +obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o +typec_wcove-y := wcove.o +obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o +obj-$(CONFIG_TYPEC_RT1711H) += tcpci_rt1711h.o +obj-$(CONFIG_TYPEC_TCPCI_MAXIM) += tcpci_maxim.o diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h index 4d441bdf24d5..82f021a82456 100644 --- a/drivers/usb/typec/tcpm/tcpci.h +++ b/drivers/usb/typec/tcpm/tcpci.h @@ -109,6 +109,7 @@ #define TCPC_RX_BYTE_CNT 0x30 #define TCPC_RX_BUF_FRAME_TYPE 0x31 +#define TCPC_RX_BUF_FRAME_TYPE_SOP 0 #define TCPC_RX_HDR 0x32 #define TCPC_RX_DATA 0x34 /* through 0x4f */ diff --git a/drivers/usb/typec/tcpm/tcpci_maxim.c b/drivers/usb/typec/tcpm/tcpci_maxim.c new file mode 100644 index 000000000000..b61f290a8f96 --- /dev/null +++ b/drivers/usb/typec/tcpm/tcpci_maxim.c @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020, Google LLC + * + * MAXIM TCPCI based TCPC driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tcpci.h" + +#define PD_ACTIVITY_TIMEOUT_MS 10000 + +#define TCPC_VENDOR_ALERT 0x80 + +#define TCPC_RECEIVE_BUFFER_COUNT_OFFSET 0 +#define TCPC_RECEIVE_BUFFER_FRAME_TYPE_OFFSET 1 +#define TCPC_RECEIVE_BUFFER_RX_BYTE_BUF_OFFSET 2 + +/* + * LongMessage not supported, hence 32 bytes for buf to be read from RECEIVE_BUFFER. + * DEVICE_CAPABILITIES_2.LongMessage = 0, the value in READABLE_BYTE_COUNT reg shall be + * less than or equal to 31. Since, RECEIVE_BUFFER len = 31 + 1(READABLE_BYTE_COUNT). + */ +#define TCPC_RECEIVE_BUFFER_LEN 32 + +#define MAX_BUCK_BOOST_SID 0x69 +#define MAX_BUCK_BOOST_OP 0xb9 +#define MAX_BUCK_BOOST_OFF 0 +#define MAX_BUCK_BOOST_SOURCE 0xa +#define MAX_BUCK_BOOST_SINK 0x5 + +struct max_tcpci_chip { + struct tcpci_data data; + struct tcpci *tcpci; + struct device *dev; + struct i2c_client *client; + struct tcpm_port *port; +}; + +static const struct regmap_range max_tcpci_tcpci_range[] = { + regmap_reg_range(0x00, 0x95) +}; + +const struct regmap_access_table max_tcpci_tcpci_write_table = { + .yes_ranges = max_tcpci_tcpci_range, + .n_yes_ranges = ARRAY_SIZE(max_tcpci_tcpci_range), +}; + +static const struct regmap_config max_tcpci_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x95, + .wr_table = &max_tcpci_tcpci_write_table, +}; + +static struct max_tcpci_chip *tdata_to_max_tcpci(struct tcpci_data *tdata) +{ + return container_of(tdata, struct max_tcpci_chip, data); +} + +static int max_tcpci_read16(struct max_tcpci_chip *chip, unsigned int reg, u16 *val) +{ + return regmap_raw_read(chip->data.regmap, reg, val, sizeof(u16)); +} + +static int max_tcpci_write16(struct max_tcpci_chip *chip, unsigned int reg, u16 val) +{ + return regmap_raw_write(chip->data.regmap, reg, &val, sizeof(u16)); +} + +static int max_tcpci_read8(struct max_tcpci_chip *chip, unsigned int reg, u8 *val) +{ + return regmap_raw_read(chip->data.regmap, reg, val, sizeof(u8)); +} + +static int max_tcpci_write8(struct max_tcpci_chip *chip, unsigned int reg, u8 val) +{ + return regmap_raw_write(chip->data.regmap, reg, &val, sizeof(u8)); +} + +static void max_tcpci_init_regs(struct max_tcpci_chip *chip) +{ + u16 alert_mask = 0; + int ret; + + ret = max_tcpci_write16(chip, TCPC_ALERT, 0xffff); + if (ret < 0) { + dev_err(chip->dev, "Error writing to TCPC_ALERT ret:%d\n", ret); + return; + } + + ret = max_tcpci_write16(chip, TCPC_VENDOR_ALERT, 0xffff); + if (ret < 0) { + dev_err(chip->dev, "Error writing to TCPC_VENDOR_ALERT ret:%d\n", ret); + return; + } + + alert_mask = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_TX_FAILED | + TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_RX_STATUS | TCPC_ALERT_CC_STATUS | + TCPC_ALERT_VBUS_DISCNCT | TCPC_ALERT_RX_BUF_OVF | TCPC_ALERT_POWER_STATUS; + + ret = max_tcpci_write16(chip, TCPC_ALERT_MASK, alert_mask); + if (ret < 0) { + dev_err(chip->dev, "Error writing to TCPC_ALERT_MASK ret:%d\n", ret); + return; + } + + /* Enable vbus voltage monitoring and voltage alerts */ + ret = max_tcpci_write8(chip, TCPC_POWER_CTRL, 0); + if (ret < 0) { + dev_err(chip->dev, "Error writing to TCPC_POWER_CTRL ret:%d\n", ret); + return; + } +} + +static void process_rx(struct max_tcpci_chip *chip, u16 status) +{ + struct pd_message msg; + u8 count, frame_type, rx_buf[TCPC_RECEIVE_BUFFER_LEN]; + int ret, payload_index; + u8 *rx_buf_ptr; + + /* + * READABLE_BYTE_COUNT: Indicates the number of bytes in the RX_BUF_BYTE_x registers + * plus one (for the RX_BUF_FRAME_TYPE) Table 4-36. + * Read the count and frame type. + */ + ret = regmap_raw_read(chip->data.regmap, TCPC_RX_BYTE_CNT, rx_buf, 2); + if (ret < 0) { + dev_err(chip->dev, "TCPC_RX_BYTE_CNT read failed ret:%d", ret); + return; + } + + count = rx_buf[TCPC_RECEIVE_BUFFER_COUNT_OFFSET]; + frame_type = rx_buf[TCPC_RECEIVE_BUFFER_FRAME_TYPE_OFFSET]; + + if (count == 0 || frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP) { + max_tcpci_write16(chip, TCPC_ALERT, TCPC_ALERT_RX_STATUS); + dev_err(chip->dev, "%s", count == 0 ? "error: count is 0" : + "error frame_type is not SOP"); + return; + } + + if (count > sizeof(struct pd_message) || count + 1 > TCPC_RECEIVE_BUFFER_LEN) { + dev_err(chip->dev, "Invalid TCPC_RX_BYTE_CNT %d", count); + return; + } + + /* + * Read count + 1 as RX_BUF_BYTE_x is hidden and can only be read through + * TCPC_RX_BYTE_CNT + */ + count += 1; + ret = regmap_raw_read(chip->data.regmap, TCPC_RX_BYTE_CNT, rx_buf, count); + if (ret < 0) { + dev_err(chip->dev, "Error: TCPC_RX_BYTE_CNT read failed: %d", ret); + return; + } + + rx_buf_ptr = rx_buf + TCPC_RECEIVE_BUFFER_RX_BYTE_BUF_OFFSET; + msg.header = cpu_to_le16(*(u16 *)rx_buf_ptr); + rx_buf_ptr = rx_buf_ptr + sizeof(msg.header); + for (payload_index = 0; payload_index < pd_header_cnt_le(msg.header); payload_index++, + rx_buf_ptr += sizeof(msg.payload[0])) + msg.payload[payload_index] = cpu_to_le32(*(u32 *)rx_buf_ptr); + + /* + * Read complete, clear RX status alert bit. + * Clear overflow as well if set. + */ + ret = max_tcpci_write16(chip, TCPC_ALERT, status & TCPC_ALERT_RX_BUF_OVF ? + TCPC_ALERT_RX_STATUS | TCPC_ALERT_RX_BUF_OVF : + TCPC_ALERT_RX_STATUS); + if (ret < 0) + return; + + tcpm_pd_receive(chip->port, &msg); +} + +static int max_tcpci_set_vbus(struct tcpci *tcpci, struct tcpci_data *tdata, bool source, bool sink) +{ + struct max_tcpci_chip *chip = tdata_to_max_tcpci(tdata); + u8 buffer_source[2] = {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_SOURCE}; + u8 buffer_sink[2] = {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_SINK}; + u8 buffer_none[2] = {MAX_BUCK_BOOST_OP, MAX_BUCK_BOOST_OFF}; + struct i2c_client *i2c = chip->client; + int ret; + + struct i2c_msg msgs[] = { + { + .addr = MAX_BUCK_BOOST_SID, + .flags = i2c->flags & I2C_M_TEN, + .len = 2, + .buf = source ? buffer_source : sink ? buffer_sink : buffer_none, + }, + }; + + if (source && sink) { + dev_err(chip->dev, "Both source and sink set\n"); + return -EINVAL; + } + + ret = i2c_transfer(i2c->adapter, msgs, 1); + + return ret < 0 ? ret : 1; +} + +static void process_power_status(struct max_tcpci_chip *chip) +{ + u8 pwr_status; + int ret; + + ret = max_tcpci_read8(chip, TCPC_POWER_STATUS, &pwr_status); + if (ret < 0) + return; + + if (pwr_status == 0xff) + max_tcpci_init_regs(chip); + else + tcpm_vbus_change(chip->port); +} + +static void process_tx(struct max_tcpci_chip *chip, u16 status) +{ + if (status & TCPC_ALERT_TX_SUCCESS) + tcpm_pd_transmit_complete(chip->port, TCPC_TX_SUCCESS); + else if (status & TCPC_ALERT_TX_DISCARDED) + tcpm_pd_transmit_complete(chip->port, TCPC_TX_DISCARDED); + else if (status & TCPC_ALERT_TX_FAILED) + tcpm_pd_transmit_complete(chip->port, TCPC_TX_FAILED); + + /* Reinit regs as Hard reset sets them to default value */ + if ((status & TCPC_ALERT_TX_SUCCESS) && (status & TCPC_ALERT_TX_FAILED)) + max_tcpci_init_regs(chip); +} + +static irqreturn_t _max_tcpci_irq(struct max_tcpci_chip *chip, u16 status) +{ + u16 mask; + int ret; + + /* + * Clear alert status for everything except RX_STATUS, which shouldn't + * be cleared until we have successfully retrieved message. + */ + if (status & ~TCPC_ALERT_RX_STATUS) { + mask = status & TCPC_ALERT_RX_BUF_OVF ? + status & ~(TCPC_ALERT_RX_STATUS | TCPC_ALERT_RX_BUF_OVF) : + status & ~TCPC_ALERT_RX_STATUS; + ret = max_tcpci_write16(chip, TCPC_ALERT, mask); + if (ret < 0) { + dev_err(chip->dev, "ALERT clear failed\n"); + return ret; + } + } + + if (status & TCPC_ALERT_RX_BUF_OVF && !(status & TCPC_ALERT_RX_STATUS)) { + ret = max_tcpci_write16(chip, TCPC_ALERT, (TCPC_ALERT_RX_STATUS | + TCPC_ALERT_RX_BUF_OVF)); + if (ret < 0) { + dev_err(chip->dev, "ALERT clear failed\n"); + return ret; + } + } + + if (status & TCPC_ALERT_RX_STATUS) + process_rx(chip, status); + + if (status & TCPC_ALERT_TX_DISCARDED) + dev_info(chip->dev, "TX_DISCARDED"); + + if (status & TCPC_ALERT_VBUS_DISCNCT) + tcpm_vbus_change(chip->port); + + if (status & TCPC_ALERT_CC_STATUS) + tcpm_cc_change(chip->port); + + if (status & TCPC_ALERT_POWER_STATUS) + process_power_status(chip); + + if (status & TCPC_ALERT_RX_HARD_RST) { + tcpm_pd_hard_reset(chip->port); + max_tcpci_init_regs(chip); + } + + if (status & TCPC_ALERT_TX_SUCCESS || status & TCPC_ALERT_TX_DISCARDED || status & + TCPC_ALERT_TX_FAILED) + process_tx(chip, status); + + return IRQ_HANDLED; +} + +static irqreturn_t max_tcpci_irq(int irq, void *dev_id) +{ + struct max_tcpci_chip *chip = dev_id; + u16 status; + irqreturn_t irq_return; + int ret; + + if (!chip->port) + return IRQ_HANDLED; + + ret = max_tcpci_read16(chip, TCPC_ALERT, &status); + if (ret < 0) { + dev_err(chip->dev, "ALERT read failed\n"); + return ret; + } + while (status) { + irq_return = _max_tcpci_irq(chip, status); + /* Do not return if the ALERT is already set. */ + ret = max_tcpci_read16(chip, TCPC_ALERT, &status); + if (ret < 0) + break; + } + + return irq_return; +} + +static irqreturn_t max_tcpci_isr(int irq, void *dev_id) +{ + struct max_tcpci_chip *chip = dev_id; + + pm_wakeup_event(chip->dev, PD_ACTIVITY_TIMEOUT_MS); + + if (!chip->port) + return IRQ_HANDLED; + + return IRQ_WAKE_THREAD; +} + +static int max_tcpci_init_alert(struct max_tcpci_chip *chip, struct i2c_client *client) +{ + int ret, irq_gpio; + + irq_gpio = of_get_named_gpio(client->dev.of_node, "usbpd,usbpd_int", 0); + client->irq = gpio_to_irq(irq_gpio); + if (!client->irq) + return -ENODEV; + + ret = devm_request_threaded_irq(chip->dev, client->irq, max_tcpci_isr, max_tcpci_irq, + (IRQF_TRIGGER_LOW | IRQF_ONESHOT), dev_name(chip->dev), + chip); + + if (ret < 0) + return ret; + + enable_irq_wake(client->irq); + return 0; +} + +static int max_tcpci_start_toggling(struct tcpci *tcpci, struct tcpci_data *tdata, + enum typec_cc_status cc) +{ + struct max_tcpci_chip *chip = tdata_to_max_tcpci(tdata); + + max_tcpci_init_regs(chip); + + return 0; +} + +static int tcpci_init(struct tcpci *tcpci, struct tcpci_data *data) +{ + /* + * Generic TCPCI overwrites the regs once this driver initializes + * them. Prevent this by returning -1. + */ + return -1; +} + +static int max_tcpci_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) +{ + int ret; + struct max_tcpci_chip *chip; + u8 power_status; + + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->client = client; + chip->data.regmap = devm_regmap_init_i2c(client, &max_tcpci_regmap_config); + if (IS_ERR(chip->data.regmap)) { + dev_err(&client->dev, "Regmap init failed\n"); + return PTR_ERR(chip->data.regmap); + } + + chip->dev = &client->dev; + i2c_set_clientdata(client, chip); + + ret = max_tcpci_read8(chip, TCPC_POWER_STATUS, &power_status); + if (ret < 0) + return ret; + + if (power_status & TCPC_POWER_STATUS_UNINIT) { + dev_err(&client->dev, "TCPC not ready!"); + return -EPROBE_DEFER; + } + + /* Chip level tcpci callbacks */ + chip->data.set_vbus = max_tcpci_set_vbus; + chip->data.start_drp_toggling = max_tcpci_start_toggling; + chip->data.TX_BUF_BYTE_x_hidden = true; + chip->data.init = tcpci_init; + + max_tcpci_init_regs(chip); + chip->tcpci = tcpci_register_port(chip->dev, &chip->data); + if (IS_ERR_OR_NULL(chip->tcpci)) { + dev_err(&client->dev, "TCPCI port registration failed"); + ret = PTR_ERR(chip->tcpci); + return PTR_ERR(chip->tcpci); + } + chip->port = tcpci_get_tcpm_port(chip->tcpci); + ret = max_tcpci_init_alert(chip, client); + if (ret < 0) + goto unreg_port; + + device_init_wakeup(chip->dev, true); + return 0; + +unreg_port: + tcpci_unregister_port(chip->tcpci); + + return ret; +} + +static int max_tcpci_remove(struct i2c_client *client) +{ + struct max_tcpci_chip *chip = i2c_get_clientdata(client); + + if (!IS_ERR_OR_NULL(chip->tcpci)) + tcpci_unregister_port(chip->tcpci); + + return 0; +} + +static const struct i2c_device_id max_tcpci_id[] = { + { "maxtcpc", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max_tcpci_id); + +#ifdef CONFIG_OF +static const struct of_device_id max_tcpci_of_match[] = { + { .compatible = "maxim,tcpc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, max_tcpci_of_match); +#endif + +static struct i2c_driver max_tcpci_i2c_driver = { + .driver = { + .name = "maxtcpc", + .of_match_table = of_match_ptr(max_tcpci_of_match), + }, + .probe = max_tcpci_probe, + .remove = max_tcpci_remove, + .id_table = max_tcpci_id, +}; +module_i2c_driver(max_tcpci_i2c_driver); + +MODULE_AUTHOR("Badhri Jagan Sridharan "); +MODULE_DESCRIPTION("Maxim TCPCI based USB Type-C Port Controller Interface Driver"); +MODULE_LICENSE("GPL v2"); From patchwork Tue Aug 25 04:22:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734831 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5CCBA138A for ; Tue, 25 Aug 2020 04:23:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3A7AA20738 for ; Tue, 25 Aug 2020 04:23:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="SWck33LS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728675AbgHYEW6 (ORCPT ); Tue, 25 Aug 2020 00:22:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50910 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728619AbgHYEWs (ORCPT ); Tue, 25 Aug 2020 00:22:48 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3276EC061755 for ; Mon, 24 Aug 2020 21:22:47 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 78so1902634pgf.5 for ; Mon, 24 Aug 2020 21:22:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=xSJS/XKA/aUbgtCi/q0K7inzUjymBY7nSgjzrufvP5I=; b=SWck33LSi0EUA97KEivGtM62HLq7cI9NPByz2VNQN5Yj76sbRwA6eIbsgtw8t23Bo1 4dpzmutg2ZM1LAJHCqo01eRTrUM9a/MKq6F7uNwM1uO7gJn/bocbf5OvUlnWy0M1yraV Heefpw9QTivgPe9clxyaQp7XfjjLvU8jD8sjFD0WyP3mliSoP4ypB5g3bjOc+uzw8zUs orCxBMEIdseOw4S9L+tyozs83Lp0XsJT0NoekcAenBCZytN4OLq9EQ9I+2MMKYZI9fwt 1DdK4dQP6isJnXpvq278juj4El9L1p4/f5qH5gTMSnu/Ndpk/krM/OppVWZLdRoGxIRE nT7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=xSJS/XKA/aUbgtCi/q0K7inzUjymBY7nSgjzrufvP5I=; b=Ifi3rkEJf96CU1M4cdX4wF0kRUcyXZtRUyb/rozYXP39E3Bre6AQx+j8yiwYi9H3Aw hj5oDUMor0Gxf0jZUgzr+qjF1cSewubuZ8bidKp/W2MkqhnjOjInyGDX6s4pojHhUTXb BV5SXhDkYL+aAqyCcAXnjd1TEsR6Z2gcXOR0zZM50TLMPXX0+MVY7mozymlp/MALYsyE fkN/96nK9RVEP04qSkxSBT+b2P1gY9KDetUnPuoXa0HasMeIHQbj+bLO6EXLOcxyYQF5 al++zWiq+aeL7iKM0JBJumr6CaNifdmHYDCecV3YxxZ34624s+poACpFg+80TeY86PFO objg== X-Gm-Message-State: AOAM532wSvb+0qiHqh8P3Ik2/NmIOzWVxqa9H9mpfH1/r3dFGWzBzxQi luBWCwLorM8hraC5g9BdDEDuS2DvaH8= X-Google-Smtp-Source: ABdhPJwHNxFi0Ec+H6bmOoX2PQxOar5hmeGLFWZaRs3cPffAINCKLYgzjt/DsBEo87S7HZEhfXLkegbK/LQ= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a63:3e0c:: with SMTP id l12mr2515256pga.190.1598329366531; Mon, 24 Aug 2020 21:22:46 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:04 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-9-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 08/14 v1] dt-bindings: connector: Add property to set initial current cap for FRS From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This change adds frs-typec-current which allows setting the initial current capability of the new source when vSafe5V is applied during PD3.0 sink Fast Role Swap. Signed-off-by: Badhri Jagan Sridharan --- .../bindings/connector/usb-connector.txt | 128 ++++++++++++++++++ include/dt-bindings/usb/pd.h | 10 ++ 2 files changed, 138 insertions(+) create mode 100644 Documentation/devicetree/bindings/connector/usb-connector.txt diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt new file mode 100644 index 000000000000..e2f6e0f07d00 --- /dev/null +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt @@ -0,0 +1,128 @@ +USB Connector +============= + +USB connector node represents physical USB connector. It should be +a child of USB interface controller. + +Required properties: +- compatible: describes type of the connector, must be one of: + "usb-a-connector", + "usb-b-connector", + "usb-c-connector". + +Optional properties: +- label: symbolic name for the connector, +- type: size of the connector, should be specified in case of USB-A, USB-B + non-fullsize connectors: "mini", "micro". + +Optional properties for usb-c-connector: +- power-role: should be one of "source", "sink" or "dual"(DRP) if typec + connector has power support. +- try-power-role: preferred power role if "dual"(DRP) can support Try.SNK + or Try.SRC, should be "sink" for Try.SNK or "source" for Try.SRC. +- data-role: should be one of "host", "device", "dual"(DRD) if typec + connector supports USB data. +- frs-typec-current - Initial current capability of the new source when vSafe5V + is applied during PD3.0 Fast Role Swap. "Table 6-14 Fixed Supply PDO - Sink" + of "USB Power Delivery Specification Revision 3.0, Version 1.2" provides the + different power levels and "6.4.1.3.1.6 Fast Role Swap USB Type-C Current" + provides a detailed description of the field. + 0: Fast role swap not supported + 1: Default USB Power + 2: 1.5A @ 5V + 3: 3A @ 5V. + +Required properties for usb-c-connector with power delivery support: +- source-pdos: An array of u32 with each entry providing supported power + source data object(PDO), the detailed bit definitions of PDO can be found + in "Universal Serial Bus Power Delivery Specification" chapter 6.4.1.2 + Source_Capabilities Message, the order of each entry(PDO) should follow + the PD spec chapter 6.4.1. Required for power source and power dual role. + User can specify the source PDO array via PDO_FIXED/BATT/VAR/PPS_APDO() + defined in dt-bindings/usb/pd.h. +- sink-pdos: An array of u32 with each entry providing supported power + sink data object(PDO), the detailed bit definitions of PDO can be found + in "Universal Serial Bus Power Delivery Specification" chapter 6.4.1.3 + Sink Capabilities Message, the order of each entry(PDO) should follow + the PD spec chapter 6.4.1. Required for power sink and power dual role. + User can specify the sink PDO array via PDO_FIXED/BATT/VAR/PPS_APDO() defined + in dt-bindings/usb/pd.h. +- op-sink-microwatt: Sink required operating power in microwatt, if source + can't offer the power, Capability Mismatch is set. Required for power + sink and power dual role. + +Required nodes: +- any data bus to the connector should be modeled using the OF graph bindings + specified in bindings/graph.txt, unless the bus is between parent node and + the connector. Since single connector can have multpile data buses every bus + has assigned OF graph port number as follows: + 0: High Speed (HS), present in all connectors, + 1: Super Speed (SS), present in SS capable connectors, + 2: Sideband use (SBU), present in USB-C. + +Examples +-------- + +1. Micro-USB connector with HS lines routed via controller (MUIC): + +muic-max77843@66 { + ... + usb_con: connector { + compatible = "usb-b-connector"; + label = "micro-USB"; + type = "micro"; + }; +}; + +2. USB-C connector attached to CC controller (s2mm005), HS lines routed +to companion PMIC (max77865), SS lines to USB3 PHY and SBU to DisplayPort. +DisplayPort video lines are routed to the connector via SS mux in USB3 PHY. + +ccic: s2mm005@33 { + ... + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usb_con_hs: endpoint { + remote-endpoint = <&max77865_usbc_hs>; + }; + }; + port@1 { + reg = <1>; + usb_con_ss: endpoint { + remote-endpoint = <&usbdrd_phy_ss>; + }; + }; + port@2 { + reg = <2>; + usb_con_sbu: endpoint { + remote-endpoint = <&dp_aux>; + }; + }; + }; + }; +}; + +3. USB-C connector attached to a typec port controller(ptn5110), which has +power delivery support and enables drp. + +typec: ptn5110@50 { + ... + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "dual"; + try-power-role = "sink"; + source-pdos = ; + sink-pdos = ; + op-sink-microwatt = <10000000>; + }; +}; diff --git a/include/dt-bindings/usb/pd.h b/include/dt-bindings/usb/pd.h index 985f2bbd4d24..db1ad4532197 100644 --- a/include/dt-bindings/usb/pd.h +++ b/include/dt-bindings/usb/pd.h @@ -35,6 +35,16 @@ #define VSAFE5V 5000 /* mv units */ +/* + * Based on "Table 6-14 Fixed Supply PDO - Sink" of "USB Power Delivery Specification Revision 3.0, + * Version 1.2" + * Initial current capability of the new source when vSafe5V is applied. + */ +#define FRS_NOT_SUPPORTED 0 +#define FRS_DEFAULT_POWER 1 +#define FRS_5V_1P5A 2 +#define FRS_5V_3A 3 + #define PDO_BATT_MAX_VOLT_SHIFT 20 /* 50mV units */ #define PDO_BATT_MIN_VOLT_SHIFT 10 /* 50mV units */ #define PDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */ From patchwork Tue Aug 25 04:22:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734825 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 737CF138A for ; Tue, 25 Aug 2020 04:22:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 46F2320738 for ; Tue, 25 Aug 2020 04:22:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="mmmB2Exv" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728663AbgHYEW4 (ORCPT ); Tue, 25 Aug 2020 00:22:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50920 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728641AbgHYEWt (ORCPT ); Tue, 25 Aug 2020 00:22:49 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 42AF6C061574 for ; Mon, 24 Aug 2020 21:22:49 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id z8so903479pje.0 for ; Mon, 24 Aug 2020 21:22:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=0lRmp2/7y7+M4Cv+GnGEUWhRIv+1zE3ZXMhtLLZglQU=; b=mmmB2ExvCiOI90EB7zT8G5dQklQ382yJAR7geqEUVTaBAcepreLYAvb3U8o8YRaLhJ eaXTeDTcfenGjtS80Z2gPrllG4xDrArvjaCgi5q7mo9bWFl6g3udlFh6W4l2+RJ6zOl2 LE1g1l2Jb/EaiuUJdGEEyirVoJ6/9tf3onhQuyjcnvO1K57enXRWZ5RY8Z2WZiWzvTyQ pmXK1Kq2Zsm1UXcLZimuSR72pTWER8tO8D3ynrhcUCpDOFHn/IHaZplS7h5rsUjLBKc9 y2A1uY9lPgc9BWy8kHFP6I0DgFTjlmhAN5F3JXm1UbdGdVenFtXW0YX3D7TNxTczjsN8 8OyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=0lRmp2/7y7+M4Cv+GnGEUWhRIv+1zE3ZXMhtLLZglQU=; b=tHeEtje7mUyyHgRvqHQr8JIZSUzphfwhrWQFPjEMbKQ3DZN8/329WNZf1wwShCQSH5 c05pl3U//fGBe7+SDB3xoLECrdPKxKma3ZU/8yS9105g92w8iPUoHx6fBdPCPHYt9Gfn UcBwx/lk+hfyKjKBfXHL7DiuQBxHvzUefJXVcegNn52z6VgmeAKCL/Y0Tj2BTOZvlQ8n JBTGNfId2ge2ilhw20UJk/BJHzPFjnekovfwhUh2h1ganeUtnTLelYaTkUOsk5O7D51H 8bAJFC8/xaFBeoc0mz//xZywFBVPInFj4K964FsHcjwZ/n15HvHanq7bs/V95iSaHkR4 sMrA== X-Gm-Message-State: AOAM530bScR/dQbhPvYN6O6RD+1LEM0z6AYkI+uKcSwHLhjBpKKasePK JfXJaKwSYVggp/zvFlIUpJcfAsDakhA= X-Google-Smtp-Source: ABdhPJwhnbqEM/2frajI0zlNJPY9cCkPjk7bZfX0sh3YW1qzTJ7Ep7T4teMKe85gb870KoohDlLUXiVwnJk= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a17:90a:5aa2:: with SMTP id n31mr48795pji.33.1598329368736; Mon, 24 Aug 2020 21:22:48 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:05 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-10-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 09/14 v1] usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS) From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org PD 3.0 spec defines a new mechanism for power role swap called Fast role swap. This change enables TCPM to support FRS when acting as sink. Once the explicit contract is negotiated, sink port is expected to query the source port for sink caps to determine whether the source is FRS capable. Bits 23 & 24 of fixed pdo of the sink caps from the source, when set, indicates the current needed by the source when fast role swap is in progress(Implicit contract phasae). 0 indicates that the source does not support Fast Role Swap. Upon receiving the FRS signal from the source, TCPC(TCPM_FRS_EVENT) informs TCPM to start the Fast role swap sequence. 1. TCPM sends FRS PD message: FR_SWAP_SEND 2. If response is not received within the expiry of SenderResponseTimer, Error recovery is triggered.: FR_SWAP_SEND_TIMEOUT 3. Upon receipt of the accept message, TCPM waits for PSSourceOffTimer for PS_READY message from the partner: FR_SWAP_SNK_SRC_NEW_SINK_READY. TCPC is expected to autonomously turn on vbus once the FRS signal is received and vbus voltage falls below vsafe5v within tSrcFrSwap. This is different from traditional power role swap where the vbus sourcing is turned on by TCPM. 4. By this time, TCPC most likely would have started to source vbus, TCPM waits for tSrcFrSwap to see if the lower level TCPC driver signals TCPM_SOURCING_VBUS event: FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED. 5. When TCPC signals sourcing vbus, TCPM sends PS_READY msg and changes the CC pin from Rd to Rp. This is the end of fast role swap sequence and TCPM initiates the sequnce to negotiate explicit contract by transitioning into SRC_STARTUP after SwapSrcStart. The code is written based on the sequence described in "Figure 8-107: Dual-role Port in Sink to Source Fast Role Swap State Diagram" of USB Power Delivery Specification Revision 3.0, Version 1.2. Signed-off-by: Badhri Jagan Sridharan Reported-by: kernel test robot --- drivers/usb/typec/tcpm/tcpm.c | 191 +++++++++++++++++++++++++++++++++- include/linux/usb/pd.h | 20 ++-- include/linux/usb/tcpm.h | 8 +- include/linux/usb/typec.h | 13 +++ 4 files changed, 220 insertions(+), 12 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 3ef37202ee37..6ea4613af905 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -103,6 +103,13 @@ S(VCONN_SWAP_TURN_ON_VCONN), \ S(VCONN_SWAP_TURN_OFF_VCONN), \ \ + S(FR_SWAP_SEND), \ + S(FR_SWAP_SEND_TIMEOUT), \ + S(FR_SWAP_SNK_SRC_TRANSITION_TO_OFF), \ + S(FR_SWAP_SNK_SRC_NEW_SINK_READY), \ + S(FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED), \ + S(FR_SWAP_CANCEL), \ + \ S(SNK_TRY), \ S(SNK_TRY_WAIT), \ S(SNK_TRY_WAIT_DEBOUNCE), \ @@ -124,6 +131,9 @@ S(GET_PPS_STATUS_SEND), \ S(GET_PPS_STATUS_SEND_TIMEOUT), \ \ + S(GET_SINK_CAP), \ + S(GET_SINK_CAP_TIMEOUT), \ + \ S(ERROR_RECOVERY), \ S(PORT_RESET), \ S(PORT_RESET_WAIT_OFF) @@ -172,6 +182,8 @@ enum adev_actions { #define TCPM_CC_EVENT BIT(0) #define TCPM_VBUS_EVENT BIT(1) #define TCPM_RESET_EVENT BIT(2) +#define TCPM_FRS_EVENT BIT(3) +#define TCPM_SOURCING_VBUS BIT(4) #define LOG_BUFFER_ENTRIES 1024 #define LOG_BUFFER_ENTRY_SIZE 128 @@ -181,6 +193,8 @@ enum adev_actions { #define SVID_DISCOVERY_MAX 16 #define ALTMODE_DISCOVERY_MAX (SVID_DISCOVERY_MAX * MODE_DISCOVERY_MAX) +#define GET_SINK_CAP_RETRY_MS 100 + struct pd_mode_data { int svid_index; /* current SVID index */ int nsvids; @@ -256,6 +270,7 @@ struct tcpm_port { struct work_struct event_work; struct delayed_work state_machine; struct delayed_work vdm_state_machine; + struct delayed_work enable_frs; bool state_machine_running; struct completion tx_complete; @@ -330,6 +345,12 @@ struct tcpm_port { /* port belongs to a self powered device */ bool self_powered; + /* FRS */ + enum frs_typec_current frs_current; + + /* Sink caps have been queried */ + bool sink_cap_done; + #ifdef CONFIG_DEBUG_FS struct dentry *dentry; struct mutex logbuffer_lock; /* log buffer access lock */ @@ -1646,6 +1667,9 @@ static void tcpm_pd_data_request(struct tcpm_port *port, unsigned int cnt = pd_header_cnt_le(msg->header); unsigned int rev = pd_header_rev_le(msg->header); unsigned int i; + enum frs_typec_current frs_current; + bool frs_enable; + int ret; switch (type) { case PD_DATA_SOURCE_CAP: @@ -1715,7 +1739,21 @@ static void tcpm_pd_data_request(struct tcpm_port *port, /* We don't do anything with this at the moment... */ for (i = 0; i < cnt; i++) port->sink_caps[i] = le32_to_cpu(msg->payload[i]); + + frs_current = (port->sink_caps[0] & PDO_FIXED_FRS_CURR_MASK) >> + PDO_FIXED_FRS_CURR_SHIFT; + frs_enable = frs_current && (frs_current <= port->typec_caps.frs_current); + tcpm_log(port, + "Port partner FRS capable partner_frs_current:%u port_frs_current:%u enable:%c", + frs_current, port->typec_caps.frs_current, frs_enable ? 'y' : 'n'); + if (frs_enable) { + ret = port->tcpc->enable_frs(port->tcpc, true); + tcpm_log(port, "Enable FRS %s, ret:%d\n", ret ? "fail" : "success", ret); + } + port->nr_sink_caps = cnt; + port->sink_cap_done = true; + tcpm_set_state(port, SNK_READY, 0); break; case PD_DATA_VENDOR_DEF: tcpm_handle_vdm_request(port, msg->payload, cnt); @@ -1810,6 +1848,9 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, case VCONN_SWAP_WAIT_FOR_VCONN: tcpm_set_state(port, VCONN_SWAP_TURN_OFF_VCONN, 0); break; + case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF: + tcpm_set_state(port, FR_SWAP_SNK_SRC_NEW_SINK_READY, 0); + break; default: break; } @@ -1849,6 +1890,13 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, -EAGAIN : -EOPNOTSUPP); tcpm_set_state(port, VCONN_SWAP_CANCEL, 0); break; + case FR_SWAP_SEND: + tcpm_set_state(port, FR_SWAP_CANCEL, 0); + break; + case GET_SINK_CAP: + port->sink_cap_done = true; + tcpm_set_state(port, ready_state(port), 0); + break; default: break; } @@ -1883,6 +1931,9 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, case VCONN_SWAP_SEND: tcpm_set_state(port, VCONN_SWAP_START, 0); break; + case FR_SWAP_SEND: + tcpm_set_state(port, FR_SWAP_SNK_SRC_TRANSITION_TO_OFF, 0); + break; default: break; } @@ -2783,6 +2834,10 @@ static void tcpm_reset_port(struct tcpm_port *port) port->try_src_count = 0; port->try_snk_count = 0; port->usb_type = POWER_SUPPLY_USB_TYPE_C; + port->nr_sink_caps = 0; + port->sink_cap_done = false; + if (port->tcpc->enable_frs) + port->tcpc->enable_frs(port->tcpc, false); power_supply_changed(port->psy); } @@ -3334,10 +3389,9 @@ static void run_state_machine(struct tcpm_port *port) tcpm_swap_complete(port, 0); tcpm_typec_connect(port); tcpm_check_send_discover(port); + mod_delayed_work(port->wq, &port->enable_frs, msecs_to_jiffies(0)); tcpm_pps_complete(port, port->pps_status); - power_supply_changed(port->psy); - break; /* Accessory states */ @@ -3361,9 +3415,13 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, HARD_RESET_START, 0); break; case HARD_RESET_START: + port->sink_cap_done = false; + if (port->tcpc->enable_frs) + port->tcpc->enable_frs(port->tcpc, false); port->hard_reset_count++; port->tcpc->set_pd_rx(port->tcpc, false); tcpm_unregister_altmodes(port); + port->nr_sink_caps = 0; port->send_discover = true; if (port->pwr_role == TYPEC_SOURCE) tcpm_set_state(port, SRC_HARD_RESET_VBUS_OFF, @@ -3477,6 +3535,35 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, ready_state(port), 0); break; + case FR_SWAP_SEND: + if (tcpm_pd_send_control(port, PD_CTRL_FR_SWAP)) { + tcpm_set_state(port, ERROR_RECOVERY, 0); + break; + } + tcpm_set_state_cond(port, FR_SWAP_SEND_TIMEOUT, PD_T_SENDER_RESPONSE); + break; + case FR_SWAP_SEND_TIMEOUT: + tcpm_set_state(port, ERROR_RECOVERY, 0); + break; + case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF: + tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_OFF); + break; + case FR_SWAP_SNK_SRC_NEW_SINK_READY: + if (port->vbus_source) + tcpm_set_state(port, FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED, 0); + else + tcpm_set_state(port, ERROR_RECOVERY, PD_T_RECEIVER_RESPONSE); + break; + case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED: + tcpm_set_pwr_role(port, TYPEC_SOURCE); + if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) { + tcpm_set_state(port, ERROR_RECOVERY, 0); + break; + } + tcpm_set_cc(port, tcpm_rp_cc(port)); + tcpm_set_state(port, SRC_STARTUP, PD_T_SWAP_SRC_START); + break; + /* PR_Swap states */ case PR_SWAP_ACCEPT: tcpm_pd_send_control(port, PD_CTRL_ACCEPT); @@ -3595,6 +3682,7 @@ static void run_state_machine(struct tcpm_port *port) case PR_SWAP_CANCEL: case VCONN_SWAP_CANCEL: tcpm_swap_complete(port, port->swap_status); + case FR_SWAP_CANCEL: if (port->pwr_role == TYPEC_SOURCE) tcpm_set_state(port, SRC_READY, 0); else @@ -3634,6 +3722,14 @@ static void run_state_machine(struct tcpm_port *port) case GET_PPS_STATUS_SEND_TIMEOUT: tcpm_set_state(port, ready_state(port), 0); break; + case GET_SINK_CAP: + tcpm_pd_send_control(port, PD_CTRL_GET_SINK_CAP); + tcpm_set_state(port, GET_SINK_CAP_TIMEOUT, PD_T_SENDER_RESPONSE); + break; + case GET_SINK_CAP_TIMEOUT: + port->sink_cap_done = true; + tcpm_set_state(port, ready_state(port), 0); + break; case ERROR_RECOVERY: tcpm_swap_complete(port, -EPROTO); tcpm_pps_complete(port, -EPROTO); @@ -3850,6 +3946,13 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1, * Ignore it. */ break; + case FR_SWAP_SEND: + case FR_SWAP_SEND_TIMEOUT: + case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF: + case FR_SWAP_SNK_SRC_NEW_SINK_READY: + case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED: + /* Do nothing, CC change expected */ + break; case PORT_RESET: case PORT_RESET_WAIT_OFF: @@ -3920,6 +4023,9 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port) case SRC_TRY_DEBOUNCE: /* Do nothing, waiting for sink detection */ break; + case FR_SWAP_SNK_SRC_NEW_SINK_READY: + tcpm_set_state(port, FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED, 0); + break; case PORT_RESET: case PORT_RESET_WAIT_OFF: @@ -3995,6 +4101,14 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port) */ break; + case FR_SWAP_SEND: + case FR_SWAP_SEND_TIMEOUT: + case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF: + case FR_SWAP_SNK_SRC_NEW_SINK_READY: + case FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED: + /* Do nothing, vbus drop expected */ + break; + default: if (port->pwr_role == TYPEC_SINK && port->attached) @@ -4049,6 +4163,25 @@ static void tcpm_pd_event_handler(struct work_struct *work) if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2) == 0) _tcpm_cc_change(port, cc1, cc2); } + if (events & TCPM_FRS_EVENT) { + if (port->state == SNK_READY) + tcpm_set_state(port, FR_SWAP_SEND, 0); + else + tcpm_log(port, "Discarding FRS_SIGNAL! Not in sink ready"); + } + if (events & TCPM_SOURCING_VBUS) { + tcpm_log(port, "sourcing vbus"); + /* + * In fast role swap case TCPC autonomously sources vbus. Set vbus_source + * true as TCPM wouldn't have called tcpm_set_vbus. + * + * When vbus is sourced on the command on TCPM i.e. TCPM called + * tcpm_set_vbus to source vbus, vbus_source would already be true. + */ + port->vbus_source = true; + _tcpm_pd_vbus_on(port); + } + spin_lock(&port->pd_event_lock); } spin_unlock(&port->pd_event_lock); @@ -4082,6 +4215,50 @@ void tcpm_pd_hard_reset(struct tcpm_port *port) } EXPORT_SYMBOL_GPL(tcpm_pd_hard_reset); +void tcpm_sink_frs(struct tcpm_port *port) +{ + spin_lock(&port->pd_event_lock); + port->pd_events = TCPM_FRS_EVENT; + spin_unlock(&port->pd_event_lock); + queue_work(port->wq, &port->event_work); +} +EXPORT_SYMBOL_GPL(tcpm_sink_frs); + +void tcpm_sourcing_vbus(struct tcpm_port *port) +{ + spin_lock(&port->pd_event_lock); + port->pd_events = TCPM_SOURCING_VBUS; + spin_unlock(&port->pd_event_lock); + queue_work(port->wq, &port->event_work); +} +EXPORT_SYMBOL_GPL(tcpm_sourcing_vbus); + +static void tcpm_enable_frs(struct work_struct *work) +{ + struct tcpm_port *port = container_of(work, struct tcpm_port, enable_frs.work); + + mutex_lock(&port->lock); + /* Not FRS capable */ + if (!port->connected || port->port_type != TYPEC_PORT_DRP || + port->pwr_opmode != TYPEC_PWR_MODE_PD || + !port->tcpc->enable_frs || + /* Sink caps queried */ + port->sink_cap_done || port->negotiated_rev < PD_REV30) + goto unlock; + + /* Send when the state machine is idle */ + if (port->state != SNK_READY || port->vdm_state != VDM_STATE_DONE || port->send_discover) + goto resched; + + tcpm_set_state(port, GET_SINK_CAP, 0); + port->sink_cap_done = true; + +resched: + mod_delayed_work(port->wq, &port->enable_frs, msecs_to_jiffies(GET_SINK_CAP_RETRY_MS)); +unlock: + mutex_unlock(&port->lock); +} + static int tcpm_dr_set(struct typec_port *p, enum typec_data_role data) { struct tcpm_port *port = typec_get_drvdata(p); @@ -4489,7 +4666,7 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, { const char *cap_str; int ret; - u32 mw; + u32 mw, frs_current; if (!fwnode) return -EINVAL; @@ -4558,6 +4735,13 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, port->self_powered = fwnode_property_read_bool(fwnode, "self-powered"); + /* FRS can only be supported byb DRP ports */ + if (port->port_type == TYPEC_PORT_DRP) { + ret = fwnode_property_read_u32(fwnode, "frs-typec-current", &frs_current); + if (ret >= 0 && frs_current <= FRS_5V_3A) + port->typec_caps.frs_current = frs_current; + } + return 0; } @@ -4813,6 +4997,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) INIT_DELAYED_WORK(&port->state_machine, tcpm_state_machine_work); INIT_DELAYED_WORK(&port->vdm_state_machine, vdm_state_machine_work); INIT_WORK(&port->event_work, tcpm_pd_event_handler); + INIT_DELAYED_WORK(&port->enable_frs, tcpm_enable_frs); spin_lock_init(&port->pd_event_lock); diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h index b6c233e79bd4..5d8a29c683a4 100644 --- a/include/linux/usb/pd.h +++ b/include/linux/usb/pd.h @@ -219,14 +219,16 @@ enum pd_pdo_type { #define PDO_CURR_MASK 0x3ff #define PDO_PWR_MASK 0x3ff -#define PDO_FIXED_DUAL_ROLE BIT(29) /* Power role swap supported */ -#define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (Source) */ -#define PDO_FIXED_HIGHER_CAP BIT(28) /* Requires more than vSafe5V (Sink) */ -#define PDO_FIXED_EXTPOWER BIT(27) /* Externally powered */ -#define PDO_FIXED_USB_COMM BIT(26) /* USB communications capable */ -#define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap supported */ -#define PDO_FIXED_VOLT_SHIFT 10 /* 50mV units */ -#define PDO_FIXED_CURR_SHIFT 0 /* 10mA units */ +#define PDO_FIXED_DUAL_ROLE BIT(29) /* Power role swap supported */ +#define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (Source) */ +#define PDO_FIXED_HIGHER_CAP BIT(28) /* Requires more than vSafe5V (Sink) */ +#define PDO_FIXED_EXTPOWER BIT(27) /* Externally powered */ +#define PDO_FIXED_USB_COMM BIT(26) /* USB communications capable */ +#define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap supported */ +#define PDO_FIXED_FRS_CURR_MASK (BIT(24) | BIT(23)) /* FR_Swap Current (Sink) */ +#define PDO_FIXED_FRS_CURR_SHIFT 23 +#define PDO_FIXED_VOLT_SHIFT 10 /* 50mV units */ +#define PDO_FIXED_CURR_SHIFT 0 /* 10mA units */ #define PDO_FIXED_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_FIXED_VOLT_SHIFT) #define PDO_FIXED_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_FIXED_CURR_SHIFT) @@ -454,6 +456,7 @@ static inline unsigned int rdo_max_power(u32 rdo) #define PD_T_DB_DETECT 10000 /* 10 - 15 seconds */ #define PD_T_SEND_SOURCE_CAP 150 /* 100 - 200 ms */ #define PD_T_SENDER_RESPONSE 60 /* 24 - 30 ms, relaxed */ +#define PD_T_RECEIVER_RESPONSE 15 /* 15ms max */ #define PD_T_SOURCE_ACTIVITY 45 #define PD_T_SINK_ACTIVITY 135 #define PD_T_SINK_WAIT_CAP 240 @@ -473,6 +476,7 @@ static inline unsigned int rdo_max_power(u32 rdo) #define PD_T_ERROR_RECOVERY 100 /* minimum 25 is insufficient */ #define PD_T_SRCSWAPSTDBY 625 /* Maximum of 650ms */ #define PD_T_NEWSRC 250 /* Maximum of 275ms */ +#define PD_T_SWAP_SRC_START 20 /* Minimum of 20ms */ #define PD_T_DRP_TRY 100 /* 75 - 150 ms */ #define PD_T_DRP_TRYWAIT 600 /* 400 - 800 ms */ diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index 89f58760cf48..09762d26fa0c 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h @@ -78,8 +78,11 @@ enum tcpm_transmit_type { * automatically if a connection is established. * @try_role: Optional; called to set a preferred role * @pd_transmit:Called to transmit PD message - * @mux: Pointer to multiplexer data * @set_bist_data: Turn on/off bist data mode for compliance testing + * @enable_frs: + * Optional; Called to enable/disable PD 3.0 fast role swap. + * Enabling frs is accessory dependent as not all PD3.0 + * accessories support fast role swap. */ struct tcpc_dev { struct fwnode_handle *fwnode; @@ -105,6 +108,7 @@ struct tcpc_dev { int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type, const struct pd_message *msg); int (*set_bist_data)(struct tcpc_dev *dev, bool on); + int (*enable_frs)(struct tcpc_dev *dev, bool enable); }; struct tcpm_port; @@ -114,6 +118,8 @@ void tcpm_unregister_port(struct tcpm_port *port); void tcpm_vbus_change(struct tcpm_port *port); void tcpm_cc_change(struct tcpm_port *port); +void tcpm_sink_frs(struct tcpm_port *port); +void tcpm_sourcing_vbus(struct tcpm_port *port); void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg); void tcpm_pd_transmit_complete(struct tcpm_port *port, diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h index 9cb1bec94b71..2ec7451a14ab 100644 --- a/include/linux/usb/typec.h +++ b/include/linux/usb/typec.h @@ -204,6 +204,18 @@ struct typec_operations { enum typec_port_type type); }; +/* + * Initial current capability of the new source when vSafe5V is applied during PD3.0 Fast Role Swap. + * Based on "Table 6-14 Fixed Supply PDO - Sink" of "USB Power Delivery Specification Revision 3.0, + * Version 1.2" + */ +enum frs_typec_current { + FRS_NOT_SUPPORTED, + FRS_DEFAULT_POWER, + FRS_5V_1P5A, + FRS_5V_3A, +}; + /* * struct typec_capability - USB Type-C Port Capabilities * @type: Supported power role of the port @@ -226,6 +238,7 @@ struct typec_capability { int prefer_role; enum typec_accessory accessory[TYPEC_MAX_ACCESSORY]; unsigned int orientation_aware:1; + enum frs_typec_current frs_current; struct fwnode_handle *fwnode; void *driver_data; From patchwork Tue Aug 25 04:22:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734837 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 91EFE138A for ; Tue, 25 Aug 2020 04:23:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7968920738 for ; Tue, 25 Aug 2020 04:23:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="YFdvLbfu" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728758AbgHYEX2 (ORCPT ); Tue, 25 Aug 2020 00:23:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50930 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728576AbgHYEWv (ORCPT ); Tue, 25 Aug 2020 00:22:51 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 25D6AC061797 for ; Mon, 24 Aug 2020 21:22:51 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id lx6so890617pjb.9 for ; Mon, 24 Aug 2020 21:22:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=Vf05DHbJOL8YiBgNY4RcEwAfFMau7ErjLwduxlsjLdo=; b=YFdvLbfuNEJOET5kjewhbsqwCOZ0iwwmylh9OKTb1DDvbbUo/f5M1W+AAgZCsQpYBQ UgQFNEdlEYlNHkXGZP3HWfXHW2CisBYqCknHiJGJpM5Mz0jw/L7IBAc4WcA7DaBJ4IXG Sv/6I+1/leX8sBLiINDSEcQkpjnSNS97so1BfkXBe4Q6xivbrd1WB1FpnR14G0rfLc0B 3NquMc3XPk8BL2pAA8WUoAOAbGfuVxAuzKVSBoOgBWxXeA+Kmp8zOs4lXc/vjvRnhhxG 56nhUNShRrQErheoGsHJbCM/C5dkWEMQQGOgyEk+n8mTyw/N5PA9qxMOLcAwwZ8mVJAz u6IQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Vf05DHbJOL8YiBgNY4RcEwAfFMau7ErjLwduxlsjLdo=; b=puH/8zui/+e/Q2KgPK5MUNgCEYcNTMs+jK1Gclbq6tve2fPNbyClj+ipe99OUbWfv1 1eryV8W5CPh+QM3Qun5bBLY1ZcPYXY7w40iH9BBoWGjk+bm/mkj3Ni1MAQt8N1+4mb9M ef9/i3TFLCS0lVRUIef7dHk3IGc6uZK7x41YR0qZO7Gt2O4MlUOonB0c89zJlrajS7Dx 83p9oW2g9hsrhTgUMeSKKeBp1OfyYVzeZUPPUFAEOGklS6jELqrY7nvIyl6DNp/g78QI t98LgwSTYF3n6E8Y1RX9ynzD9+S9k5Sp0G/dusntr+dcduYrBc0FhJt0TAAXTDFWuBYx vtPA== X-Gm-Message-State: AOAM53269QRHj0ptsFPyXK1Caa0EwAbzaTKf4lVb6tco8BOkdVhjsgc+ AnByOxFoqUuZkf54aVQUh9rYYm8zQ/0= X-Google-Smtp-Source: ABdhPJy+tvS3+K7sfYIGeYaZ5HlFjz8vLgYSBHkYoDYFx2Jh9ydO5cH2HKTHEGm0OOG4GYBiwuAZuHGV1sA= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a17:90a:e558:: with SMTP id ei24mr72404pjb.54.1598329370679; Mon, 24 Aug 2020 21:22:50 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:06 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-11-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 10/14 v1] usb: typec: tcpci: Implement callbacks for FRS From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Implement tcpc.enable_frs to enable TCPC to receive Fast role swap signal. Additionally set the sink disconnect threshold to 4v to prevent disconnect during Fast Role swap. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/tcpci.c | 17 +++++++++++++++++ drivers/usb/typec/tcpm/tcpci.h | 8 ++++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 89d28e3fbee8..13d2e1c2ff20 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -268,6 +268,22 @@ static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable) enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0); } +static int tcpci_enable_frs(struct tcpc_dev *dev, bool enable) +{ + struct tcpci *tcpci = tcpc_to_tcpci(dev); + int ret; + + /* To prevent disconnect during FRS, set disconnect threshold to 3.5V */ + ret = tcpci_write16(tcpci, TCPC_VBUS_SINK_DISCONNECT_THRESH, enable ? 0 : 0x8c); + if (ret < 0) + return ret; + + ret = regmap_update_bits(tcpci->regmap, TCPC_POWER_CTRL, TCPC_FAST_ROLE_SWAP_EN, enable ? + TCPC_FAST_ROLE_SWAP_EN : 0); + + return ret; +} + static int tcpci_set_bist_data(struct tcpc_dev *tcpc, bool enable) { struct tcpci *tcpci = tcpc_to_tcpci(tcpc); @@ -610,6 +626,7 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data) tcpci->tcpc.set_roles = tcpci_set_roles; tcpci->tcpc.pd_transmit = tcpci_pd_transmit; tcpci->tcpc.set_bist_data = tcpci_set_bist_data; + tcpci->tcpc.enable_frs = tcpci_enable_frs; err = tcpci_parse_config(tcpci); if (err < 0) diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h index 82f021a82456..5ef07a56d67a 100644 --- a/drivers/usb/typec/tcpm/tcpci.h +++ b/drivers/usb/typec/tcpm/tcpci.h @@ -16,6 +16,7 @@ #define TCPC_PD_INT_REV 0xa #define TCPC_ALERT 0x10 +#define TCPC_ALERT_EXTND BIT(14) #define TCPC_ALERT_EXTENDED_STATUS BIT(13) #define TCPC_ALERT_VBUS_DISCNCT BIT(11) #define TCPC_ALERT_RX_BUF_OVF BIT(10) @@ -37,6 +38,9 @@ #define TCPC_EXTENDED_STATUS_MASK 0x16 #define TCPC_EXTENDED_STATUS_MASK_VSAFE0V BIT(0) +#define TCPC_ALERT_EXTENDED_MASK 0x17 +#define TCPC_SINK_FAST_ROLE_SWAP BIT(0) + #define TCPC_CONFIG_STD_OUTPUT 0x18 #define TCPC_TCPC_CTRL 0x19 @@ -63,6 +67,7 @@ #define TCPC_POWER_CTRL 0x1c #define TCPC_POWER_CTRL_VCONN_ENABLE BIT(0) +#define TCPC_FAST_ROLE_SWAP_EN BIT(7) #define TCPC_CC_STATUS 0x1d #define TCPC_CC_STATUS_TOGGLING BIT(5) @@ -74,11 +79,14 @@ #define TCPC_POWER_STATUS 0x1e #define TCPC_POWER_STATUS_UNINIT BIT(6) +#define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4) #define TCPC_POWER_STATUS_VBUS_DET BIT(3) #define TCPC_POWER_STATUS_VBUS_PRES BIT(2) #define TCPC_FAULT_STATUS 0x1f +#define TCPC_ALERT_EXTENDED 0x21 + #define TCPC_COMMAND 0x23 #define TCPC_CMD_WAKE_I2C 0x11 #define TCPC_CMD_DISABLE_VBUS_DETECT 0x22 From patchwork Tue Aug 25 04:22:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734839 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 529FE138A for ; Tue, 25 Aug 2020 04:23:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 39C9A20737 for ; Tue, 25 Aug 2020 04:23:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="YqtZ49pJ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728745AbgHYEX2 (ORCPT ); Tue, 25 Aug 2020 00:23:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50922 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728653AbgHYEWy (ORCPT ); Tue, 25 Aug 2020 00:22:54 -0400 Received: from mail-qv1-xf4a.google.com (mail-qv1-xf4a.google.com [IPv6:2607:f8b0:4864:20::f4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 681F9C061755 for ; Mon, 24 Aug 2020 21:22:54 -0700 (PDT) Received: by mail-qv1-xf4a.google.com with SMTP id h6so7896208qvz.14 for ; Mon, 24 Aug 2020 21:22:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=Nv5tc6KahqHd2NBKcfPXCDAaClr/I8kOXQmUHCJ9qWQ=; b=YqtZ49pJFfw//Tms6srxB9cmG6SIMAsPfgiC2cbBRjzdOKnk3y7KFv8E5qzMu+TQza aMQp2eGCeAlq0EKOoTbiQZoj6jnqDkiErdDtaXvfFO2DAXy2N6MZW2xx0uMV8zgo/+hA KWUzDsx+qQpyUDgyuEQwYOx+rF/BDpRhb+NSSMhCu1r0f/erlqTu2+legGwWHWUsKrzy VQGnzfaBKfu+c717oQoHVwwPSRyOU9Q9cLiT5KkmVKWDcej3+suM5Ky9F784FXv2gRxY X7AIZtPk2y/kzUtNpcaCJ3PAqu3L7+rIsEfA3+N2BzABpSNa/gYL6b6P4Zv55ZyliTI1 TffQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Nv5tc6KahqHd2NBKcfPXCDAaClr/I8kOXQmUHCJ9qWQ=; b=VbMogXdL/IyZu8jpP3PXeU6TqraAvRaSPq9wBZw4EU0wPAQG/HOxzoLGOIQ9AbAnqO k3Gz4KRAfPDp8KC1UArQnGmENe7L61jw3M6zdLhRxczXEYsYFKw+ofBx5snJ+BkYQMtG /Bwwd9cDXwQ0c/uOYe8ePqEH3/+WZEzB7Lsx7qQbIu/kaSg2CC/ec9K2hoZ0h0pD+CLK hKOk5qi0eGQRwWl35Ez+kQMWj/ZcKyDaZ8fZ3rK6prFJRASrgsXSP3RqmPmp3Nw6bCfh mCUd1bJt6LSayla11HjU0y7SqZVME4n8Iyqnv/1xjs8aROPyG9JgLMB6+qmdroslH3yd 9pUg== X-Gm-Message-State: AOAM5333+i73bak6539f5YvCAgxLlF+A8+7NlIfs7IihgZVdZYbKUaTO ywPVDF3UwMqzwVjplUZUeK/m7JHKL0g= X-Google-Smtp-Source: ABdhPJyxdJTRBEww26jqyEBYkoSZj8teumSAJ0bi3oYNf5zYDACJTuOdVs9cm1hocyvPsrPZUaRz/v9WtsE= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a0c:f607:: with SMTP id r7mr8103797qvm.219.1598329373011; Mon, 24 Aug 2020 21:22:53 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:07 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-12-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 11/14 v1] usb: typec: tcpci_maxim: Add support for Sink FRS From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Upon receiving ALERT_EXTENDED.TCPC_SINK_FAST_ROLE_SWAP signal tcpm to start Sink fast role swap signal. Inform when TCPM is sourcing vbus. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/tcpci_maxim.c | 50 +++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpci_maxim.c b/drivers/usb/typec/tcpm/tcpci_maxim.c index b61f290a8f96..6ba808ad901a 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim.c +++ b/drivers/usb/typec/tcpm/tcpci_maxim.c @@ -106,13 +106,22 @@ static void max_tcpci_init_regs(struct max_tcpci_chip *chip) return; } + ret = max_tcpci_write8(chip, TCPC_ALERT_EXTENDED, 0xff); + if (ret < 0) { + dev_err(chip->dev, "Unable to clear TCPC_ALERT_EXTENDED ret:%d\n", ret); + return; + } + alert_mask = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_TX_FAILED | TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_RX_STATUS | TCPC_ALERT_CC_STATUS | - TCPC_ALERT_VBUS_DISCNCT | TCPC_ALERT_RX_BUF_OVF | TCPC_ALERT_POWER_STATUS; + TCPC_ALERT_VBUS_DISCNCT | TCPC_ALERT_RX_BUF_OVF | TCPC_ALERT_POWER_STATUS | + /* Enable Extended alert for detecting Fast Role Swap Signal */ + TCPC_ALERT_EXTND; ret = max_tcpci_write16(chip, TCPC_ALERT_MASK, alert_mask); if (ret < 0) { - dev_err(chip->dev, "Error writing to TCPC_ALERT_MASK ret:%d\n", ret); + dev_err(chip->dev, + "Error enabling TCPC_ALERT: TCPC_ALERT_MASK write failed ret:%d\n", ret); return; } @@ -122,6 +131,10 @@ static void max_tcpci_init_regs(struct max_tcpci_chip *chip) dev_err(chip->dev, "Error writing to TCPC_POWER_CTRL ret:%d\n", ret); return; } + + ret = max_tcpci_write8(chip, TCPC_ALERT_EXTENDED_MASK, TCPC_SINK_FAST_ROLE_SWAP); + if (ret < 0) + return; } static void process_rx(struct max_tcpci_chip *chip, u16 status) @@ -225,10 +238,23 @@ static void process_power_status(struct max_tcpci_chip *chip) if (ret < 0) return; - if (pwr_status == 0xff) + if (pwr_status == 0xff) { max_tcpci_init_regs(chip); - else + } else if (pwr_status & TCPC_POWER_STATUS_SOURCING_VBUS) { + tcpm_sourcing_vbus(chip->port); + /* + * Alawys re-enable boost here. + * In normal case, when say an headset is attached, TCPM would + * have instructed to TCPC to enable boost, so the call is a + * no-op. + * But for Fast Role Swap case, Boost turns on autonomously without + * AP intervention, but, needs AP to enable source mode explicitly + * for AP to regain control. + */ + max_tcpci_set_vbus(chip->tcpci, &chip->data, true, false); + } else { tcpm_vbus_change(chip->port); + } } static void process_tx(struct max_tcpci_chip *chip, u16 status) @@ -249,6 +275,7 @@ static irqreturn_t _max_tcpci_irq(struct max_tcpci_chip *chip, u16 status) { u16 mask; int ret; + u8 reg_status; /* * Clear alert status for everything except RX_STATUS, which shouldn't @@ -274,6 +301,21 @@ static irqreturn_t _max_tcpci_irq(struct max_tcpci_chip *chip, u16 status) } } + if (status & TCPC_ALERT_EXTND) { + ret = max_tcpci_read8(chip, TCPC_ALERT_EXTENDED, ®_status); + if (ret < 0) + return ret; + + ret = max_tcpci_write8(chip, TCPC_ALERT_EXTENDED, reg_status); + if (ret < 0) + return ret; + + if (reg_status & TCPC_SINK_FAST_ROLE_SWAP) { + dev_info(chip->dev, "FRS Signal"); + tcpm_sink_frs(chip->port); + } + } + if (status & TCPC_ALERT_RX_STATUS) process_rx(chip, status); From patchwork Tue Aug 25 04:22:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734833 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9A802138A for ; Tue, 25 Aug 2020 04:23:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 75F6F20737 for ; Tue, 25 Aug 2020 04:23:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="WOXaWbji" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728708AbgHYEXV (ORCPT ); Tue, 25 Aug 2020 00:23:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728660AbgHYEW4 (ORCPT ); Tue, 25 Aug 2020 00:22:56 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 23737C0613ED for ; Mon, 24 Aug 2020 21:22:56 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id k11so13471302ybp.1 for ; Mon, 24 Aug 2020 21:22:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=re3WB9b8nc3WlI0r60WtJVdfgMlyTelDUyLrb8k+gck=; b=WOXaWbjiAcpyl0hP1lMije0EBGepV3IpmQx9AhmgW8YSxGA9ye5/YDiBFcFvj9WuNd Uov9hFHDHpo755KTfPviSWxE7+aOLSpISpTeiwXuws/VNb+NGJxRq6BnRjpfHphMA9YO pKUQvVAOavAh+bGecv/4XSd/fYmbqOCYmVNZ8hqU2gOtmkhfy/agGhmoDbMsoGjk1E5X iDoqGRbdizlSCZsYDBrocO3YIXVKNCAHh0GRTXgiT+SVjkFX5KLr6ugsjSq/LwoTQXLD B+Qnv4HzNmR4bUxEgDzlftrlJm3RDHpik/NzCY4Pg0raHQP+QPXNC6tbXqpIxWfvO6/O cRGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=re3WB9b8nc3WlI0r60WtJVdfgMlyTelDUyLrb8k+gck=; b=jHn0TDwXH6h0iphtdkW6GLUqAUEh9lMadXwBLWB+C3AhHtv6mAy/+nV9+5hQD3Kaon JQRsbQQKYJmZVcsf3VqyNBCaB2Hyd/9oMZQOilAJcBSLf6QsDkmhED9cJjATuDVr+WMC 6VOrnWgFKT4v4OvK7I/bS2VVKuoNinMinvcOOhE+MRmUzBTPVPE5WNj1gUUCfiXQcf8G Z2T9vFjcMdSuDHOKW18I5GcVmryb6Rdtp+eY5R9bpOZL0yYjr756U5ewdiXtsSWZGZqR 9DGiGhT7VUqUIjgEfTE9GSRof4W8vY2j/AgWyhtwj92lzPhuzFZgmpwY5aSAWSBl5zUr GvFA== X-Gm-Message-State: AOAM5326xeHbeFvMYzKVP/dIBac8RzajhmU2RHpJDqZHA9VfQYWHdMNs I6xveOgL70gaZro2kZEYrjSs4MBRm4U= X-Google-Smtp-Source: ABdhPJyNEAX0zYxqCzK1N5c9VTW3uiLMcdF19jHjhkNOmZ8A/fFlEjCnktLhEwoEirSarjG5E+KVFpBITdI= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a25:c58c:: with SMTP id v134mr12518576ybe.138.1598329375332; Mon, 24 Aug 2020 21:22:55 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:08 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-13-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 12/14] usb: typec: tcpm: Implement enabling Auto Discharge disconnect support From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org TCPCI spec allows TCPC hardware to autonomously discharge the vbus capacitance upon disconnect. The expectation is that the TCPM enables AutoDischargeDisconnect while entering SNK/SRC_ATTACHED states. Hardware then automously discharges vbus when the vbus falls below a certain threshold i.e. VBUS_SINK_DISCONNECT_THRESHOLD. Apart from enabling the vbus discharge circuit, AutoDischargeDisconnect is also used a flag to move TCPCI based TCPC implementations into Attached.Snk/Attached.Src state as mentioned in Figure 4-15. TCPC State Diagram before a Connection of the USB Type-C Port Controller Interface Specification. In such TCPC implementations, setting AutoDischargeDisconnect would prevent TCPC into entering "Connection_Invalid" state as well. Signed-off-by: Badhri Jagan Sridharan Change-Id: I09c407eb228d69eb1259008eeb14c429b0fda765 --- drivers/usb/typec/tcpm/tcpm.c | 80 +++++++++++++++++++++++++++++++++-- include/linux/usb/tcpm.h | 16 +++++++ 2 files changed, 92 insertions(+), 4 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 6ea4613af905..fe58cf908144 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -1660,6 +1660,25 @@ static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, } } +static int tcpm_set_auto_vbus_discharge_threshold(struct tcpm_port *port, enum typec_role port_role, + enum typec_pwr_opmode mode, bool pps_active, + u32 requested_vbus_voltage) +{ + int ret; + + if (!port->tcpc->set_auto_vbus_discharge_threshold) + return 0; + + ret = port->tcpc->set_auto_vbus_discharge_threshold(port->tcpc, port_role, mode, pps_active, + requested_vbus_voltage); + tcpm_log_force(port, + "set_auto_vbus_discharge_threshold pwr_role:%s mode:%d pps_active:%c vbus:%u ret:%d", + port_role == TYPEC_SINK ? "sink" : "source", mode, pps_active ? 'y' : 'n', + requested_vbus_voltage, ret); + + return ret; +} + static void tcpm_pd_data_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1829,6 +1848,10 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, port->current_limit, port->supply_voltage); port->explicit_contract = true; + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, + TYPEC_PWR_MODE_PD, + port->pps_data.active, + port->supply_voltage); tcpm_set_state(port, SNK_READY, 0); } else { /* @@ -2743,8 +2766,14 @@ static int tcpm_src_attach(struct tcpm_port *port) if (ret < 0) return ret; - ret = tcpm_set_roles(port, true, TYPEC_SOURCE, - tcpm_data_role_for_source(port)); + if (port->tcpc->enable_auto_vbus_discharge) { + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, TYPEC_PWR_MODE_USB, + false, VSAFE5V); + ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true); + tcpm_log_force(port, "enable vbus discharge ret:%d", ret); + } + + ret = tcpm_set_roles(port, true, TYPEC_SOURCE, tcpm_data_role_for_sink(port)); if (ret < 0) return ret; @@ -2811,6 +2840,12 @@ static void tcpm_unregister_altmodes(struct tcpm_port *port) static void tcpm_reset_port(struct tcpm_port *port) { + int ret; + + if (port->tcpc->enable_auto_vbus_discharge) { + ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, false); + tcpm_log_force(port, "Disable vbus discharge ret:%d", ret); + } tcpm_unregister_altmodes(port); tcpm_typec_disconnect(port); port->attached = false; @@ -2875,8 +2910,14 @@ static int tcpm_snk_attach(struct tcpm_port *port) if (ret < 0) return ret; - ret = tcpm_set_roles(port, true, TYPEC_SINK, - tcpm_data_role_for_sink(port)); + if (port->tcpc->enable_auto_vbus_discharge) { + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, TYPEC_PWR_MODE_USB, false, + VSAFE5V); + ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, true); + tcpm_log_force(port, "enable vbus discharge ret:%d", ret); + } + + ret = tcpm_set_roles(port, true, TYPEC_SINK, tcpm_data_role_for_sink(port)); if (ret < 0) return ret; @@ -3430,6 +3471,14 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SNK_HARD_RESET_SINK_OFF, 0); break; case SRC_HARD_RESET_VBUS_OFF: + /* + * 7.1.5 Response to Hard Resets + * Hard Reset Signaling indicates a communication failure has occurred and the + * Source Shall stop driving VCONN, Shall remove Rp from the VCONN pin and Shall + * drive VBUS to vSafe0V as shown in Figure 7-9. + */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, TYPEC_PWR_MODE_USB, + false, 0); tcpm_set_vconn(port, true); tcpm_set_vbus(port, false); tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE, @@ -3440,9 +3489,13 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_vbus(port, true); port->tcpc->set_pd_rx(port->tcpc, true); tcpm_set_attached_state(port, true); + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, TYPEC_PWR_MODE_USB, + false, VSAFE5V); tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON); break; case SNK_HARD_RESET_SINK_OFF: + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, TYPEC_PWR_MODE_USB, false, + 0); memset(&port->pps_data, 0, sizeof(port->pps_data)); tcpm_set_vconn(port, false); if (port->pd_capable) @@ -3485,6 +3538,8 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_charge(port, true); } tcpm_set_attached_state(port, true); + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, TYPEC_PWR_MODE_USB, false, + VSAFE5V); tcpm_set_state(port, SNK_STARTUP, 0); break; @@ -3586,6 +3641,12 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, PR_SWAP_SNK_SRC_SINK_OFF, 0); break; case PR_SWAP_SRC_SNK_TRANSITION_OFF: + /* + * Prevent vbus discharge circuit from turning on during PR_SWAP + * as this is not a disconnect. + */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, TYPEC_PWR_MODE_USB, + port->pps_data.active, 0); tcpm_set_vbus(port, false); port->explicit_contract = false; /* allow time for Vbus discharge, must be < tSrcSwapStdby */ @@ -3614,9 +3675,18 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON); break; case PR_SWAP_SRC_SNK_SINK_ON: + /* Set the vbus disconnect threshold for implicit contract */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, TYPEC_PWR_MODE_USB, false, + VSAFE5V); tcpm_set_state(port, SNK_STARTUP, 0); break; case PR_SWAP_SNK_SRC_SINK_OFF: + /* + * Prevent vbus discharge circuit from turning on during PR_SWAP + * as this is not a disconnect. + */ + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SINK, TYPEC_PWR_MODE_USB, + port->pps_data.active, 0); tcpm_set_charge(port, false); tcpm_set_state(port, hard_reset_state(port), PD_T_PS_SOURCE_OFF); @@ -3642,6 +3712,8 @@ static void run_state_machine(struct tcpm_port *port) */ tcpm_set_pwr_role(port, TYPEC_SOURCE); tcpm_pd_send_control(port, PD_CTRL_PS_RDY); + tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_SOURCE, TYPEC_PWR_MODE_USB, + false, VSAFE5V); tcpm_set_state(port, SRC_STARTUP, 0); break; diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index 09762d26fa0c..a1707def51c3 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h @@ -83,6 +83,18 @@ enum tcpm_transmit_type { * Optional; Called to enable/disable PD 3.0 fast role swap. * Enabling frs is accessory dependent as not all PD3.0 * accessories support fast role swap. + * @enable_auto_vbus_discharge: + * Optional; TCPCI spec based TCPC implementations can optionally + * support hardware to autonomously dischrge vbus upon disconnecting + * as sink or source. TCPM signals TCPC to enable the mechanism upon + * entering connected state and signals disabling upon disconnect. + * @set_auto_vbus_discharge_threshold: + * Mandatory when enable_auto_vbus_discharge is implemented. TCPM + * calls this function to allow lower levels drivers to program the + * vbus threshold voltage below which the vbus discharge circuit + * will be turned on. requested_vbus_voltage is set to 0 when vbus + * is going to disappear knowingly i.e. during PR_SWAP and + * HARD_RESET etc. */ struct tcpc_dev { struct fwnode_handle *fwnode; @@ -109,6 +121,10 @@ struct tcpc_dev { const struct pd_message *msg); int (*set_bist_data)(struct tcpc_dev *dev, bool on); int (*enable_frs)(struct tcpc_dev *dev, bool enable); + int (*enable_auto_vbus_discharge)(struct tcpc_dev *dev, bool enable); + int (*set_auto_vbus_discharge_threshold)(struct tcpc_dev *dev, enum typec_role port_role, + enum typec_pwr_opmode mode, bool pps_active, + u32 requested_vbus_voltage); }; struct tcpm_port; From patchwork Tue Aug 25 04:22:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734827 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 04433739 for ; Tue, 25 Aug 2020 04:23:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DB5792073A for ; Tue, 25 Aug 2020 04:23:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="iiGIlPDO" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728696AbgHYEXA (ORCPT ); Tue, 25 Aug 2020 00:23:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50950 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728684AbgHYEW6 (ORCPT ); Tue, 25 Aug 2020 00:22:58 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81D8BC061574 for ; Mon, 24 Aug 2020 21:22:58 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id lx6so890844pjb.9 for ; Mon, 24 Aug 2020 21:22:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=MSjuJlqwZbeT/5gqoAJ2R9KeJjOh0ok3YdAVNY4kQaQ=; b=iiGIlPDOuad/QAjayZvFuF9m6tB9LjCXcmIMy8uLi85cby6M0mje5/RE6FryMc5jzU 87st0DVi/rwSFdumypv1bjZ0JYLvyFksJxFRNcHzHvf+e346hdcQbVySpRqhFcxI8haY gbsCaQmSxvd99S0w6IZUjp6qfkQ3SPhtcxkcYZE+DTnPyymDT8aodQrGhmfMSnVg8bi3 IDuZr2O5DkdTDn615ZI/QDSQOxU2ijLydeA5tmwhEq9sS2V4ZJrJlLuU8v192ha3J62P Hzq2Vb9L9PB7Yi65Xwt2tSfmEx3vGH0WaCRwfZh7GXhq0IHD6/Lewyn428Pgp+tO7T7g IvRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=MSjuJlqwZbeT/5gqoAJ2R9KeJjOh0ok3YdAVNY4kQaQ=; b=hsFdDPjLTgTtPogDZ7496xjZAojtld5Rkhm5sjjIsB2beiFD8XP8w7cPUi3a/fTT6P qmOfFsOPL4kMfBMKyY32LofZK5j/VOZW5Q8Kz6Et8C6i2tv7ytNAvE0gFic55rnzrct9 bi9PrXXOGoj/GdaoYZTB4zfGMqCGOl4vfBKfhaqmRJUHsjydZo6VIFpaQOT51u9Iak3j Payk61rfzHQRmO7nTCcIYpTkUIHj0FNRFrku3nTOBusDTr0Hb6mhl4blmIQsuC25NTCG Obhnu8VDdsMLlUQjYfqqY7uYIpQv2xH0nK2lp4i+kKLsX/eSt53eCbZfrd935m391YiO vZfA== X-Gm-Message-State: AOAM531O2gbxGnLn2QACmPIW20gkA7Hwq4gbLppGCBxBuceNVehe5YCV MhlrETeghwSNEzi84xsBW4DMHwM4pPA= X-Google-Smtp-Source: ABdhPJzBTyW+pz3D1TsoZ/ckSs2GKW2XpSlJoOPGekFFwT/3u4C/xG6pxz48LFAsil4v0+HC4sTHI9Hsi7E= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a05:6a00:22cc:: with SMTP id f12mr6383025pfj.42.1598329377892; Mon, 24 Aug 2020 21:22:57 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:09 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-14-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 13/14 v1] usb: typec: tcpci: Implement Auto discharge disconnect callbacks From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Implement callbacks for enabling/disabling POWER_CONTROL.AutoDischargeDisconnect. TCPCI spec allows TCPC hardware to autonomously discharge the vbus capacitance upon disconnect. The expectation is that the TCPM enables AutoDischargeDisconnect while entering SNK/SRC_ATTACHED states. Hardware then automously discharges vbus when the vbus falls below a certain threshold i.e. VBUS_SINK_DISCONNECT_THRESHOLD. Apart from enabling the vbus discharge circuit, AutoDischargeDisconnect is also used a flag to move TCPCI based TCPC implementations into Attached.Snk/Attached.Src state as mentioned in Figure 4-15. TCPC State Diagram before a Connection of the USB Type-C Port Controller Interface Specification. In such TCPC implementations, setting AutoDischargeDisconnect would prevent TCPC into entering "Connection_Invalid" state as well. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/tcpci.c | 33 +++++++++++++++++++++++++++++++++ drivers/usb/typec/tcpm/tcpci.h | 22 ++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 13d2e1c2ff20..e876f13ddf31 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -268,6 +268,33 @@ static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable) enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0); } +static int tcpci_enable_auto_vbus_discharge(struct tcpc_dev *dev, bool enable) +{ + struct tcpci *tcpci = tcpc_to_tcpci(dev); + int ret; + + ret = regmap_update_bits(tcpci->regmap, TCPC_POWER_CTRL, TCPC_POWER_CTRL_AUTO_DISCHARGE, + enable ? TCPC_POWER_CTRL_AUTO_DISCHARGE : 0); + return ret; +} + +static int tcpci_set_auto_vbus_discharge_threshold(struct tcpc_dev *dev, enum typec_role port_role, + enum typec_pwr_opmode mode, bool pps_active, + u32 requested_vbus_voltage) +{ + struct tcpci *tcpci = tcpc_to_tcpci(dev); + int (*set_auto_vbus_threshold)(struct tcpci *tcpci, struct tcpci_data *data, + enum typec_role port_role, enum typec_pwr_opmode mode, + bool pps_active, u32 requested_vbus_voltage); + + set_auto_vbus_threshold = tcpci->data->set_auto_vbus_discharge_threshold; + if (set_auto_vbus_threshold) + return set_auto_vbus_threshold(tcpci, tcpci->data, port_role, mode, pps_active, + requested_vbus_voltage); + + return 0; +} + static int tcpci_enable_frs(struct tcpc_dev *dev, bool enable) { struct tcpci *tcpci = tcpc_to_tcpci(dev); @@ -628,6 +655,12 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data) tcpci->tcpc.set_bist_data = tcpci_set_bist_data; tcpci->tcpc.enable_frs = tcpci_enable_frs; + if (tcpci->data->auto_discharge_disconnect) { + tcpci->tcpc.enable_auto_vbus_discharge = tcpci_enable_auto_vbus_discharge; + tcpci->tcpc.set_auto_vbus_discharge_threshold = + tcpci_set_auto_vbus_discharge_threshold; + } + err = tcpci_parse_config(tcpci); if (err < 0) return ERR_PTR(err); diff --git a/drivers/usb/typec/tcpm/tcpci.h b/drivers/usb/typec/tcpm/tcpci.h index 5ef07a56d67a..6a0aea34e544 100644 --- a/drivers/usb/typec/tcpm/tcpci.h +++ b/drivers/usb/typec/tcpm/tcpci.h @@ -8,6 +8,8 @@ #ifndef __LINUX_USB_TCPCI_H #define __LINUX_USB_TCPCI_H +#include + #define TCPC_VENDOR_ID 0x0 #define TCPC_PRODUCT_ID 0x2 #define TCPC_BCD_DEV 0x4 @@ -67,6 +69,7 @@ #define TCPC_POWER_CTRL 0x1c #define TCPC_POWER_CTRL_VCONN_ENABLE BIT(0) +#define TCPC_POWER_CTRL_AUTO_DISCHARGE BIT(4) #define TCPC_FAST_ROLE_SWAP_EN BIT(7) #define TCPC_CC_STATUS 0x1d @@ -133,6 +136,8 @@ #define TCPC_VBUS_VOLTAGE 0x70 #define TCPC_VBUS_SINK_DISCONNECT_THRESH 0x72 +#define TCPC_VBUS_SINK_DISCONNECT_THRESH_LSB 25 +#define TCPC_VBUS_SINK_DISCONNECT_THRESH_MAX 1023 #define TCPC_VBUS_STOP_DISCHARGE_THRESH 0x74 #define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76 #define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78 @@ -140,20 +145,33 @@ /* I2C_WRITE_BYTE_COUNT + 1 when TX_BUF_BYTE_x is only accessible I2C_WRITE_BYTE_COUNT */ #define TCPC_TRANSMIT_BUFFER_MAX_LEN 31 +struct tcpci; + /* - * @TX_BUF_BYTE_x_hidden + * @TX_BUF_BYTE_x_hidden: * optional; Set when TX_BUF_BYTE_x can only be accessed through I2C_WRITE_BYTE_COUNT. + * @auto_discharge_disconnect: + * Optional; Enables TCPC to autonously discharge vbus on disconnect. + * @set_auto_vbus_discharge_threshold: + * Mandatory when @auto_discharge_disconnect is sets. Allows + * programming the voltage threshold of vbus below which TCPC + * enables the vbus discharge circuit. */ -struct tcpci; struct tcpci_data { struct regmap *regmap; unsigned char TX_BUF_BYTE_x_hidden:1; + unsigned char auto_discharge_disconnect:1; + int (*init)(struct tcpci *tcpci, struct tcpci_data *data); int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data, bool enable); int (*start_drp_toggling)(struct tcpci *tcpci, struct tcpci_data *data, enum typec_cc_status cc); int (*set_vbus)(struct tcpci *tcpci, struct tcpci_data *data, bool source, bool sink); + int (*set_auto_vbus_discharge_threshold)(struct tcpci *tcpci, struct tcpci_data *data, + enum typec_role port_role, + enum typec_pwr_opmode mode, bool pps_active, + u32 requested_vbus_voltage); }; struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data); From patchwork Tue Aug 25 04:22:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Badhri Jagan Sridharan X-Patchwork-Id: 11734829 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D8C6D138A for ; Tue, 25 Aug 2020 04:23:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C13302074A for ; Tue, 25 Aug 2020 04:23:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="iOrrBtpC" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728649AbgHYEXI (ORCPT ); Tue, 25 Aug 2020 00:23:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50964 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728700AbgHYEXB (ORCPT ); Tue, 25 Aug 2020 00:23:01 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BE759C061574 for ; Mon, 24 Aug 2020 21:23:00 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id u128so8255493ybg.17 for ; Mon, 24 Aug 2020 21:23:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=q3nSt4wRkjHfPpuinxzh6IcLdnhOBWqWD7BzNcZASGQ=; b=iOrrBtpCQqPWL/QlRPN8dY8agdU97ZafJw0zhs2XYhVClb+5t/7QCKvQV8CdwF4Gxo PIBqCcgPKqEzUz0aX9V9RT1yhN5WzpJrN6lxoulJ5fJfwUQjPZr2SvpmPI6i8LkeOpyq 40+qR96cq0/ttPQys9m1tE7if0Nwzhl4xlbYN5rVN0gfPMX0mIPwfzzsoyUwKqJz+ft3 o9M+fVIUr2mSja1CQR+ycnVxw+WPzADXn9JNm2SHWg40dp+vOXrERTNE8NqIodBgTvUe hGmNJ4wIAiTfICfOWOSMoIj8E4GnLgHR7WHYOiHzQlfKQY+fqFH1C2a8JffXyu+KpyuN FGaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=q3nSt4wRkjHfPpuinxzh6IcLdnhOBWqWD7BzNcZASGQ=; b=N2huQxaal1hW1iyEL+lmbcpr8XZV5bJ8vdX5CdSe08VL5koR9b0N7vA2EJwAfySh3d Nfr0Fy91oyeZntS4nfDiG9jmD4sz098UyzGrp6rVJUWCbTk0+7+ckBai850OnXT4N1fV cg1h6bT356uh8h6gSE0kl20oEz0fRS7No+JABv9qo/MWj0YTSPjDHeEIktI9yr527WGA R3A0GCCDX0XIgO4dEdp2am4Q8NpbHRQ64vwv7oEPhSB6E8xX4h7Y1Jx8Ux6tWvC8KJPj mkDULl7Lm6ioDx3Z9uOvtJjk7i5Sj+18BR7JhspB4nu2r6Vn06AFMoXsHBsrzLxVpKC9 pPww== X-Gm-Message-State: AOAM531apPP5ZRbEUwZ6kcCxyHcBAVRFg9xdMAtM6vcZjXTeqnbAIH88 ARyTiDeyqfbsigeHE4HyJLOSzCOoZz0= X-Google-Smtp-Source: ABdhPJyMPsru/KTYSkksb0IP69mOSU2XoMbDyBkPpREK+vNx8sbowVpDDOakiySCRKujuqH3qC8CgwD7rJs= X-Received: from badhri.mtv.corp.google.com ([2620:15c:211:1:f292:1cff:fee0:66cf]) (user=badhri job=sendgmr) by 2002:a25:c50d:: with SMTP id v13mr12071638ybe.206.1598329380022; Mon, 24 Aug 2020 21:23:00 -0700 (PDT) Date: Mon, 24 Aug 2020 21:22:10 -0700 In-Reply-To: <20200825042210.300632-1-badhri@google.com> Message-Id: <20200825042210.300632-15-badhri@google.com> Mime-Version: 1.0 References: <20200825042210.300632-1-badhri@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH 14/14 v1] usb: typec: tcpci_maxim: Implemnent set_auto_vbus_discharge_threshold From: Badhri Jagan Sridharan To: Guenter Roeck , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Badhri Jagan Sridharan Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Programs VBUS_SINK_DISCONNECT_THRESHOLD based on the power_role, voltage requested as sink, mode of operation. The programmed threshold is based on vSinkDisconnect and vSinkDisconnectPD values. Signed-off-by: Badhri Jagan Sridharan --- drivers/usb/typec/tcpm/tcpci_maxim.c | 48 ++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpci_maxim.c b/drivers/usb/typec/tcpm/tcpci_maxim.c index 6ba808ad901a..e35bd995c037 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim.c +++ b/drivers/usb/typec/tcpm/tcpci_maxim.c @@ -137,6 +137,52 @@ static void max_tcpci_init_regs(struct max_tcpci_chip *chip) return; } +static int max_tcpci_set_auto_vbus_discharge_threshold(struct tcpci *tcpci, struct tcpci_data *data, + enum typec_role port_role, + enum typec_pwr_opmode mode, bool pps_active, + u32 requested_vbus_voltage_mv) +{ + struct max_tcpci_chip *chip = tdata_to_max_tcpci(data); + u32 threshold = 0; + u8 pwr_ctrl; + + /* + * Indicates that vbus is going to go away due PR_SWAP, hard reset etc. + * Do not discharge vbus here. + */ + if (requested_vbus_voltage_mv == 0) + goto write_thresh; + + if (port_role == TYPEC_SINK) { + max_tcpci_read8(chip, TCPC_POWER_CTRL, &pwr_ctrl); + if (pwr_ctrl & TCPC_FAST_ROLE_SWAP_EN) { + /* To prevent disconnect when the source is fast role swap is capable. */ + threshold = 3500; + } else if (mode == TYPEC_PWR_MODE_PD) { + if (pps_active) + threshold = (95 * requested_vbus_voltage_mv / 100) - 850; + else + threshold = (95 * requested_vbus_voltage_mv / 100) - 1250; + } else { + /* 3.5V for non-pd sink */ + threshold = 3500; + } + } else { + /* 4V for source */ + threshold = 4000; + } + + threshold = threshold / TCPC_VBUS_SINK_DISCONNECT_THRESH_LSB; + + if (threshold > TCPC_VBUS_SINK_DISCONNECT_THRESH_MAX) { + dev_err(chip->dev, "VBUS_SINK_DISCONNECT_THRESH out of range"); + return -EINVAL; + } + +write_thresh: + return max_tcpci_write16(chip, TCPC_VBUS_SINK_DISCONNECT_THRESH, threshold); +} + static void process_rx(struct max_tcpci_chip *chip, u16 status) { struct pd_message msg; @@ -454,6 +500,8 @@ static int max_tcpci_probe(struct i2c_client *client, const struct i2c_device_id chip->data.start_drp_toggling = max_tcpci_start_toggling; chip->data.TX_BUF_BYTE_x_hidden = true; chip->data.init = tcpci_init; + chip->data.set_auto_vbus_discharge_threshold = max_tcpci_set_auto_vbus_discharge_threshold; + chip->data.auto_discharge_disconnect = true; max_tcpci_init_regs(chip); chip->tcpci = tcpci_register_port(chip->dev, &chip->data);