From patchwork Wed Nov 16 12:30:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abel Vesa X-Patchwork-Id: 21024 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp112882wru; Wed, 16 Nov 2022 04:32:38 -0800 (PST) X-Google-Smtp-Source: AA0mqf4Pg125EauCM84NpqM/a4HIyemlAyRaD8eoCgr5ihOVYQI5PwW1FVFlrdOgRdNAt2NQTyjp X-Received: by 2002:a17:906:c082:b0:7ad:f43a:cb0a with SMTP id f2-20020a170906c08200b007adf43acb0amr16884329ejz.560.1668601958276; Wed, 16 Nov 2022 04:32:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668601958; cv=none; d=google.com; s=arc-20160816; b=wdLVEtFnip9seOVoAX+lDnztAC3iHAME0kQtlZaxS/WAQ/kUqZdLLIrQwenAt9X9/w mQY8ODqa/SvjWtReBxHPu2kNvJhC1n+bzP+fLnXC9PGnMfn7Zy7LaZvGSG6Sx3qSJb5d bqTIZZc6UXT3WuGe9mUDKY1hcGcK6Ghres3WwM+klQifFobF8hJ5yJKNUMVfKzY+9oJw G0KxRGmM57/ug0mpr8TDMH/UtTstCwXJRzsum8Mj7p6/UexYoozfF/nqMzYpskj3KHtd 5+zwqcUGHU8N+8by7Qw31tvA85P+qUzgJ5hXqh+ff+DadOYx0VUGx7sSVmPP5VwdtviL yLog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=lMcRJuxeNKzK+RXQpDGGFzbRIm01UwZgF0vUOiP8QjU=; b=G4dYtU8O5d2M/aJ6+qTkXAVQtkMpNrcQxwEP+mMpqvseHQSGX7uSDQahXkc5sBz9rs EjNOalDQ8PoGHMj1SLlLEp3BIVNS9SXlTuwSgk6LTU5X/pNgHHPKOi906hrl5vOYohO2 BL/7RcPSB7B16tuTqE84OhEiRMsFrD8yaE7Zn4b9R02iFseXhD99lOdRyIadhy7lxmDb 0qLARP7wNhPHaeSmoAX2Y2iAOyiWLrmJ1xPlopJWJiHHlYLIpc45M1NVDnggXcs7TJc2 Zh6T0hQnTm2wjYpTsGS3P5yVx2pOj6Jh2dsTjzknaeTtBw13fsGxBGX2dHxdzqW1fpuy nOaw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dwW1wbGh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o11-20020a170906974b00b0078d4a0c77f9si16090960ejy.458.2022.11.16.04.32.13; Wed, 16 Nov 2022 04:32:38 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dwW1wbGh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238787AbiKPMbb (ORCPT + 99 others); Wed, 16 Nov 2022 07:31:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48706 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238368AbiKPMbA (ORCPT ); Wed, 16 Nov 2022 07:31:00 -0500 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 06E6EDEE0 for ; Wed, 16 Nov 2022 04:30:37 -0800 (PST) Received: by mail-wr1-x42c.google.com with SMTP id j15so29700235wrq.3 for ; Wed, 16 Nov 2022 04:30:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lMcRJuxeNKzK+RXQpDGGFzbRIm01UwZgF0vUOiP8QjU=; b=dwW1wbGhQleITUuPQ+cN9PCikMnpSJ0Id+5N6GH/3UlXZuhKO8z14q+9Bo8vKTDlnl Cmv6fgzMwChjsltijJ4ztvQx40mqjpDWyM4A7ZAR7JE26yEj5z9Ht35kKKyifAr1xibw lkh3L9IhPzfdlmD6A8VULs6y8zSSEkqSuKTJ9WRQqslhWn7fNk7SFmXGGi+V4+wWgx/f il4JTFMWXepV8I4AwPAl/qdYLf/+LevZGwUk0RiSrs/2S4J1B+YnHLthLGjnXL3UkOr8 5KOmSWtY+gNqsEWmOM+FM4qRYPDLl+TJCNA3TBQankmlyf6tspqNKdlUo9uO+E2vdEop Odug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lMcRJuxeNKzK+RXQpDGGFzbRIm01UwZgF0vUOiP8QjU=; b=mIgwDHd6n74uDWkBPjxog0ofWEOwdEi39yUxgTGz0ft2WPzFvSeFiK4P69uQtHvSYI u/ymPzLcdRajn2rSVI57S4bHLdX4z1YnfJlOomn3doHwKHghxQ4wI10EVJH2bFy++8BA EisIKzJY7OzFtZIWE15Y30Y9uO4beEKcOKs1HbvZz94nrWBeM6PBXsB0XfAuXH+asdAM tRahuYZfdX2qlZ1Sj1S7UCLJy7tLWzUJ5KsTFTiVd34gho//GEZDmMVvnIUHNMA/2nMI 6I6xjaqjWhrsgNhr6UAP6eHfGDKclPoqIJyIjEypFTQq+FQnosqcW7YZ0RHvM9GJ36YQ NmgA== X-Gm-Message-State: ANoB5pkZNomrurG+GodccFVIfeNRN+zgh0cxSlYRa2d/3TxfqpxIqtZ9 h/pSe3+2WEiMeXblCrplAkMLqw== X-Received: by 2002:a5d:6e0c:0:b0:236:5abb:590a with SMTP id h12-20020a5d6e0c000000b002365abb590amr13595607wrz.700.1668601835375; Wed, 16 Nov 2022 04:30:35 -0800 (PST) Received: from localhost.localdomain ([94.52.112.99]) by smtp.gmail.com with ESMTPSA id l42-20020a05600c1d2a00b003cf4eac8e80sm2870991wms.23.2022.11.16.04.30.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Nov 2022 04:30:34 -0800 (PST) From: Abel Vesa To: Andy Gross , Bjorn Andersson , Konrad Dybcio , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski Cc: Linux Kernel Mailing List , devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-scsi@vger.kernel.org, linux-usb@vger.kernel.org Subject: [RFC PATCH 1/3] usb: Add USB repeater generic framework Date: Wed, 16 Nov 2022 14:30:17 +0200 Message-Id: <20221116123019.2753230-2-abel.vesa@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221116123019.2753230-1-abel.vesa@linaro.org> References: <20221116123019.2753230-1-abel.vesa@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749655967103868882?= X-GMAIL-MSGID: =?utf-8?q?1749655967103868882?= With more SoCs moving towards eUSB2, such platforms will have to use a USB 2.0 compliance repeater. This repeater HW-wise usually deals with level shifting, but depending on the implementation it can do much more. So add a ganeric USB framework that would allow either a generic PHY or some USB host controller to control and get a repeater from a devicetree phandle. This framework will further be used by platform specific drivers to register the repeater and implement platform specific ops. Signed-off-by: Abel Vesa --- drivers/usb/Kconfig | 2 + drivers/usb/Makefile | 2 + drivers/usb/repeater/Kconfig | 9 ++ drivers/usb/repeater/Makefile | 6 + drivers/usb/repeater/repeater.c | 198 ++++++++++++++++++++++++++++++++ include/linux/usb/repeater.h | 78 +++++++++++++ 6 files changed, 295 insertions(+) create mode 100644 drivers/usb/repeater/Kconfig create mode 100644 drivers/usb/repeater/Makefile create mode 100644 drivers/usb/repeater/repeater.c create mode 100644 include/linux/usb/repeater.h diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index a871a988829d..c9ad102a0fa9 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -176,6 +176,8 @@ source "drivers/usb/gadget/Kconfig" source "drivers/usb/typec/Kconfig" +source "drivers/usb/repeater/Kconfig" + source "drivers/usb/roles/Kconfig" endif # USB_SUPPORT diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index a81e6ef293af..c96c66304edd 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -67,4 +67,6 @@ obj-$(CONFIG_USBIP_CORE) += usbip/ obj-$(CONFIG_TYPEC) += typec/ +obj-$(CONFIG_USB_REPEATER) += repeater/ + obj-$(CONFIG_USB_ROLE_SWITCH) += roles/ diff --git a/drivers/usb/repeater/Kconfig b/drivers/usb/repeater/Kconfig new file mode 100644 index 000000000000..e12cd22c0adb --- /dev/null +++ b/drivers/usb/repeater/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 + +config USB_REPEATER + tristate "USB Repeater Framework" + help + Enable this to allow the USB PHY drivers and the connected repeater + driver to bind together and to provide the USB driver ways to perform + set of operations with repeater for USB2 functionality using PHY and + controller driver. diff --git a/drivers/usb/repeater/Makefile b/drivers/usb/repeater/Makefile new file mode 100644 index 000000000000..2d1b5f348976 --- /dev/null +++ b/drivers/usb/repeater/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for USB repeater drivers +# + +obj-$(CONFIG_USB_REPEATER) += repeater.o diff --git a/drivers/usb/repeater/repeater.c b/drivers/usb/repeater/repeater.c new file mode 100644 index 000000000000..e97a95422735 --- /dev/null +++ b/drivers/usb/repeater/repeater.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include + +static LIST_HEAD(usb_repeater_list); +static DEFINE_SPINLOCK(usb_repeater_lock); + +/** + * usb_put_repeater - release the USB repeater + * @rptr: the repeater returned by usb_get_repeater() + * + * Releases a refcount the caller received from usb_get_repeater(). + * + * For use by USB PHY drivers. + */ +void usb_put_repeater(struct usb_repeater *rptr) +{ + if (rptr) { + put_device(rptr->dev); + if (rptr->dev->driver && rptr->dev->driver->owner) { + struct module *owner = rptr->dev->driver->owner; + + module_put(owner); + } + } +} +EXPORT_SYMBOL_GPL(usb_put_repeater); + +static struct usb_repeater *of_usb_find_repeater(struct device_node *node) +{ + struct usb_repeater *rptr; + + if (!of_device_is_available(node)) + return ERR_PTR(-ENODEV); + + list_for_each_entry(rptr, &usb_repeater_list, head) { + if (node != rptr->dev->of_node) + continue; + + return rptr; + } + + return ERR_PTR(-EPROBE_DEFER); +} + +static void devm_usb_repeater_release(struct device *dev, void *res) +{ + struct usb_repeater *rptr = *(struct usb_repeater **)res; + + usb_put_repeater(rptr); +} + +/** + * devm_usb_get_repeater_by_node - find the USB repeater by device_node + * @dev: device that requests this USB repeater + * @node: the device_node for the USB repeater device. + * @nb: a notifier_block to register with the USB repeater. + * + * Returns the USB repeater driver associated with the given device_node, + * after getting a refcount to it, -ENODEV if there is no such repeater or + * -EPROBE_DEFER if the device is not yet loaded. While at that, it + * also associates the device with + * the repeater using devres. On driver detach, release function is invoked + * on the devres data, then, devres data is freed. + * + * For use by peripheral drivers for devices related to a repeater, + * such as a charger. + */ +struct usb_repeater *devm_usb_get_repeater_by_node(struct device *dev, + struct device_node *node, + struct notifier_block *nb) +{ + struct usb_repeater *rptr = ERR_PTR(-ENOMEM); + struct usb_repeater *rptr_devm; + unsigned long flags; + + rptr_devm = devres_alloc(devm_usb_repeater_release, + sizeof(*rptr_devm), GFP_KERNEL); + if (!rptr_devm) { + dev_dbg(dev, "failed to allocate memory for devres\n"); + goto err0; + } + + spin_lock_irqsave(&usb_repeater_lock, flags); + + rptr = of_usb_find_repeater(node); + if (IS_ERR(rptr)) { + devres_free(rptr_devm); + goto err0; + } + + if (!try_module_get(rptr->dev->driver->owner)) { + rptr = ERR_PTR(-ENODEV); + devres_free(rptr_devm); + goto err0; + } + devres_add(dev, rptr_devm); + + get_device(rptr->dev); +err0: + spin_unlock_irqrestore(&usb_repeater_lock, flags); + + return rptr; +} +EXPORT_SYMBOL_GPL(devm_usb_get_repeater_by_node); + +/** + * devm_usb_get_repeater_by_phandle - find the USB repeater by phandle + * @dev: device that requests this repeater + * @phandle: name of the property holding the repeater phandle value + * @index: the index of the repeater + * + * Returns the USB repeater driver associated with the given phandle value, + * after getting a refcount to it, -ENODEV if there is no such repeater or + * -EPROBE_DEFER if there is a phandle to the repeater, but the device is + * not yet loaded. While at that, it also associates the device with + * the repeater using devres. On driver detach, release function is invoked + * on the devres data, then, devres data is freed. + * + * For use by USB PHY drivers. + */ +struct usb_repeater *devm_usb_get_repeater_by_phandle(struct device *dev, + const char *phandle, u8 index) +{ + struct device_node *node; + struct usb_repeater *rptr; + + if (!dev->of_node) { + dev_dbg(dev, "device does not have a device node entry\n"); + return ERR_PTR(-EINVAL); + } + + node = of_parse_phandle(dev->of_node, phandle, index); + if (!node) { + dev_dbg(dev, "failed to get %s phandle in %pOF node\n", phandle, + dev->of_node); + return ERR_PTR(-ENODEV); + } + rptr = devm_usb_get_repeater_by_node(dev, node, NULL); + of_node_put(node); + return rptr; +} +EXPORT_SYMBOL_GPL(devm_usb_get_repeater_by_phandle); + +/** + * usb_add_repeater_dev - declare the USB repeater + * @rptr: the USB repeater to be used; or NULL + * + * This call is exclusively for use by repeater drivers to + * register the device to allow the USB phy driver to control it + * via repeater specific ops. + */ +int usb_add_repeater_dev(struct usb_repeater *rptr) +{ + unsigned long flags; + + if (!rptr->dev) { + dev_err(rptr->dev, "no device provided for repeater\n"); + return -EINVAL; + } + + spin_lock_irqsave(&usb_repeater_lock, flags); + list_add_tail(&rptr->head, &usb_repeater_list); + spin_unlock_irqrestore(&usb_repeater_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(usb_add_repeater_dev); + +/** + * usb_remove_repeater - remove the USB repeater + * @rptr: the USB Repeater to be removed; + * + * This reverts the effects of usb_add_repeater_dev + */ +void usb_remove_repeater_dev(struct usb_repeater *rptr) +{ + unsigned long flags; + + spin_lock_irqsave(&usb_repeater_lock, flags); + if (rptr) + list_del(&rptr->head); + spin_unlock_irqrestore(&usb_repeater_lock, flags); +} +EXPORT_SYMBOL_GPL(usb_remove_repeater_dev); + +MODULE_DESCRIPTION("USB Repeater Framework"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/usb/repeater.h b/include/linux/usb/repeater.h new file mode 100644 index 000000000000..e68e0936f1e5 --- /dev/null +++ b/include/linux/usb/repeater.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * USB Repeater defines + */ + +#ifndef __LINUX_USB_REPEATER_H +#define __LINUX_USB_REPEATER_H + +struct usb_repeater { + struct device *dev; + const char *label; + unsigned int flags; + + struct list_head head; + int (*reset)(struct usb_repeater *rptr, bool assert); + int (*init)(struct usb_repeater *rptr); + int (*power_on)(struct usb_repeater *rptr); + int (*power_off)(struct usb_repeater *rptr); +}; + +#if IS_ENABLED(CONFIG_USB_REPEATER) +extern struct usb_repeater *devm_usb_get_repeater_by_phandle(struct device *dev, + const char *phandle, u8 index); +extern struct usb_repeater *devm_usb_get_repeater_by_node(struct device *dev, + struct device_node *node, struct notifier_block *nb); +extern int usb_add_repeater_dev(struct usb_repeater *rptr); +extern void usb_remove_repeater_dev(struct usb_repeater *rptr); +#else +static inline struct usb_repeater *devm_usb_get_repeater_by_phandle(struct device *dev, + const char *phandle, u8 index) +{ + return ERR_PTR(-ENXIO); +} + +static inline struct usb_repeater *devm_usb_get_repeater_by_node(struct device *dev, + struct device_node *node, struct notifier_block *nb) +{ + return ERR_PTR(-ENXIO); +} + +static inline int usb_add_repeater_dev(struct usb_repeater *rptr) { return 0; } +static inline void usb_remove_repeater_dev(struct usb_repeater *rptr) { } + +#endif + +static inline int usb_repeater_reset(struct usb_repeater *rptr, bool assert) +{ + if (rptr && rptr->reset != NULL) + return rptr->reset(rptr, assert); + else + return 0; +} + +static inline int usb_repeater_init(struct usb_repeater *rptr) +{ + if (rptr && rptr->init != NULL) + return rptr->init(rptr); + else + return 0; +} + +static inline int usb_repeater_power_on(struct usb_repeater *rptr) +{ + if (rptr && rptr->power_on != NULL) + return rptr->power_on(rptr); + else + return 0; +} + +static inline int usb_repeater_power_off(struct usb_repeater *rptr) +{ + if (rptr && rptr->power_off != NULL) + return rptr->power_off(rptr); + else + return 0; +} + +#endif /* __LINUX_USB_REPEATER_H */ From patchwork Wed Nov 16 12:30:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abel Vesa X-Patchwork-Id: 21025 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp112940wru; Wed, 16 Nov 2022 04:32:45 -0800 (PST) X-Google-Smtp-Source: AA0mqf7k1d1uGOtJUiuELfXO+YxNx7zsvQZsQ/WwlJNVe7jUxMTLT6C++nbaEwr7qJZOIm0R4z32 X-Received: by 2002:aa7:c6d5:0:b0:461:2915:e41d with SMTP id b21-20020aa7c6d5000000b004612915e41dmr18709007eds.184.1668601965591; Wed, 16 Nov 2022 04:32:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668601965; cv=none; d=google.com; s=arc-20160816; b=0ZA+2kepD5jlxXuNPsqQl20I/upufCDuyH4m/c0g20LdfaK/H5ViSh/X3I33sx6QMf cNZ3vcbSyCH0MHzPqHEBpOIl565Z1uFVbdB7pb2yijqyPoAxNWRgYJ6fx7rolAwrQg8m MUCuf+C3cWsAgvWaYAeBQDswX5Ff6oM3D/bKw5zPpoqoflbOShMRA8qd9YnzfFzOATpv oMy0GfHgtSMMVtiXjaeOlLeFMzunFfX0zR1xPmSfjC830Zt3dtGFCOKLeSyHIyOr37HE IgQtfE10UKYaMxy1iR8liw2d4R0cfeyrBmcsgI/iP7ij583tN8hvvUtrsUtiZQIv/Z0k COlA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=8nJxt9QrKnPjdX4FLTqxuaRyNG0lj0vQQUUKMLh4iHk=; b=UV+yloddXcxzAOO3+cuqhQT1cWc4qgrErLm4HfLH7rs93kVs+GUHUOE25kXQElSSYa Xdl48AziWOs342Hv/0nDRPWVe9ixeV6bjQdqhywB3UlNTrIpfUP0kezU1QYIVXAngjf0 zqBNjb2phhJ8T2sSuaXEY4PGg0qRzDjze4J9LpDChgAXYJdXK2MRZtZkmmXnbLjLbNJ/ CKziy8TOnw/zJPvQ+95JRCinl5sm4Ca1ApyFRBflABMr+E5qCcNOPdMIe2TteRJClTDA So75G31BI3S0CQN2x+6WryR43kBl1c6/4SP3oCyHaGjlBFVAXr3eKFS+3jEGsUVyLyE8 hEsA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rIlo6EgH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ne39-20020a1709077ba700b007ade8dd3517si15754116ejc.936.2022.11.16.04.32.20; Wed, 16 Nov 2022 04:32:45 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rIlo6EgH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232903AbiKPMbk (ORCPT + 99 others); Wed, 16 Nov 2022 07:31:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233361AbiKPMbB (ORCPT ); Wed, 16 Nov 2022 07:31:01 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2EE74E09C for ; Wed, 16 Nov 2022 04:30:38 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id z14so29506130wrn.7 for ; Wed, 16 Nov 2022 04:30:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8nJxt9QrKnPjdX4FLTqxuaRyNG0lj0vQQUUKMLh4iHk=; b=rIlo6EgH1ESzdhDRESiPYw617PV6yijGCXHCINyQ0owOLcAWoim0ahP6gC4RLTix9n V/x9m5pwlyv0bUtMKrMB0AN4Qd8MuOmGQMBSivtdsvSHWkO8p3IMgpQohZd+eLBg52M+ 28SikkR+0COasuKSGoFTj7lASWLSHY8QjcjuZJVxGNEUnnBbedGUGDTj8WqzscFFd0aR vnx4Xgst+Dwo9yZD0Vcs/s7CyiTL86fq7RmhTaQHbisF6ko7w7Z0dW70KsTPCsuMDr5/ ZHdxuQoDhkDP0ATh7U1LwuXoDQ3aVOakSRrz3k7K4XbgoNi/BvXb0DKQjlKvmCQKMQO9 ThHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8nJxt9QrKnPjdX4FLTqxuaRyNG0lj0vQQUUKMLh4iHk=; b=BMIIiVXnOJp2Hgt8fgzdngyF/aqa2/9HZwT+HBa9CMRMZ7ehjSqdWpLIapUMMjQ+wt foE4yupKdA4TzQDdSmpeLkor2abJ+zhpAz0q9wjssGlQUN6tzE2lzv5bKrwnr7Lu/NpV 11NK01ltsaNh9FDwAI74vb8ABQPUXzi3HKBbgewIUeEK79QKUpOs2HetRWwE1L9JLghk AvHSYFICOKqN0X7u7kJuEIOnp6Qn43iV16PNHndg6/lEYufYHROEANOIVyv4Kfjd1HLm /STP9ggpWMUhZxhNI+Dy6ztrlYtrMc6FkgJJa2F+1G6v6nK8Nn+EhKj5UXRcCeQOp2tt suow== X-Gm-Message-State: ANoB5pkNPO5YTnEaZbOFOdlD9R8A6bkAMbzKajekXWZZl+4IoOQLizsz CSKq0vQht3EszMmOhdecPLIYuA== X-Received: by 2002:adf:e507:0:b0:236:6442:3a48 with SMTP id j7-20020adfe507000000b0023664423a48mr13432715wrm.41.1668601836673; Wed, 16 Nov 2022 04:30:36 -0800 (PST) Received: from localhost.localdomain ([94.52.112.99]) by smtp.gmail.com with ESMTPSA id l42-20020a05600c1d2a00b003cf4eac8e80sm2870991wms.23.2022.11.16.04.30.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Nov 2022 04:30:36 -0800 (PST) From: Abel Vesa To: Andy Gross , Bjorn Andersson , Konrad Dybcio , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski Cc: Linux Kernel Mailing List , devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-scsi@vger.kernel.org, linux-usb@vger.kernel.org Subject: [RFC PATCH 2/3] dt-bindings: usb: Add qcom,snps-eusb2-repeater schema Date: Wed, 16 Nov 2022 14:30:18 +0200 Message-Id: <20221116123019.2753230-3-abel.vesa@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221116123019.2753230-1-abel.vesa@linaro.org> References: <20221116123019.2753230-1-abel.vesa@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749655974697118359?= X-GMAIL-MSGID: =?utf-8?q?1749655974697118359?= Add dt-binding schema for the Qualcomm SNPS eUSB2 repeater. Signed-off-by: Abel Vesa --- .../usb/qcom,snps-eusb2-repeater.yaml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/qcom,snps-eusb2-repeater.yaml diff --git a/Documentation/devicetree/bindings/usb/qcom,snps-eusb2-repeater.yaml b/Documentation/devicetree/bindings/usb/qcom,snps-eusb2-repeater.yaml new file mode 100644 index 000000000000..f2b5ace675eb --- /dev/null +++ b/Documentation/devicetree/bindings/usb/qcom,snps-eusb2-repeater.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/qcom,snps-eusb2-repeater.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Synopsis eUSB2 to USB 2.0 repeater + +maintainers: + - Abel Vesa + +properties: + compatible: + const: qcom,pm8550b-eusb2-repeater + + reg: + maxItems: 1 + + vdd18-supply: true + + vdd3-supply: true + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + pm8550b: pmic@7 { + compatible = "qcom,pm8550", "qcom,spmi-pmic"; + reg = <0x7 SPMI_USID>; + #address-cells = <1>; + #size-cells = <0>; + + pm8550b_eusb2_repeater: usb-repeater@fd00 { + compatible = "qcom,pm8550b-eusb2-repeater"; + reg = <0xfd00>; + }; + }; +... From patchwork Wed Nov 16 12:30:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abel Vesa X-Patchwork-Id: 21026 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp113714wru; Wed, 16 Nov 2022 04:34:09 -0800 (PST) X-Google-Smtp-Source: AA0mqf7d3d0vN83FMRS8k9ES4N0olvqTFKsRp7ON/fW1VLa6R4Rcr95XvYnNLZ0HXchT4ebRIX0X X-Received: by 2002:a17:907:77c4:b0:78d:2af:a818 with SMTP id kz4-20020a17090777c400b0078d02afa818mr17088953ejc.675.1668602049456; Wed, 16 Nov 2022 04:34:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668602049; cv=none; d=google.com; s=arc-20160816; b=UWq6PiJiONUr+Nh1zMT0EDBsobw8EcwgqIcwbpcWIS+JhjT+M+vpij/6gu82ZNWj/7 R/qrwSLqQ/CxNWQTgv8wVsr0Pe5fPdAlv0b9Do9foqhqRpVe5kH4Nnd5Yzbeah8LeRRX 3vNa6dXwx1PkOEKf52lVexp/4Qit2b6t4kcqQGQ7CNhaJIhSdzcnRF/oyHMr/8QYeQWu pMDgMDnaryk8VNjBu71494JWbEnRzQp/Y6UzuN7yI7lEtmd9/CXlWJZK/tDs60J+qiyW yalelbCvMJq/Fu3MkLxRPP/IaGRe9s11CdoI6jTd8ZDZbcC958aytPy60NJS8w9J/spo GyuA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=giz1O34wJy7wAaesQ+FF9P4d8dC3HL0qQyzf5aCfDtI=; b=eaeBwJ6jD8SzYv1ovWj015UCl+p+ul7Sg73B9J6BRJE24zPRWgCrT25fchx9L+40u6 fa6aU303NJ3VT8nZlHio5awQDYL8EDhDTnQcAor84sJYJy4SJT3UdYoAJ3nZJBIGGrav YBTbKoAnJLsa250gdj1v7qewGPYppvO3ybx12dgUkCW8EXWTj9mkaIJ5ww4z1+ToWF5D JkTDodhNycEsOmMjGWbnObNKXnWRWhvHbBwEziKadYKxt2qxntksv1ihPLyKgC97Rl1N 6ytqV+kGmZwYT+6UN0abafNfSWVA0VESvJw2St9+N748xYT6e2Pk8pfxdyeZaYLP7olY o8uw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=f629j43m; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bc10-20020a056402204a00b00457f5aa9dc6si13031344edb.528.2022.11.16.04.33.44; Wed, 16 Nov 2022 04:34:09 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=f629j43m; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233773AbiKPMbq (ORCPT + 99 others); Wed, 16 Nov 2022 07:31:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46226 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238925AbiKPMbD (ORCPT ); Wed, 16 Nov 2022 07:31:03 -0500 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A57A5101EC for ; Wed, 16 Nov 2022 04:30:39 -0800 (PST) Received: by mail-wr1-x429.google.com with SMTP id l14so29678671wrw.2 for ; Wed, 16 Nov 2022 04:30:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=giz1O34wJy7wAaesQ+FF9P4d8dC3HL0qQyzf5aCfDtI=; b=f629j43mafTaOsWIuSAx2miVnTB7i3LJ4zxycA8qlKgosC41Di6RVChbXNnhQ6zpLk CkylExavPLU0yzIZi6p9QV5xdTc8x3OBqWRKGM3yXzkvmz/+V+OKPyag10pzQBq7FxQl pzm1+iG7natxVG/vrjkQYvUlt03U8VkrZ7WtjRO8xuwsUHrhQvBwnmEp3Lf3Hqrbz8NH Ie+VikfwnaeJpb/1x89S9pGE4Uo4dFXU8m+V7P36iHWnle2khpHtN4tNROZZasCtyFju NzEpnyavk4UvkFFEuxuQ5XxEZ7/0NbXMrMv4V+j5jqwxq71AQiyuM8ZMuXDkEqLoIMoK ClQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=giz1O34wJy7wAaesQ+FF9P4d8dC3HL0qQyzf5aCfDtI=; b=CbIbAMUve5uNoUkmsWaxs7QD78kMDgXAx3XpXUherZrBWbUeWUkb2StCELdAfPEeS7 Im7BzKvFJqBgVVW+/vXBPYYuLozG3n0FQp1zb2EybJTmzw4UJZcfVku+9ZRqTnyQbPh8 gevqcGYvXMz3nmlp2dMPpU6rdRAHSh9kW/mKEq9HPzAul6NfgwNoL68087B2vCMZQ7Sp KZEYeGtppNYFJqlKgYhL11Hkp2VkR9XJRclM8nWfX9k7mSjk5riasZaVXR/EqeoGdvYu CsEDup297KhmxUNWmBZ9q9C4fPJ43sR3km2JcuV4aRa0jgEOTmwqBz4TvSMwzSlnjlMF fd0A== X-Gm-Message-State: ANoB5pleTeG+xiaGrPpWpL+3aMwHY4Q6h5TfaFR6HrWSIRsvvIUP61g+ sSrAAh6d42k5YSw1HeeMYXIk3w== X-Received: by 2002:a05:6000:12cf:b0:236:6e75:dc37 with SMTP id l15-20020a05600012cf00b002366e75dc37mr12858672wrx.504.1668601838129; Wed, 16 Nov 2022 04:30:38 -0800 (PST) Received: from localhost.localdomain ([94.52.112.99]) by smtp.gmail.com with ESMTPSA id l42-20020a05600c1d2a00b003cf4eac8e80sm2870991wms.23.2022.11.16.04.30.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Nov 2022 04:30:37 -0800 (PST) From: Abel Vesa To: Andy Gross , Bjorn Andersson , Konrad Dybcio , Greg Kroah-Hartman , Rob Herring , Krzysztof Kozlowski Cc: Linux Kernel Mailing List , devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-scsi@vger.kernel.org, linux-usb@vger.kernel.org Subject: [RFC PATCH 3/3] usb: repeater: Add Qualcomm PMIC eUSB2 driver Date: Wed, 16 Nov 2022 14:30:19 +0200 Message-Id: <20221116123019.2753230-4-abel.vesa@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221116123019.2753230-1-abel.vesa@linaro.org> References: <20221116123019.2753230-1-abel.vesa@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749656062251698375?= X-GMAIL-MSGID: =?utf-8?q?1749656062251698375?= PM8550B contains a eUSB2 repeater used for making the eUSB2 from SM8550 USB 2.0 compliant. Add a platform specific repeater driver. It implements ops for init, reset and power on/off. On init, there is a configuration table that needs to be written to the repeater's registers. Signed-off-by: Abel Vesa --- drivers/usb/repeater/Kconfig | 11 + drivers/usb/repeater/Makefile | 1 + .../usb/repeater/repeater-qcom-pmic-eusb2.c | 251 ++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 drivers/usb/repeater/repeater-qcom-pmic-eusb2.c diff --git a/drivers/usb/repeater/Kconfig b/drivers/usb/repeater/Kconfig index e12cd22c0adb..20baeb8f950c 100644 --- a/drivers/usb/repeater/Kconfig +++ b/drivers/usb/repeater/Kconfig @@ -7,3 +7,14 @@ config USB_REPEATER driver to bind together and to provide the USB driver ways to perform set of operations with repeater for USB2 functionality using PHY and controller driver. + +config QCOM_PMIC_EUSB2_REPEATER + tristate "USB eUSB2 Repeater driver" + select USB_REPEATER + help + Enable this to support the USB eUSB2 repeater on Qualcomm PMIC chips. + This driver provides support to reset, initialize, power up and configure + the eUSB2 repeater for USB HS/FS/LS functionality where eUSB2 repeater + is used. + + To compile the driver as a module, choose M here. diff --git a/drivers/usb/repeater/Makefile b/drivers/usb/repeater/Makefile index 2d1b5f348976..fed128407315 100644 --- a/drivers/usb/repeater/Makefile +++ b/drivers/usb/repeater/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_USB_REPEATER) += repeater.o +obj-$(CONFIG_QCOM_PMIC_EUSB2_REPEATER) += repeater-qcom-pmic-eusb2.o diff --git a/drivers/usb/repeater/repeater-qcom-pmic-eusb2.c b/drivers/usb/repeater/repeater-qcom-pmic-eusb2.c new file mode 100644 index 000000000000..1b6d46c28da4 --- /dev/null +++ b/drivers/usb/repeater/repeater-qcom-pmic-eusb2.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include + +/* eUSB2 status registers */ +#define EUSB2_RPTR_STATUS 0x08 +#define RPTR_OK BIT(7) + +/* eUSB2 control registers */ +#define EUSB2_EN_CTL1 0x46 +#define EUSB2_RPTR_EN BIT(7) + +#define PHY_HOST_MODE BIT(0) +#define EUSB2_FORCE_EN_5 0xE8 +#define F_CLK_19P2M_EN BIT(6) +#define F_CLK_19P2M_EN_SHIFT 6 + +#define EUSB2_FORCE_VAL_5 0xED +#define V_CLK_19P2M_EN BIT(6) +#define V_CLK_19P2M_EN_SHIFT 6 + +#define EUSB2_TUNE_IUSB2 0x51 +#define EUSB2_TUNE_SQUELCH_U 0x54 +#define EUSB2_TUNE_USB2_PREEM 0x57 + +#define QCOM_EUSB2_REPEATER_INIT_CFG(o, v) \ + { \ + .offset = o, \ + .val = v, \ + } + +#define to_qcom_eusb2_repeater(x) \ + container_of((x), struct qcom_eusb2_repeater, repeater) + +struct qcom_eusb2_repeater_init_tbl { + unsigned int offset; + unsigned int val; +}; + +struct qcom_eusb2_repeater { + struct usb_repeater repeater; + struct regmap *regmap; + u16 base; + struct regulator_bulk_data *vregs; + const struct qcom_eusb2_repeater_cfg *cfg; +}; + +struct qcom_eusb2_repeater_cfg { + const struct qcom_eusb2_repeater_init_tbl *init_tbl; + int init_tbl_num; + /* regulators to be requested */ + const char * const *vreg_list; + int num_vregs; +}; + +static const char * const pm8550b_vreg_l[] = { + "vdd18", "vdd3", +}; + +static const struct qcom_eusb2_repeater_init_tbl pm8550b_init_tbl[] = { + QCOM_EUSB2_REPEATER_INIT_CFG(EUSB2_TUNE_IUSB2, 0x8), + QCOM_EUSB2_REPEATER_INIT_CFG(EUSB2_TUNE_SQUELCH_U, 0x3), + QCOM_EUSB2_REPEATER_INIT_CFG(EUSB2_TUNE_USB2_PREEM, 0x5), +}; + +static const struct qcom_eusb2_repeater_cfg pm8550b_eusb2_cfg = { + .init_tbl = pm8550b_init_tbl, + .init_tbl_num = ARRAY_SIZE(pm8550b_init_tbl), + .vreg_list = pm8550b_vreg_l, + .num_vregs = ARRAY_SIZE(pm8550b_vreg_l), +}; + +static int qcom_eusb2_repeater_init_vregs(struct qcom_eusb2_repeater *rptr) +{ + int num = rptr->cfg->num_vregs; + struct device *dev = rptr->repeater.dev; + int i; + + rptr->vregs = devm_kcalloc(dev, num, sizeof(*rptr->vregs), GFP_KERNEL); + if (!rptr->vregs) + return -ENOMEM; + + for (i = 0; i < num; i++) + rptr->vregs[i].supply = rptr->cfg->vreg_list[i]; + + return devm_regulator_bulk_get(dev, num, rptr->vregs); +} + +static int qcom_eusb2_repeater_cfg_init(struct qcom_eusb2_repeater *rptr) +{ + const struct qcom_eusb2_repeater_init_tbl *init_tbl = rptr->cfg->init_tbl; + int num = rptr->cfg->init_tbl_num; + int i; + + for (i = 0; i < num; i++) + regmap_update_bits(rptr->regmap, rptr->base + init_tbl[i].offset, + init_tbl[i].val, init_tbl[i].val); + return 0; +} + +static int qcom_eusb2_repeater_init(struct usb_repeater *r) +{ + struct qcom_eusb2_repeater *rptr = to_qcom_eusb2_repeater(r); + int ret = 0; + u32 val; + + qcom_eusb2_repeater_cfg_init(rptr); + + if (r->flags & PHY_HOST_MODE) { + /* + * CM.Lx is prohibited when repeater is already into Lx state as + * per eUSB 1.2 Spec. Below implement software workaround until + * PHY and controller is fixing seen observation. + */ + regmap_update_bits(rptr->regmap, rptr->base + EUSB2_FORCE_EN_5, + F_CLK_19P2M_EN, F_CLK_19P2M_EN); + regmap_update_bits(rptr->regmap, rptr->base + EUSB2_FORCE_VAL_5, + V_CLK_19P2M_EN, V_CLK_19P2M_EN); + } else { + /* + * In device mode clear host mode related workaround as there + * is no repeater reset available, and enable/disable of + * repeater doesn't clear previous value due to shared + * regulators (say host <-> device mode switch). + */ + regmap_update_bits(rptr->regmap, rptr->base + EUSB2_FORCE_EN_5, + F_CLK_19P2M_EN, 0); + regmap_update_bits(rptr->regmap, rptr->base + EUSB2_FORCE_VAL_5, + V_CLK_19P2M_EN, 0); + } + + ret = regmap_read_poll_timeout(rptr->regmap, rptr->base + EUSB2_RPTR_STATUS, val, + val & RPTR_OK, 10, 5); + if (ret) + dev_err(r->dev, "initialization timed-out\n"); + + return ret; +} + +static int qcom_eusb2_repeater_reset(struct usb_repeater *r, bool assert) +{ + struct qcom_eusb2_repeater *rptr = to_qcom_eusb2_repeater(r); + + return regmap_update_bits(rptr->regmap, rptr->base + EUSB2_EN_CTL1, + EUSB2_RPTR_EN, assert ? EUSB2_RPTR_EN : 0x0); +} + +static int qcom_eusb2_repeater_power_on(struct usb_repeater *r) +{ + struct qcom_eusb2_repeater *rptr = to_qcom_eusb2_repeater(r); + + return regulator_bulk_enable(rptr->cfg->num_vregs, rptr->vregs); +} + +static int qcom_eusb2_repeater_power_off(struct usb_repeater *r) +{ + struct qcom_eusb2_repeater *rptr = to_qcom_eusb2_repeater(r); + + return regulator_bulk_disable(rptr->cfg->num_vregs, rptr->vregs); +} + +static int qcom_eusb2_repeater_probe(struct platform_device *pdev) +{ + struct qcom_eusb2_repeater *rptr; + struct device *dev = &pdev->dev; + struct device_node *node; + u32 res; + int ret; + + node = dev->of_node; + + rptr = devm_kzalloc(dev, sizeof(*rptr), GFP_KERNEL); + if (!rptr) + return -ENOMEM; + + rptr->repeater.dev = dev; + dev_set_drvdata(dev, rptr); + + /* Get the specific init parameters of QMP phy */ + rptr->cfg = of_device_get_match_data(dev); + if (!rptr->cfg) + return -EINVAL; + + rptr->regmap = dev_get_regmap(dev->parent, NULL); + if (!rptr->regmap) + return -ENXIO; + + ret = of_property_read_u32(node, "reg", &res); + if (ret < 0) + return ret; + + rptr->base = res; + + ret = qcom_eusb2_repeater_init_vregs(rptr); + if (ret < 0) { + dev_err(dev, "unable to get supplies\n"); + return ret; + } + + rptr->repeater.init = qcom_eusb2_repeater_init; + rptr->repeater.reset = qcom_eusb2_repeater_reset; + rptr->repeater.power_on = qcom_eusb2_repeater_power_on; + rptr->repeater.power_off = qcom_eusb2_repeater_power_off; + + return usb_add_repeater_dev(&rptr->repeater); +} + +static int qcom_eusb2_repeater_remove(struct platform_device *pdev) +{ + struct qcom_eusb2_repeater *rptr = platform_get_drvdata(pdev); + + if (!rptr) + return 0; + + usb_remove_repeater_dev(&rptr->repeater); + qcom_eusb2_repeater_power_off(&rptr->repeater); + return 0; +} + +static const struct of_device_id qcom_eusb2_repeater_id_table[] = { + { + .compatible = "qcom,pm8550b-eusb2-repeater", + .data = &pm8550b_eusb2_cfg, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, qcom_eusb2_repeater_id_table); + +static struct platform_driver qcom_eusb2_repeater_driver = { + .probe = qcom_eusb2_repeater_probe, + .remove = qcom_eusb2_repeater_remove, + .driver = { + .name = "qcom-pmic-eusb2-repeater", + .of_match_table = of_match_ptr(qcom_eusb2_repeater_id_table), + }, +}; + +module_platform_driver(qcom_eusb2_repeater_driver); +MODULE_DESCRIPTION("Qualcomm PMIC eUSB2 repeater driver"); +MODULE_LICENSE("GPL");