From patchwork Fri Jan 15 16:33:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyle Tso X-Patchwork-Id: 12023211 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4E95C433E6 for ; Fri, 15 Jan 2021 16:34:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A2B37239A4 for ; Fri, 15 Jan 2021 16:34:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727842AbhAOQeN (ORCPT ); Fri, 15 Jan 2021 11:34:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727332AbhAOQeN (ORCPT ); Fri, 15 Jan 2021 11:34:13 -0500 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 E4272C061794 for ; Fri, 15 Jan 2021 08:33:32 -0800 (PST) Received: by mail-pj1-x104a.google.com with SMTP id u14so6263038pjl.2 for ; Fri, 15 Jan 2021 08:33:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:message-id:mime-version:subject:from:to:cc; bh=62Wh0CeYlqFdRUYiB3/MOzXQKL6e2IcczSb2KRUZCqI=; b=OuyIjO3hp0uQC2TSHc2qrTIXxfnOs7ztiwn9EZ7R5CzNuGeG0A4f6aKQO9vUq6cIza nkLu/E+w0oU4SYLPL0alNRU23Oe6NzHShuBDdUYlJBx4um1+6OAYYfMtZGhT+lHDEfCM kNy0YXyn32VkUVrOgRDPt+mNlq1eGL2LghbD/ixdvFv3doHDTtjIArc5oq5elbXUSOrQ VlsSYynidpdk9q3U0ydVU8MEF0lxkc11FZwxEzwEE04BSrbtr/bwDjjQpq3Mu6iqP0w0 sLyQitiaMKL7RwolGt6EY2YUkuJ3sFXbb+nRQLWMB7EIe0DVHegQ1hmG/Yl+Fo/3aPze xx5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:message-id:mime-version:subject:from :to:cc; bh=62Wh0CeYlqFdRUYiB3/MOzXQKL6e2IcczSb2KRUZCqI=; b=AEqwvSGmc71WfVjl/Rz66P7ESr2bPvLRWVKa88suioUnZnRzvZGDUe4WT58JMpA5SZ Zp0CyM6yauDuxpD13ZGp7YeUrmFKwIbGBzizyHMkx8R4JD+Nl5t/yzQZVW3xNQcKnsUI Hs34hHiNMZ0VEMv7G+1PY/G7paFVQR2h0ZOAFB5hhe9B1GG+BL1DE/JnlOub+SicKnPt cRbikfgEOM/R6rEq3h6AtTj/K3uXMJuwVh2GWKHVnOxI2fuhKnGZIrv41k0uVHqVAuts eaKo7RhzOKYBdyibA+V7ke3uCYjNzMNOIt1fuHQkiiwiaNUvffma/8yMhKCkoCgstGgH A8jA== X-Gm-Message-State: AOAM532DnihVK3QknpJxuv4fNz5g6zFLNtDgQeMnAuJzvknYEIFLA92g GJ7t2NmxfYG4Dv4K1g4EbmwWRIi9IFNi X-Google-Smtp-Source: ABdhPJyhoTSneMN702u7mmXV5SKQRhJqAx9inqTZ/91e9ET9qgOo5p861OBlWOzP9+MW/eDDPo76oOUiwFcL Sender: "kyletso via sendgmr" X-Received: from kyletso.ntc.corp.google.com ([2401:fa00:fc:202:c526:801e:f282:58de]) (user=kyletso job=sendgmr) by 2002:a62:b410:0:b029:1a4:7868:7e4e with SMTP id h16-20020a62b4100000b02901a478687e4emr13709797pfn.62.1610728412345; Fri, 15 Jan 2021 08:33:32 -0800 (PST) Date: Sat, 16 Jan 2021 00:33:11 +0800 Message-Id: <20210115163311.391332-1-kyletso@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.30.0.284.gd98b1dd5eaa7-goog Subject: [PATCH] usb: typec: tcpm: Create legacy PDOs for PD2 connection From: Kyle Tso To: linux@roeck-us.net, heikki.krogerus@linux.intel.com, gregkh@linuxfoundation.org Cc: badhri@google.com, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Kyle Tso Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org If the port partner is PD2, the PDOs of the local port should follow the format defined in PD2 Spec. Dynamically modify the pre-defined PD3 PDOs and transform them into PD2 format before sending them to the PD2 port partner. Signed-off-by: Kyle Tso Reviewed-by: Guenter Roeck Reviewed-by: Heikki Krogerus --- drivers/usb/typec/tcpm/tcpm.c | 62 +++++++++++++++++++++++++++++------ include/linux/usb/pd.h | 1 + 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 22a85b396f69..1220ab1ed47d 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -911,13 +911,47 @@ static int tcpm_set_pwr_role(struct tcpm_port *port, enum typec_role role) return 0; } +/* + * Transform the PDO to be compliant to PD rev2.0. + * Return 0 if the PDO type is not defined in PD rev2.0. + * Otherwise, return the converted PDO. + */ +static u32 tcpm_forge_legacy_pdo(struct tcpm_port *port, u32 pdo, enum typec_role role) +{ + switch (pdo_type(pdo)) { + case PDO_TYPE_FIXED: + if (role == TYPEC_SINK) + return pdo & ~PDO_FIXED_FRS_CURR_MASK; + else + return pdo & ~PDO_FIXED_UNCHUNK_EXT; + case PDO_TYPE_VAR: + case PDO_TYPE_BATT: + return pdo; + case PDO_TYPE_APDO: + default: + return 0; + } +} + static int tcpm_pd_send_source_caps(struct tcpm_port *port) { struct pd_message msg; - int i; + u32 pdo; + unsigned int i, nr_pdo = 0; memset(&msg, 0, sizeof(msg)); - if (!port->nr_src_pdo) { + + for (i = 0; i < port->nr_src_pdo; i++) { + if (port->negotiated_rev >= PD_REV30) { + msg.payload[nr_pdo++] = cpu_to_le32(port->src_pdo[i]); + } else { + pdo = tcpm_forge_legacy_pdo(port, port->src_pdo[i], TYPEC_SOURCE); + if (pdo) + msg.payload[nr_pdo++] = cpu_to_le32(pdo); + } + } + + if (!nr_pdo) { /* No source capabilities defined, sink only */ msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, @@ -930,10 +964,8 @@ static int tcpm_pd_send_source_caps(struct tcpm_port *port) port->data_role, port->negotiated_rev, port->message_id, - port->nr_src_pdo); + nr_pdo); } - for (i = 0; i < port->nr_src_pdo; i++) - msg.payload[i] = cpu_to_le32(port->src_pdo[i]); return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); } @@ -941,10 +973,22 @@ static int tcpm_pd_send_source_caps(struct tcpm_port *port) static int tcpm_pd_send_sink_caps(struct tcpm_port *port) { struct pd_message msg; - int i; + u32 pdo; + unsigned int i, nr_pdo = 0; memset(&msg, 0, sizeof(msg)); - if (!port->nr_snk_pdo) { + + for (i = 0; i < port->nr_snk_pdo; i++) { + if (port->negotiated_rev >= PD_REV30) { + msg.payload[nr_pdo++] = cpu_to_le32(port->snk_pdo[i]); + } else { + pdo = tcpm_forge_legacy_pdo(port, port->snk_pdo[i], TYPEC_SINK); + if (pdo) + msg.payload[nr_pdo++] = cpu_to_le32(pdo); + } + } + + if (!nr_pdo) { /* No sink capabilities defined, source only */ msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, @@ -957,10 +1001,8 @@ static int tcpm_pd_send_sink_caps(struct tcpm_port *port) port->data_role, port->negotiated_rev, port->message_id, - port->nr_snk_pdo); + nr_pdo); } - for (i = 0; i < port->nr_snk_pdo; i++) - msg.payload[i] = cpu_to_le32(port->snk_pdo[i]); return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); } diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h index bb9a782e1411..88f64bce5dea 100644 --- a/include/linux/usb/pd.h +++ b/include/linux/usb/pd.h @@ -225,6 +225,7 @@ enum pd_pdo_type { #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_UNCHUNK_EXT BIT(24) /* Unchunked Extended Message supported (Source) */ #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 */