From patchwork Fri Apr 22 22:23:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 565045 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 27F6CC4167B for ; Fri, 22 Apr 2022 22:55:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233711AbiDVW54 (ORCPT ); Fri, 22 Apr 2022 18:57:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51334 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234215AbiDVW5m (ORCPT ); Fri, 22 Apr 2022 18:57:42 -0400 Received: from mail-oa1-x35.google.com (mail-oa1-x35.google.com [IPv6:2001:4860:4864:20::35]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70BA4263CAB for ; Fri, 22 Apr 2022 15:21:53 -0700 (PDT) Received: by mail-oa1-x35.google.com with SMTP id 586e51a60fabf-e604f712ecso10045278fac.9 for ; Fri, 22 Apr 2022 15:21:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5WJANqKYC0uOwc9pHxoXMF3q63zMtKx1xf7OKCPf+Fc=; b=uthw0bR1T+hvsbqlpfq3kVyFnz9kfquznheJF2Eheau3SbrFUFBM7k946RQICA84iL +xpnkZGMw1h4UFs7xnhomn2V/SPwp8JDVJd0W8G6QjwWpDTomn60Qthg9pD41nGlmEbA q1irLx6H2YqzHFC1iZsDi7wc9GA+p1B9vYBJ7iAQ04qQdGWVvh+016mXSXPiQbrxOUo/ 74H6WCKYAs7uWiCAQrBON9ZjJxP/zpH7kljtCxymFwaVZhi3IN81Fx0hcijrD0akLZN1 rPM53YiQ7OsGxA/XkBFssJI+Ni33ftKFLAH+KoOGkYH5po//lrEASLlirdXtRDjqaZ1u G3cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5WJANqKYC0uOwc9pHxoXMF3q63zMtKx1xf7OKCPf+Fc=; b=NoCmOqxb6D/JWBfguP5hSWxa3TOlaSzKiZ+bZBwAS+62vNoH3CShDFXDUJwGLD3RFe nAMpgpIjqW1wxWGqELSdb2KZZinfNLLNwHkbk4z1cem8vcDf8DKbO7sJ147bPjQh+fYR gkXkbNvYxKrafaWsbAUDNLofZizAwWNNacJ1fIOesGlWsRG28l8IAE49il1dcZYM2aMh 0cDS++zAyXBcVwOURl2L3utSstapCFXtUwTps/u1F9wGSP8B71H6Us3Db1Fz+MHkoZss SsaecFIX8sLzcK10Oi3Ga/lKYzZsOn2DeX8kdyFIkH9dSegoOxgqe/EnwN65szaDOVO0 LsEw== X-Gm-Message-State: AOAM532PtniMM/28DN+Qs4zeWTbnSy8F/FgTVGcWhr1VHl1yTKds810O nr4muCUr/4aI9mi1GEvIkFKI4w== X-Google-Smtp-Source: ABdhPJwSUqlaOIAUy4BPNAE9huiM3YDyDvJ842NV6mi/ujWxNBcGD09OfXFrcIPMy0Dxb7jgYWU22A== X-Received: by 2002:a05:6870:e244:b0:e9:150b:5d21 with SMTP id d4-20020a056870e24400b000e9150b5d21mr318161oac.234.1650666112565; Fri, 22 Apr 2022 15:21:52 -0700 (PDT) Received: from ripper.. ([2600:1700:a0:3dc8:205:1bff:fec0:b9b3]) by smtp.gmail.com with ESMTPSA id js4-20020a056870bac400b000e687cdf5adsm1049224oab.55.2022.04.22.15.21.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Apr 2022 15:21:52 -0700 (PDT) From: Bjorn Andersson To: Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Andy Shevchenko , Daniel Scally , Heikki Krogerus , Sakari Ailus , "Rafael J. Wysocki" , Hans de Goede Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org Subject: [PATCH v5 2/7] device property: Use multi-connection matchers for single case Date: Fri, 22 Apr 2022 15:23:46 -0700 Message-Id: <20220422222351.1297276-3-bjorn.andersson@linaro.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220422222351.1297276-1-bjorn.andersson@linaro.org> References: <20220422222351.1297276-1-bjorn.andersson@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The newly introduced helpers for searching for matches in the case of multiple connections can be resused by the single-connection case, so do this to save some duplication. Reviewed-by: Andy Shevchenko Signed-off-by: Bjorn Andersson --- Changes since v4: - None drivers/base/property.c | 55 ++++------------------------------------- 1 file changed, 5 insertions(+), 50 deletions(-) diff --git a/drivers/base/property.c b/drivers/base/property.c index babab8cec7a0..337c95fea217 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -1176,31 +1176,6 @@ const void *device_get_match_data(struct device *dev) } EXPORT_SYMBOL_GPL(device_get_match_data); -static void * -fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id, - void *data, devcon_match_fn_t match) -{ - struct fwnode_handle *node; - struct fwnode_handle *ep; - void *ret; - - fwnode_graph_for_each_endpoint(fwnode, ep) { - node = fwnode_graph_get_remote_port_parent(ep); - if (!fwnode_device_is_available(node)) { - fwnode_handle_put(node); - continue; - } - - ret = match(node, con_id, data); - fwnode_handle_put(node); - if (ret) { - fwnode_handle_put(ep); - return ret; - } - } - return NULL; -} - static unsigned int fwnode_graph_devcon_matches(struct fwnode_handle *fwnode, const char *con_id, void *data, devcon_match_fn_t match, @@ -1235,28 +1210,6 @@ static unsigned int fwnode_graph_devcon_matches(struct fwnode_handle *fwnode, return count; } -static void * -fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id, - void *data, devcon_match_fn_t match) -{ - struct fwnode_handle *node; - void *ret; - int i; - - for (i = 0; ; i++) { - node = fwnode_find_reference(fwnode, con_id, i); - if (IS_ERR(node)) - break; - - ret = match(node, NULL, data); - fwnode_handle_put(node); - if (ret) - return ret; - } - - return NULL; -} - static unsigned int fwnode_devcon_matches(struct fwnode_handle *fwnode, const char *con_id, void *data, devcon_match_fn_t match, @@ -1303,16 +1256,18 @@ void *fwnode_connection_find_match(struct fwnode_handle *fwnode, const char *con_id, void *data, devcon_match_fn_t match) { + unsigned int count; void *ret; if (!fwnode || !match) return NULL; - ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); - if (ret) + count = fwnode_graph_devcon_matches(fwnode, con_id, data, match, &ret, 1); + if (count) return ret; - return fwnode_devcon_match(fwnode, con_id, data, match); + count = fwnode_devcon_matches(fwnode, con_id, data, match, &ret, 1); + return count ? ret : NULL; } EXPORT_SYMBOL_GPL(fwnode_connection_find_match); From patchwork Fri Apr 22 22:23:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 565044 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D2604C433F5 for ; Fri, 22 Apr 2022 22:55:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233936AbiDVW55 (ORCPT ); Fri, 22 Apr 2022 18:57:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51298 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234218AbiDVW5m (ORCPT ); Fri, 22 Apr 2022 18:57:42 -0400 Received: from mail-oi1-x232.google.com (mail-oi1-x232.google.com [IPv6:2607:f8b0:4864:20::232]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7907335DCDB for ; Fri, 22 Apr 2022 15:21:54 -0700 (PDT) Received: by mail-oi1-x232.google.com with SMTP id z2so10576556oic.6 for ; Fri, 22 Apr 2022 15:21:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AvSAQb1M8ai7iREtClhTlQbpfuCOvIwvoizOPDtnCrk=; b=Pc1e+PMZm5IuYicnb0WwTJ3NxS7TWcDp5tMa6jMLdMKAY3An0CjGAK0elizA3QrGdx qzxqjjVPtpGIT6IPsJIq1xPrBEMGIwCLBxMej9K4Y+EHPh8ksv960DhiDp443oAUcbFZ Jhsny1PFJ8tHy9iAkzQntJe638zmBWWED/CGHiAsKTL/om+PCaUq7KuJMxwxuIDtdN+z b24DjqO1UN/wg00srUSnjInLBJasjhNV6itXuEF4Xm2wa8jd5dq6Aeb5ibdQYQLy6MJu UaPkjfulA0/O5DsIxHPt15xV9ek4CamZlac5+XwtbU0OWOkFk0ROC2t/7ED58vXNdNM2 saOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AvSAQb1M8ai7iREtClhTlQbpfuCOvIwvoizOPDtnCrk=; b=lIzPamwbELSrk34vrrPPb8N2zfHNYexllS3t0rWuxBQlfxZ9lMF3IBN2xyLP8yL/vF vndzr+6Ex0ZNjX6h3UG87Z6zGkZBKQSL4xdhnksGBttgAcwNlVcD3qP4LmFxysHKAn9G Y8+sVcaLlhnXd0KrmZlM+X/w9UVGDxcGPODiSECGr0muigw/Tsw8grAsATADkWVQTooL eR0JmJBz2z0uFpeJnKcBbcGv1YlHFcNkRs4ejyhCfj09aS2NNQrP49JkE6lFT3jHLzez lYtZXYwQN1vtHJQLBv79BpLX2IUPstkSYcaOLbDmA1z9AW8kmZD8IQ3FtXiTHGQGBZg8 QqqQ== X-Gm-Message-State: AOAM533KALWLI7IyphLTHx8u2rBCaHA6Y0mLou+RceRQsTWa7ABy7IBo ffswj+WjqbKu9e85TQB8o12uUw== X-Google-Smtp-Source: ABdhPJxPQFhhi1f//zKscwPmmuTNsN+HkKo9ZZPLpV1bgBPsKMaslivRlGVFdAXX/APr6Tx55vb/oQ== X-Received: by 2002:a05:6808:3b8:b0:322:a783:8fc8 with SMTP id n24-20020a05680803b800b00322a7838fc8mr7584151oie.189.1650666113629; Fri, 22 Apr 2022 15:21:53 -0700 (PDT) Received: from ripper.. ([2600:1700:a0:3dc8:205:1bff:fec0:b9b3]) by smtp.gmail.com with ESMTPSA id js4-20020a056870bac400b000e687cdf5adsm1049224oab.55.2022.04.22.15.21.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Apr 2022 15:21:53 -0700 (PDT) From: Bjorn Andersson To: Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Andy Shevchenko , Daniel Scally , Heikki Krogerus , Sakari Ailus , "Rafael J. Wysocki" , Hans de Goede Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org Subject: [PATCH v5 3/7] usb: typec: mux: Check dev_set_name() return value Date: Fri, 22 Apr 2022 15:23:47 -0700 Message-Id: <20220422222351.1297276-4-bjorn.andersson@linaro.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220422222351.1297276-1-bjorn.andersson@linaro.org> References: <20220422222351.1297276-1-bjorn.andersson@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org It's possible that dev_set_name() returns -ENOMEM, catch and handle this. Fixes: 3370db35193b ("usb: typec: Registering real device entries for the muxes") Reported-by: Andy Shevchenko Acked-by: Heikki Krogerus Signed-off-by: Bjorn Andersson Reviewed-by: Andy Shevchenko --- Changes since v4: - Added Fixes tag drivers/usb/typec/mux.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index c8340de0ed49..d2aaf294b649 100644 --- a/drivers/usb/typec/mux.c +++ b/drivers/usb/typec/mux.c @@ -131,8 +131,11 @@ typec_switch_register(struct device *parent, sw->dev.class = &typec_mux_class; sw->dev.type = &typec_switch_dev_type; sw->dev.driver_data = desc->drvdata; - dev_set_name(&sw->dev, "%s-switch", - desc->name ? desc->name : dev_name(parent)); + ret = dev_set_name(&sw->dev, "%s-switch", desc->name ? desc->name : dev_name(parent)); + if (ret) { + put_device(&sw->dev); + return ERR_PTR(ret); + } ret = device_add(&sw->dev); if (ret) { @@ -338,8 +341,11 @@ typec_mux_register(struct device *parent, const struct typec_mux_desc *desc) mux->dev.class = &typec_mux_class; mux->dev.type = &typec_mux_dev_type; mux->dev.driver_data = desc->drvdata; - dev_set_name(&mux->dev, "%s-mux", - desc->name ? desc->name : dev_name(parent)); + ret = dev_set_name(&mux->dev, "%s-mux", desc->name ? desc->name : dev_name(parent)); + if (ret) { + put_device(&mux->dev); + return ERR_PTR(ret); + } ret = device_add(&mux->dev); if (ret) { From patchwork Fri Apr 22 22:23:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 565046 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 46791C433EF for ; Fri, 22 Apr 2022 22:54:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233613AbiDVW5E (ORCPT ); Fri, 22 Apr 2022 18:57:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51298 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233793AbiDVW46 (ORCPT ); Fri, 22 Apr 2022 18:56:58 -0400 Received: from mail-oa1-x29.google.com (mail-oa1-x29.google.com [IPv6:2001:4860:4864:20::29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0C16C375E4F for ; Fri, 22 Apr 2022 15:21:56 -0700 (PDT) Received: by mail-oa1-x29.google.com with SMTP id 586e51a60fabf-e2afb80550so10087495fac.1 for ; Fri, 22 Apr 2022 15:21:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MZN6Zt3nDrquMGvxHt/QElrh6H38NKlikXj3lsOy1lI=; b=dSoGWyLvstbL4O3lghCrhJfbLZQ9PPNdEpiAqQBZaeCuTDnM3EHyVR4hCZlbt6YUG0 7COIeBGGRULeoKoqIdyJdVyoQ2dNh0KYpCJgcxfQ+Hgoh9r5dKnHY9t+8aKkXTRKjqhg WHzuwIDLzMZ0WFe/lfX5M/v/eaq9SVAAOLUFcESQmQX/QqJ/s+m/iKuOObFmbhTgbACE Hb8r52nPhXwgwhp06wfhayF5zq4pssB0xgvgPwe1YCtqIzT+pJb9b/Nj91Jjk3DImzVR PYyWwTf5fze35nZ0hO0B88nNWNnC867JHDGKpHdSDPRsYhYt6Cad0VK7Pcg9l15IA39x LdtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MZN6Zt3nDrquMGvxHt/QElrh6H38NKlikXj3lsOy1lI=; b=uKNm03aHEpkdFxRXFbEHHbXwYilZnn2D/dowJ8ydCZTiqXig7aZbGH8LRfpfqYcap7 klN0GAU9nlZ/n8bj8sZ6KT59dhOa28KALo2EEyx3ZYzQEZvsZC/c54gAQkWyOvz6jeRz IB1b4m1NZCmvb6SbiE047b1fK9kzoZhGNe5MFF4JVkYLWjO+6/Ib27gWCdqwqLpuyxHU 2zbTAvSYGe4pXtTyYH/gTzgkAyRlDQTz1B+Mi8krMiuc7EgGJQZy8mtKCt3kwE5n4vAn Vd6lkJQnFUPFepmtuc9wrOBZpo+6HM6hFwCuBQ5kUz6Cy2G5km5G3Sf78VHVUuvb4umF gYCQ== X-Gm-Message-State: AOAM532EwhUAPT5yShd1u5rooaZG8C+txoHB5oDok7WpoHkjP96k1JYK KNk19OC0XDNYzh4IcqOPJQ13IA== X-Google-Smtp-Source: ABdhPJxx8HVT12hM8dHtgpR8ya/52JDTLcKh4apdtUfXZReIakG45ZoMf581rVq74RFPawXvKQvkhg== X-Received: by 2002:a05:6870:9a21:b0:e5:c836:9456 with SMTP id fo33-20020a0568709a2100b000e5c8369456mr2956229oab.282.1650666115987; Fri, 22 Apr 2022 15:21:55 -0700 (PDT) Received: from ripper.. ([2600:1700:a0:3dc8:205:1bff:fec0:b9b3]) by smtp.gmail.com with ESMTPSA id js4-20020a056870bac400b000e687cdf5adsm1049224oab.55.2022.04.22.15.21.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Apr 2022 15:21:55 -0700 (PDT) From: Bjorn Andersson To: Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Andy Shevchenko , Daniel Scally , Heikki Krogerus , Sakari Ailus , "Rafael J. Wysocki" , Hans de Goede Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org Subject: [PATCH v5 5/7] usb: typec: mux: Allow multiple mux_devs per mux Date: Fri, 22 Apr 2022 15:23:49 -0700 Message-Id: <20220422222351.1297276-6-bjorn.andersson@linaro.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220422222351.1297276-1-bjorn.andersson@linaro.org> References: <20220422222351.1297276-1-bjorn.andersson@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org In the Qualcomm platforms the USB/DP PHY handles muxing and orientation switching of the SuperSpeed lines, but the SBU lines needs to be connected and switched by external (to the SoC) hardware. It's therefor necessary to be able to have the TypeC controller operate multiple TypeC muxes and switches. Use the newly introduced indirection object to handle this, to avoid having to taint the TypeC controllers with knowledge about the downstream hardware configuration. The max number of devs per indirection is set to 3, which account for being able to mux/switch the USB HS, SS and SBU lines, as per defined defined in the usb-c-connector binding. This number could be grown if need arrises at a later point in time. Acked-by: Heikki Krogerus Signed-off-by: Bjorn Andersson --- Changes since v4: - None drivers/usb/typec/mux.c | 128 ++++++++++++++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 26 deletions(-) diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index bb6c095b4af9..fd55c2c516a5 100644 --- a/drivers/usb/typec/mux.c +++ b/drivers/usb/typec/mux.c @@ -17,8 +17,11 @@ #include "class.h" #include "mux.h" +#define TYPEC_MUX_MAX_DEVS 3 + struct typec_switch { - struct typec_switch_dev *sw_dev; + struct typec_switch_dev *sw_devs[TYPEC_MUX_MAX_DEVS]; + unsigned int num_sw_devs; }; static int switch_fwnode_match(struct device *dev, const void *fwnode) @@ -67,25 +70,50 @@ static void *typec_switch_match(struct fwnode_handle *fwnode, const char *id, */ struct typec_switch *fwnode_typec_switch_get(struct fwnode_handle *fwnode) { - struct typec_switch_dev *sw_dev; + struct typec_switch_dev *sw_devs[TYPEC_MUX_MAX_DEVS]; struct typec_switch *sw; + int count; + int err; + int i; sw = kzalloc(sizeof(*sw), GFP_KERNEL); if (!sw) return ERR_PTR(-ENOMEM); - sw_dev = fwnode_connection_find_match(fwnode, "orientation-switch", NULL, - typec_switch_match); - if (IS_ERR_OR_NULL(sw_dev)) { + count = fwnode_connection_find_matches(fwnode, "orientation-switch", NULL, + typec_switch_match, + (void **)sw_devs, + ARRAY_SIZE(sw_devs)); + if (count <= 0) { kfree(sw); - return ERR_CAST(sw_dev); + return NULL; } - WARN_ON(!try_module_get(sw_dev->dev.parent->driver->owner)); + for (i = 0; i < count; i++) { + if (IS_ERR(sw_devs[i])) { + err = PTR_ERR(sw_devs[i]); + goto put_sw_devs; + } + } - sw->sw_dev = sw_dev; + for (i = 0; i < count; i++) { + WARN_ON(!try_module_get(sw_devs[i]->dev.parent->driver->owner)); + sw->sw_devs[i] = sw_devs[i]; + } + + sw->num_sw_devs = count; return sw; + +put_sw_devs: + for (i = 0; i < count; i++) { + if (!IS_ERR(sw_devs[i])) + put_device(&sw_devs[i]->dev); + } + + kfree(sw); + + return ERR_PTR(err); } EXPORT_SYMBOL_GPL(fwnode_typec_switch_get); @@ -98,14 +126,17 @@ EXPORT_SYMBOL_GPL(fwnode_typec_switch_get); void typec_switch_put(struct typec_switch *sw) { struct typec_switch_dev *sw_dev; + unsigned int i; if (IS_ERR_OR_NULL(sw)) return; - sw_dev = sw->sw_dev; + for (i = 0; i < sw->num_sw_devs; i++) { + sw_dev = sw->sw_devs[i]; - module_put(sw_dev->dev.parent->driver->owner); - put_device(&sw_dev->dev); + module_put(sw_dev->dev.parent->driver->owner); + put_device(&sw_dev->dev); + } kfree(sw); } EXPORT_SYMBOL_GPL(typec_switch_put); @@ -173,13 +204,21 @@ int typec_switch_set(struct typec_switch *sw, enum typec_orientation orientation) { struct typec_switch_dev *sw_dev; + unsigned int i; + int ret; if (IS_ERR_OR_NULL(sw)) return 0; - sw_dev = sw->sw_dev; + for (i = 0; i < sw->num_sw_devs; i++) { + sw_dev = sw->sw_devs[i]; + + ret = sw_dev->set(sw_dev, orientation); + if (ret) + return ret; + } - return sw_dev->set(sw_dev, orientation); + return 0; } EXPORT_SYMBOL_GPL(typec_switch_set); @@ -211,7 +250,8 @@ EXPORT_SYMBOL_GPL(typec_switch_get_drvdata); /* ------------------------------------------------------------------------- */ struct typec_mux { - struct typec_mux_dev *mux_dev; + struct typec_mux_dev *mux_devs[TYPEC_MUX_MAX_DEVS]; + unsigned int num_mux_devs; }; static int mux_fwnode_match(struct device *dev, const void *fwnode) @@ -294,25 +334,50 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id, struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode, const struct typec_altmode_desc *desc) { - struct typec_mux_dev *mux_dev; + struct typec_mux_dev *mux_devs[TYPEC_MUX_MAX_DEVS]; struct typec_mux *mux; + int count; + int err; + int i; mux = kzalloc(sizeof(*mux), GFP_KERNEL); if (!mux) return ERR_PTR(-ENOMEM); - mux_dev = fwnode_connection_find_match(fwnode, "mode-switch", (void *)desc, - typec_mux_match); - if (IS_ERR_OR_NULL(mux_dev)) { + count = fwnode_connection_find_matches(fwnode, "mode-switch", + (void *)desc, typec_mux_match, + (void **)mux_devs, + ARRAY_SIZE(mux_devs)); + if (count <= 0) { kfree(mux); - return ERR_CAST(mux_dev); + return NULL; } - WARN_ON(!try_module_get(mux_dev->dev.parent->driver->owner)); + for (i = 0; i < count; i++) { + if (IS_ERR(mux_devs[i])) { + err = PTR_ERR(mux_devs[i]); + goto put_mux_devs; + } + } + + for (i = 0; i < count; i++) { + WARN_ON(!try_module_get(mux_devs[i]->dev.parent->driver->owner)); + mux->mux_devs[i] = mux_devs[i]; + } - mux->mux_dev = mux_dev; + mux->num_mux_devs = count; return mux; + +put_mux_devs: + for (i = 0; i < count; i++) { + if (!IS_ERR(mux_devs[i])) + put_device(&mux_devs[i]->dev); + } + + kfree(mux); + + return ERR_PTR(err); } EXPORT_SYMBOL_GPL(fwnode_typec_mux_get); @@ -325,13 +390,16 @@ EXPORT_SYMBOL_GPL(fwnode_typec_mux_get); void typec_mux_put(struct typec_mux *mux) { struct typec_mux_dev *mux_dev; + unsigned int i; if (IS_ERR_OR_NULL(mux)) return; - mux_dev = mux->mux_dev; - module_put(mux_dev->dev.parent->driver->owner); - put_device(&mux_dev->dev); + for (i = 0; i < mux->num_mux_devs; i++) { + mux_dev = mux->mux_devs[i]; + module_put(mux_dev->dev.parent->driver->owner); + put_device(&mux_dev->dev); + } kfree(mux); } EXPORT_SYMBOL_GPL(typec_mux_put); @@ -339,13 +407,21 @@ EXPORT_SYMBOL_GPL(typec_mux_put); int typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state) { struct typec_mux_dev *mux_dev; + unsigned int i; + int ret; if (IS_ERR_OR_NULL(mux)) return 0; - mux_dev = mux->mux_dev; + for (i = 0; i < mux->num_mux_devs; i++) { + mux_dev = mux->mux_devs[i]; + + ret = mux_dev->set(mux_dev, state); + if (ret) + return ret; + } - return mux_dev->set(mux_dev, state); + return 0; } EXPORT_SYMBOL_GPL(typec_mux_set); From patchwork Fri Apr 22 22:23:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 565043 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8C37BC433F5 for ; Fri, 22 Apr 2022 22:55:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233545AbiDVW6X (ORCPT ); Fri, 22 Apr 2022 18:58:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51622 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234245AbiDVW5n (ORCPT ); Fri, 22 Apr 2022 18:57:43 -0400 Received: from mail-oa1-x34.google.com (mail-oa1-x34.google.com [IPv6:2001:4860:4864:20::34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7A5463766B5 for ; Fri, 22 Apr 2022 15:21:59 -0700 (PDT) Received: by mail-oa1-x34.google.com with SMTP id 586e51a60fabf-e604f712ecso10045465fac.9 for ; Fri, 22 Apr 2022 15:21:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=YfdyUeRBKR7/kufYH33kid5tsUaSAg2QglexM2TYAZE=; b=S25cr15PWqZVQoaeR93yTdLNOyjL74an2NA5fiXvUN03SfqBvkwUc6/NJ90wfypL6n 7qnczyOLRDGNi6Qy28R0x8oTvofoG9WX/Fc27z5mU0aF1mw0AB7pFoU6mLVNG/5JGeVW OLj2uQPq8NFb6be6O4z0NPT1JhEAWH2HfCh9e/NBdrzGjq9oKTg4VDm9F+Li5xCUfOEv ULg+g6VaAjSjYqTqGODCKxJAIEtj6flZaplXDSM8WtFAFZrHaSEgt4p3gmRhd1MC8wvr e+lRijbqUCY2tzpQHXe+yGcltJKrP9sBBoqrHPWSs+mansOmL6v0I1MDmZKJBUHp0BuZ +hDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=YfdyUeRBKR7/kufYH33kid5tsUaSAg2QglexM2TYAZE=; b=P//3Irx7FfqjpedSyc6w9YKmp5wtGoQ+MxsLNL6wQtgiSt3MSXAtTRGrWE8pq003Bo ITtmt9NaCeVXyCJxp5OkF71FRWh6uc7r01zGC9OddD3STpcBflxC9sdkJoD/ymJKjRlD 5yBJ7qyqLMwNasu/7xw+6K4Y4CydqoybSv2l71ctYQp5uLwmAu0HvY2z1IOV5QQhkbYn oQyL3jGcRcjqgrvPa0pLD5W929zfWIhvACVcbYcsbMGzcVwGCnQRPeCvtl/PeTjGLFgT JvQbcBePGFV9k5zNNEZa0IViSrv0E52ZknS+kNNb1tXZNPXzx6u2suDWDb8Yr3HWnTmv VePg== X-Gm-Message-State: AOAM533bR+Ey5sxoKbfA3JD0bDkX6EcchT15D41UZ3/RtS85B/ZUBZ6m 1J+KdtHyvCmGXN9pREhLLBBtZA== X-Google-Smtp-Source: ABdhPJxzLx2x/E6WOR5Si0YdPNktJBV8OkVVmeAAG7G+uedRUBkDjgfJ8N9psrJxZUh6jlA7ixI/8g== X-Received: by 2002:a05:6870:5802:b0:de:ce5e:33ea with SMTP id r2-20020a056870580200b000dece5e33eamr2967613oap.57.1650666118478; Fri, 22 Apr 2022 15:21:58 -0700 (PDT) Received: from ripper.. ([2600:1700:a0:3dc8:205:1bff:fec0:b9b3]) by smtp.gmail.com with ESMTPSA id js4-20020a056870bac400b000e687cdf5adsm1049224oab.55.2022.04.22.15.21.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Apr 2022 15:21:57 -0700 (PDT) From: Bjorn Andersson To: Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski , Andy Shevchenko , Daniel Scally , Heikki Krogerus , Sakari Ailus , "Rafael J. Wysocki" , Hans de Goede Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org Subject: [PATCH v5 7/7] usb: typec: mux: Add On Semi fsa4480 driver Date: Fri, 22 Apr 2022 15:23:51 -0700 Message-Id: <20220422222351.1297276-8-bjorn.andersson@linaro.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220422222351.1297276-1-bjorn.andersson@linaro.org> References: <20220422222351.1297276-1-bjorn.andersson@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The ON Semiconductor FSA4480 is a USB Type-C port multimedia switch with support for analog audio headsets. It allows sharing a common USB Type-C port to pass USB2.0 signal, analog audio, sideband use wires and analog microphone signal. Due to lacking upstream audio support for testing, the audio muxing is left untouched, but implementation of muxing the SBU lines is provided as a pair of Type-C mux and switch devices. This provides the necessary support for enabling the DisplayPort altmode on devices with this circuit. Signed-off-by: Bjorn Andersson Reviewed-by: Heikki Krogerus --- Changes since v4: - Disable locking of the regmap - Use dev_fwnode() instead of explicit dereference drivers/usb/typec/mux/Kconfig | 10 ++ drivers/usb/typec/mux/Makefile | 1 + drivers/usb/typec/mux/fsa4480.c | 218 ++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 drivers/usb/typec/mux/fsa4480.c diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig index edead555835e..5eb2c17d72c1 100644 --- a/drivers/usb/typec/mux/Kconfig +++ b/drivers/usb/typec/mux/Kconfig @@ -2,6 +2,16 @@ menu "USB Type-C Multiplexer/DeMultiplexer Switch support" +config TYPEC_MUX_FSA4480 + tristate "ON Semi FSA4480 Analog Audio Switch driver" + depends on I2C + select REGMAP_I2C + help + Driver for the ON Semiconductor FSA4480 Analog Audio Switch, which + provides support for muxing analog audio and sideband signals on a + common USB Type-C connector. + If compiled as a module, the module will be named fsa4480. + config TYPEC_MUX_PI3USB30532 tristate "Pericom PI3USB30532 Type-C cross switch driver" depends on I2C diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile index 280a6f553115..e52a56c16bfb 100644 --- a/drivers/usb/typec/mux/Makefile +++ b/drivers/usb/typec/mux/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_TYPEC_MUX_FSA4480) += fsa4480.o obj-$(CONFIG_TYPEC_MUX_PI3USB30532) += pi3usb30532.o obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o diff --git a/drivers/usb/typec/mux/fsa4480.c b/drivers/usb/typec/mux/fsa4480.c new file mode 100644 index 000000000000..6184f5367190 --- /dev/null +++ b/drivers/usb/typec/mux/fsa4480.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021-2022 Linaro Ltd. + * Copyright (C) 2018-2020 The Linux Foundation + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define FSA4480_SWITCH_ENABLE 0x04 +#define FSA4480_SWITCH_SELECT 0x05 +#define FSA4480_SWITCH_STATUS1 0x07 +#define FSA4480_SLOW_L 0x08 +#define FSA4480_SLOW_R 0x09 +#define FSA4480_SLOW_MIC 0x0a +#define FSA4480_SLOW_SENSE 0x0b +#define FSA4480_SLOW_GND 0x0c +#define FSA4480_DELAY_L_R 0x0d +#define FSA4480_DELAY_L_MIC 0x0e +#define FSA4480_DELAY_L_SENSE 0x0f +#define FSA4480_DELAY_L_AGND 0x10 +#define FSA4480_RESET 0x1e +#define FSA4480_MAX_REGISTER 0x1f + +#define FSA4480_ENABLE_DEVICE BIT(7) +#define FSA4480_ENABLE_SBU GENMASK(6, 5) +#define FSA4480_ENABLE_USB GENMASK(4, 3) + +#define FSA4480_SEL_SBU_REVERSE GENMASK(6, 5) +#define FSA4480_SEL_USB GENMASK(4, 3) + +struct fsa4480 { + struct i2c_client *client; + + /* used to serialize concurrent change requests */ + struct mutex lock; + + struct typec_switch_dev *sw; + struct typec_mux_dev *mux; + + struct regmap *regmap; + + u8 cur_enable; + u8 cur_select; +}; + +static const struct regmap_config fsa4480_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = FSA4480_MAX_REGISTER, + /* Accesses only done under fsa4480->lock */ + .disable_locking = true, +}; + +static int fsa4480_switch_set(struct typec_switch_dev *sw, + enum typec_orientation orientation) +{ + struct fsa4480 *fsa = typec_switch_get_drvdata(sw); + u8 new_sel; + + mutex_lock(&fsa->lock); + new_sel = FSA4480_SEL_USB; + if (orientation == TYPEC_ORIENTATION_REVERSE) + new_sel |= FSA4480_SEL_SBU_REVERSE; + + if (new_sel == fsa->cur_select) + goto out_unlock; + + if (fsa->cur_enable & FSA4480_ENABLE_SBU) { + /* Disable SBU output while re-configuring the switch */ + regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, + fsa->cur_enable & ~FSA4480_ENABLE_SBU); + + /* 35us to allow the SBU switch to turn off */ + usleep_range(35, 1000); + } + + regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, new_sel); + fsa->cur_select = new_sel; + + if (fsa->cur_enable & FSA4480_ENABLE_SBU) { + regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable); + + /* 15us to allow the SBU switch to turn on again */ + usleep_range(15, 1000); + } + +out_unlock: + mutex_unlock(&fsa->lock); + + return 0; +} + +static int fsa4480_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) +{ + struct fsa4480 *fsa = typec_mux_get_drvdata(mux); + u8 new_enable; + + mutex_lock(&fsa->lock); + + new_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB; + if (state->mode >= TYPEC_DP_STATE_A) + new_enable |= FSA4480_ENABLE_SBU; + + if (new_enable == fsa->cur_enable) + goto out_unlock; + + regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, new_enable); + fsa->cur_enable = new_enable; + + if (new_enable & FSA4480_ENABLE_SBU) { + /* 15us to allow the SBU switch to turn off */ + usleep_range(15, 1000); + } + +out_unlock: + mutex_unlock(&fsa->lock); + + return 0; +} + +static int fsa4480_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct typec_switch_desc sw_desc = { }; + struct typec_mux_desc mux_desc = { }; + struct fsa4480 *fsa; + + fsa = devm_kzalloc(dev, sizeof(*fsa), GFP_KERNEL); + if (!fsa) + return -ENOMEM; + + fsa->client = client; + mutex_init(&fsa->lock); + + fsa->regmap = devm_regmap_init_i2c(client, &fsa4480_regmap_config); + if (IS_ERR(fsa->regmap)) + return dev_err_probe(dev, PTR_ERR(fsa->regmap), "failed to initialize regmap\n"); + + fsa->cur_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB; + fsa->cur_select = FSA4480_SEL_USB; + + /* set default settings */ + regmap_write(fsa->regmap, FSA4480_SLOW_L, 0x00); + regmap_write(fsa->regmap, FSA4480_SLOW_R, 0x00); + regmap_write(fsa->regmap, FSA4480_SLOW_MIC, 0x00); + regmap_write(fsa->regmap, FSA4480_SLOW_SENSE, 0x00); + regmap_write(fsa->regmap, FSA4480_SLOW_GND, 0x00); + regmap_write(fsa->regmap, FSA4480_DELAY_L_R, 0x00); + regmap_write(fsa->regmap, FSA4480_DELAY_L_MIC, 0x00); + regmap_write(fsa->regmap, FSA4480_DELAY_L_SENSE, 0x00); + regmap_write(fsa->regmap, FSA4480_DELAY_L_AGND, 0x09); + regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, fsa->cur_select); + regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable); + + sw_desc.drvdata = fsa; + sw_desc.fwnode = dev_fwnode(dev); + sw_desc.set = fsa4480_switch_set; + + fsa->sw = typec_switch_register(dev, &sw_desc); + if (IS_ERR(fsa->sw)) + return dev_err_probe(dev, PTR_ERR(fsa->sw), "failed to register typec switch\n"); + + mux_desc.drvdata = fsa; + mux_desc.fwnode = dev_fwnode(dev); + mux_desc.set = fsa4480_mux_set; + + fsa->mux = typec_mux_register(dev, &mux_desc); + if (IS_ERR(fsa->mux)) { + typec_switch_unregister(fsa->sw); + return dev_err_probe(dev, PTR_ERR(fsa->mux), "failed to register typec mux\n"); + } + + i2c_set_clientdata(client, fsa); + return 0; +} + +static int fsa4480_remove(struct i2c_client *client) +{ + struct fsa4480 *fsa = i2c_get_clientdata(client); + + typec_mux_unregister(fsa->mux); + typec_switch_unregister(fsa->sw); + + return 0; +} + +static const struct i2c_device_id fsa4480_table[] = { + { "fsa4480" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, fsa4480_table); + +static const struct of_device_id fsa4480_of_table[] = { + { .compatible = "fcs,fsa4480" }, + { } +}; +MODULE_DEVICE_TABLE(of, fsa4480_of_table); + +static struct i2c_driver fsa4480_driver = { + .driver = { + .name = "fsa4480", + .of_match_table = fsa4480_of_table, + }, + .probe_new = fsa4480_probe, + .remove = fsa4480_remove, + .id_table = fsa4480_table, +}; +module_i2c_driver(fsa4480_driver); + +MODULE_DESCRIPTION("ON Semiconductor FSA4480 driver"); +MODULE_LICENSE("GPL v2");