From patchwork Mon Jan 8 19:16:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186113 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1225879dyq; Mon, 8 Jan 2024 11:17:27 -0800 (PST) X-Google-Smtp-Source: AGHT+IFfwc07EzPeJIElqL4+1nBKcHF66qZZE3rwJR3lyfUSyqBuIRfHKT+s4BV9RszRZRMGCIpJ X-Received: by 2002:a17:902:6547:b0:1d4:dec9:f163 with SMTP id d7-20020a170902654700b001d4dec9f163mr4498528pln.2.1704741447112; Mon, 08 Jan 2024 11:17:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741447; cv=none; d=google.com; s=arc-20160816; b=tFvVqDUk0GJO5sUxlJ1TPict9Fg3ZHzVvJyPEGVDkyP7/0hYkAyhiDIc1jpSoO6WlU AdzVburhPSMWWfD9Y9DTvoQAA9TQNYlnpOfHn7PSafXwjfx+13Pl33/RHMnHyyZYQFUi l6qlGg7QYHEaNfDRrQTZluGo4lJoJpZu6fg8bCqN3BWKn3QmIJibpBlsNXq10J49QOjW eyj2giVaqWV7qRUt04O35FWX703vNiM6VNTCKXb3Q8kVwM2/13wm1rvlpjOel2i+ep/L rXbEr9D0XCjL9jQTUwNoD/n66HSoyMu/Y/D7FJEPQ1rKUHaz8PKoPcv8ZhAnS6zrdMK5 E66w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=/Wth/8UoV+aL5LC0kJi/DVxESpme0aBOkMeRoyQ8VPg=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=rUMmCDCqeaml9snQpaia3Vb1KmW0XG3RijBOKBYhIaEji1o8zucoic6qGJcgtIOs6Z qLGKfZfwu49tpsaJFGQ1VL4qp33MBF5WundAgjEQJxFlhyT2rgZtNU6jXbvLHNFnqGbG FvhbtySvpUvG4jTCd+aWle9ao5HL/fJbQsaECfqblsVoDXUzPVA5gp3OA1DnvW0NxQlY N1vvpKBboVs9UvADj2wZI14KMeKzPixfIWq+Wn1QSbTWwhitWLOyC8go+IrcNLw9yYxN XgZEnkZQ+hTpVFBwi1zggsYSMJMBKtJiY/Kg9rZjeYChGz9tQz0TIQ9VQdfsNyz4PVY7 Ra+Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=JX5s4fAP; spf=pass (google.com: domain of linux-kernel+bounces-20018-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20018-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id u6-20020a17090282c600b001d3eaa80970si293345plz.174.2024.01.08.11.17.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:17:27 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20018-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=JX5s4fAP; spf=pass (google.com: domain of linux-kernel+bounces-20018-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20018-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id BF24E28335F for ; Mon, 8 Jan 2024 19:17:26 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8665C55797; Mon, 8 Jan 2024 19:16:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="JX5s4fAP" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E1F3054FA5 for ; Mon, 8 Jan 2024 19:16:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-5f874219ff9so10799787b3.0 for ; Mon, 08 Jan 2024 11:16:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741392; x=1705346192; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=/Wth/8UoV+aL5LC0kJi/DVxESpme0aBOkMeRoyQ8VPg=; b=JX5s4fAPwkuDPyS0kVqY5cblfmoiicWE7EptOaOfAeV18pajJIDRKziwuawvDCgbWJ Xu8Qh0B6zij3cTry78J5D+Qayr3XWL0MzdN5o8ED0v8KX4k4Y8blHkGpIfXxEc50CIZB YYzzC0XBR8JEw81mnaIPA4wDzWPCmtYhHrnD6CE1JV6DuM8q2ATQ4j3iY4PcSfKMqPws DY5g15CE7qUY8dyT0uCU/YUh98wssxcOWRJNJNgakyiwQPETEDv6Cvb5AWMpKFa3HaVB 0rW1s9DOdcp1gMV2Nh1cxSd5KpKb68ZPDqZPKD13RpDZ75Fqs/bnRDaTCk4Y8zfu0Nk+ jKfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741392; x=1705346192; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=/Wth/8UoV+aL5LC0kJi/DVxESpme0aBOkMeRoyQ8VPg=; b=J3qUOH6NT+v8F+/HT95kRlu5K09pgHi/wltnFOE8ghF8TYAx1Dn8qmRvzo/a615XnU UiTwuEOwqqRrEYgMQuO/PKbCyaJXKv6ZrsHlSPIyqqcodIkc3+WieKlmqDsOzMqcVeNL L+FiwGA5mtgL215h0hynWK3SI5s4hhFRZWkYMcWh+/3X0bdtCFaRhTV4cTXWzCjSUGOd UydWaYLDCpaUlK6jsWvpdkDvNDMccMgPP7awwhmAgdY+vpJbx86trHlp/+cfskDhkMvx maCncV+3HV3I0QVImCLr3oRAKYyghx6HhwylTgWRrHiBC95As2Z0LIsQ/hn8QAa59YZD Vvbw== X-Gm-Message-State: AOJu0YxJoQ7JyvwP+d0SNQd/Af37IEU20yN10JjfhiQp+pIbH68mCnan BHbhOHbGKfyYo5IVVO3lncIgGrqB7wNyeLxsIdqI9w== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a81:c706:0:b0:5f9:32c7:cc51 with SMTP id m6-20020a81c706000000b005f932c7cc51mr75760ywi.0.1704741391912; Mon, 08 Jan 2024 11:16:31 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:14 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=7965; i=rdbabiera@google.com; h=from:subject; bh=Y9LvmKwg8nyhTWBiDudZ8gZ35eWUccV05qkVwo8b+M0=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvFgT/z57lck7+abNwa/fptx4uGjZ/2e+p+M+BMlzS /NPDI4711HKwiDGwSArpsii659ncONK6pY5nDXGMHNYmUCGMHBxCsBEJn5iZJi8Xafn1tHJNzSm x9YGffB28s7Jn+p2fer2jP9TXmnN/ZTN8E+DN3fm6y8hfdv7nmiI3rKfwGum9Mf1h+Bi13b7tzc LOvgB X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-15-rdbabiera@google.com> Subject: [PATCH v3 01/12] usb: typec: altmodes: add typec_cable_ops to typec_altmode From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787550967238401896 X-GMAIL-MSGID: 1787550967238401896 Add typec_cable_ops struct for enter, exit, and vdm. The struct is added to typec_altmode so port alt modes can have access to partner and cable specific callbacks, and alt mode drivers can specify operations over SOP' and SOP'' without modifying the existing API. typec_port_register_cable_ops is added as a new symbol for port drivers to use to register cable operations to their registered port alt modes. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- Changes since v2: * fixed documentation prototype errors --- drivers/usb/typec/bus.c | 102 ++++++++++++++++++++++++++++++ drivers/usb/typec/class.c | 19 ++++++ include/linux/usb/typec.h | 4 ++ include/linux/usb/typec_altmode.h | 20 ++++++ 4 files changed, 145 insertions(+) diff --git a/drivers/usb/typec/bus.c b/drivers/usb/typec/bus.c index e95ec7e382bb..6ea103e1abae 100644 --- a/drivers/usb/typec/bus.c +++ b/drivers/usb/typec/bus.c @@ -244,6 +244,108 @@ typec_altmode_get_partner(struct typec_altmode *adev) } EXPORT_SYMBOL_GPL(typec_altmode_get_partner); +/* -------------------------------------------------------------------------- */ +/* API for cable alternate modes */ + +/** + * typec_cable_altmode_enter - Enter Mode + * @adev: The alternate mode + * @sop: Cable plug target for Enter Mode command + * @vdo: VDO for the Enter Mode command + * + * Alternate mode drivers use this function to enter mode on the cable plug. + * If the alternate mode does not require VDO, @vdo must be NULL. + */ +int typec_cable_altmode_enter(struct typec_altmode *adev, enum typec_plug_index sop, u32 *vdo) +{ + struct altmode *partner = to_altmode(adev)->partner; + struct typec_altmode *pdev; + + if (!adev || adev->active) + return 0; + + if (!partner) + return -ENODEV; + + pdev = &partner->adev; + + if (!pdev->active) + return -EPERM; + + if (!pdev->cable_ops || !pdev->cable_ops->enter) + return -EOPNOTSUPP; + + return pdev->cable_ops->enter(pdev, sop, vdo); +} +EXPORT_SYMBOL_GPL(typec_cable_altmode_enter); + +/** + * typec_cable_altmode_exit - Exit Mode + * @adev: The alternate mode + * @sop: Cable plug target for Exit Mode command + * + * The alternate mode drivers use this function to exit mode on the cable plug. + */ +int typec_cable_altmode_exit(struct typec_altmode *adev, enum typec_plug_index sop) +{ + struct altmode *partner = to_altmode(adev)->partner; + struct typec_altmode *pdev; + + if (!adev || !adev->active) + return 0; + + if (!partner) + return -ENODEV; + + pdev = &partner->adev; + + if (!pdev->cable_ops || !pdev->cable_ops->exit) + return -EOPNOTSUPP; + + return pdev->cable_ops->exit(pdev, sop); +} +EXPORT_SYMBOL_GPL(typec_cable_altmode_exit); + +/** + * typec_cable_altmode_vdm - Send Vendor Defined Messages (VDM) between the cable plug and port. + * @adev: Alternate mode handle + * @sop: Cable plug target for VDM + * @header: VDM Header + * @vdo: Array of Vendor Defined Data Objects + * @count: Number of Data Objects + * + * The alternate mode drivers use this function for SVID specific communication + * with the cable plugs. The port drivers use it to deliver the Structured VDMs + * received from the cable plugs to the alternate mode drivers. + */ +int typec_cable_altmode_vdm(struct typec_altmode *adev, enum typec_plug_index sop, + const u32 header, const u32 *vdo, int count) +{ + struct altmode *altmode; + struct typec_altmode *pdev; + + if (!adev) + return 0; + + altmode = to_altmode(adev); + + if (is_typec_plug(adev->dev.parent)) { + if (!altmode->partner) + return -ENODEV; + pdev = &altmode->partner->adev; + } else { + if (!altmode->plug[sop]) + return -ENODEV; + pdev = &altmode->plug[sop]->adev; + } + + if (!pdev->cable_ops || !pdev->cable_ops->vdm) + return -EOPNOTSUPP; + + return pdev->cable_ops->vdm(pdev, sop, header, vdo, count); +} +EXPORT_SYMBOL_GPL(typec_cable_altmode_vdm); + /* -------------------------------------------------------------------------- */ /* API for the alternate mode drivers */ diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index 015aa9253353..8fc9795d6bd4 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -2280,6 +2280,25 @@ void typec_port_register_altmodes(struct typec_port *port, } EXPORT_SYMBOL_GPL(typec_port_register_altmodes); +/** + * typec_port_register_cable_ops - Register typec_cable_ops to port altmodes + * @altmodes: USB Type-C Port's altmode vector + * @max_altmodes: The maximum number of alt modes supported by the port + * @ops: Cable alternate mode vector + */ +void typec_port_register_cable_ops(struct typec_altmode **altmodes, int max_altmodes, + const struct typec_cable_ops *ops) +{ + int i; + + for (i = 0; i < max_altmodes; i++) { + if (!altmodes[i]) + return; + altmodes[i]->cable_ops = ops; + } +} +EXPORT_SYMBOL_GPL(typec_port_register_cable_ops); + /** * typec_register_port - Register a USB Type-C Port * @parent: Parent device diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h index a05d6f6f2536..38f93d72fd1b 100644 --- a/include/linux/usb/typec.h +++ b/include/linux/usb/typec.h @@ -18,6 +18,7 @@ struct typec_cable; struct typec_plug; struct typec_port; struct typec_altmode_ops; +struct typec_cable_ops; struct fwnode_handle; struct device; @@ -157,6 +158,9 @@ void typec_port_register_altmodes(struct typec_port *port, const struct typec_altmode_ops *ops, void *drvdata, struct typec_altmode **altmodes, size_t n); +void typec_port_register_cable_ops(struct typec_altmode **altmodes, int max_altmodes, + const struct typec_cable_ops *ops); + void typec_unregister_altmode(struct typec_altmode *altmode); struct typec_port *typec_altmode2port(struct typec_altmode *alt); diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_altmode.h index 28aeef8f9e7b..72ec8058543a 100644 --- a/include/linux/usb/typec_altmode.h +++ b/include/linux/usb/typec_altmode.h @@ -20,6 +20,7 @@ struct typec_altmode_ops; * @active: Tells has the mode been entered or not * @desc: Optional human readable description of the mode * @ops: Operations vector from the driver + * @cable_ops: Cable operations vector from the driver. */ struct typec_altmode { struct device dev; @@ -30,6 +31,7 @@ struct typec_altmode { char *desc; const struct typec_altmode_ops *ops; + const struct typec_cable_ops *cable_ops; }; #define to_typec_altmode(d) container_of(d, struct typec_altmode, dev) @@ -75,6 +77,24 @@ int typec_altmode_notify(struct typec_altmode *altmode, unsigned long conf, const struct typec_altmode * typec_altmode_get_partner(struct typec_altmode *altmode); +/** + * struct typec_cable_ops - Cable alternate mode operations vector + * @enter: Operations to be executed with Enter Mode Command + * @exit: Operations to be executed with Exit Mode Command + * @vdm: Callback for SVID specific commands + */ +struct typec_cable_ops { + int (*enter)(struct typec_altmode *altmode, enum typec_plug_index sop, u32 *vdo); + int (*exit)(struct typec_altmode *altmode, enum typec_plug_index sop); + int (*vdm)(struct typec_altmode *altmode, enum typec_plug_index sop, + const u32 hdr, const u32 *vdo, int cnt); +}; + +int typec_cable_altmode_enter(struct typec_altmode *altmode, enum typec_plug_index sop, u32 *vdo); +int typec_cable_altmode_exit(struct typec_altmode *altmode, enum typec_plug_index sop); +int typec_cable_altmode_vdm(struct typec_altmode *altmode, enum typec_plug_index sop, + const u32 header, const u32 *vdo, int count); + /* * These are the connector states (USB, Safe and Alt Mode) defined in USB Type-C * Specification. SVID specific connector states are expected to follow and From patchwork Mon Jan 8 19:16:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186114 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1225892dyq; Mon, 8 Jan 2024 11:17:29 -0800 (PST) X-Google-Smtp-Source: AGHT+IEcvuAA2570eGsWFVHS+chOYfAj7Bj5y+kMu9EXupvSVPdvXswuHp1H1CMl3SAIbJ6OxF99 X-Received: by 2002:a05:6808:3c97:b0:3bc:2ea7:535d with SMTP id gs23-20020a0568083c9700b003bc2ea7535dmr6290677oib.113.1704741448961; Mon, 08 Jan 2024 11:17:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741448; cv=none; d=google.com; s=arc-20160816; b=XbdMBmcHXVR/n5q2DNaQMWpSsFIEAee5H7axMsDvlRw4Fvi8unIf3bOC+5mDj2GEPn xQrt/n7H+2YGyI++hPAuWeCIYdUuWwbpJFLA7AKX8PxSpsnI56qbcedNYxYYC05g5DuG 3U9AjYRSHgZiXuFYAFuCLlMLdTqG1NqHGC8RJraPbrebWW2YlyWuNW61F6UkbfTKBpjO GydlfE7549dVPYKBU5epDL8ldqkfT6/QBaVAJWWLB2M4CHGlRV6GXOGSgVoMbSFk+bMX P3an464KLCaTTQ8P9i+w3r0lhfaO7bxfVQi8Ydnlaxp52srIYKwnSwEJrXn6Ot0WJdto /grQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=6cTxGOovJ9V9dXlWmUdvT596HOaLkkrDzIVt7n3ymDs=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=BGtt0yX+RL17uxjTqXxar9klN5VxTtRr0yKbgiZ04tg4+H/n/IfdgUwcIaOu1b0gSs wYEXEhIeC68MKPlHBHZ/BysNskqRslVud+DN5ugv3gYF+dlhe8cu7iVwzdHkXTPtElOp QmbjSykRPp2nXhAVKTlXmnVx36S6vqC+8uK4enf3z/alBY/Bc8/kUVn/jqkc+a+W1RDT atD4IbmkZuFWfDGvb01l0nf1uvI/z3/8Tf1+OFiOXfW/I1Q4vpNgsiAusEAfHiogkduK pXRQ8HlEVxgj9GUP9simcPd5WbU1fzgUPOErW+CmwkHflLNIU75xKMNtGH3pfoBFSnKo 8H5w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=l28wfI91; spf=pass (google.com: domain of linux-kernel+bounces-20019-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20019-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id e20-20020a05620a12d400b00781eea772basi312502qkl.526.2024.01.08.11.17.28 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:17:28 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20019-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=l28wfI91; spf=pass (google.com: domain of linux-kernel+bounces-20019-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20019-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id ABBF41C23EC8 for ; Mon, 8 Jan 2024 19:17:28 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A315155C30; Mon, 8 Jan 2024 19:16:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="l28wfI91" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F07655764 for ; Mon, 8 Jan 2024 19:16:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-5f6f51cd7e8so24407147b3.1 for ; Mon, 08 Jan 2024 11:16:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741393; x=1705346193; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=6cTxGOovJ9V9dXlWmUdvT596HOaLkkrDzIVt7n3ymDs=; b=l28wfI91yJ5LrTmUvphWBvDyTt5ZrIAc+S0Xoyj/AnxDbqscLQlk6r5cy6Kfdz06wb dp+1gTIrwrbd0/4FhG5h4HnrA6b2RBcHWKOnKd/SCj/ESadXO2ZDM7Zo80cjoapXskZR mWERzBVLIDOTG7uNyzkaW1W13WEqU9xvNt/MJsNGeIDf2N7f7e/TzegxbBTxjb0U7UvI xg5gbaIVj5gcA0sayvVsd7OX2k+qyqFp7Hbv06p65FZdq2/7L/j/vQ5lQrC3zteufmaF 9tY4tt7IuZbuLID3A0mzmEk1tgRQB14HmUkecBm8/avFOgFc9Npyk2hSrrgAvAj0kH18 zJZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741393; x=1705346193; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=6cTxGOovJ9V9dXlWmUdvT596HOaLkkrDzIVt7n3ymDs=; b=aLiunJClxXC6ZAsC/0hNoHlV3sr+pQy7uBtqqTctd2gLdLMRm04sRrKdvZnJRaRugK y+HURwzpI1ck9lqm+X7H8uNNTc4eSw4EFHAwb6uY+TM/wxu63AbX3Xi1HZy9ikd8yXvP RG9gYmaAXBYlqPaP5RssVvGZqWSzcR+FXlX/a2OWJoeNVD1swcqlNznSkLHEoc/wesLv EsvwEVFcX+IqCtcOEC/e+C36idDsb9j6TPZpuTu6AX00rEnP+LwLOgRSx4bSdsD6VPB0 6hnjxOHslTRKgIhN70bR1FAa50PYafRRLwlfYY5IaRnlXPataaLVq3sHZQ9BmZUsdwht X2XA== X-Gm-Message-State: AOJu0YzWzP3acXYtutzQoQc8KpXf3PQXVPPKR9DxSyTx5aLCgGR4AWVS /xsJ7YET9IIaLbiso3CTZ2DehdhsYNbSwYie3NOpwg== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a05:690c:309:b0:5e6:579e:65dd with SMTP id bg9-20020a05690c030900b005e6579e65ddmr1849078ywb.3.1704741393710; Mon, 08 Jan 2024 11:16:33 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:15 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=4597; i=rdbabiera@google.com; h=from:subject; bh=j+lKxg3/XM4yeeEZLecb85/FMhalIVj7y0+SqcQ18x0=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvFgbQqZ9ln1+4MHumiKL+T+Df/e/MZ76wHDlxfh1V 6yUFnozd5SyMIhxMMiKKbLo+ucZ3LiSumUOZ40xzBxWJpAhDFycAjCRT1sZ/of9Vxe8dMKE5cXn ppKLnSaWmysUZ0uq55terVhg87KT9zIjw3YFcdW65cx9Vl7LKjMXWs1eq60eyHH6veCF+ZYL9aa dYwYA X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-16-rdbabiera@google.com> Subject: [PATCH v3 02/12] usb: typec: altmodes: add svdm version info for typec cables From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787550969773200386 X-GMAIL-MSGID: 1787550969773200386 Add typec_cable_set_svdm_version and typec_get_cable_svdm version symbols. Cables can operate under a lower PD revision than the port partner, and the max SVDM version is tied to the PD revision. So, typec_cable maintains its own svdm_version. Add typec_altmode_get_cable_svdm_version to return the cable's negotiated svdm_version for altmode drivers to use. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- Changes from v2: * added reviewed-by tag --- drivers/usb/typec/class.c | 40 +++++++++++++++++++++++++++++++ drivers/usb/typec/class.h | 1 + include/linux/usb/typec.h | 3 +++ include/linux/usb/typec_altmode.h | 10 ++++++++ 4 files changed, 54 insertions(+) diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index 8fc9795d6bd4..caea2b829980 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -2131,6 +2131,46 @@ int typec_get_negotiated_svdm_version(struct typec_port *port) } EXPORT_SYMBOL_GPL(typec_get_negotiated_svdm_version); +/** + * typec_get_cable_svdm_version - Get cable negotiated SVDM Version + * @port: USB Type-C Port. + * + * Get the negotiated SVDM Version for the cable. The Version is set to the port + * default value based on the PD Revision during cable registration, and updated + * after a successful Discover Identity if the negotiated value is less than the + * default. + * + * Returns usb_pd_svdm_ver if the cable has been registered otherwise -ENODEV. + */ +int typec_get_cable_svdm_version(struct typec_port *port) +{ + enum usb_pd_svdm_ver svdm_version; + struct device *cable_dev; + + cable_dev = device_find_child(&port->dev, NULL, cable_match); + if (!cable_dev) + return -ENODEV; + + svdm_version = to_typec_cable(cable_dev)->svdm_version; + put_device(cable_dev); + + return svdm_version; +} +EXPORT_SYMBOL_GPL(typec_get_cable_svdm_version); + +/** + * typec_cable_set_svdm_version - Set negotiated Structured VDM (SVDM) Version + * @cable: USB Type-C Active Cable that supports SVDM + * @svdm_version: Negotiated SVDM Version + * + * This routine is used to save the negotiated SVDM Version. + */ +void typec_cable_set_svdm_version(struct typec_cable *cable, enum usb_pd_svdm_ver svdm_version) +{ + cable->svdm_version = svdm_version; +} +EXPORT_SYMBOL_GPL(typec_cable_set_svdm_version); + /** * typec_get_drvdata - Return private driver data pointer * @port: USB Type-C port diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h index c36761ba3f59..759b98355eeb 100644 --- a/drivers/usb/typec/class.h +++ b/drivers/usb/typec/class.h @@ -23,6 +23,7 @@ struct typec_cable { struct usb_pd_identity *identity; unsigned int active:1; u16 pd_revision; /* 0300H = "3.0" */ + enum usb_pd_svdm_ver svdm_version; }; struct typec_partner { diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h index 38f93d72fd1b..b35b427561ab 100644 --- a/include/linux/usb/typec.h +++ b/include/linux/usb/typec.h @@ -337,6 +337,9 @@ void typec_partner_set_svdm_version(struct typec_partner *partner, enum usb_pd_svdm_ver svdm_version); int typec_get_negotiated_svdm_version(struct typec_port *port); +int typec_get_cable_svdm_version(struct typec_port *port); +void typec_cable_set_svdm_version(struct typec_cable *cable, enum usb_pd_svdm_ver svdm_version); + struct usb_power_delivery *typec_partner_usb_power_delivery_register(struct typec_partner *partner, struct usb_power_delivery_desc *desc); diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_altmode.h index 72ec8058543a..b3c0866ea70f 100644 --- a/include/linux/usb/typec_altmode.h +++ b/include/linux/usb/typec_altmode.h @@ -95,6 +95,16 @@ int typec_cable_altmode_exit(struct typec_altmode *altmode, enum typec_plug_inde int typec_cable_altmode_vdm(struct typec_altmode *altmode, enum typec_plug_index sop, const u32 header, const u32 *vdo, int count); +/** + * typec_altmode_get_cable_svdm_version - Get negotiated SVDM version for cable plug + * @altmode: Handle to the alternate mode + */ +static inline int +typec_altmode_get_cable_svdm_version(struct typec_altmode *altmode) +{ + return typec_get_cable_svdm_version(typec_altmode2port(altmode)); +} + /* * These are the connector states (USB, Safe and Alt Mode) defined in USB Type-C * Specification. SVID specific connector states are expected to follow and From patchwork Mon Jan 8 19:16:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186115 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1226077dyq; Mon, 8 Jan 2024 11:17:50 -0800 (PST) X-Google-Smtp-Source: AGHT+IGK1byDDLjG6su1s546BsMQTadkIPMJhV6Hajw4WyHWqhRcSS0EcZBLhq3d+xzCELmzOvzq X-Received: by 2002:a05:6e02:12e2:b0:360:6203:f4 with SMTP id l2-20020a056e0212e200b00360620300f4mr4261051iln.0.1704741470161; Mon, 08 Jan 2024 11:17:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741470; cv=none; d=google.com; s=arc-20160816; b=tjeWOd/by71H4b4umcXu8iB6kCdPjeCaIV8tArtX+KoEddUnt0hJgSI92qpmAW19SU gEme1QvwPu/u7RMpcplhO7AYkMFqNPXr1P78EWDDnvEoHMwfKDd6KA8i52SnKgRyeqhu /bxvwVGGtIrEFAnCnXJ9yqYe2mLt3+UGDSoQkCPZfMgWj7cRryWCUH0pQOBhjOrSdj5R 18l2shv4fzW6pnmv2aiOm+/KHEiqLol26XUENgOWImeTZydrcXuHgQrnitkneHL3+bgq qpvPwBZaFFafrEaSra5wgv58dPl2UQio11Ty1eQM+uGxAu1GB5ba7Rr8NaJusmUgOBPK nGIg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=CVjThMZLotAdWb9TIioEoi19kF6hz6fkppa/3qq7zYI=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=KuAvmqRyTYVjwifrxokWQETzDuM8vBxEpZ5VdranLKrEop5ZKQY2gkYSIuX/CdieVo BE+8FptlwY5CQflzP8Mw2YaAC+mg62PKXTpOFiRKYmIpwEJdeaRWxcB/3qEkGXfDXtmu CZl97xrBG+Wy/sXpz/VFZCZkcGqYRE2Z1OgJx6ib+usAKmnCCE+vdKFzLnGszbe4YpTU 0IQyTuH4sG7Ol8u6D8FdOFHf5syP6t2yoUbwy+5tNDCA4m90tZbrlAGY2LZyG566eJCl t7jiYpljJcbOn98+YWQF0eYS4LeBPePh0VR13Dg7ydSQevyW/VCRuf0QPwNqbxds04H4 ++Zw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=gXjA9WZK; spf=pass (google.com: domain of linux-kernel+bounces-20020-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20020-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id q21-20020a638c55000000b005c66404de05si264509pgn.413.2024.01.08.11.17.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:17:50 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20020-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=gXjA9WZK; spf=pass (google.com: domain of linux-kernel+bounces-20020-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20020-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id C04E0284DD7 for ; Mon, 8 Jan 2024 19:17:49 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9A0A654FA6; Mon, 8 Jan 2024 19:16:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gXjA9WZK" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-pg1-f202.google.com (mail-pg1-f202.google.com [209.85.215.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 15F9955780 for ; Mon, 8 Jan 2024 19:16:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-5cde2b113e7so481448a12.2 for ; Mon, 08 Jan 2024 11:16:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741395; x=1705346195; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=CVjThMZLotAdWb9TIioEoi19kF6hz6fkppa/3qq7zYI=; b=gXjA9WZKQE618v3eomvwmqVc0HmFl12Pr3USpMwXCUw2qFTAw1aG/M1PwDohAgy6dz RJAJgrVINOeor6NvkoIJ+eLElk+xFxcVbVeFV6K4mWcDxf0MKlm7i/OPIF1g2/1swrC1 k55CwwCkZYl3p9nzGAksScZueBMh2yDsOmnh2WLnNU8Mq2k42CzjGjDzvOylWzsnO+V7 jgkb/OzwQcLo6yIQykTsFV26nGQH6GUCJ8Tu48gT8ZeapQqtUIOohg758t3TMtjzJFAx I5o3wtuUXc7KDf8uNAkB3q+TbKqRuF5XVZjPhkxyOTLx1P6RUypKtsCuoUJ6b68wImNY g7Bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741395; x=1705346195; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=CVjThMZLotAdWb9TIioEoi19kF6hz6fkppa/3qq7zYI=; b=Kb/BI97OPXrdRR7/+PBpLMQBhUwnC2iFVQm5e/IW75e9J64GEUMifhZvQJpg7t5OPT Ll/+PP2dY9U5sffDJKMXBIVtlol1b9SkRaBxOkOgqeUk9SwrInFU1ytzBFTam6ADdINX fJNDF0CWmgNnyv0nNWkfq5I9+IAOjHwjCSYP8YMY9SheZJueq/UIKty+L0dAm3d//aL3 I1huhAY6oHmizi4o4Hpf0vO9zFFPbBDYmC0RoaNExVknaX9EY/2mlMTXPKZ96YNpOtJy SOWaQaVGtQUtkXCCfGZ2khI/qtDi2jOvDVdazdBtBq4/P8p6rn/cRtxzgkt1aWdTeukE jfhg== X-Gm-Message-State: AOJu0YwperNZKD5eSWNMGWVaU/cC5xhmix0MpAiI+ZPyq/XRE7tuH0Da hyTA10eYBn3oVhCpxSzKy8tQRcNZ09NYyizKVqfJGw== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a63:1c54:0:b0:5ca:43c7:a67 with SMTP id c20-20020a631c54000000b005ca43c70a67mr23049pgm.9.1704741395247; Mon, 08 Jan 2024 11:16:35 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:16 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=4338; i=rdbabiera@google.com; h=from:subject; bh=putn0Ho6wv9tIgjQ9wNDNZ2hIDbeB2w3mtNH9bjlwx0=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvFjfXD6++XiP0TlvxS1e0R8fJxR032DmMN/EyiVeJ NE7b25RRykLgxgHg6yYIouuf57BjSupW+Zw1hjDzGFlAhnCwMUpABNJaWP4X/Be13n6O/XbTmsP WjzKnD0ptO/hqs4N69V6G2vuPdaUucnIcG+e5DIhF8uQD/JnHk/aleHXf6eGLeO9jnp+rdmdx65 yfAA= X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-17-rdbabiera@google.com> Subject: [PATCH v3 03/12] usb: typec: tcpci: add cable_comm_capable attribute From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787550991575307585 X-GMAIL-MSGID: 1787550991575307585 Add cable_comm_capable to tcpci_data for tcpci drivers to indicate that the port tcpc is capable of communicating to cables over SOP. A corresponding tcpci callback tcpci_cable_comm_capable returns this value. The tcpm will primarily use this in later patches to determine if the port can transmit and receive SOP' messages. Maxim based tcpci drivers are capable of SOP' communication, so the cable_comm_capable flag is set to true. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- Changes since v2: * Added reviewed-by tag Changes since v1: * Moved tcpm_pd_receive changes to separate patch --- drivers/usb/typec/tcpm/tcpci.c | 8 ++++++++ drivers/usb/typec/tcpm/tcpci_maxim_core.c | 1 + include/linux/usb/tcpci.h | 3 +++ include/linux/usb/tcpm.h | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 0ee3e6e29bb1..1ededbcecc09 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -584,6 +584,13 @@ static int tcpci_pd_transmit(struct tcpc_dev *tcpc, enum tcpm_transmit_type type return 0; } +static bool tcpci_cable_comm_capable(struct tcpc_dev *tcpc) +{ + struct tcpci *tcpci = tcpc_to_tcpci(tcpc); + + return tcpci->data->cable_comm_capable; +} + static int tcpci_init(struct tcpc_dev *tcpc) { struct tcpci *tcpci = tcpc_to_tcpci(tcpc); @@ -793,6 +800,7 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data) tcpci->tcpc.enable_frs = tcpci_enable_frs; tcpci->tcpc.frs_sourcing_vbus = tcpci_frs_sourcing_vbus; tcpci->tcpc.set_partner_usb_comm_capable = tcpci_set_partner_usb_comm_capable; + tcpci->tcpc.cable_comm_capable = tcpci_cable_comm_capable; if (tcpci->data->check_contaminant) tcpci->tcpc.check_contaminant = tcpci_check_contaminant; diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c index 7fb966fd639b..7b2d4e6e52a2 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c +++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c @@ -478,6 +478,7 @@ static int max_tcpci_probe(struct i2c_client *client) chip->data.vbus_vsafe0v = true; chip->data.set_partner_usb_comm_capable = max_tcpci_set_partner_usb_comm_capable; chip->data.check_contaminant = max_tcpci_check_contaminant; + chip->data.cable_comm_capable = true; max_tcpci_init_regs(chip); chip->tcpci = tcpci_register_port(chip->dev, &chip->data); diff --git a/include/linux/usb/tcpci.h b/include/linux/usb/tcpci.h index 467e8045e9f8..1d0b849defd0 100644 --- a/include/linux/usb/tcpci.h +++ b/include/linux/usb/tcpci.h @@ -198,12 +198,15 @@ struct tcpci; * Chip level drivers are expected to check for contaminant and call * tcpm_clean_port when the port is clean to put the port back into * toggling state. + * @cable_comm_capable + * optional; Set when TCPC can communicate with cable plugs over SOP' */ struct tcpci_data { struct regmap *regmap; unsigned char TX_BUF_BYTE_x_hidden:1; unsigned char auto_discharge_disconnect:1; unsigned char vbus_vsafe0v:1; + unsigned char cable_comm_capable:1; int (*init)(struct tcpci *tcpci, struct tcpci_data *data); int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data, diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index 65fac5e1f317..430fa3ec69bb 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h @@ -119,6 +119,9 @@ enum tcpm_transmit_type { * at the end of the deboumce period or when the port is still * toggling. Chip level drivers are expected to check for contaminant * and call tcpm_clean_port when the port is clean. + * @cable_comm_capable + * Optional; Returns whether cable communication over SOP' is supported + * by the tcpc */ struct tcpc_dev { struct fwnode_handle *fwnode; @@ -154,6 +157,7 @@ struct tcpc_dev { bool (*is_vbus_vsafe0v)(struct tcpc_dev *dev); void (*set_partner_usb_comm_capable)(struct tcpc_dev *dev, bool enable); void (*check_contaminant)(struct tcpc_dev *dev); + bool (*cable_comm_capable)(struct tcpc_dev *dev); }; struct tcpm_port; From patchwork Mon Jan 8 19:16:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186116 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1226184dyq; Mon, 8 Jan 2024 11:18:04 -0800 (PST) X-Google-Smtp-Source: AGHT+IFH9wxAFYnTAJOhiV+sCF5c9LWEpOPVPzo3NU64GhaBjcWGyC5R5CLTKywJ+onbNXdIXqOQ X-Received: by 2002:a17:902:904c:b0:1d4:bcfa:2b0e with SMTP id w12-20020a170902904c00b001d4bcfa2b0emr1775153plz.93.1704741484550; Mon, 08 Jan 2024 11:18:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741484; cv=none; d=google.com; s=arc-20160816; b=Dmv6nFLePCrHs12wy6SVj5rNDm3lRRWsHNLXE6ELos85dSRxrhJCyz6xijZulM21ms vVyu5H5vrVf9+NAH/DnxKFYl/fnF9REB0xFA4/2iiB/WYXSKWGQIyQVLctDBT9z9ttFq X3PBOUqRpChCAe8eyJd0OjrfSTecrSffe6QZ+7CWwdREGmUDAq2Q0LZF06Fo1XNi6C8W r9DyxJl4Byv0gN7HzYI15TOR/8K4P6wetYhCHIMHLjOOPtwAA6JJcOM6avh0iSpk5g+N tqoFOx3C85InKRoH2o6jB+C/bSLvjgGjY1PLVlif8456q2YZ7io3J/FGqjgghUTZCzBw halw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=VA6GXsaY8kxjlMQ9qtGQVmBvg/30vKloMaDh2oUyHwI=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=0IAjIE0zMWZ7ZAO+6XCLOOR+1hSTSs2SYO+IPnNKAkXV08+gb0caE9CwD3rx2gtss+ VbC3oUIHAIR4W5L8EqxWjMCPbE6H0g4KsvYEpsW/krECRaOUMAsQdvbJRbMlx7CUI9T9 xideFe/upDDmycUGxX25TiLJg32sRC5val3CWgGulyH1GE8KXXct0j/7txsFL+FxUzIq KYkzEnxS7CPOfakI6xq6xVPHTBok/9KykcYT5V6zUyACYeeNzxqqLr3wVkxiL+CU/PPU AW00ZUGW8TUBTMwxOAh2N15o+qW5vg5Nk8V5+1bzFkSp/5af7oDDY4sr2CshasaVcIsT gpXw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=pkvB1Ko1; spf=pass (google.com: domain of linux-kernel+bounces-20021-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20021-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id x1-20020a170902b40100b001d42e759b53si278640plr.288.2024.01.08.11.18.04 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:18:04 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20021-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=pkvB1Ko1; spf=pass (google.com: domain of linux-kernel+bounces-20021-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20021-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 6940EB20F0A for ; Mon, 8 Jan 2024 19:18:03 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 28D3E55E79; Mon, 8 Jan 2024 19:16:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="pkvB1Ko1" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C5AD55C22 for ; Mon, 8 Jan 2024 19:16:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-1d552f40a4aso1842295ad.0 for ; Mon, 08 Jan 2024 11:16:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741397; x=1705346197; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=VA6GXsaY8kxjlMQ9qtGQVmBvg/30vKloMaDh2oUyHwI=; b=pkvB1Ko1EQ/BiNJ5bHJoxAn0AY8XniHOnH+oqKecqEaTcuDyAu82LCkvJmoV+cTDTv tyLZTDZSS5dxiYI2B017M1UMNKLwFxlu2uhWzHogegBeCIAVIobGb8pHyZSUiaTJgDOK I7telnMY9ESpt/bvyj3SZI9PcoMqBRdw+0tseCa50Y049eKHzZ9eX2ES4SYCZkNeOee3 +1OYHgyQMVF8p2OG5K90JAT0bjvz4owR6L5IyoLJSWEBNAQ8iGsXxnunfDjXs3h/pyzt wR84+v3IPult/NjOMxna7kzDhpXMjVcY9p+xcvyHlj86gbD4CICdnsd2aKMi/auwL+k1 V7tg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741397; x=1705346197; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=VA6GXsaY8kxjlMQ9qtGQVmBvg/30vKloMaDh2oUyHwI=; b=NreqEibTRC7SxEg6pHiIuNEJ6uYFdHqBGmktURGgNxQyHM0XZ9HzRXcnm3pIuO7BIq QZdIr3FsEaAOCDnibf03ekr0SGjSlhYbvmhPOINCl8OzEa4qoN/9coXJuab0Nxd3gI3r aHRf9l1DuQqbSttZa8LBTBd7rNqyEfwN2KSV6bctuqpVGqAU1cofAlZbTPq/N5PhZeKM cLPu/in1pUnDpb/kSXO4juWvY4Cv00E9IiMSQQayssP0IJHUCgnzp36pa6Ca8/Zvly8J RDDojUIOUe0MhcWq1ZIa1sNMak6cRWfwSIR2o00DUAQx9QnJXO170wcSpnqjMAVj2rFh oBEA== X-Gm-Message-State: AOJu0YzTyfAMUYS9pFAr8t3pJSqb4Y55/LpQhoni1hfXiEkRaLmWMZas YLKOVmcjSOv5fuf1Y175QjVH5VzpcxF8FjGqcFHFrw== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a17:902:c946:b0:1d5:82f:4fe9 with SMTP id i6-20020a170902c94600b001d5082f4fe9mr23296pla.2.1704741397360; Mon, 08 Jan 2024 11:16:37 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:17 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=8407; i=rdbabiera@google.com; h=from:subject; bh=MgJ6WW9+Da7xRutzrTnX/nmyFQBobvHWlziyx0kihc4=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvNiWcdoc2x3dznzoxfqlIcym25aqxLEukGB9Kh05V fcDP8P9jlIWBjEOBlkxRRZd/zyDG1dSt8zhrDGGmcPKBDKEgYtTACZy8APD/zDFqf4qM/g2fs3+ anDn26JPH1Kcw3z9Hb48Kwo4cu/001+MDOvULiwOnbVRTeXm/2cX/fT/bdpto+dY7bfmkFVCzuw juYwA X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-18-rdbabiera@google.com> Subject: [PATCH v3 04/12] usb: typec: tcpci: add tcpm_transmit_type to tcpm_pd_receive From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787551006847471045 X-GMAIL-MSGID: 1787551006847471045 tcpm_pd_receive adds the SOP type as a parameter, and passes it within the pd_rx_event struct for tcpm_pd_rx_handler to use. For now, the handler drops all SOP' messages. Maxim based tcpci drivers are capable of SOP' communication, so process_rx now takes the SOP type into account and passes the value to tcpm_pd_receive. tcpci_set_pd_rx now utilizes the cable_comm_capable flag to determine if TCPC_RX_DETECT_SOP1 should be added to the bitfield when enabling PD message reception. For all other consumers of tcpm_pd_receive, default the new field to TCPC_TX_SOP. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- Changes since v2: * added reviewed-by tag --- drivers/usb/typec/tcpm/fusb302.c | 2 +- .../typec/tcpm/qcom/qcom_pmic_typec_pdphy.c | 2 +- drivers/usb/typec/tcpm/tcpci.c | 7 +++++-- drivers/usb/typec/tcpm/tcpci_maxim_core.c | 20 ++++++++++++++++--- drivers/usb/typec/tcpm/tcpm.c | 10 +++++++++- drivers/usb/typec/tcpm/wcove.c | 2 +- include/linux/usb/tcpci.h | 1 + include/linux/usb/tcpm.h | 3 ++- 8 files changed, 37 insertions(+), 10 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index bc21006e979c..ef18a448b740 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -1467,7 +1467,7 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip, if ((!len) && (pd_header_type_le(msg->header) == PD_CTRL_GOOD_CRC)) tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); else - tcpm_pd_receive(chip->tcpm_port, msg); + tcpm_pd_receive(chip->tcpm_port, msg, TCPC_TX_SOP); return ret; } diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c index 52c81378e36e..a3154085ae32 100644 --- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c @@ -299,7 +299,7 @@ static void qcom_pmic_typec_pdphy_pd_receive(struct pmic_typec_pdphy *pmic_typec if (!ret) { dev_vdbg(dev, "pd_receive: handing %d bytes to tcpm\n", size); - tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg); + tcpm_pd_receive(pmic_typec_pdphy->tcpm_port, &msg, TCPC_TX_SOP); } } diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 1ededbcecc09..8ea4ed159a13 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -445,8 +445,11 @@ static int tcpci_set_pd_rx(struct tcpc_dev *tcpc, bool enable) unsigned int reg = 0; int ret; - if (enable) + if (enable) { reg = TCPC_RX_DETECT_SOP | TCPC_RX_DETECT_HARD_RESET; + if (tcpci->data->cable_comm_capable) + reg |= TCPC_RX_DETECT_SOP1; + } ret = regmap_write(tcpci->regmap, TCPC_RX_DETECT, reg); if (ret < 0) return ret; @@ -719,7 +722,7 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci) /* Read complete, clear RX status alert bit */ tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS); - tcpm_pd_receive(tcpci->port, &msg); + tcpm_pd_receive(tcpci->port, &msg, TCPC_TX_SOP); } if (tcpci->data->vbus_vsafe0v && (status & TCPC_ALERT_EXTENDED_STATUS)) { diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c index 7b2d4e6e52a2..f9f838df43f7 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c +++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c @@ -128,6 +128,7 @@ static void process_rx(struct max_tcpci_chip *chip, u16 status) u8 count, frame_type, rx_buf[TCPC_RECEIVE_BUFFER_LEN]; int ret, payload_index; u8 *rx_buf_ptr; + enum tcpm_transmit_type rx_type; /* * READABLE_BYTE_COUNT: Indicates the number of bytes in the RX_BUF_BYTE_x registers @@ -143,10 +144,23 @@ static void process_rx(struct max_tcpci_chip *chip, u16 status) 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) { + switch (frame_type) { + case TCPC_RX_BUF_FRAME_TYPE_SOP1: + rx_type = TCPC_TX_SOP_PRIME; + break; + case TCPC_RX_BUF_FRAME_TYPE_SOP: + rx_type = TCPC_TX_SOP; + break; + default: + rx_type = TCPC_TX_SOP; + break; + } + + if (count == 0 || (frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP && + frame_type != TCPC_RX_BUF_FRAME_TYPE_SOP1)) { max_tcpci_write16(chip, TCPC_ALERT, TCPC_ALERT_RX_STATUS); dev_err(chip->dev, "%s\n", count == 0 ? "error: count is 0" : - "error frame_type is not SOP"); + "error frame_type is not SOP/SOP'"); return; } @@ -183,7 +197,7 @@ static void process_rx(struct max_tcpci_chip *chip, u16 status) if (ret < 0) return; - tcpm_pd_receive(chip->port, &msg); + tcpm_pd_receive(chip->port, &msg, rx_type); } static int max_tcpci_set_vbus(struct tcpci *tcpci, struct tcpci_data *tdata, bool source, bool sink) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 5945e3a2b0f7..ff0fcf560c88 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -518,6 +518,7 @@ struct pd_rx_event { struct kthread_work work; struct tcpm_port *port; struct pd_message msg; + enum tcpm_transmit_type rx_sop_type; }; static const char * const pd_rev[] = { @@ -2981,12 +2982,17 @@ static void tcpm_pd_rx_handler(struct kthread_work *work) const struct pd_message *msg = &event->msg; unsigned int cnt = pd_header_cnt_le(msg->header); struct tcpm_port *port = event->port; + enum tcpm_transmit_type rx_sop_type = event->rx_sop_type; mutex_lock(&port->lock); tcpm_log(port, "PD RX, header: %#x [%d]", le16_to_cpu(msg->header), port->attached); + /* Ignore SOP' for now */ + if (rx_sop_type == TCPC_TX_SOP_PRIME) + goto done; + if (port->attached) { enum pd_ctrl_msg_type type = pd_header_type_le(msg->header); unsigned int msgid = pd_header_msgid_le(msg->header); @@ -3028,7 +3034,8 @@ static void tcpm_pd_rx_handler(struct kthread_work *work) kfree(event); } -void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg) +void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg, + enum tcpm_transmit_type rx_sop_type) { struct pd_rx_event *event; @@ -3038,6 +3045,7 @@ void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg) kthread_init_work(&event->work, tcpm_pd_rx_handler); event->port = port; + event->rx_sop_type = rx_sop_type; memcpy(&event->msg, msg, sizeof(*msg)); kthread_queue_work(port->wq, &event->work); } diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c index 87d4abde0ea2..cf719307b3f6 100644 --- a/drivers/usb/typec/tcpm/wcove.c +++ b/drivers/usb/typec/tcpm/wcove.c @@ -535,7 +535,7 @@ static irqreturn_t wcove_typec_irq(int irq, void *data) goto err; } - tcpm_pd_receive(wcove->tcpm, &msg); + tcpm_pd_receive(wcove->tcpm, &msg, TCPC_TX_SOP); ret = regmap_read(wcove->regmap, USBC_RXSTATUS, &status); diff --git a/include/linux/usb/tcpci.h b/include/linux/usb/tcpci.h index 1d0b849defd0..9ed6d62c9c5f 100644 --- a/include/linux/usb/tcpci.h +++ b/include/linux/usb/tcpci.h @@ -145,6 +145,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_BUF_FRAME_TYPE_SOP1 1 #define TCPC_RX_HDR 0x32 #define TCPC_RX_DATA 0x34 /* through 0x4f */ diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index 430fa3ec69bb..41d1ac9c8bbf 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h @@ -170,7 +170,8 @@ 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); + const struct pd_message *msg, + enum tcpm_transmit_type rx_sop_type); void tcpm_pd_transmit_complete(struct tcpm_port *port, enum tcpm_transmit_status status); void tcpm_pd_hard_reset(struct tcpm_port *port); From patchwork Mon Jan 8 19:16:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186117 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1226496dyq; Mon, 8 Jan 2024 11:18:48 -0800 (PST) X-Google-Smtp-Source: AGHT+IFBM0KzsLoSUOT8NLyCBfT7K8B27G1Xx1g2vfdjkF1CxScb6/nwDi57Bso6N8FCD/O4/mQf X-Received: by 2002:a5b:7cd:0:b0:dbe:5ee6:da47 with SMTP id t13-20020a5b07cd000000b00dbe5ee6da47mr1775647ybq.87.1704741528167; Mon, 08 Jan 2024 11:18:48 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741528; cv=none; d=google.com; s=arc-20160816; b=d7CeVycohcJLesBzoIz61ndQxNtTjLgKKQ6tNuREYGJjnmFvRw9yu1LEXaoBLU1JMX iEBpB0tTZej19jitl38G1ai3GjsLtlfMqgwOKAWfGEYK5udXFFEP6P8/AhNMp6lr04qL tWCGsa8/TP0qmwUt01pFF2ZwYoWGT8qXgQ3QpET7emXEtQ43sNtofoJO3RPxIN3cyja1 b8Uwxw/fR6scmmquJ90G3PiSXD5uuuYbTbbpQkGh1RNlcbUBftC5DZYwWOP+Q+jllrxq 9ULD/Lebj+y0HzYDX/MT6hMmZ5uwbo2GxlgDpWr/HWrF/5i/EBK/MlddoEGkQiOeUVZM t4qg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=lCFcT67haIvrMJOBRNynFQICJX8kaEkP4Zr3tNyyoJU=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=GBVhLGVkYili4IbgyCVvVt+F5sY520G4mjUmcmglB2+SSdUxPaidpf6LHN3Zhe30+h zYIo+ACvKgRy5kRk5GcjX6cRSg0/pV8FYSQUuqRTW0oqaiKye/f0HdJeQxOItnU7DnK9 kSbnTTpOXP234XWNjBt52e+4BRCmA73r5LPzXOtIoxi7ibhKFxrvj+EXnuUMTNdBLZxa 6JMuGH03f2O2d4LzZYkWAkrp9rf+ykTlS7r0DeY43uHrkrwgGt5IcaFpTdh/RW9kUcuP qDDIdS9WdKS10KWhsAgxtF/4ub3v3c8Rh1DguyaeBYUfHh21FxIZavMPyW2sbHjYM0z+ +8fQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="jgC8/UDv"; spf=pass (google.com: domain of linux-kernel+bounces-20023-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20023-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id c7-20020ac87dc7000000b004299803615csi357713qte.304.2024.01.08.11.18.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:18:48 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20023-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="jgC8/UDv"; spf=pass (google.com: domain of linux-kernel+bounces-20023-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20023-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id DE5EE1C23FFF for ; Mon, 8 Jan 2024 19:18:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 520EA5674E; Mon, 8 Jan 2024 19:16:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="jgC8/UDv" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48C2855E71 for ; Mon, 8 Jan 2024 19:16:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-28d1199b572so1039049a91.2 for ; Mon, 08 Jan 2024 11:16:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741401; x=1705346201; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=lCFcT67haIvrMJOBRNynFQICJX8kaEkP4Zr3tNyyoJU=; b=jgC8/UDvtujTpvSXkXFuQVvt30CBKAYpJNkzvDRIoEy8Xw8zFQBanaDt11saQhEnXJ FfObx9M2leUjC6a3R2VKGn2UWcJFIqCjW5e4RsfK4CTEOCKqaIzUDr5QtoBwEpe6YeYa PIj4epVNefrIddJBTwBj3c0MM+VbgjdxnUDmgcHhuj+B5z9cKU7wxGXp5slNiu9XOfTC GLCEKc5NrY0Tq1k66FJNPmXoLM20ScLyWXE9cG8rUFXXHY/EXp7dlHesAG2WjzGFrWIx KayHQdrWTsTt/E9IPkRGzero39eORxEIiNJ/uh0GWAPFKd+mSgNkjcND0E1OWguX81ms QhTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741401; x=1705346201; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=lCFcT67haIvrMJOBRNynFQICJX8kaEkP4Zr3tNyyoJU=; b=F/OFDeeM9z9PDQbPIxB8gLx/dQPR9A62pTRFSZSgI7JXwBTQzw5q7ZJUUrr0rY1yOC JnCwLwel+RIxZkSdBS5Q9YkDB6KZ/r40QFBoVBTO6Dz3aH6Frw8paA83UZuIeMxJC8Y5 P2qmQranLo5GF65+LK1H19xW9l++jCjG2usWhpaKHkjiKmER+AqJ3lNRCb0fnhP91ifD kHAJ7gyZdygXTFOotB0NOzpdPCsd2t2DsGKugUdb5pPUyFVhsEcHo+nCRV/Ed2S3NiZu 7XIpfsN80rLJPqWEiC/Fg1v6ICNy8fmYdWqyMOX8XDm+oULIfGhuwsy4iTvV7p7CjCbo vwRw== X-Gm-Message-State: AOJu0Yx/rf9QqVYqBe7q4Ksaafy5aHfBX//Ei/glAWMCXyHLfmvYKCLn pVQFXGWkcK0QnelIxJiztgwGWNTYdPwfwmOAH0wKvw== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a17:90a:6843:b0:28d:2946:982e with SMTP id e3-20020a17090a684300b0028d2946982emr392502pjm.2.1704741400760; Mon, 08 Jan 2024 11:16:40 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:19 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=14840; i=rdbabiera@google.com; h=from:subject; bh=E7QPpw6LJd82MkJ9eDbREwgUi0xuVsvNCylwVs7TV+Y=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvNgXKl7l2mKiKXQ9S+90hcWE1PYWh4u6k6JeZRdmp gX/6jjWUcrCIMbBICumyKLrn2dw40rqljmcNcYwc1iZQIYwcHEKwEQ+XGb471txpD5uUd8Fh9de omZHPy6deOkJh+rUxhhxv2Mzebd4FzEy/A+0ddTmfdi3JNQ4PWmy/GP7nYn6Lg8bvt9ZVXhCXvg hNwA= X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-20-rdbabiera@google.com> Subject: [PATCH v3 06/12] usb: typec: tcpm: add control message support to sop' From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787551052624975461 X-GMAIL-MSGID: 1787551052624975461 Add tx_sop_type to tcpm_pd_send_control and rx_sop_type to tcpm_pd_ctrl_request. TCPC_TX_SOP is added to all pd_send_control calls, but TCPC_TX_SOP_PRIME is added to pd_send_control for a SOFT_RESET message sent after a Vconn swap that makes the Port the Vconn source. Likewise, tcpm_pd_ctrl_request resets the proper protocol layer depending on rx_sop_type for SOFT_RESET. VCONN_SWAP_TURN_ON_VCONN now moves to a new state, VCONN_SWAP_SEND_SOFT_RESET. This state sends SOFT_RESET over SOP' before transitioning to the ready state if applicable. It transitions after PD_T_VCONN_STABLE, definied in pd.h as the time required for Vconn to be on before transmitting messages. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- Changes since v2: * Added reviewed-by tag --- drivers/usb/typec/tcpm/tcpm.c | 159 ++++++++++++++++++++++++---------- include/linux/usb/pd.h | 1 + 2 files changed, 115 insertions(+), 45 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index d2ca85c8fec6..a59927925714 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -108,6 +108,7 @@ S(VCONN_SWAP_WAIT_FOR_VCONN), \ S(VCONN_SWAP_TURN_ON_VCONN), \ S(VCONN_SWAP_TURN_OFF_VCONN), \ + S(VCONN_SWAP_SEND_SOFT_RESET), \ \ S(FR_SWAP_SEND), \ S(FR_SWAP_SEND_TIMEOUT), \ @@ -2395,7 +2396,8 @@ static inline enum tcpm_state ready_state(struct tcpm_port *port) } static int tcpm_pd_send_control(struct tcpm_port *port, - enum pd_ctrl_msg_type type); + enum pd_ctrl_msg_type type, + enum tcpm_transmit_type tx_sop_type); static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, int cnt) @@ -2749,10 +2751,12 @@ static void tcpm_pps_complete(struct tcpm_port *port, int result) } static void tcpm_pd_ctrl_request(struct tcpm_port *port, - const struct pd_message *msg) + const struct pd_message *msg, + enum tcpm_transmit_type rx_sop_type) { enum pd_ctrl_msg_type type = pd_header_type_le(msg->header); enum tcpm_state next_state; + unsigned int rev = pd_header_rev_le(msg->header); /* * Stop VDM state machine if interrupted by other Messages while NOT_SUPP is allowed in @@ -2917,6 +2921,16 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, case SOFT_RESET_SEND: if (port->ams == SOFT_RESET_AMS) tcpm_ams_finish(port); + /* + * SOP' Soft Reset is done after Vconn Swap, + * which returns to ready state + */ + if (rx_sop_type == TCPC_TX_SOP_PRIME) { + if (rev < port->negotiated_rev_prime) + port->negotiated_rev_prime = rev; + tcpm_set_state(port, ready_state(port), 0); + break; + } if (port->pwr_role == TYPEC_SOURCE) { port->upcoming_state = SRC_SEND_CAPABILITIES; tcpm_ams_start(port, POWER_NEGOTIATION); @@ -3116,8 +3130,7 @@ static void tcpm_pd_rx_handler(struct kthread_work *work) if (msgid == port->rx_msgid_prime) goto done; port->rx_msgid_prime = msgid; - /* Ignore SOP' for now */ - goto done; + break; case TCPC_TX_SOP: default: if (msgid == port->rx_msgid && type != PD_CTRL_SOFT_RESET) @@ -3141,7 +3154,7 @@ static void tcpm_pd_rx_handler(struct kthread_work *work) else if (cnt) tcpm_pd_data_request(port, msg); else - tcpm_pd_ctrl_request(port, msg); + tcpm_pd_ctrl_request(port, msg, rx_sop_type); } } @@ -3168,17 +3181,40 @@ void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg, EXPORT_SYMBOL_GPL(tcpm_pd_receive); static int tcpm_pd_send_control(struct tcpm_port *port, - enum pd_ctrl_msg_type type) + enum pd_ctrl_msg_type type, + enum tcpm_transmit_type tx_sop_type) { struct pd_message msg; memset(&msg, 0, sizeof(msg)); - msg.header = PD_HEADER_LE(type, port->pwr_role, - port->data_role, - port->negotiated_rev, - port->message_id, 0); + switch (tx_sop_type) { + case TCPC_TX_SOP_PRIME: + msg.header = PD_HEADER_LE(type, + 0, /* Cable Plug Indicator for DFP/UFP */ + 0, /* Reserved */ + port->negotiated_rev, + port->message_id_prime, + 0); + break; + case TCPC_TX_SOP: + msg.header = PD_HEADER_LE(type, + port->pwr_role, + port->data_role, + port->negotiated_rev, + port->message_id, + 0); + break; + default: + msg.header = PD_HEADER_LE(type, + port->pwr_role, + port->data_role, + port->negotiated_rev, + port->message_id, + 0); + break; + } - return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); + return tcpm_pd_transmit(port, tx_sop_type, &msg); } /* @@ -3197,13 +3233,13 @@ static bool tcpm_send_queued_message(struct tcpm_port *port) switch (queued_message) { case PD_MSG_CTRL_WAIT: - tcpm_pd_send_control(port, PD_CTRL_WAIT); + tcpm_pd_send_control(port, PD_CTRL_WAIT, TCPC_TX_SOP); break; case PD_MSG_CTRL_REJECT: - tcpm_pd_send_control(port, PD_CTRL_REJECT); + tcpm_pd_send_control(port, PD_CTRL_REJECT, TCPC_TX_SOP); break; case PD_MSG_CTRL_NOT_SUPP: - tcpm_pd_send_control(port, PD_CTRL_NOT_SUPP); + tcpm_pd_send_control(port, PD_CTRL_NOT_SUPP, TCPC_TX_SOP); break; case PD_MSG_DATA_SINK_CAP: ret = tcpm_pd_send_sink_caps(port); @@ -4218,7 +4254,7 @@ static void run_state_machine(struct tcpm_port *port) case SRC_NEGOTIATE_CAPABILITIES: ret = tcpm_pd_check_request(port); if (ret < 0) { - tcpm_pd_send_control(port, PD_CTRL_REJECT); + tcpm_pd_send_control(port, PD_CTRL_REJECT, TCPC_TX_SOP); if (!port->explicit_contract) { tcpm_set_state(port, SRC_WAIT_NEW_CAPABILITIES, 0); @@ -4226,7 +4262,7 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, SRC_READY, 0); } } else { - tcpm_pd_send_control(port, PD_CTRL_ACCEPT); + tcpm_pd_send_control(port, PD_CTRL_ACCEPT, TCPC_TX_SOP); tcpm_set_partner_usb_comm_capable(port, !!(port->sink_request & RDO_USB_COMM)); tcpm_set_state(port, SRC_TRANSITION_SUPPLY, @@ -4235,7 +4271,7 @@ static void run_state_machine(struct tcpm_port *port) break; case SRC_TRANSITION_SUPPLY: /* XXX: regulator_set_voltage(vbus, ...) */ - tcpm_pd_send_control(port, PD_CTRL_PS_RDY); + tcpm_pd_send_control(port, PD_CTRL_PS_RDY, TCPC_TX_SOP); port->explicit_contract = true; typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_PD); port->pwr_opmode = TYPEC_PWR_MODE_PD; @@ -4720,7 +4756,7 @@ static void run_state_machine(struct tcpm_port *port) /* remove existing capabilities */ usb_power_delivery_unregister_capabilities(port->partner_source_caps); port->partner_source_caps = NULL; - tcpm_pd_send_control(port, PD_CTRL_ACCEPT); + tcpm_pd_send_control(port, PD_CTRL_ACCEPT, TCPC_TX_SOP); tcpm_ams_finish(port); if (port->pwr_role == TYPEC_SOURCE) { port->upcoming_state = SRC_SEND_CAPABILITIES; @@ -4737,28 +4773,41 @@ static void run_state_machine(struct tcpm_port *port) tcpm_ams_start(port, SOFT_RESET_AMS); break; case SOFT_RESET_SEND: - port->message_id = 0; - port->rx_msgid = -1; - /* remove existing capabilities */ - usb_power_delivery_unregister_capabilities(port->partner_source_caps); - port->partner_source_caps = NULL; - if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET)) - tcpm_set_state_cond(port, hard_reset_state(port), 0); - else - tcpm_set_state_cond(port, hard_reset_state(port), - PD_T_SENDER_RESPONSE); + /* + * Power Delivery 3.0 Section 6.3.13 + * + * A Soft_Reset Message Shall be targeted at a specific entity + * depending on the type of SOP* packet used. + */ + if (port->tx_sop_type == TCPC_TX_SOP_PRIME) { + port->message_id_prime = 0; + port->rx_msgid_prime = -1; + tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET, TCPC_TX_SOP_PRIME); + tcpm_set_state_cond(port, ready_state(port), PD_T_SENDER_RESPONSE); + } else { + port->message_id = 0; + port->rx_msgid = -1; + /* remove existing capabilities */ + usb_power_delivery_unregister_capabilities(port->partner_source_caps); + port->partner_source_caps = NULL; + if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET, TCPC_TX_SOP)) + tcpm_set_state_cond(port, hard_reset_state(port), 0); + else + tcpm_set_state_cond(port, hard_reset_state(port), + PD_T_SENDER_RESPONSE); + } break; /* DR_Swap states */ case DR_SWAP_SEND: - tcpm_pd_send_control(port, PD_CTRL_DR_SWAP); + tcpm_pd_send_control(port, PD_CTRL_DR_SWAP, TCPC_TX_SOP); if (port->data_role == TYPEC_DEVICE || port->negotiated_rev > PD_REV20) port->send_discover = true; tcpm_set_state_cond(port, DR_SWAP_SEND_TIMEOUT, PD_T_SENDER_RESPONSE); break; case DR_SWAP_ACCEPT: - tcpm_pd_send_control(port, PD_CTRL_ACCEPT); + tcpm_pd_send_control(port, PD_CTRL_ACCEPT, TCPC_TX_SOP); if (port->data_role == TYPEC_DEVICE || port->negotiated_rev > PD_REV20) port->send_discover = true; tcpm_set_state_cond(port, DR_SWAP_CHANGE_DR, 0); @@ -4782,7 +4831,7 @@ static void run_state_machine(struct tcpm_port *port) break; case FR_SWAP_SEND: - if (tcpm_pd_send_control(port, PD_CTRL_FR_SWAP)) { + if (tcpm_pd_send_control(port, PD_CTRL_FR_SWAP, TCPC_TX_SOP)) { tcpm_set_state(port, ERROR_RECOVERY, 0); break; } @@ -4802,7 +4851,7 @@ static void run_state_machine(struct tcpm_port *port) 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)) { + if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY, TCPC_TX_SOP)) { tcpm_set_state(port, ERROR_RECOVERY, 0); break; } @@ -4812,11 +4861,11 @@ static void run_state_machine(struct tcpm_port *port) /* PR_Swap states */ case PR_SWAP_ACCEPT: - tcpm_pd_send_control(port, PD_CTRL_ACCEPT); + tcpm_pd_send_control(port, PD_CTRL_ACCEPT, TCPC_TX_SOP); tcpm_set_state(port, PR_SWAP_START, 0); break; case PR_SWAP_SEND: - tcpm_pd_send_control(port, PD_CTRL_PR_SWAP); + tcpm_pd_send_control(port, PD_CTRL_PR_SWAP, TCPC_TX_SOP); tcpm_set_state_cond(port, PR_SWAP_SEND_TIMEOUT, PD_T_SENDER_RESPONSE); break; @@ -4858,7 +4907,7 @@ static void run_state_machine(struct tcpm_port *port) * supply is turned off" */ tcpm_set_pwr_role(port, TYPEC_SINK); - if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) { + if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY, TCPC_TX_SOP)) { tcpm_set_state(port, ERROR_RECOVERY, 0); break; } @@ -4905,17 +4954,17 @@ static void run_state_machine(struct tcpm_port *port) * Source." */ tcpm_set_pwr_role(port, TYPEC_SOURCE); - tcpm_pd_send_control(port, PD_CTRL_PS_RDY); + tcpm_pd_send_control(port, PD_CTRL_PS_RDY, TCPC_TX_SOP); tcpm_set_state(port, SRC_STARTUP, PD_T_SWAP_SRC_START); break; case VCONN_SWAP_ACCEPT: - tcpm_pd_send_control(port, PD_CTRL_ACCEPT); + tcpm_pd_send_control(port, PD_CTRL_ACCEPT, TCPC_TX_SOP); tcpm_ams_finish(port); tcpm_set_state(port, VCONN_SWAP_START, 0); break; case VCONN_SWAP_SEND: - tcpm_pd_send_control(port, PD_CTRL_VCONN_SWAP); + tcpm_pd_send_control(port, PD_CTRL_VCONN_SWAP, TCPC_TX_SOP); tcpm_set_state(port, VCONN_SWAP_SEND_TIMEOUT, PD_T_SENDER_RESPONSE); break; @@ -4934,14 +4983,34 @@ static void run_state_machine(struct tcpm_port *port) PD_T_VCONN_SOURCE_ON); break; case VCONN_SWAP_TURN_ON_VCONN: - tcpm_set_vconn(port, true); - tcpm_pd_send_control(port, PD_CTRL_PS_RDY); - tcpm_set_state(port, ready_state(port), 0); + ret = tcpm_set_vconn(port, true); + tcpm_pd_send_control(port, PD_CTRL_PS_RDY, TCPC_TX_SOP); + /* + * USB PD 3.0 Section 6.4.4.3.1 + * + * Note that a Cable Plug or VPD will not be ready for PD + * Communication until tVCONNStable after VCONN has been applied + */ + if (!ret) + tcpm_set_state(port, VCONN_SWAP_SEND_SOFT_RESET, + PD_T_VCONN_STABLE); + else + tcpm_set_state(port, ready_state(port), 0); break; case VCONN_SWAP_TURN_OFF_VCONN: tcpm_set_vconn(port, false); tcpm_set_state(port, ready_state(port), 0); break; + case VCONN_SWAP_SEND_SOFT_RESET: + tcpm_swap_complete(port, port->swap_status); + if (tcpm_can_communicate_sop_prime(port)) { + port->tx_sop_type = TCPC_TX_SOP_PRIME; + port->upcoming_state = SOFT_RESET_SEND; + tcpm_ams_start(port, SOFT_RESET_AMS); + } else { + tcpm_set_state(port, ready_state(port), 0); + } + break; case DR_SWAP_CANCEL: case PR_SWAP_CANCEL: @@ -4977,7 +5046,7 @@ static void run_state_machine(struct tcpm_port *port) } break; case GET_STATUS_SEND: - tcpm_pd_send_control(port, PD_CTRL_GET_STATUS); + tcpm_pd_send_control(port, PD_CTRL_GET_STATUS, TCPC_TX_SOP); tcpm_set_state(port, GET_STATUS_SEND_TIMEOUT, PD_T_SENDER_RESPONSE); break; @@ -4985,7 +5054,7 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, ready_state(port), 0); break; case GET_PPS_STATUS_SEND: - tcpm_pd_send_control(port, PD_CTRL_GET_PPS_STATUS); + tcpm_pd_send_control(port, PD_CTRL_GET_PPS_STATUS, TCPC_TX_SOP); tcpm_set_state(port, GET_PPS_STATUS_SEND_TIMEOUT, PD_T_SENDER_RESPONSE); break; @@ -4993,7 +5062,7 @@ static void run_state_machine(struct tcpm_port *port) tcpm_set_state(port, ready_state(port), 0); break; case GET_SINK_CAP: - tcpm_pd_send_control(port, PD_CTRL_GET_SINK_CAP); + tcpm_pd_send_control(port, PD_CTRL_GET_SINK_CAP, TCPC_TX_SOP); tcpm_set_state(port, GET_SINK_CAP_TIMEOUT, PD_T_SENDER_RESPONSE); break; case GET_SINK_CAP_TIMEOUT: @@ -5033,7 +5102,7 @@ static void run_state_machine(struct tcpm_port *port) /* Chunk state */ case CHUNK_NOT_SUPP: - tcpm_pd_send_control(port, PD_CTRL_NOT_SUPP); + tcpm_pd_send_control(port, PD_CTRL_NOT_SUPP, TCPC_TX_SOP); tcpm_set_state(port, port->pwr_role == TYPEC_SOURCE ? SRC_READY : SNK_READY, 0); break; default: diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h index eb626af0e4e7..d50098fb16b5 100644 --- a/include/linux/usb/pd.h +++ b/include/linux/usb/pd.h @@ -483,6 +483,7 @@ static inline unsigned int rdo_max_power(u32 rdo) #define PD_T_BIST_CONT_MODE 50 /* 30 - 60 ms */ #define PD_T_SINK_TX 16 /* 16 - 20 ms */ #define PD_T_CHUNK_NOT_SUPP 42 /* 40 - 50 ms */ +#define PD_T_VCONN_STABLE 50 #define PD_T_DRP_TRY 100 /* 75 - 150 ms */ #define PD_T_DRP_TRYWAIT 600 /* 400 - 800 ms */ From patchwork Mon Jan 8 19:16:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186118 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1226557dyq; Mon, 8 Jan 2024 11:18:56 -0800 (PST) X-Google-Smtp-Source: AGHT+IG7u+Gu0VHUd0ufNk0ZARH/V2AkXE0I5uXpIABnpw5Tikk3vKPpvs/v3JDxco5JTU8nsKwh X-Received: by 2002:a50:cd94:0:b0:554:241f:3f42 with SMTP id p20-20020a50cd94000000b00554241f3f42mr2276603edi.58.1704741536400; Mon, 08 Jan 2024 11:18:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741536; cv=none; d=google.com; s=arc-20160816; b=x57EHasMu6BlnytS2w9W1H5TzAkxpgmBg8ikp9j0qZVRtfYOqYSqlidXmnOGoA8RVH 8IL8KGbXLXIH7X2WmOpnbgfm2GcaS9eJfMNdAUQx0L1vp80TkK0tJrjY6HMPEVOWTZWe eP5ksgOjJAiREBXd7UOc+bCkSKcFUWUOjjdCs6wFJ0US9gwoHdG/hTWips3iuv9x7qzu 25hQECczuiWWRcDVKEtBpUJFAek5CFNZYagT5hsjzstUqfIxS8do0vPlO4e2MOmvx+Er UIfbhHuChKJIqmPlRRhrZ+YUngzzDPSSGz6OeCUl2oOma/t0LfaK6OAV+aWdnjrtpYCX k3PA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=5S3fHVY510eUierrKJ56dka07t+3wFOx1R5zr9DqTHs=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=qNPR/t/Kl71OteVdcoPm6YpdclguAEwHAmdrxe1xuEes7GDB08EnxspXmhAe6fnUpy OumZUBb3xFeXeCb9iBGVSXUK7xtkG6yPzc/cnaAbxnYO823ON7VPB6HT6ojB5Phl6B2Y DEnv4rPPO8esFD/x4kW1ZBpcDYuaUWzCO5+PjOb+n+wktOd8O1K4Ylz1u+17ChxefRnx 7Sfai0eTh0MtfBrI4k3a+V/ml1YOKIzMfyDt4UfBqkSMjiYETWvIL1vNl+ysBOHFpMGB +XEBQiH//POr3SBMwPkuOx0YQXULQEw4CHedQ0QfjpG2aiVGfx1Ogm9culdtsyrnzBa/ 8AbA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=gM5ZWCLY; spf=pass (google.com: domain of linux-kernel+bounces-20024-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20024-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id da20-20020a056402177400b00554e7f46b09si119581edb.520.2024.01.08.11.18.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:18:56 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20024-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=gM5ZWCLY; spf=pass (google.com: domain of linux-kernel+bounces-20024-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20024-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id C5AD41F23E50 for ; Mon, 8 Jan 2024 19:18:55 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4BBA156762; Mon, 8 Jan 2024 19:16:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gM5ZWCLY" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36CAB56450 for ; Mon, 8 Jan 2024 19:16:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-5e74c97832aso26781007b3.2 for ; Mon, 08 Jan 2024 11:16:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741402; x=1705346202; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=5S3fHVY510eUierrKJ56dka07t+3wFOx1R5zr9DqTHs=; b=gM5ZWCLYuMfkMQYbndkZLn8rVK46csVp2ePV5PIC6OuaW4Yx3ZmdTIuWK0XfF2dsCD H192tx6YkuqJw2ps8xKCVuArT6iqoZ2gYyZJqzD4yE/njMOY9Pe+h9Dl+O0KPJjJVFTJ CoVTaQk0wAxvPSqyNIPBLXte5HM96R+x+0kj6vB/puYkjopuDdygCROfv3b9Xb/GUkQV cbztEgBHyGmrc5AZ8+DabUhDGgG8PJFVSUiqNTC6wFUvqpOq/dCmrKG7/wzIdxzDsoRv F3/jInxx4P39oZvtkXxmOcq30igMSbHIU5g+s5Eb843szFdDtJ7+Xs4EYGSd8JdN+6wD 71TA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741402; x=1705346202; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5S3fHVY510eUierrKJ56dka07t+3wFOx1R5zr9DqTHs=; b=rHz+N4/ruRXD1xOnsTEPgm63QvZSYXu7Jjd2p/mTturpad94nL0wCVZ95lMDX3+eH6 o1+Kem/3h3SjwrswISbJ/PFGvjGCb0g1A3M+uTBG+o2yIqMh9KbXoDH/hHXE2qY4QvVD 1sgWb5AaD5+9pPMJtfzM12pCZsBpmC4cM6R5Wf9QAniwici53dPOOrBZh6+p2beQwaIY eNnCg1eO5FlkuDm2KZ+BuwEE9ytvDFsdSVQxQCkUmQu/CmIDkxN0FQqWiGKlOpfvE9s+ ZfoM20eO2ts/1/A2iR26FzougzcPA+ds8aZY6ICGcFUjoCtgGVH9m8pZwpxMLi7h96ym mY4w== X-Gm-Message-State: AOJu0Yw5sZ5tjGWhWMK+08IBlIj8hYEXiBpN1X8a+9XLhonfo+tSLm37 w0rMkSpruRn8RhEFx1vtK8NOB9edBFBrRayQUcxcJQ== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a05:690c:309:b0:5e6:579e:65dd with SMTP id bg9-20020a05690c030900b005e6579e65ddmr1849203ywb.3.1704741402488; Mon, 08 Jan 2024 11:16:42 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:20 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=6690; i=rdbabiera@google.com; h=from:subject; bh=vyvXaH6qWtx30SqHG/OIUPIttfFPXwU8n6ukoXI76xM=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvNj5JWNamh/8XLvd4Gpy8sGUhXyXH1iFT6w8ONnxJ 2PTtE9/O0pZGMQ4GGTFFFl0/fMMblxJ3TKHs8YYZg4rE8gQBi5OAZhI8iOGP5zeOpknPH9ELnq+ SF3XM/6o2jOVG+83Oi47ETVPkfv93ChGhsn10vZTtetdE6aW2hif50+eMv3K7I8T2nfd3ZuzuiH 9Oh8A X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-21-rdbabiera@google.com> Subject: [PATCH v3 07/12] usb: typec: tcpci: add attempt_vconn_swap_discovery callback From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787551061328561862 X-GMAIL-MSGID: 1787551061328561862 Add attempt_vconn_swap_discovery callback to determine whether the TCPM should perform a Vconn swap following Discover Identity on SOP. The tcpci will return false unless chip level drivers implement the callback. Maxim based TCPCs will return true unless the last connection resulted in a Vconn Over Current Fault, which may be the result of the Vconn swap. In addition to the port resetting, the TCPCI will veto the next Vconn swap from occurring. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- Changes since v2: * Added reviewed-by tag --- drivers/usb/typec/tcpm/tcpci.c | 11 +++++++++++ drivers/usb/typec/tcpm/tcpci_maxim.h | 1 + drivers/usb/typec/tcpm/tcpci_maxim_core.c | 17 ++++++++++++++++- include/linux/usb/tcpci.h | 9 +++++++++ include/linux/usb/tcpm.h | 9 +++++++++ 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index 8ea4ed159a13..40c7b6224c74 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -594,6 +594,16 @@ static bool tcpci_cable_comm_capable(struct tcpc_dev *tcpc) return tcpci->data->cable_comm_capable; } +static bool tcpci_attempt_vconn_swap_discovery(struct tcpc_dev *tcpc) +{ + struct tcpci *tcpci = tcpc_to_tcpci(tcpc); + + if (tcpci->data->attempt_vconn_swap_discovery) + return tcpci->data->attempt_vconn_swap_discovery(tcpci, tcpci->data); + + return false; +} + static int tcpci_init(struct tcpc_dev *tcpc) { struct tcpci *tcpci = tcpc_to_tcpci(tcpc); @@ -804,6 +814,7 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data) tcpci->tcpc.frs_sourcing_vbus = tcpci_frs_sourcing_vbus; tcpci->tcpc.set_partner_usb_comm_capable = tcpci_set_partner_usb_comm_capable; tcpci->tcpc.cable_comm_capable = tcpci_cable_comm_capable; + tcpci->tcpc.attempt_vconn_swap_discovery = tcpci_attempt_vconn_swap_discovery; if (tcpci->data->check_contaminant) tcpci->tcpc.check_contaminant = tcpci_check_contaminant; diff --git a/drivers/usb/typec/tcpm/tcpci_maxim.h b/drivers/usb/typec/tcpm/tcpci_maxim.h index 2c1c4d161b0d..78ff3b73ee7e 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim.h +++ b/drivers/usb/typec/tcpm/tcpci_maxim.h @@ -62,6 +62,7 @@ struct max_tcpci_chip { struct i2c_client *client; struct tcpm_port *port; enum contamiant_state contaminant_state; + bool veto_vconn_swap; }; static inline int max_tcpci_read16(struct max_tcpci_chip *chip, unsigned int reg, u16 *val) diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c index f9f838df43f7..eec3bcec119c 100644 --- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c +++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c @@ -323,8 +323,10 @@ static irqreturn_t _max_tcpci_irq(struct max_tcpci_chip *chip, u16 status) if (ret < 0) return ret; - if (reg_status & TCPC_FAULT_STATUS_VCONN_OC) + if (reg_status & TCPC_FAULT_STATUS_VCONN_OC) { + chip->veto_vconn_swap = true; tcpm_port_error_recovery(chip->port); + } } if (status & TCPC_ALERT_EXTND) { @@ -458,6 +460,18 @@ static void max_tcpci_check_contaminant(struct tcpci *tcpci, struct tcpci_data * tcpm_port_clean(chip->port); } +static bool max_tcpci_attempt_vconn_swap_discovery(struct tcpci *tcpci, struct tcpci_data *tdata) +{ + struct max_tcpci_chip *chip = tdata_to_max_tcpci(tdata); + + if (chip->veto_vconn_swap) { + chip->veto_vconn_swap = false; + return false; + } + + return true; +} + static int max_tcpci_probe(struct i2c_client *client) { int ret; @@ -493,6 +507,7 @@ static int max_tcpci_probe(struct i2c_client *client) chip->data.set_partner_usb_comm_capable = max_tcpci_set_partner_usb_comm_capable; chip->data.check_contaminant = max_tcpci_check_contaminant; chip->data.cable_comm_capable = true; + chip->data.attempt_vconn_swap_discovery = max_tcpci_attempt_vconn_swap_discovery; max_tcpci_init_regs(chip); chip->tcpci = tcpci_register_port(chip->dev, &chip->data); diff --git a/include/linux/usb/tcpci.h b/include/linux/usb/tcpci.h index 9ed6d62c9c5f..47a86b8a4a50 100644 --- a/include/linux/usb/tcpci.h +++ b/include/linux/usb/tcpci.h @@ -201,6 +201,14 @@ struct tcpci; * toggling state. * @cable_comm_capable * optional; Set when TCPC can communicate with cable plugs over SOP' + * @attempt_vconn_swap_discovery: + * Optional; The callback is called by the TCPM when the result of + * a Discover Identity request indicates that the port partner is + * a receptacle capable of modal operation. Chip level TCPCI drivers + * can implement their own policy to determine if and when a Vconn + * swap following Discover Identity on SOP' occurs. + * Return true when the TCPM is allowed to request a Vconn swap + * after Discovery Identity on SOP. */ struct tcpci_data { struct regmap *regmap; @@ -219,6 +227,7 @@ struct tcpci_data { void (*set_partner_usb_comm_capable)(struct tcpci *tcpci, struct tcpci_data *data, bool capable); void (*check_contaminant)(struct tcpci *tcpci, struct tcpci_data *data); + bool (*attempt_vconn_swap_discovery)(struct tcpci *tcpci, struct tcpci_data *data); }; struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data); diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index 41d1ac9c8bbf..6671427f7eeb 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h @@ -122,6 +122,14 @@ enum tcpm_transmit_type { * @cable_comm_capable * Optional; Returns whether cable communication over SOP' is supported * by the tcpc + * @attempt_vconn_swap_discovery: + * Optional; The callback is called by the TCPM when the result of + * a Discover Identity request indicates that the port partner is + * a receptacle capable of modal operation. Chip level TCPCI drivers + * can implement their own policy to determine if and when a Vconn + * swap following Discover Identity on SOP' occurs. + * Return true when the TCPM is allowed to request a Vconn swap + * after Discovery Identity on SOP. */ struct tcpc_dev { struct fwnode_handle *fwnode; @@ -158,6 +166,7 @@ struct tcpc_dev { void (*set_partner_usb_comm_capable)(struct tcpc_dev *dev, bool enable); void (*check_contaminant)(struct tcpc_dev *dev); bool (*cable_comm_capable)(struct tcpc_dev *dev); + bool (*attempt_vconn_swap_discovery)(struct tcpc_dev *dev); }; struct tcpm_port; From patchwork Mon Jan 8 19:16:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186120 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1226899dyq; Mon, 8 Jan 2024 11:19:47 -0800 (PST) X-Google-Smtp-Source: AGHT+IFBvdcPY/WCqfQxYJmhiXLCLQbWfdAXDiTz++qRxAakwOeQK9Kw6OdL/ilV/qOWi8I1NrCB X-Received: by 2002:a9d:5e09:0:b0:6d8:567d:ed18 with SMTP id d9-20020a9d5e09000000b006d8567ded18mr3068539oti.7.1704741587295; Mon, 08 Jan 2024 11:19:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741587; cv=none; d=google.com; s=arc-20160816; b=sIbmwaB3BI9GsexMtz8o8pa/iGuBshT/muPgTyxtMWfKmDer82raKF85cU6rYnhvBo ob/exJZOE26cur5fAlzZ3Gqnty4K7fEwPCOvRV0rVOh9HJXoZ/8n/t1cpNceSXood1dD cicYwPmB351QdgE+hSTNmRLLQMvYIQo1IXmyxQvBWGhqn1FXnkCxKNjKm4bWXwCsvdAG 18+KME4pNOi2ZqiIdhOLsQcoWhWJlcNjCUfsHbBARGpv/boFr32Aj2WscFED4j6+N97I lGpwm4mmRuvWYx7JM3KTB3//GfTpxkHQLH7orBA4lVS/WyI5UR09s2V295dDIP0P6E3z 9UUQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=J1nbO5wXN63w+1D6jndrBSTuc6V0fA5TsyIoTp7gqVE=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=bRJKIL/WrLEo5G/AzkJ9mEP4kuND23+45FforPv3lTCP5HuClC4SIt6KJdNyVclXTk FvRlC7eJQB8oI/frZFwOnaPDSuoZWiPcxA+4gKnc9gA0QZ1JAYOfqw9GfXbQXk8OCpZ7 S2esBhCKZPXmSHs21tEqaAQ0rlIIj7U/eGYcN/HVudlxj4B+IqBpZJgYm8ALypgSuK64 22PJ/70kEN5ZsIZYj91jjCdzdunvTjDwMg9hPyiCSHTUxHoCn10ujDZbB6G2MRGK1iFX vTfMT/bR8r5pRMQwpk1fZ7H0OnUhCXDdfzeF3eqrXLT3/Dip1dKcrz13nFjSYCKxo2qM XpxQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=oeD3UxaY; spf=pass (google.com: domain of linux-kernel+bounces-20026-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20026-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id c7-20020ac87dc7000000b004299803615csi357713qte.304.2024.01.08.11.19.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:19:47 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20026-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=oeD3UxaY; spf=pass (google.com: domain of linux-kernel+bounces-20026-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20026-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 075891C23FBD for ; Mon, 8 Jan 2024 19:19:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4803257309; Mon, 8 Jan 2024 19:16:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="oeD3UxaY" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 44B0356475 for ; Mon, 8 Jan 2024 19:16:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-dbea293017dso2406006276.1 for ; Mon, 08 Jan 2024 11:16:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741404; x=1705346204; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=J1nbO5wXN63w+1D6jndrBSTuc6V0fA5TsyIoTp7gqVE=; b=oeD3UxaYDO7CvTwo3rRbOvin1bh1webfZlrrQUbkU8l4cC9Z/OBxxE2DNDv6/ZMrMu RA5gODH/XsTzxpQqJ2RUuYmEwx+67GI0oYznHtrSjr1zt+OIpvnsDPtDmBKXamhmk6u/ d7bJxMhkxvoyZC0mqiNaNpt6VhIf0b1En9O5KRDRmjEQ8yRxTWIaIwDAhzRdhPbKJf1v g677Bhg+yIzO1XmJtSuc0bWTWBX6SX5Y16gKKl5lTZAEntAjKi0yQEqhSvDPTuaGjMJT cobt6pvbbm/MolY+PmIU+N/Nsg5oUqAuOY1Aq4qP7UJ6XxTxriXxRR9TqbNVM4lQHBKr Gw1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741404; x=1705346204; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=J1nbO5wXN63w+1D6jndrBSTuc6V0fA5TsyIoTp7gqVE=; b=kZxHFAr/E4wG4KhWSUODpPBGaR8LUY5ido6FXz+0NZt6PXmDwCgMR2Gt0Suk3EmjKu Bo+DaqRZRhbrvSONL8GwMF71pToWjQo7aFjWYYQ0o42xbh7mOa9b4nqEt29cftVoLGv0 ijWQtznqgyi1DEoBa5m6+ZOFs7W5OjV/eTN7K2z/oiiX+QNkGV97OhJmbE643PxrAUki ZcaaUVrjBEfEqRA4PWOHzg/VcRvmhmad3DHtJtauVmiUD9vO1zSfPQBJAGobcMdteYRa cDAMtjyS2NulHJjfKqFApvm2IcP+QokPeuBYVR5PsVKJMd3+Y8ipF7dU8P3VytIRaHg8 Oi9g== X-Gm-Message-State: AOJu0YxAozjMT+IH47PQRUgD0DXrRfzEa0mVLBb79WWQN3BsYCz3ykTJ vg3bf8IAv7uxDtUuf8o0VXMOh2EL+mbdGsriT+C+nw== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a05:6902:2301:b0:dbe:fe5f:8a19 with SMTP id do1-20020a056902230100b00dbefe5f8a19mr455660ybb.1.1704741404422; Mon, 08 Jan 2024 11:16:44 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:21 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=27005; i=rdbabiera@google.com; h=from:subject; bh=qQhyQDsfAt4IL0q2T2CPhosqlJIik58btEAo+vFXT/4=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvDikj4Tele9r1Xzb5Be19eLBhVlXpUI0XnSz7bTdx ZwZ+l6ho5SFQYyDQVZMkUXXP8/gxpXULXM4a4xh5rAygQxh4OIUgIlEWTD8YmaY+CA5plhu1U3n 1G21If+D89USMv51zVnLcoZ/UuajFIb/1dePn+WxnLLrrpd+UEalx7YzE5ucrtQXO7TMVZlnnZf ICQA= X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-22-rdbabiera@google.com> Subject: [PATCH v3 08/12] usb: typec: tcpm: add discover identity support for SOP' From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787551114483056107 X-GMAIL-MSGID: 1787551114483056107 Add data message handling and Discover Identity SVDM over SOP' This patch contains the following changes: 1. pd_vdo Add VDO indices for active and passive cables, documentation to reflect expected number of objects depending on PD Revision, and macro to indicate port parter is data host capable. 2. tcpm Add typec_cable and typec_plug to tcpm_port to maintain cable and plug information. tcpm_port also adds send_discover_prime to indicate that Discover Identity should be sent out of the ready state. tcpm_queue_vdm and tcpm_send_vdm now take the SOP* type when transmitting messages. tcpm_handle_vdm_request and tcpm_pd_svdm also use the SOP* type. tcpm_pd_svdm handles Discover Identity messages for SOP and SOP'. In the SOP case, the port uses tcpm_attempt_vconn_swap_discovery to determine if a Vconn swap is needed for cable communication. Otherwise, the port will send Discover Identity on SOP' if it can, or default to Discover SVIDs. svdm_consume_identity_sop_prime consumes the result of Discover Identity on SOP'. It fills out cable identity and description, and it registers the cable. The SOP' plug is registered as well. The VDM state machine is adjusted to construct messages based on the SOP* type. If a transmission error occurs after the max number of retries for Discover Identity over SOP', then the port will send Discover SVIDs over SOP. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- Changes since v2: * Added reviewed-by tag Changes since v1: * Moved typec_cable_set_svdm_version and typec_cable_get_svdm_version symbols into independent patch. * Minor change to svdm_version handing for SOP' in tcpm_pd_svdm --- drivers/usb/typec/tcpm/tcpm.c | 388 +++++++++++++++++++++++++++++----- include/linux/usb/pd_vdo.h | 8 +- 2 files changed, 347 insertions(+), 49 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index a59927925714..a870fbc6bc35 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -328,6 +328,12 @@ struct tcpm_port { struct typec_partner_desc partner_desc; struct typec_partner *partner; + struct usb_pd_identity cable_ident; + struct typec_cable_desc cable_desc; + struct typec_cable *cable; + struct typec_plug_desc plug_prime_desc; + struct typec_plug *plug_prime; + enum typec_cc_status cc_req; enum typec_cc_status src_rp; /* work only if pd_supported == false */ @@ -508,6 +514,12 @@ struct tcpm_port { bool potential_contaminant; /* SOP* Related Fields */ + /* + * Flag to determine if SOP' Discover Identity is available. The flag + * is set if Discover Identity on SOP' does not immediately follow + * Discover Identity on SOP. + */ + bool send_discover_prime; /* * tx_sop_type determines which SOP* a message is being sent on. * For messages that are queued and not sent immediately such as in @@ -1508,7 +1520,7 @@ static int tcpm_ams_start(struct tcpm_port *port, enum tcpm_ams ams) * VDM/VDO handling functions */ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header, - const u32 *data, int cnt) + const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type) { u32 vdo_hdr = port->vdo_data[0]; @@ -1516,7 +1528,10 @@ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header, /* If is sending discover_identity, handle received message first */ if (PD_VDO_SVDM(vdo_hdr) && PD_VDO_CMD(vdo_hdr) == CMD_DISCOVER_IDENT) { - port->send_discover = true; + if (tx_sop_type == TCPC_TX_SOP_PRIME) + port->send_discover_prime = true; + else + port->send_discover = true; mod_send_discover_delayed_work(port, SEND_DISCOVER_RETRY_MS); } else { /* Make sure we are not still processing a previous VDM packet */ @@ -1531,6 +1546,8 @@ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header, port->vdm_state = VDM_STATE_READY; port->vdm_sm_running = true; + port->tx_sop_type = tx_sop_type; + mod_vdm_delayed_work(port, 0); } @@ -1538,7 +1555,7 @@ static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header, const u32 *data, int cnt) { mutex_lock(&port->lock); - tcpm_queue_vdm(port, header, data, cnt); + tcpm_queue_vdm(port, header, data, cnt, TCPC_TX_SOP); mutex_unlock(&port->lock); } @@ -1560,6 +1577,63 @@ static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt) PD_PRODUCT_PID(product), product & 0xffff); } +static void svdm_consume_identity_sop_prime(struct tcpm_port *port, const u32 *p, int cnt) +{ + u32 idh = p[VDO_INDEX_IDH]; + u32 product = p[VDO_INDEX_PRODUCT]; + int svdm_version; + + /* + * Attempt to consume identity only if cable currently is not set + */ + if (!IS_ERR_OR_NULL(port->cable)) + goto register_plug; + + /* Reset cable identity */ + memset(&port->cable_ident, 0, sizeof(port->cable_ident)); + + /* Fill out id header, cert, product, cable VDO 1 */ + port->cable_ident.id_header = idh; + port->cable_ident.cert_stat = p[VDO_INDEX_CSTAT]; + port->cable_ident.product = product; + port->cable_ident.vdo[0] = p[VDO_INDEX_CABLE_1]; + + /* Fill out cable desc, infer svdm_version from pd revision */ + port->cable_desc.type = (enum typec_plug_type) (VDO_TYPEC_CABLE_TYPE(p[VDO_INDEX_CABLE_1]) + + USB_PLUG_TYPE_A); + port->cable_desc.active = PD_IDH_PTYPE(idh) == IDH_PTYPE_ACABLE ? 1 : 0; + /* Log PD Revision and additional cable VDO from negotiated revision */ + switch (port->negotiated_rev_prime) { + case PD_REV30: + port->cable_desc.pd_revision = 0x0300; + if (port->cable_desc.active) + port->cable_ident.vdo[1] = p[VDO_INDEX_CABLE_2]; + break; + case PD_REV20: + port->cable_desc.pd_revision = 0x0200; + break; + default: + port->cable_desc.pd_revision = 0x0200; + break; + } + port->cable_desc.identity = &port->cable_ident; + /* Register Cable, set identity and svdm_version */ + port->cable = typec_register_cable(port->typec_port, &port->cable_desc); + if (IS_ERR_OR_NULL(port->cable)) + return; + typec_cable_set_identity(port->cable); + /* Get SVDM version */ + svdm_version = PD_VDO_SVDM_VER(p[VDO_INDEX_HDR]); + typec_cable_set_svdm_version(port->cable, svdm_version); + +register_plug: + if (IS_ERR_OR_NULL(port->plug_prime)) { + port->plug_prime_desc.index = TYPEC_PLUG_SOP_P; + port->plug_prime = typec_register_plug(port->cable, + &port->plug_prime_desc); + } +} + static bool svdm_consume_svids(struct tcpm_port *port, const u32 *p, int cnt) { struct pd_mode_data *pmdata = &port->mode_data; @@ -1654,6 +1728,7 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port) } #define supports_modal(port) PD_IDH_MODAL_SUPP((port)->partner_ident.id_header) +#define supports_host(port) PD_IDH_HOST_SUPP((port->partner_ident.id_header)) /* * Helper to determine whether the port is capable of SOP' communication at the @@ -1706,9 +1781,35 @@ static bool tcpm_can_communicate_sop_prime(struct tcpm_port *port) return false; } +static bool tcpm_attempt_vconn_swap_discovery(struct tcpm_port *port) +{ + if (!port->tcpc->attempt_vconn_swap_discovery) + return false; + + /* Port is already source, no need to perform swap */ + if (port->vconn_role == TYPEC_SOURCE) + return false; + + /* + * Partner needs to support Alternate Modes with modal support. If + * partner is also capable of being a USB Host, it could be a device + * that supports Alternate Modes as the DFP. + */ + if (!supports_modal(port) || supports_host(port)) + return false; + + if ((port->negotiated_rev == PD_REV20 && port->data_role == TYPEC_HOST) || + port->negotiated_rev == PD_REV30) + return port->tcpc->attempt_vconn_swap_discovery(port->tcpc); + + return false; +} + static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, const u32 *p, int cnt, u32 *response, - enum adev_actions *adev_action) + enum adev_actions *adev_action, + enum tcpm_transmit_type rx_sop_type, + enum tcpm_transmit_type *response_tx_sop_type) { struct typec_port *typec = port->typec_port; struct typec_altmode *pdev; @@ -1718,6 +1819,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, int cmd_type; int cmd; int i; + int ret; cmd_type = PD_VDO_CMDT(p[0]); cmd = PD_VDO_CMD(p[0]); @@ -1730,9 +1832,25 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, pdev = typec_match_altmode(port->partner_altmode, ALTMODE_DISCOVERY_MAX, PD_VDO_VID(p[0]), PD_VDO_OPOS(p[0])); - svdm_version = typec_get_negotiated_svdm_version(typec); - if (svdm_version < 0) - return 0; + switch (rx_sop_type) { + case TCPC_TX_SOP_PRIME: + if (!IS_ERR_OR_NULL(port->cable)) { + svdm_version = typec_get_cable_svdm_version(typec); + if (PD_VDO_SVDM_VER(p[0]) < svdm_version) + typec_cable_set_svdm_version(port->cable, svdm_version); + } + break; + case TCPC_TX_SOP: + svdm_version = typec_get_negotiated_svdm_version(typec); + if (svdm_version < 0) + return 0; + break; + default: + svdm_version = typec_get_negotiated_svdm_version(typec); + if (svdm_version < 0) + return 0; + break; + } switch (cmd_type) { case CMDT_INIT: @@ -1802,22 +1920,89 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, (VDO_SVDM_VERS(typec_get_negotiated_svdm_version(typec))); break; case CMDT_RSP_ACK: - /* silently drop message if we are not connected */ - if (IS_ERR_OR_NULL(port->partner)) + /* + * Silently drop message if we are not connected, but can process + * if SOP' Discover Identity prior to explicit contract. + */ + if (IS_ERR_OR_NULL(port->partner) && + !(rx_sop_type == TCPC_TX_SOP_PRIME && cmd == CMD_DISCOVER_IDENT)) break; tcpm_ams_finish(port); switch (cmd) { + /* + * SVDM Command Flow for SOP and SOP': + * SOP Discover Identity + * SOP' Discover Identity + * SOP Discover SVIDs + * Discover Modes + * + * Perform Discover SOP' if the port can communicate with cable + * plug. + */ case CMD_DISCOVER_IDENT: - if (PD_VDO_SVDM_VER(p[0]) < svdm_version) - typec_partner_set_svdm_version(port->partner, - PD_VDO_SVDM_VER(p[0])); - /* 6.4.4.3.1 */ - svdm_consume_identity(port, p, cnt); - response[0] = VDO(USB_SID_PD, 1, typec_get_negotiated_svdm_version(typec), - CMD_DISCOVER_SVID); - rlen = 1; + switch (rx_sop_type) { + case TCPC_TX_SOP: + if (PD_VDO_SVDM_VER(p[0]) < svdm_version) { + typec_partner_set_svdm_version(port->partner, + PD_VDO_SVDM_VER(p[0])); + /* If cable is discovered before partner, downgrade svdm */ + if (!IS_ERR_OR_NULL(port->cable) && + (typec_get_cable_svdm_version(port->typec_port) > + svdm_version)) + typec_cable_set_svdm_version(port->cable, + svdm_version); + } + /* 6.4.4.3.1 */ + svdm_consume_identity(port, p, cnt); + /* Attempt Vconn swap, delay SOP' discovery if necessary */ + if (tcpm_attempt_vconn_swap_discovery(port)) { + port->send_discover_prime = true; + port->upcoming_state = VCONN_SWAP_SEND; + ret = tcpm_ams_start(port, VCONN_SWAP); + if (!ret) + return 0; + port->upcoming_state = INVALID_STATE; + port->send_discover_prime = false; + } + + /* + * Attempt Discover Identity on SOP' if the + * cable was not discovered previously, and use + * the SVDM version of the partner to probe. + */ + if (IS_ERR_OR_NULL(port->cable) && + tcpm_can_communicate_sop_prime(port)) { + *response_tx_sop_type = TCPC_TX_SOP_PRIME; + port->send_discover_prime = true; + response[0] = VDO(USB_SID_PD, 1, + typec_get_negotiated_svdm_version(typec), + CMD_DISCOVER_IDENT); + rlen = 1; + } else { + *response_tx_sop_type = TCPC_TX_SOP; + response[0] = VDO(USB_SID_PD, 1, + typec_get_negotiated_svdm_version(typec), + CMD_DISCOVER_SVID); + rlen = 1; + } + break; + case TCPC_TX_SOP_PRIME: + /* + * svdm_consume_identity_sop_prime will determine + * the svdm_version for the cable moving forward. + */ + svdm_consume_identity_sop_prime(port, p, cnt); + *response_tx_sop_type = TCPC_TX_SOP; + response[0] = VDO(USB_SID_PD, 1, + typec_get_negotiated_svdm_version(typec), + CMD_DISCOVER_SVID); + rlen = 1; + break; + default: + return 0; + } break; case CMD_DISCOVER_SVID: /* 6.4.4.3.2 */ @@ -1903,13 +2088,15 @@ static void tcpm_pd_handle_msg(struct tcpm_port *port, enum tcpm_ams ams); static void tcpm_handle_vdm_request(struct tcpm_port *port, - const __le32 *payload, int cnt) + const __le32 *payload, int cnt, + enum tcpm_transmit_type rx_sop_type) { enum adev_actions adev_action = ADEV_NONE; struct typec_altmode *adev; u32 p[PD_MAX_PAYLOAD]; u32 response[8] = { }; int i, rlen = 0; + enum tcpm_transmit_type response_tx_sop_type = TCPC_TX_SOP; for (i = 0; i < cnt; i++) p[i] = le32_to_cpu(payload[i]); @@ -1944,7 +2131,8 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port, * - We will send NAK and the flag will be cleared in the state machine. */ port->vdm_sm_running = true; - rlen = tcpm_pd_svdm(port, adev, p, cnt, response, &adev_action); + rlen = tcpm_pd_svdm(port, adev, p, cnt, response, &adev_action, + rx_sop_type, &response_tx_sop_type); } else { if (port->negotiated_rev >= PD_REV30) tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS); @@ -2012,19 +2200,38 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port, mutex_lock(&port->lock); if (rlen > 0) - tcpm_queue_vdm(port, response[0], &response[1], rlen - 1); + tcpm_queue_vdm(port, response[0], &response[1], rlen - 1, response_tx_sop_type); else port->vdm_sm_running = false; } static void tcpm_send_vdm(struct tcpm_port *port, u32 vid, int cmd, - const u32 *data, int count) + const u32 *data, int count, enum tcpm_transmit_type tx_sop_type) { - int svdm_version = typec_get_negotiated_svdm_version(port->typec_port); + int svdm_version; u32 header; - if (svdm_version < 0) - return; + switch (tx_sop_type) { + case TCPC_TX_SOP_PRIME: + /* + * If the port partner is discovered, then the port partner's + * SVDM Version will be returned + */ + svdm_version = typec_get_cable_svdm_version(port->typec_port); + if (svdm_version < 0) + svdm_version = SVDM_VER_MAX; + break; + case TCPC_TX_SOP: + svdm_version = typec_get_negotiated_svdm_version(port->typec_port); + if (svdm_version < 0) + return; + break; + default: + svdm_version = typec_get_negotiated_svdm_version(port->typec_port); + if (svdm_version < 0) + return; + break; + } if (WARN_ON(count > VDO_MAX_SIZE - 1)) count = VDO_MAX_SIZE - 1; @@ -2033,7 +2240,7 @@ static void tcpm_send_vdm(struct tcpm_port *port, u32 vid, int cmd, header = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ? 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), svdm_version, cmd); - tcpm_queue_vdm(port, header, data, count); + tcpm_queue_vdm(port, header, data, count, tx_sop_type); } static unsigned int vdm_ready_timeout(u32 vdm_hdr) @@ -2067,6 +2274,7 @@ static void vdm_run_state_machine(struct tcpm_port *port) struct pd_message msg; int i, res = 0; u32 vdo_hdr = port->vdo_data[0]; + u32 response[8] = { }; switch (port->vdm_state) { case VDM_STATE_READY: @@ -2091,7 +2299,17 @@ static void vdm_run_state_machine(struct tcpm_port *port) case CMD_DISCOVER_IDENT: res = tcpm_ams_start(port, DISCOVER_IDENTITY); if (res == 0) { - port->send_discover = false; + switch (port->tx_sop_type) { + case TCPC_TX_SOP_PRIME: + port->send_discover_prime = false; + break; + case TCPC_TX_SOP: + port->send_discover = false; + break; + default: + port->send_discover = false; + break; + } } else if (res == -EAGAIN) { port->vdo_data[0] = 0; mod_send_discover_delayed_work(port, @@ -2160,19 +2378,49 @@ static void vdm_run_state_machine(struct tcpm_port *port) tcpm_ams_finish(port); } else { tcpm_ams_finish(port); + if (port->tx_sop_type == TCPC_TX_SOP) + break; + /* Handle SOP' Transmission Errors */ + switch (PD_VDO_CMD(vdo_hdr)) { + /* + * If Discover Identity fails on SOP', then resume + * discovery process on SOP only. + */ + case CMD_DISCOVER_IDENT: + port->vdo_data[0] = 0; + response[0] = VDO(USB_SID_PD, 1, + typec_get_negotiated_svdm_version( + port->typec_port), + CMD_DISCOVER_SVID); + tcpm_queue_vdm(port, response[0], &response[1], + 0, TCPC_TX_SOP); + break; + default: + break; + } } break; case VDM_STATE_SEND_MESSAGE: /* Prepare and send VDM */ memset(&msg, 0, sizeof(msg)); - msg.header = PD_HEADER_LE(PD_DATA_VENDOR_DEF, - port->pwr_role, - port->data_role, - port->negotiated_rev, - port->message_id, port->vdo_count); + if (port->tx_sop_type == TCPC_TX_SOP_PRIME) { + msg.header = PD_HEADER_LE(PD_DATA_VENDOR_DEF, + 0, /* Cable Plug Indicator for DFP/UFP */ + 0, /* Reserved */ + port->negotiated_rev_prime, + port->message_id_prime, + port->vdo_count); + } else { + msg.header = PD_HEADER_LE(PD_DATA_VENDOR_DEF, + port->pwr_role, + port->data_role, + port->negotiated_rev, + port->message_id, + port->vdo_count); + } for (i = 0; i < port->vdo_count; i++) msg.payload[i] = cpu_to_le32(port->vdo_data[i]); - res = tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); + res = tcpm_pd_transmit(port, port->tx_sop_type, &msg); if (res < 0) { port->vdm_state = VDM_STATE_ERR_SEND; } else { @@ -2559,7 +2807,8 @@ static int tcpm_register_sink_caps(struct tcpm_port *port) } static void tcpm_pd_data_request(struct tcpm_port *port, - const struct pd_message *msg) + const struct pd_message *msg, + enum tcpm_transmit_type rx_sop_type) { enum pd_data_msg_type type = pd_header_type_le(msg->header); unsigned int cnt = pd_header_cnt_le(msg->header); @@ -2600,8 +2849,11 @@ static void tcpm_pd_data_request(struct tcpm_port *port, break; } - if (rev < PD_MAX_REV) + if (rev < PD_MAX_REV) { port->negotiated_rev = rev; + if (port->negotiated_rev_prime > port->negotiated_rev) + port->negotiated_rev_prime = port->negotiated_rev; + } if (port->pwr_role == TYPEC_SOURCE) { if (port->ams == GET_SOURCE_CAPABILITIES) @@ -2652,8 +2904,11 @@ static void tcpm_pd_data_request(struct tcpm_port *port, break; } - if (rev < PD_MAX_REV) + if (rev < PD_MAX_REV) { port->negotiated_rev = rev; + if (port->negotiated_rev_prime > port->negotiated_rev) + port->negotiated_rev_prime = port->negotiated_rev; + } if (port->pwr_role != TYPEC_SOURCE || cnt != 1) { tcpm_pd_handle_msg(port, @@ -2709,7 +2964,7 @@ static void tcpm_pd_data_request(struct tcpm_port *port, NONE_AMS); break; case PD_DATA_VENDOR_DEF: - tcpm_handle_vdm_request(port, msg->payload, cnt); + tcpm_handle_vdm_request(port, msg->payload, cnt, rx_sop_type); break; case PD_DATA_BIST: port->bist_request = le32_to_cpu(msg->payload[0]); @@ -3152,7 +3407,7 @@ static void tcpm_pd_rx_handler(struct kthread_work *work) if (le16_to_cpu(msg->header) & PD_HEADER_EXT_HDR) tcpm_pd_ext_msg_request(port, msg); else if (cnt) - tcpm_pd_data_request(port, msg); + tcpm_pd_data_request(port, msg, rx_sop_type); else tcpm_pd_ctrl_request(port, msg, rx_sop_type); } @@ -3809,6 +4064,7 @@ static int tcpm_src_attach(struct tcpm_port *port) port->attached = true; port->send_discover = true; + port->send_discover_prime = false; return 0; @@ -3825,6 +4081,15 @@ static int tcpm_src_attach(struct tcpm_port *port) static void tcpm_typec_disconnect(struct tcpm_port *port) { + /* + * Unregister plug/cable outside of port->connected because cable can + * be discovered before SRC_READY/SNK_READY states where port->connected + * is set. + */ + typec_unregister_plug(port->plug_prime); + typec_unregister_cable(port->cable); + port->plug_prime = NULL; + port->cable = NULL; if (port->connected) { typec_partner_set_usb_power_delivery(port->partner, NULL); typec_unregister_partner(port->partner); @@ -3947,6 +4212,7 @@ static int tcpm_snk_attach(struct tcpm_port *port) port->attached = true; port->send_discover = true; + port->send_discover_prime = false; return 0; } @@ -4308,14 +4574,23 @@ static void run_state_machine(struct tcpm_port *port) * 6.4.4.3.1 Discover Identity * "The Discover Identity Command Shall only be sent to SOP when there is an * Explicit Contract." - * For now, this driver only supports SOP for DISCOVER_IDENTITY, thus using - * port->explicit_contract to decide whether to send the command. + * + * Discover Identity on SOP' should be discovered prior to the + * ready state, but if done after a Vconn Swap following Discover + * Identity on SOP then the discovery process can be run here + * as well. */ if (port->explicit_contract) { - tcpm_set_initial_svdm_version(port); + if (port->send_discover_prime) { + port->tx_sop_type = TCPC_TX_SOP_PRIME; + } else { + port->tx_sop_type = TCPC_TX_SOP; + tcpm_set_initial_svdm_version(port); + } mod_send_discover_delayed_work(port, 0); } else { port->send_discover = false; + port->send_discover_prime = false; } /* @@ -4607,14 +4882,23 @@ static void run_state_machine(struct tcpm_port *port) * 6.4.4.3.1 Discover Identity * "The Discover Identity Command Shall only be sent to SOP when there is an * Explicit Contract." - * For now, this driver only supports SOP for DISCOVER_IDENTITY, thus using - * port->explicit_contract. + * + * Discover Identity on SOP' should be discovered prior to the + * ready state, but if done after a Vconn Swap following Discover + * Identity on SOP then the discovery process can be run here + * as well. */ if (port->explicit_contract) { - tcpm_set_initial_svdm_version(port); + if (port->send_discover_prime) { + port->tx_sop_type = TCPC_TX_SOP_PRIME; + } else { + port->tx_sop_type = TCPC_TX_SOP; + tcpm_set_initial_svdm_version(port); + } mod_send_discover_delayed_work(port, 0); } else { port->send_discover = false; + port->send_discover_prime = false; } power_supply_changed(port->psy); @@ -4655,6 +4939,7 @@ static void run_state_machine(struct tcpm_port *port) tcpm_unregister_altmodes(port); port->nr_sink_caps = 0; port->send_discover = true; + port->send_discover_prime = false; if (port->pwr_role == TYPEC_SOURCE) tcpm_set_state(port, SRC_HARD_RESET_VBUS_OFF, PD_T_PS_HARD_RESET); @@ -4801,20 +5086,25 @@ static void run_state_machine(struct tcpm_port *port) /* DR_Swap states */ case DR_SWAP_SEND: tcpm_pd_send_control(port, PD_CTRL_DR_SWAP, TCPC_TX_SOP); - if (port->data_role == TYPEC_DEVICE || port->negotiated_rev > PD_REV20) + if (port->data_role == TYPEC_DEVICE || port->negotiated_rev > PD_REV20) { port->send_discover = true; + port->send_discover_prime = false; + } tcpm_set_state_cond(port, DR_SWAP_SEND_TIMEOUT, PD_T_SENDER_RESPONSE); break; case DR_SWAP_ACCEPT: tcpm_pd_send_control(port, PD_CTRL_ACCEPT, TCPC_TX_SOP); - if (port->data_role == TYPEC_DEVICE || port->negotiated_rev > PD_REV20) + if (port->data_role == TYPEC_DEVICE || port->negotiated_rev > PD_REV20) { port->send_discover = true; + port->send_discover_prime = false; + } tcpm_set_state_cond(port, DR_SWAP_CHANGE_DR, 0); break; case DR_SWAP_SEND_TIMEOUT: tcpm_swap_complete(port, -ETIMEDOUT); port->send_discover = false; + port->send_discover_prime = false; tcpm_ams_finish(port); tcpm_set_state(port, ready_state(port), 0); break; @@ -5796,7 +6086,8 @@ static void tcpm_enable_frs_work(struct kthread_work *work) goto unlock; /* Send when the state machine is idle */ - if (port->state != SNK_READY || port->vdm_sm_running || port->send_discover) + if (port->state != SNK_READY || port->vdm_sm_running || port->send_discover || + port->send_discover_prime) goto resched; port->upcoming_state = GET_SINK_CAP; @@ -5819,11 +6110,12 @@ static void tcpm_send_discover_work(struct kthread_work *work) mutex_lock(&port->lock); /* No need to send DISCOVER_IDENTITY anymore */ - if (!port->send_discover) + if (!port->send_discover && !port->send_discover_prime) goto unlock; if (port->data_role == TYPEC_DEVICE && port->negotiated_rev < PD_REV30) { port->send_discover = false; + port->send_discover_prime = false; goto unlock; } @@ -5833,7 +6125,7 @@ static void tcpm_send_discover_work(struct kthread_work *work) goto unlock; } - tcpm_send_vdm(port, USB_SID_PD, CMD_DISCOVER_IDENT, NULL, 0); + tcpm_send_vdm(port, USB_SID_PD, CMD_DISCOVER_IDENT, NULL, 0, port->tx_sop_type); unlock: mutex_unlock(&port->lock); diff --git a/include/linux/usb/pd_vdo.h b/include/linux/usb/pd_vdo.h index 3a747938cdab..c09c5a12e273 100644 --- a/include/linux/usb/pd_vdo.h +++ b/include/linux/usb/pd_vdo.h @@ -86,12 +86,15 @@ * * Request is simply properly formatted SVDM header * - * Response is 4 data objects: + * Response is 4 data objects for Power Delivery 2.0 and Passive Cables for + * Power Delivery 3.0. Active Cables in Power Delivery 3.0 have 5 data objects. * [0] :: SVDM header * [1] :: Identitiy header * [2] :: Cert Stat VDO * [3] :: (Product | Cable) VDO + * [4] :: Cable VDO 1 * [4] :: AMA VDO + * [5] :: Cable VDO 2 * */ #define VDO_INDEX_HDR 0 @@ -100,6 +103,8 @@ #define VDO_INDEX_CABLE 3 #define VDO_INDEX_PRODUCT 3 #define VDO_INDEX_AMA 4 +#define VDO_INDEX_CABLE_1 4 +#define VDO_INDEX_CABLE_2 5 /* * SVDM Identity Header @@ -150,6 +155,7 @@ #define PD_IDH_MODAL_SUPP(vdo) ((vdo) & (1 << 26)) #define PD_IDH_DFP_PTYPE(vdo) (((vdo) >> 23) & 0x7) #define PD_IDH_CONN_TYPE(vdo) (((vdo) >> 21) & 0x3) +#define PD_IDH_HOST_SUPP(vdo) ((vdo) & (1 << 31)) /* * Cert Stat VDO From patchwork Mon Jan 8 19:16:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186119 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1226752dyq; Mon, 8 Jan 2024 11:19:29 -0800 (PST) X-Google-Smtp-Source: AGHT+IGZ0a5AJBzgvfH2g0OiZY6Zqxp1T4FWi9pBfyBzQtAXSSRNjLcx8wwQBR9V5YCX9/+MvLPI X-Received: by 2002:a05:6a00:1d8f:b0:6d9:8ccb:be1b with SMTP id z15-20020a056a001d8f00b006d98ccbbe1bmr1842731pfw.29.1704741569231; Mon, 08 Jan 2024 11:19:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741569; cv=none; d=google.com; s=arc-20160816; b=eHpEyjh3MkG2jQZvonb3HXBrGCWh3dwcl0HNi2TIooRkywbhjyO9kjM0KnEIrA0JzK xeK59efGjsF7oJ0BfP6b6zS2A+y6ijr3J9fbUsCY8m8qZ3NLNfJLkBcKfIV27ez+zEiK Hgl48hiehYRmM3b/08IZq5WmtDmjWxmyC+6Yku0Uw0OyekZFI1jOl88YlOvCCp0dprzh cgvyLSi3/our+gfKQTVb1ijACtG+4Xp8/K217jwpe3RxIkstOYSpdBLISCJDcWKPfiTP q0G7HTqnh8DTLURl7UQaEKArRCaQkYNyvoIeGRgsFcR1e8kZfbDVHoNgsoy7GyXYd2Ez IWsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=l1aAYuC2BqdlAhZMX9amHJf0C2KnJp96CrYM+8fPmRU=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=1IuaJsZLUD2ndkf2S/12CeUHaHY+fh3U+Do7/REhg3A6VQcSrAFmIrkbZOW/Cw5Vec q/mL6G1mSY7Euw4DaT192bzjH1LXaiSEmtHp/LxDz99+057uQyep8vK15h7bmSE0Q2ch DLnuMYdgq7+2IDBcl/f2Od0u3GdYlWwJx5FlUN31BucHAmjLLWIYPhAYakPDL/ezDxnv okdpANldVM6T1ZWY9/kiPkROSDH6/bVjcqOnMJgfDjKrgNBws3wci5+wFISyJrw44aNK s8UiESHMp3vBYCdbdxNDL/xni5W4zxmx9yFq+ngNMB1aB1GiVVj9Rap8oywi0Qa0sQ8p 21jw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=lgYUeUr+; spf=pass (google.com: domain of linux-kernel+bounces-20025-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20025-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id q21-20020a638c55000000b005c66404de05si264509pgn.413.2024.01.08.11.19.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:19:29 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20025-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=lgYUeUr+; spf=pass (google.com: domain of linux-kernel+bounces-20025-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20025-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id DB86D284E76 for ; Mon, 8 Jan 2024 19:19:28 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 0E46456B82; Mon, 8 Jan 2024 19:16:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="lgYUeUr+" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-yb1-f201.google.com (mail-yb1-f201.google.com [209.85.219.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 063EF5675D for ; Mon, 8 Jan 2024 19:16:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-yb1-f201.google.com with SMTP id 3f1490d57ef6-dbedaa77289so2445686276.0 for ; Mon, 08 Jan 2024 11:16:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741406; x=1705346206; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=l1aAYuC2BqdlAhZMX9amHJf0C2KnJp96CrYM+8fPmRU=; b=lgYUeUr+jkoiQflV2zRlJme+d7boD0WhKoyX+1cUP/mNIdLPUnAUSOsVpG2i5/MWgr oVT5aq1NKyQ/TlOWhDAgnVJ3ifMgVJWULC9jiGXAGAf9EKjxAWJMsbi+zzYIHbHguNzY wDrKVJ9/SFy/ya5k9cwGaySoL3wt/cgvfJFRWQlF2nNpy87J/e0mJpNvfWFpPxkvNUDH VROVEbmC1S6VtC5rWXlSGi/aNd+CpySLB3coR57TPVx+ciHemAojbV3N17dDI5z0qIoJ FpWZdbDv3DRHdIaCzdXn3lKuSdtzVuunzmKRTNbwzTBN57RPnhlkdhnX+K8/7h8DZhlc NFJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741406; x=1705346206; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=l1aAYuC2BqdlAhZMX9amHJf0C2KnJp96CrYM+8fPmRU=; b=n9hRV1kc2BMCws4Gkv0689ZQYFkkFCQWg8opuanthkdmlVftVUvDztSC0FzkpDVw/l bspd4gTjrY90eD1Dnz/ivveeOvJfdvMukiA7iKEAvi6bz3WOvhbT4BnFXtMB+F9HLZxa UXwZLwoEyQgr9KG8uwQhC6th+YoTBL9qwyP9Y4UPn42mz5nkXtMl18lRzv7iq9fwSO4n TOuYB/ziXhcWxt6oR2aG3bC8h8lBE2rYuyNFq+RXhNNy2ivEdoXBCFKzi7VQHZcOs37d lsIQD1vRhpzjD08VuW1TDnvv7rb1eUAbz6KCsMecD2xDXUgHerikwbPtp+Qf8lUZKN67 PiLg== X-Gm-Message-State: AOJu0YxtxYGCrIM223WYJUeLwFQLsEUN7CKNzeqkWmwO6rcznuYLTiGF R9fMEcVZD9QO3DarYH245RdLcaHXDDauYKwH9lO65A== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a25:d616:0:b0:dbd:3ccf:31e4 with SMTP id n22-20020a25d616000000b00dbd3ccf31e4mr73844ybg.2.1704741406073; Mon, 08 Jan 2024 11:16:46 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:22 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=4856; i=rdbabiera@google.com; h=from:subject; bh=uVQYc5B6QgFBFc2IJXXGnnh5LigcI8G8edyIRV6rpWM=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvDi2pX/PPjKl+uBu+TOzYowm1jbe/jXb/cnnlz/vb srwnsS6vqOUhUGMg0FWTJFF1z/P4MaV1C1zOGuMYeawMoEMYeDiFICJrIhhZFh0yk6HKe5W+cEZ 04OyVBlD2W5oWc1++3mnz6TfGswR+j8Y/mdMi/K7tF3Zt+2javSvQpaoNsHy35yZLScfFpbJ/lx 4kwUA X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-23-rdbabiera@google.com> Subject: [PATCH v3 09/12] usb: typec: tcpm: add state machine support for SRC_VDM_IDENTITY_REQUEST From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787551095706748364 X-GMAIL-MSGID: 1787551095706748364 Add SRC_VDM_IDENTITY_REQUEST state which first enters after SRC_STARTUP. The state sends Discover Identity on SOP' and transitions to SRC_SEND_CAPABILITIES. SRC_SEND_CAPABILITIES will transition back into SRC_VDM_IDENTITY_REQUEST instead of retrying immediately. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- Changes since v2: * Added reviewed-by tag --- drivers/usb/typec/tcpm/tcpm.c | 49 ++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index a870fbc6bc35..1ce525c8f97c 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -146,7 +146,9 @@ S(PORT_RESET_WAIT_OFF), \ \ S(AMS_START), \ - S(CHUNK_NOT_SUPP) + S(CHUNK_NOT_SUPP), \ + \ + S(SRC_VDM_IDENTITY_REQUEST) #define FOREACH_AMS(S) \ S(NONE_AMS), \ @@ -1963,6 +1965,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, ret = tcpm_ams_start(port, VCONN_SWAP); if (!ret) return 0; + /* Cannot perform Vconn swap */ port->upcoming_state = INVALID_STATE; port->send_discover_prime = false; } @@ -1994,6 +1997,16 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, * the svdm_version for the cable moving forward. */ svdm_consume_identity_sop_prime(port, p, cnt); + + /* + * If received in SRC_VDM_IDENTITY_REQUEST, continue + * to SRC_SEND_CAPABILITIES + */ + if (port->state == SRC_VDM_IDENTITY_REQUEST) { + tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); + return 0; + } + *response_tx_sop_type = TCPC_TX_SOP; response[0] = VDO(USB_SID_PD, 1, typec_get_negotiated_svdm_version(typec), @@ -2288,7 +2301,8 @@ static void vdm_run_state_machine(struct tcpm_port *port) * if there's traffic or we're not in PDO ready state don't send * a VDM. */ - if (port->state != SRC_READY && port->state != SNK_READY) { + if (port->state != SRC_READY && port->state != SNK_READY && + port->state != SRC_VDM_IDENTITY_REQUEST) { port->vdm_sm_running = false; break; } @@ -2364,13 +2378,22 @@ static void vdm_run_state_machine(struct tcpm_port *port) tcpm_ams_finish(port); break; case VDM_STATE_ERR_SEND: + /* + * When sending Discover Identity to SOP' before establishing an + * explicit contract, do not retry. Instead, weave sending + * Source_Capabilities over SOP and Discover Identity over SOP'. + */ + if (port->state == SRC_VDM_IDENTITY_REQUEST) { + tcpm_ams_finish(port); + port->vdm_state = VDM_STATE_DONE; + tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); /* * A partner which does not support USB PD will not reply, * so this is not a fatal error. At the same time, some * devices may not return GoodCRC under some circumstances, * so we need to retry. */ - if (port->vdm_retries < 3) { + } else if (port->vdm_retries < 3) { tcpm_log(port, "VDM Tx error, retry"); port->vdm_retries++; port->vdm_state = VDM_STATE_READY; @@ -4478,8 +4501,12 @@ static void run_state_machine(struct tcpm_port *port) } ret = tcpm_pd_send_source_caps(port); if (ret < 0) { - tcpm_set_state(port, SRC_SEND_CAPABILITIES, - PD_T_SEND_SOURCE_CAP); + if (tcpm_can_communicate_sop_prime(port) && + IS_ERR_OR_NULL(port->cable)) + tcpm_set_state(port, SRC_VDM_IDENTITY_REQUEST, 0); + else + tcpm_set_state(port, SRC_SEND_CAPABILITIES, + PD_T_SEND_SOURCE_CAP); } else { /* * Per standard, we should clear the reset counter here. @@ -5395,6 +5422,15 @@ static void run_state_machine(struct tcpm_port *port) tcpm_pd_send_control(port, PD_CTRL_NOT_SUPP, TCPC_TX_SOP); tcpm_set_state(port, port->pwr_role == TYPEC_SOURCE ? SRC_READY : SNK_READY, 0); break; + + /* Cable states */ + case SRC_VDM_IDENTITY_REQUEST: + port->send_discover_prime = true; + port->tx_sop_type = TCPC_TX_SOP_PRIME; + mod_send_discover_delayed_work(port, 0); + port->upcoming_state = SRC_SEND_CAPABILITIES; + break; + default: WARN(1, "Unexpected port state %d\n", port->state); break; @@ -6120,7 +6156,8 @@ static void tcpm_send_discover_work(struct kthread_work *work) } /* Retry if the port is not idle */ - if ((port->state != SRC_READY && port->state != SNK_READY) || port->vdm_sm_running) { + if ((port->state != SRC_READY && port->state != SNK_READY && + port->state != SRC_VDM_IDENTITY_REQUEST) || port->vdm_sm_running) { mod_send_discover_delayed_work(port, SEND_DISCOVER_RETRY_MS); goto unlock; } From patchwork Mon Jan 8 19:16:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186121 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1227036dyq; Mon, 8 Jan 2024 11:20:08 -0800 (PST) X-Google-Smtp-Source: AGHT+IEaYXEdleXVXIQFV5VwmwJnAevFGxVdxv37XOwqdmtkrfjOWkkYFNMPa45UApIehW1ouD4c X-Received: by 2002:a50:9ead:0:b0:556:d0af:3ac0 with SMTP id a42-20020a509ead000000b00556d0af3ac0mr2091721edf.8.1704741608674; Mon, 08 Jan 2024 11:20:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741608; cv=none; d=google.com; s=arc-20160816; b=WA0RG8HJFqIWl06fcd10dajs7JJiuHB1VAwx/5zGeN7hD2Zvh7fXBB6rUC9E2bsprY VXtmfabNiOm16XgBzeA351hEJAqmJJbmdtlf3iwqqQ0epHe9BxWuwnTty94VRhg+qy+C J0pXOGwakCmserBa75iXkLou3j+B/CUMZcRFs4bmX8lzm5kTb8/ccqf07r2dS3RHHfOa ai5sTJ+9V1JDO2GtoENDgp3/dvPrp6EcNsQj/42q8VD/Y2bfHH6w6WNp0mLukLJTh/w9 q9KdcH7fQsmKUZdf98VfCaFWo27wWxT7duPDfjsOTT5v+ioeqln+Z2q417zw0z4a2d5A 3g/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=Na5JEvf/r3MwURfXlreuKn4xwZvTwH3GK5IIeoV8VA0=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=GFi8sSdKQDhHbEKDKXNzYHGWdVf4AW6y+RGDETbSYIq/G1/jzq027lteBDym1Nis6z RcACOHREBwb3xc4pFHHuYD9OxEque3s0i+uX2dF2W29RBGLeLpeETiScIRgZjlMbesVu PTvnSaEOJ1E6XhuzYySSd9UyOANZe1m/AxCa4Hte9oBxZiGm0NgxDKgLw3+rsmO2u8sA sTKDaec3Pr1+K7Lew7BJx30s9QQoPNOnJdasUQRFpAASkRg/89g+d81mDgWw5O7qN6CW t0CeMrrh0Xbm3IczVJQQjTJNWce8lu1ecmyfkvg8sYe8cPezbAEK+6SoZ5j55zrolJjH c1Zw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=kyJk29Mg; spf=pass (google.com: domain of linux-kernel+bounces-20027-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20027-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id b73-20020a509f4f000000b0055343606ce3si121707edf.300.2024.01.08.11.20.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:20:08 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20027-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=kyJk29Mg; spf=pass (google.com: domain of linux-kernel+bounces-20027-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20027-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 208F31F23DA6 for ; Mon, 8 Jan 2024 19:20:08 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A4AF057320; Mon, 8 Jan 2024 19:16:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="kyJk29Mg" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D9A656769 for ; Mon, 8 Jan 2024 19:16:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-6d9c7de0620so1517201b3a.1 for ; Mon, 08 Jan 2024 11:16:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741407; x=1705346207; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Na5JEvf/r3MwURfXlreuKn4xwZvTwH3GK5IIeoV8VA0=; b=kyJk29MgMFDYWvB9/odl8jsP+XzsiazJ2HwT4r7umjn1lzXxF8DBjtZASyQ1E88XlF RZa+4gSGr9uqhMYVXyar4oCMM08gpZPuGRYnKK30m6qmAwkT80+eG0u6KEkt7+f/E6Q/ x89u/fbaM9xLrpecMv3N0ZNUbXePkgmlFesqkaUcOaAy8DnmSFpzunB+fzSnji3BG+7k MOM1NGye7rYf1Dm7tprhbRV0VP1PsxZ5TZwtp2tmqVmo4Xkda+U3wNsygbYUDQB7q9Zk AfcAJ/eZXCC+QGojGSwGxKOE+dIOMavt5Dt2ul1vcI1q4DymWGNQnCA1Fg92xHHyYOz4 laCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741407; x=1705346207; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Na5JEvf/r3MwURfXlreuKn4xwZvTwH3GK5IIeoV8VA0=; b=t1iFEQlc4KmAnP+q97yLE4fgkY92ICBafGzed5wwwKYombQcIEoXBrefUPin9T977y EhUoowLSI2J3jkxBwlqzW4xkKWGJdb6iMdP+VHgR5urwuw98MYhZjES+12EMibSqrUnc pU514/79qnDr1TB1Q0hKVs5eqHhYmk91BKXOVvwg+yTl+qZGU8C6Ed9LLIT2E2F5SJlQ 6TF8ZyDFDl/uwSgawdS12fkHqt6o0JcOAsmjK0Z6+iNMHmhNZg9bHEecVJO1R600ZgJ0 Jht44hin7oRqEp0tyjXiOrd1olDLByQ737q2G1cJdFy0ydMnhC7fQ68UWoI8qQ7VT0K/ LSWg== X-Gm-Message-State: AOJu0YyJWAyxxPMKnuiCEML8dyNFC4TL5VgPXhZ7tuy0YxBQgL37FWlK aeQsaw3/SL5nW+3QnZt2LJYvOHbmZ/xlR3EFJnpJmQ== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a05:6a00:179a:b0:6d9:ac07:c02f with SMTP id s26-20020a056a00179a00b006d9ac07c02fmr21381pfg.1.1704741407628; Mon, 08 Jan 2024 11:16:47 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:23 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=10780; i=rdbabiera@google.com; h=from:subject; bh=KUuP8hopWnsWkJsZAic1x00KIEEWk4HC34TddMZqp6c=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvDhsrRRYjqzQfX1yudavhiM6oXfK3Feu8l6tfMB5f 8e+uje/OkpZGMQ4GGTFFFl0/fMMblxJ3TKHs8YYZg4rE8gQBi5OAZhIhwUjw1/3/j0cS1lfdngb dW3YJGl+5+ytSiVX+z9z5O5MZYpl/MnIMN3n0W3FnNeBJ+7qHzWaaDnr163V5Yfnx8iZV2y9MO3 gMk4A X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-24-rdbabiera@google.com> Subject: [PATCH v3 10/12] usb: typec: tcpm: add discover svids and discover modes support for sop' From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787551137300173553 X-GMAIL-MSGID: 1787551137300173553 Adds Discover SVIDs and Discover Modes support for SOP' and Alt Mode SVDM support over SOP'. tcpm_port adds separate Alt Mode data for SOP'. svdm_consume_svids and svdm_consume_modes take the received SVDM's SOP* type to store svids/modes separately, and tcpm_register_plug_altmodes registers the active cable's alt modes. In tcpm_pd_svdm, the port will send Discover SVIDs to SOP' after Discover Modes on SOP if the connected cable is an active cable. Discover Modes on SOP' is sent following Discover SVIDs on SOP. Registering partner alt modes is delayed when an active cable is present until Discover Modes completes on SOP', or if the Discover SVIDs/Discover Modes request on SOP' encounters a transmission error. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- Changes since v2: * v2 replaced code that unregistered partner altmodes instead of adding, readded to tcpm_unregister_altmodes. Changes since v1: * Changes to tcpm_altmode_enter/exit/vdm are moved to next patch * adev_action changes are moved to next patch --- drivers/usb/typec/tcpm/tcpm.c | 161 +++++++++++++++++++++++++++++----- 1 file changed, 140 insertions(+), 21 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 1ce525c8f97c..d16edf112858 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -477,7 +477,9 @@ struct tcpm_port { /* Alternate mode data */ struct pd_mode_data mode_data; + struct pd_mode_data mode_data_prime; struct typec_altmode *partner_altmode[ALTMODE_DISCOVERY_MAX]; + struct typec_altmode *plug_prime_altmode[ALTMODE_DISCOVERY_MAX]; struct typec_altmode *port_altmode[ALTMODE_DISCOVERY_MAX]; /* Deadline in jiffies to exit src_try_wait state */ @@ -1636,9 +1638,11 @@ static void svdm_consume_identity_sop_prime(struct tcpm_port *port, const u32 *p } } -static bool svdm_consume_svids(struct tcpm_port *port, const u32 *p, int cnt) +static bool svdm_consume_svids(struct tcpm_port *port, const u32 *p, int cnt, + enum tcpm_transmit_type rx_sop_type) { - struct pd_mode_data *pmdata = &port->mode_data; + struct pd_mode_data *pmdata = rx_sop_type == TCPC_TX_SOP_PRIME ? + &port->mode_data_prime : &port->mode_data; int i; for (i = 1; i < cnt; i++) { @@ -1684,14 +1688,29 @@ static bool svdm_consume_svids(struct tcpm_port *port, const u32 *p, int cnt) return false; } -static void svdm_consume_modes(struct tcpm_port *port, const u32 *p, int cnt) +static void svdm_consume_modes(struct tcpm_port *port, const u32 *p, int cnt, + enum tcpm_transmit_type rx_sop_type) { struct pd_mode_data *pmdata = &port->mode_data; struct typec_altmode_desc *paltmode; int i; - if (pmdata->altmodes >= ARRAY_SIZE(port->partner_altmode)) { - /* Already logged in svdm_consume_svids() */ + switch (rx_sop_type) { + case TCPC_TX_SOP_PRIME: + pmdata = &port->mode_data_prime; + if (pmdata->altmodes >= ARRAY_SIZE(port->plug_prime_altmode)) { + /* Already logged in svdm_consume_svids() */ + return; + } + break; + case TCPC_TX_SOP: + pmdata = &port->mode_data; + if (pmdata->altmodes >= ARRAY_SIZE(port->partner_altmode)) { + /* Already logged in svdm_consume_svids() */ + return; + } + break; + default: return; } @@ -1729,7 +1748,28 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port) } } +static void tcpm_register_plug_altmodes(struct tcpm_port *port) +{ + struct pd_mode_data *modep = &port->mode_data_prime; + struct typec_altmode *altmode; + int i; + + typec_plug_set_num_altmodes(port->plug_prime, modep->altmodes); + + for (i = 0; i < modep->altmodes; i++) { + altmode = typec_plug_register_altmode(port->plug_prime, + &modep->altmode_desc[i]); + if (IS_ERR(altmode)) { + tcpm_log(port, "Failed to register plug SVID 0x%04x", + modep->altmode_desc[i].svid); + altmode = NULL; + } + port->plug_prime_altmode[i] = altmode; + } +} + #define supports_modal(port) PD_IDH_MODAL_SUPP((port)->partner_ident.id_header) +#define supports_modal_cable(port) PD_IDH_MODAL_SUPP((port)->cable_ident.id_header) #define supports_host(port) PD_IDH_HOST_SUPP((port->partner_ident.id_header)) /* @@ -1807,6 +1847,15 @@ static bool tcpm_attempt_vconn_swap_discovery(struct tcpm_port *port) return false; } + +static bool tcpm_cable_vdm_supported(struct tcpm_port *port) +{ + return !IS_ERR_OR_NULL(port->cable) && + typec_cable_is_active(port->cable) && + supports_modal_cable(port) && + tcpm_can_communicate_sop_prime(port); +} + static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, const u32 *p, int cnt, u32 *response, enum adev_actions *adev_action, @@ -1814,8 +1863,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, enum tcpm_transmit_type *response_tx_sop_type) { struct typec_port *typec = port->typec_port; - struct typec_altmode *pdev; - struct pd_mode_data *modep; + struct typec_altmode *pdev, *pdev_prime; + struct pd_mode_data *modep, *modep_prime; int svdm_version; int rlen = 0; int cmd_type; @@ -1836,6 +1885,11 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, switch (rx_sop_type) { case TCPC_TX_SOP_PRIME: + modep_prime = &port->mode_data_prime; + pdev_prime = typec_match_altmode(port->plug_prime_altmode, + ALTMODE_DISCOVERY_MAX, + PD_VDO_VID(p[0]), + PD_VDO_OPOS(p[0])); if (!IS_ERR_OR_NULL(port->cable)) { svdm_version = typec_get_cable_svdm_version(typec); if (PD_VDO_SVDM_VER(p[0]) < svdm_version) @@ -1843,11 +1897,21 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, } break; case TCPC_TX_SOP: + modep = &port->mode_data; + pdev = typec_match_altmode(port->partner_altmode, + ALTMODE_DISCOVERY_MAX, + PD_VDO_VID(p[0]), + PD_VDO_OPOS(p[0])); svdm_version = typec_get_negotiated_svdm_version(typec); if (svdm_version < 0) return 0; break; default: + modep = &port->mode_data; + pdev = typec_match_altmode(port->partner_altmode, + ALTMODE_DISCOVERY_MAX, + PD_VDO_VID(p[0]), + PD_VDO_OPOS(p[0])); svdm_version = typec_get_negotiated_svdm_version(typec); if (svdm_version < 0) return 0; @@ -1939,6 +2003,9 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, * SOP' Discover Identity * SOP Discover SVIDs * Discover Modes + * (Active Cables) + * SOP' Discover SVIDs + * Discover Modes * * Perform Discover SOP' if the port can communicate with cable * plug. @@ -2018,26 +2085,62 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, } break; case CMD_DISCOVER_SVID: + *response_tx_sop_type = rx_sop_type; /* 6.4.4.3.2 */ - if (svdm_consume_svids(port, p, cnt)) { + if (svdm_consume_svids(port, p, cnt, rx_sop_type)) { response[0] = VDO(USB_SID_PD, 1, svdm_version, CMD_DISCOVER_SVID); rlen = 1; - } else if (modep->nsvids && supports_modal(port)) { - response[0] = VDO(modep->svids[0], 1, svdm_version, - CMD_DISCOVER_MODES); - rlen = 1; + } else { + if (rx_sop_type == TCPC_TX_SOP) { + if (modep->nsvids && supports_modal(port)) { + response[0] = VDO(modep->svids[0], 1, svdm_version, + CMD_DISCOVER_MODES); + rlen = 1; + } + } else if (rx_sop_type == TCPC_TX_SOP_PRIME) { + if (modep_prime->nsvids) { + response[0] = VDO(modep_prime->svids[0], 1, + svdm_version, CMD_DISCOVER_MODES); + rlen = 1; + } + } } break; case CMD_DISCOVER_MODES: - /* 6.4.4.3.3 */ - svdm_consume_modes(port, p, cnt); - modep->svid_index++; - if (modep->svid_index < modep->nsvids) { - u16 svid = modep->svids[modep->svid_index]; - response[0] = VDO(svid, 1, svdm_version, CMD_DISCOVER_MODES); - rlen = 1; - } else { - tcpm_register_partner_altmodes(port); + if (rx_sop_type == TCPC_TX_SOP) { + /* 6.4.4.3.3 */ + svdm_consume_modes(port, p, cnt, rx_sop_type); + modep->svid_index++; + if (modep->svid_index < modep->nsvids) { + u16 svid = modep->svids[modep->svid_index]; + *response_tx_sop_type = TCPC_TX_SOP; + response[0] = VDO(svid, 1, svdm_version, + CMD_DISCOVER_MODES); + rlen = 1; + } else if (tcpm_cable_vdm_supported(port)) { + *response_tx_sop_type = TCPC_TX_SOP_PRIME; + response[0] = VDO(USB_SID_PD, 1, + typec_get_cable_svdm_version(typec), + CMD_DISCOVER_SVID); + rlen = 1; + } else { + tcpm_register_partner_altmodes(port); + } + } else if (rx_sop_type == TCPC_TX_SOP_PRIME) { + /* 6.4.4.3.3 */ + svdm_consume_modes(port, p, cnt, rx_sop_type); + modep_prime->svid_index++; + if (modep_prime->svid_index < modep_prime->nsvids) { + u16 svid = modep_prime->svids[modep_prime->svid_index]; + *response_tx_sop_type = TCPC_TX_SOP_PRIME; + response[0] = VDO(svid, 1, + typec_get_cable_svdm_version(typec), + CMD_DISCOVER_MODES); + rlen = 1; + } else { + tcpm_register_plug_altmodes(port); + tcpm_register_partner_altmodes(port); + } } break; case CMD_ENTER_MODE: @@ -2418,6 +2521,16 @@ static void vdm_run_state_machine(struct tcpm_port *port) tcpm_queue_vdm(port, response[0], &response[1], 0, TCPC_TX_SOP); break; + /* + * If Discover SVIDs or Discover Modes fail, then + * proceed with Alt Mode discovery process on SOP. + */ + case CMD_DISCOVER_SVID: + tcpm_register_partner_altmodes(port); + break; + case CMD_DISCOVER_MODES: + tcpm_register_partner_altmodes(port); + break; default: break; } @@ -4124,14 +4237,20 @@ static void tcpm_typec_disconnect(struct tcpm_port *port) static void tcpm_unregister_altmodes(struct tcpm_port *port) { struct pd_mode_data *modep = &port->mode_data; + struct pd_mode_data *modep_prime = &port->mode_data_prime; int i; for (i = 0; i < modep->altmodes; i++) { typec_unregister_altmode(port->partner_altmode[i]); port->partner_altmode[i] = NULL; } + for (i = 0; i < modep_prime->altmodes; i++) { + typec_unregister_altmode(port->plug_prime_altmode[i]); + port->plug_prime_altmode[i] = NULL; + } memset(modep, 0, sizeof(*modep)); + memset(modep_prime, 0, sizeof(*modep_prime)); } static void tcpm_set_partner_usb_comm_capable(struct tcpm_port *port, bool capable) From patchwork Mon Jan 8 19:16:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186122 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1227147dyq; Mon, 8 Jan 2024 11:20:22 -0800 (PST) X-Google-Smtp-Source: AGHT+IGxmO6Ml0INoTVWVcbpbLnAwt7PPYwHJM6MjdKs5eY/qk4Zk8MjgdQmqWxi7fPGN+i3hZiB X-Received: by 2002:a50:cd43:0:b0:557:9c89:7f12 with SMTP id d3-20020a50cd43000000b005579c897f12mr1535960edj.45.1704741622493; Mon, 08 Jan 2024 11:20:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741622; cv=none; d=google.com; s=arc-20160816; b=I0QnxGDPfD4h298XbYeOZjXhhPaNAt+UCO3LQ5nVq+3owBK2YMvj/cTu8nUNipZhLo TZR6f669DogjVu0D2JN4C+dBInPneBJxi+Ia2UeLfedxLeurdECrUd9LgoqloiQkqQQW 6hO5U0imYDwVOcBBWl2XUCsO7QJig3+qIFXkmMIHFcBjktAbZ3HYvm4BlHyAah8d3vNp t8I9LYMT24TZ+tXXmMexnzQClsoScIk0aSddu+p5MXHruKK/GfMY6WUbAeUl9vdioBfU T58VYkPtGqcF8ahdkySpxpcQASEE2IqcghYn0Tq+AB3RJtFKr1dSE2uW0w7IYNdT7/4C rDeA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=SrTURjyagiHJyBtcVShn21olo2si3J8rHveL7Fpwpm8=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=mZwXDQRAoTgFr/S0pMEN2k4RRwxJyuewFTuC8j/aopLLWdQn3mojOuOhIEvoXJNy8w DZkTaYl+auHKnhNr58dEG1YoVLty4mYCQEvMgm1BxIWdekUmEMMXoV+iu+FYG9d2maEW EXS6yJUwFbIrw8Hs/GpUct6p7jl/wVm0yCMnUu0RQrFrwC8aZhPoqVISTuIeZHDWgjx7 7os40bs0TFd1nLg7wtj27zIL/oOEivhYPPgFc2X5nILkkUNPQLewCXUj3bhAj5Ay6STI gPu/GoFS0NFNqYYW3NUjEDJAqTNoU/lkIzg/ZbrBvTyaEuKKU0gx2AiIaSpZncAzhfev ZOVw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=O9X2Vt0J; spf=pass (google.com: domain of linux-kernel+bounces-20028-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20028-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id da20-20020a056402177400b00554e7f46b09si119581edb.520.2024.01.08.11.20.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:20:22 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20028-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=O9X2Vt0J; spf=pass (google.com: domain of linux-kernel+bounces-20028-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20028-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id E3DE01F23DD8 for ; Mon, 8 Jan 2024 19:20:21 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A7BF357336; Mon, 8 Jan 2024 19:16:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="O9X2Vt0J" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7FA4456B73 for ; Mon, 8 Jan 2024 19:16:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-5f69158f32eso25689377b3.2 for ; Mon, 08 Jan 2024 11:16:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741409; x=1705346209; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=SrTURjyagiHJyBtcVShn21olo2si3J8rHveL7Fpwpm8=; b=O9X2Vt0JDanbJO9KxEqkTNqe3nnoTUwreYqjRxkQvYJCbLzQMa/G/F4uqLA5WF2vlz vWyB4G5/BHSXtZQceuvSY+7LOqRDcTf0JbjuRv5wHvDXNxehsE2N5iOsvmmnYivKj1G2 GSG2woo20boRRp/iD12mEfkb9DF7WN5pEhtZv3zWYtHFCXJKoNt1mDrUi8Y24ue+i6Yp 9ocEz06z+js2FNBha6lVeTkLJ/kEfC3ELKvPWh7jdVVgeiFkM2U4gm7ayv+XQ8ODjFr4 Il4RkwprMMweJboRnNISMcrwO68MSkJ2yQfCeveHRoD7bCtlffj51luLj40+OLGmloFY 7Fdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741409; x=1705346209; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=SrTURjyagiHJyBtcVShn21olo2si3J8rHveL7Fpwpm8=; b=mfeXfATqGymx25RM2yKwTkrzfPc2NqgBV4JXZzXwVbq1nL/uSpvxmfeMfZZUy4N+YV f74Wr1SSl9YST7gKu1pE1RTRqLxmX5b9OEGO1rwgYCK2DXWp08BGT+3QDNKHiVQ6ACD8 PSeiUltUUo2D4xerLRrBBsOV4Z33PoGwv0zQyr8T7W9iFjRV2Tc9kZAaZmuMiOPRW43R 1xic3SzqllKg5SIYJ4DKUksWCWYVYjLeC6ietoWNgCzkdcKR6GpKU0gljt87noDJ42dR z4zx8tQyPGxq9GtkGiOT0l8V7G4AVzJUL81aGTEnBNUUlvAUA1+jXslfFCk75OyYc4lf 82pw== X-Gm-Message-State: AOJu0YzQSK1X471ELz7MWZVbMxyyrsLgThpp78hS9CZNDsl6Mh7F8UOe kc2ZM/9Phq72+sjlfNnUFWx7I1FmGrOFGwT+kaIhVQ== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a05:690c:316:b0:5e6:96cc:9f17 with SMTP id bg22-20020a05690c031600b005e696cc9f17mr1985952ywb.7.1704741409658; Mon, 08 Jan 2024 11:16:49 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:24 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=7080; i=rdbabiera@google.com; h=from:subject; bh=zfLOD65UxztyY2+yQMPbZDKDeJGzKZyWqg0N75vilbE=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvDhfR7Ewzl01J91JJaJPku1a8cctd1ZMeLG6Kn3zx 7Uym7PfdZSyMIhxMMiKKbLo+ucZ3LiSumUOZ40xzBxWJpAhDFycAjCRo8sY/kc0Ta0KFN1y84JP +ZNT+v/EL9cFRInaC5kHMj5z+BU2s5ORYWbmucNanrbvDZfkuV5nSpib5PP1belBmW8Jy08dPnC 0kQMA X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-25-rdbabiera@google.com> Subject: [PATCH v3 11/12] usb: typec: tcpm: add alt mode enter/exit/vdm support for sop' From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787551151657031351 X-GMAIL-MSGID: 1787551151657031351 Add tcpm_cable_ops for enter, exit, and vdm to the tcpm, which are registered after registering port alt modes through typec_port_register_cable_ops. Enter Mode on SOP' now sends Exit Mode upon failure to report to the driver. tcpm_queue_vdm_unlocked now takes sop type as input. Proper adev_actions in tcpm_pd_svdm are selected for SOP' messages. Signed-off-by: RD Babiera Reviewed-by: Heikki Krogerus --- drivers/usb/typec/tcpm/tcpm.c | 126 ++++++++++++++++++++++++++++------ 1 file changed, 106 insertions(+), 20 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index d16edf112858..86d9962961c2 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -1556,7 +1556,7 @@ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header, } static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header, - const u32 *data, int cnt) + const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type) { mutex_lock(&port->lock); tcpm_queue_vdm(port, header, data, cnt, TCPC_TX_SOP); @@ -2144,14 +2144,28 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, } break; case CMD_ENTER_MODE: - if (adev && pdev) - *adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL; + *response_tx_sop_type = rx_sop_type; + if (rx_sop_type == TCPC_TX_SOP) { + if (adev && pdev) { + typec_altmode_update_active(pdev, true); + *adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL; + } + } else if (rx_sop_type == TCPC_TX_SOP_PRIME) { + if (adev && pdev_prime) { + typec_altmode_update_active(pdev_prime, true); + *adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL; + } + } return 0; case CMD_EXIT_MODE: - if (adev && pdev) { - /* Back to USB Operation */ - *adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM; - return 0; + *response_tx_sop_type = rx_sop_type; + if (rx_sop_type == TCPC_TX_SOP) { + if (adev && pdev) { + typec_altmode_update_active(pdev, false); + /* Back to USB Operation */ + *adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM; + return 0; + } } break; case VDO_CMD_VENDOR(0) ... VDO_CMD_VENDOR(15): @@ -2284,19 +2298,37 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port, typec_altmode_vdm(adev, p[0], &p[1], cnt); break; case ADEV_QUEUE_VDM: - typec_altmode_vdm(adev, p[0], &p[1], cnt); + if (response_tx_sop_type == TCPC_TX_SOP_PRIME) + typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, p[0], &p[1], cnt); + else + typec_altmode_vdm(adev, p[0], &p[1], cnt); break; case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL: - if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) { - int svdm_version = typec_get_negotiated_svdm_version( - port->typec_port); - if (svdm_version < 0) - break; + if (response_tx_sop_type == TCPC_TX_SOP_PRIME) { + if (typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, + p[0], &p[1], cnt)) { + int svdm_version = typec_get_cable_svdm_version( + port->typec_port); + if (svdm_version < 0) + break; - response[0] = VDO(adev->svid, 1, svdm_version, - CMD_EXIT_MODE); - response[0] |= VDO_OPOS(adev->mode); - rlen = 1; + response[0] = VDO(adev->svid, 1, svdm_version, + CMD_EXIT_MODE); + response[0] |= VDO_OPOS(adev->mode); + rlen = 1; + } + } else { + if (typec_altmode_vdm(adev, p[0], &p[1], cnt)) { + int svdm_version = typec_get_negotiated_svdm_version( + port->typec_port); + if (svdm_version < 0) + break; + + response[0] = VDO(adev->svid, 1, svdm_version, + CMD_EXIT_MODE); + response[0] |= VDO_OPOS(adev->mode); + rlen = 1; + } } break; case ADEV_ATTENTION: @@ -2731,7 +2763,7 @@ static int tcpm_altmode_enter(struct typec_altmode *altmode, u32 *vdo) header = VDO(altmode->svid, vdo ? 2 : 1, svdm_version, CMD_ENTER_MODE); header |= VDO_OPOS(altmode->mode); - tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0); + tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0, TCPC_TX_SOP); return 0; } @@ -2748,7 +2780,7 @@ static int tcpm_altmode_exit(struct typec_altmode *altmode) header = VDO(altmode->svid, 1, svdm_version, CMD_EXIT_MODE); header |= VDO_OPOS(altmode->mode); - tcpm_queue_vdm_unlocked(port, header, NULL, 0); + tcpm_queue_vdm_unlocked(port, header, NULL, 0, TCPC_TX_SOP); return 0; } @@ -2757,7 +2789,7 @@ static int tcpm_altmode_vdm(struct typec_altmode *altmode, { struct tcpm_port *port = typec_altmode_get_drvdata(altmode); - tcpm_queue_vdm_unlocked(port, header, data, count - 1); + tcpm_queue_vdm_unlocked(port, header, data, count - 1, TCPC_TX_SOP); return 0; } @@ -2768,6 +2800,58 @@ static const struct typec_altmode_ops tcpm_altmode_ops = { .vdm = tcpm_altmode_vdm, }; + +static int tcpm_cable_altmode_enter(struct typec_altmode *altmode, enum typec_plug_index sop, + u32 *vdo) +{ + struct tcpm_port *port = typec_altmode_get_drvdata(altmode); + int svdm_version; + u32 header; + + svdm_version = typec_get_cable_svdm_version(port->typec_port); + if (svdm_version < 0) + return svdm_version; + + header = VDO(altmode->svid, vdo ? 2 : 1, svdm_version, CMD_ENTER_MODE); + header |= VDO_OPOS(altmode->mode); + + tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0, TCPC_TX_SOP_PRIME); + return 0; +} + +static int tcpm_cable_altmode_exit(struct typec_altmode *altmode, enum typec_plug_index sop) +{ + struct tcpm_port *port = typec_altmode_get_drvdata(altmode); + int svdm_version; + u32 header; + + svdm_version = typec_get_cable_svdm_version(port->typec_port); + if (svdm_version < 0) + return svdm_version; + + header = VDO(altmode->svid, 1, svdm_version, CMD_EXIT_MODE); + header |= VDO_OPOS(altmode->mode); + + tcpm_queue_vdm_unlocked(port, header, NULL, 0, TCPC_TX_SOP_PRIME); + return 0; +} + +static int tcpm_cable_altmode_vdm(struct typec_altmode *altmode, enum typec_plug_index sop, + u32 header, const u32 *data, int count) +{ + struct tcpm_port *port = typec_altmode_get_drvdata(altmode); + + tcpm_queue_vdm_unlocked(port, header, data, count - 1, TCPC_TX_SOP_PRIME); + + return 0; +} + +static const struct typec_cable_ops tcpm_cable_ops = { + .enter = tcpm_cable_altmode_enter, + .exit = tcpm_cable_altmode_exit, + .vdm = tcpm_cable_altmode_vdm, +}; + /* * PD (data, control) command handling functions */ @@ -7507,6 +7591,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) typec_port_register_altmodes(port->typec_port, &tcpm_altmode_ops, port, port->port_altmode, ALTMODE_DISCOVERY_MAX); + typec_port_register_cable_ops(port->port_altmode, ARRAY_SIZE(port->port_altmode), + &tcpm_cable_ops); port->registered = true; mutex_lock(&port->lock); From patchwork Mon Jan 8 19:16:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: RD Babiera X-Patchwork-Id: 186123 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:37c1:b0:101:2151:f287 with SMTP id y1csp1227249dyq; Mon, 8 Jan 2024 11:20:33 -0800 (PST) X-Google-Smtp-Source: AGHT+IE3ivAngBgsGs0Ajn3l6egDGJWdxhJLNkn2lOLOyqZIaYVEfyHvedl+s11n6AHKiRp/Z4g9 X-Received: by 2002:a05:6a00:2ea8:b0:6da:dbd9:173b with SMTP id fd40-20020a056a002ea800b006dadbd9173bmr1944332pfb.49.1704741633701; Mon, 08 Jan 2024 11:20:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704741633; cv=none; d=google.com; s=arc-20160816; b=Qy4IYUMyIQjV8FnL4ga2THsC4K2qXHxEnLWhskSRDB17ntAo+3htluZkuuF4E4Aodu Z11thdGTjSMsdNz4iRqo0Fu0DZObsJ/8rPPmYIAjdcZwfai5Ulqs3Ko6kU1tnrA+Mydf DPM2Ir5kNn46e/rYCvXb2djR8/7Z5NJ7lWHrkmDQG2iJFhIb176+0piFHD7fou74i0vM ZFwZ8eAdK8g2PG5gyHg+12qGiT0fPtl+6gkZubiaaWYWL8fqENqWO2wxSm8gpUaTD1Gk HEZwDDySQ3h62RXICTxE/EuZrWoAPk2FoxsJvzN8pcYrtLB2LpYq1hUZMyO/s754uyzh GCxQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=zjkQj+MB9N/iWKqrCDCwCmeR31ulEw3qfBbLXTmMgvo=; fh=bY9M7RuwC9RhXS0a4JlzGLNcLBIsjKYIZiZHjIHDIhs=; b=uGZNfDGvDq67YbMO2GodIYN80HlAUEy0D1HELjJ9vLZQEHNgobrbs43f2287WUf1HQ Ps0Qwd18098U6IoMT+dhMsF5CobCwMMXDQRvQ2J3CgPhuXqWud23Bkgj2PSwH7P6zRbc 8+RNtZv/XDB1iQCydU7vv2zrYdpwDajliH3FUmNoy0onuYBOY867qLSQhaPbHOxNxVS6 NnkKK9IEq7PwUOS4OISGtKuVbS2DNCZiYsgxNI3bmqgzkd03UzttbTZoZM1lV10a8N4O eBiofW7XWlnc0Hsw0T09xbYNv9m04qUvmWKw5s2oo8Aag7j7OYpqeT8WEUMxKIoE5lPD qEMg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=jA+vB+J3; spf=pass (google.com: domain of linux-kernel+bounces-20029-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20029-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id y19-20020a056a00181300b006db09adea84si92480pfa.334.2024.01.08.11.20.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Jan 2024 11:20:33 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-20029-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=jA+vB+J3; spf=pass (google.com: domain of linux-kernel+bounces-20029-ouuuleilei=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-20029-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 74684282AB0 for ; Mon, 8 Jan 2024 19:20:33 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9AA9157876; Mon, 8 Jan 2024 19:16:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="jA+vB+J3" X-Original-To: linux-kernel@vger.kernel.org Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61C2E5730D for ; Mon, 8 Jan 2024 19:16:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--rdbabiera.bounces.google.com Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-5f6f51cd7e8so24413187b3.1 for ; Mon, 08 Jan 2024 11:16:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1704741411; x=1705346211; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=zjkQj+MB9N/iWKqrCDCwCmeR31ulEw3qfBbLXTmMgvo=; b=jA+vB+J3pthdeOhLskJcZYdXqXg0LYL/3ziaWdGjletiNNrFfYUm+HBZUo0ewqCFxx hZTNo1mwKm5jE6GoEv19S+jx1lpC7PVdW3cBZVWpVw/uD0ob5zG38uiwSMji7v3yPTRE MO6oXhO6i8zNDC/IPhpYDDp6Q4bFcinZYO6xoPxj3OyyrU+pVLJ9dH8ONjyaEvlp8Uir 6RpRMA2BcmbhkbB+QdGWM0K0ZDFZEAS6X6geIezRTctgwwIP+62gGQB1GE946nRzr7MM RG3oijG6Mmhr4DqGNGTPiTqwi+x7A3AVU6tVQVN04EUw/JmXhMPXkWhntcleE/KDjhqP GWXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704741411; x=1705346211; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=zjkQj+MB9N/iWKqrCDCwCmeR31ulEw3qfBbLXTmMgvo=; b=X8inm6BGSugSc0cgZ+0UglCaubuoEDaM4YpsGIZx+Mk5vOfjpl31VMRMMjroE3ighD LqnrEyeCHqEtNsRX1Lr6kVDwK8PfNKIttQXZZp53ZaQwVnM9h6fDG03PWOlNXDMTRGSm p13OVTgW5kO7ZdzbsljI6VnC34bNr3zKX82MYwr7uoldlay0UheOlQ39QlFOGagSqg59 fiWB8Uc9ULz5wjDcakz6ZwdDy65rLtVFyNsMs0fLpBQbHVk4XiFrDxwBTkZfnHQTbMeL 5EPPgY7tFS6FkrSwcRNpyvYkLyOJw7ONCpg9TCn07HWQcEXgEvsD6Z/rScfbt8pibO+h ubnQ== X-Gm-Message-State: AOJu0YzaKbbD587rG4FxP4MRYV8YVAQ3uS8McY+FhWwrICXbhvVnc6Av fqhf9cK6bpaH3mskWjTojBYXfTM4nj5/gX00IN88iQ== X-Received: from rdbabiera.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:18a8]) (user=rdbabiera job=sendgmr) by 2002:a81:a152:0:b0:5d7:a8b2:327 with SMTP id y79-20020a81a152000000b005d7a8b20327mr1834226ywg.7.1704741411416; Mon, 08 Jan 2024 11:16:51 -0800 (PST) Date: Mon, 8 Jan 2024 19:16:25 +0000 In-Reply-To: <20240108191620.987785-14-rdbabiera@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240108191620.987785-14-rdbabiera@google.com> X-Developer-Key: i=rdbabiera@google.com; a=openpgp; fpr=639A331F1A21D691815CE090416E17CA2BBBD5C8 X-Developer-Signature: v=1; a=openpgp-sha256; l=11341; i=rdbabiera@google.com; h=from:subject; bh=keVyptJJ/XKRYKKQy02EssnXTdbBLo8kv3aViPSqejc=; b=owGbwMvMwCFW0bfok0KS4TbG02pJDKlzvDgn7z+3wvGc+96lHsw6/tIxxen2Mxcq7CqfMenw4 xx1K/krHaUsDGIcDLJiiiy6/nkGN66kbpnDWWMMM4eVCWQIAxenAEzk011GhicOr66X+++9fU1k xmkbo3b/1BnuJbdbP+//GrlrQtj+CzMYGaYzNH0MeXJx1832lLMsfUetZX6ec3GYudY47d7eDvX TvAwA X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Message-ID: <20240108191620.987785-26-rdbabiera@google.com> Subject: [PATCH v3 12/12] usb: typec: altmodes/displayport: add SOP' support From: RD Babiera To: rdbabiera@google.com, heikki.krogerus@linux.intel.com, linux@roeck-us.net, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Cc: badhri@google.com, bryan.odonoghue@linaro.org, agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1787551163546661488 X-GMAIL-MSGID: 1787551163546661488 Implement active cable VDM support for SOP' according to the DisplayPort Alt Mode 2.0 specification. When probing the DisplayPort driver, the state machine will transition to Enter Mode on SOP' if an active cable altmode is detected. The SVDM flow is as followed: (1) Enter Mode SOP' (2) Enter Mode SOP (3) Status Update SOP (4) Configure SOP' (5) Configure SOP Status Update on SOP' after Enter Mode is optional and not implemented for now. When exiting the alt mode, send Exit Mode over SOP' after SOP. Should an altmode vdm fail on SOP', the DisplayPort driver will drop its reference to the plug and attempt to continue in SOP operation. Add new dp_state enums DP_STATE_ENTER_PRIME, DP_STATE_CONFIGURE_PRIME, and DP_STATE_EXIT_PRIME. dp_altmode adds typec_displayport_data for the cable plug to store the plug configuration and adds a typec_altmode reference for the cable plug. dp_altmode_configure takes the cable pin assignment capabilities into account when deciding on pin configuration. dp_altmode_configure_vdm_cable sends the configure message on SOP'. dp_altmode_activate now attempts to enter on SOP' if applicable, and will attempt to enter on SOP on failure. dp_cable_altmode_vdm handles VDMs passed to the DisplayPort driver from the tcpm. Signed-off-by: RD Babiera --- Changes since v1: * dp_altmode_configure_vdm no longer handles sop', now handled by dp_altmode_configure_vdm_cable * dp_exit_mode_handler deleted * dp_altmode_vdm no longer handles sop', now handled by dp_cable_altmode_vdm as typec_cable_ops callback assigned to plug_prime if it exists. * driver data registered to plug_prime if applicable. Changes since v2: * added mutex_unlock() call when disabling plug altmode in dp_altmode_work() --- drivers/usb/typec/altmodes/displayport.c | 162 ++++++++++++++++++++++- 1 file changed, 158 insertions(+), 4 deletions(-) diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index f81bec0c7b86..5a80776c7255 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -50,13 +50,17 @@ enum { enum dp_state { DP_STATE_IDLE, DP_STATE_ENTER, + DP_STATE_ENTER_PRIME, DP_STATE_UPDATE, DP_STATE_CONFIGURE, + DP_STATE_CONFIGURE_PRIME, DP_STATE_EXIT, + DP_STATE_EXIT_PRIME, }; struct dp_altmode { struct typec_displayport_data data; + struct typec_displayport_data data_prime; enum dp_state state; bool hpd; @@ -67,6 +71,7 @@ struct dp_altmode { struct typec_altmode *alt; const struct typec_altmode *port; struct fwnode_handle *connector_fwnode; + struct typec_altmode *plug_prime; }; static int dp_altmode_notify(struct dp_altmode *dp) @@ -99,12 +104,18 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con) conf |= DP_CONF_UFP_U_AS_DFP_D; pin_assign = DP_CAP_UFP_D_PIN_ASSIGN(dp->alt->vdo) & DP_CAP_DFP_D_PIN_ASSIGN(dp->port->vdo); + /* Account for active cable capabilities */ + if (dp->plug_prime) + pin_assign &= DP_CAP_DFP_D_PIN_ASSIGN(dp->plug_prime->vdo); break; case DP_STATUS_CON_UFP_D: case DP_STATUS_CON_BOTH: /* NOTE: First acting as DP source */ conf |= DP_CONF_UFP_U_AS_UFP_D; pin_assign = DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo) & DP_CAP_PIN_ASSIGN_DFP_D(dp->port->vdo); + /* Account for active cable capabilities */ + if (dp->plug_prime) + pin_assign &= DP_CAP_UFP_D_PIN_ASSIGN(dp->plug_prime->vdo); break; default: break; @@ -130,6 +141,8 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con) } dp->data.conf = conf; + if (dp->plug_prime) + dp->data_prime.conf = conf; return 0; } @@ -143,7 +156,9 @@ static int dp_altmode_status_update(struct dp_altmode *dp) if (configured && (dp->data.status & DP_STATUS_SWITCH_TO_USB)) { dp->data.conf = 0; - dp->state = DP_STATE_CONFIGURE; + dp->data_prime.conf = 0; + dp->state = dp->plug_prime ? DP_STATE_CONFIGURE_PRIME : + DP_STATE_CONFIGURE; } else if (dp->data.status & DP_STATUS_EXIT_DP_MODE) { dp->state = DP_STATE_EXIT; } else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) { @@ -209,6 +224,19 @@ static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf) return ret; } +static int dp_altmode_configure_vdm_cable(struct dp_altmode *dp, u32 conf) +{ + int svdm_version = typec_altmode_get_cable_svdm_version(dp->plug_prime); + u32 header; + + if (svdm_version < 0) + return svdm_version; + + header = DP_HEADER(dp, svdm_version, DP_CMD_CONFIGURE); + + return typec_cable_altmode_vdm(dp->plug_prime, TYPEC_PLUG_SOP_P, header, &conf, 2); +} + static void dp_altmode_work(struct work_struct *work) { struct dp_altmode *dp = container_of(work, struct dp_altmode, work); @@ -225,6 +253,19 @@ static void dp_altmode_work(struct work_struct *work) if (ret && ret != -EBUSY) dev_err(&dp->alt->dev, "failed to enter mode\n"); break; + case DP_STATE_ENTER_PRIME: + ret = typec_cable_altmode_enter(dp->alt, TYPEC_PLUG_SOP_P, NULL); + /* + * If we fail to enter Alt Mode on SOP', then we should drop the + * plug from the driver and attempt to run the driver without + * it. + */ + if (ret && ret != -EBUSY) { + dev_err(&dp->alt->dev, "plug failed to enter mode\n"); + dp->state = DP_STATE_ENTER; + goto disable_prime; + } + break; case DP_STATE_UPDATE: svdm_version = typec_altmode_get_svdm_version(dp->alt); if (svdm_version < 0) @@ -243,10 +284,24 @@ static void dp_altmode_work(struct work_struct *work) dev_err(&dp->alt->dev, "unable to send Configure command (%d)\n", ret); break; + case DP_STATE_CONFIGURE_PRIME: + ret = dp_altmode_configure_vdm_cable(dp, dp->data_prime.conf); + if (ret) { + dev_err(&dp->plug_prime->dev, + "unable to send Configure command (%d)\n", + ret); + dp->state = DP_STATE_CONFIGURE; + goto disable_prime; + } + break; case DP_STATE_EXIT: if (typec_altmode_exit(dp->alt)) dev_err(&dp->alt->dev, "Exit Mode Failed!\n"); break; + case DP_STATE_EXIT_PRIME: + if (typec_cable_altmode_exit(dp->plug_prime, TYPEC_PLUG_SOP_P)) + dev_err(&dp->plug_prime->dev, "Exit Mode Failed!\n"); + break; default: break; } @@ -254,6 +309,13 @@ static void dp_altmode_work(struct work_struct *work) dp->state = DP_STATE_IDLE; mutex_unlock(&dp->lock); + return; + +disable_prime: + typec_altmode_put_plug(dp->plug_prime); + dp->plug_prime = NULL; + schedule_work(&dp->work); + mutex_unlock(&dp->lock); } static void dp_altmode_attention(struct typec_altmode *alt, const u32 vdo) @@ -314,6 +376,8 @@ static int dp_altmode_vdm(struct typec_altmode *alt, dp->hpd = false; sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); } + if (dp->plug_prime) + dp->state = DP_STATE_EXIT_PRIME; break; case DP_CMD_STATUS_UPDATE: dp->data.status = *vdo; @@ -348,10 +412,84 @@ static int dp_altmode_vdm(struct typec_altmode *alt, return ret; } +static int dp_cable_altmode_vdm(struct typec_altmode *alt, enum typec_plug_index sop, + const u32 hdr, const u32 *vdo, int count) +{ + struct dp_altmode *dp = typec_altmode_get_drvdata(alt); + int cmd_type = PD_VDO_CMDT(hdr); + int cmd = PD_VDO_CMD(hdr); + int ret = 0; + + mutex_lock(&dp->lock); + + if (dp->state != DP_STATE_IDLE) { + ret = -EBUSY; + goto err_unlock; + } + + switch (cmd_type) { + case CMDT_RSP_ACK: + switch (cmd) { + case CMD_ENTER_MODE: + typec_altmode_update_active(dp->plug_prime, true); + dp->state = DP_STATE_ENTER; + break; + case CMD_EXIT_MODE: + dp->data_prime.status = 0; + dp->data_prime.conf = 0; + typec_altmode_update_active(dp->plug_prime, false); + break; + case DP_CMD_CONFIGURE: + dp->state = DP_STATE_CONFIGURE; + break; + default: + break; + } + break; + case CMDT_RSP_NAK: + switch (cmd) { + case DP_CMD_CONFIGURE: + dp->data_prime.conf = 0; + /* Attempt to configure on SOP, drop plug */ + typec_altmode_put_plug(dp->plug_prime); + dp->plug_prime = NULL; + dp->state = DP_STATE_CONFIGURE; + break; + default: + break; + } + break; + default: + break; + } + + if (dp->state != DP_STATE_IDLE) + schedule_work(&dp->work); + +err_unlock: + mutex_unlock(&dp->lock); + return ret; +} + static int dp_altmode_activate(struct typec_altmode *alt, int activate) { - return activate ? typec_altmode_enter(alt, NULL) : - typec_altmode_exit(alt); + struct dp_altmode *dp = typec_altmode_get_drvdata(alt); + int ret; + + if (activate) { + if (dp->plug_prime) { + ret = typec_cable_altmode_enter(alt, TYPEC_PLUG_SOP_P, NULL); + if (ret < 0) { + typec_altmode_put_plug(dp->plug_prime); + dp->plug_prime = NULL; + } else { + return ret; + } + } + return typec_altmode_enter(alt, NULL); + } else { + return typec_altmode_exit(alt); + } } static const struct typec_altmode_ops dp_altmode_ops = { @@ -360,6 +498,10 @@ static const struct typec_altmode_ops dp_altmode_ops = { .activate = dp_altmode_activate, }; +static const struct typec_cable_ops dp_cable_ops = { + .vdm = dp_cable_altmode_vdm, +}; + static const char * const configurations[] = { [DP_CONF_USB] = "USB", [DP_CONF_DFP_D] = "source", @@ -501,6 +643,7 @@ pin_assignment_store(struct device *dev, struct device_attribute *attr, /* Only send Configure command if a configuration has been set */ if (dp->alt->active && DP_CONF_CURRENTLY(dp->data.conf)) { + /* todo: send manual configure over SOP'*/ ret = dp_altmode_configure_vdm(dp, conf); if (ret) goto out_unlock; @@ -574,6 +717,7 @@ static const struct attribute_group dp_altmode_group = { int dp_altmode_probe(struct typec_altmode *alt) { const struct typec_altmode *port = typec_altmode_get_partner(alt); + struct typec_altmode *plug = typec_altmode_get_plug(alt, TYPEC_PLUG_SOP_P); struct fwnode_handle *fwnode; struct dp_altmode *dp; int ret; @@ -603,6 +747,13 @@ int dp_altmode_probe(struct typec_altmode *alt) alt->desc = "DisplayPort"; alt->ops = &dp_altmode_ops; + if (plug) { + plug->desc = "Displayport"; + plug->cable_ops = &dp_cable_ops; + } + + dp->plug_prime = plug; + fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */ if (fwnode_property_present(fwnode, "displayport")) dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0); @@ -612,8 +763,10 @@ int dp_altmode_probe(struct typec_altmode *alt) dp->connector_fwnode = NULL; typec_altmode_set_drvdata(alt, dp); + if (plug) + typec_altmode_set_drvdata(plug, dp); - dp->state = DP_STATE_ENTER; + dp->state = plug ? DP_STATE_ENTER_PRIME : DP_STATE_ENTER; schedule_work(&dp->work); return 0; @@ -626,6 +779,7 @@ void dp_altmode_remove(struct typec_altmode *alt) sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group); cancel_work_sync(&dp->work); + typec_altmode_put_plug(dp->plug_prime); if (dp->connector_fwnode) { drm_connector_oob_hotplug_event(dp->connector_fwnode,