From patchwork Sun Feb 18 18:44:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Blumenstingl X-Patchwork-Id: 10226893 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AAC5A60244 for ; Sun, 18 Feb 2018 18:49:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 98020286EE for ; Sun, 18 Feb 2018 18:49:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 89DAF2891B; Sun, 18 Feb 2018 18:49:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 70BC2286EE for ; Sun, 18 Feb 2018 18:49:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=KoNS2VJ+R0qExohsl4NGsTlI/H1+r88UfGS35Kp44bM=; b=oF8qfc57mcqy/Q/7+Df9PgXzOz MjVmabOZPLV1lEUbrWS5jAfvhkhQ0vfbzG/faQnvGbQAJQOkfVhsQTKrbPM6s1OMoD5aEeNNPSHnQ MF3+P4o84Tq2fanQ+jtmeaX/712vZIASKsPH0TrV3ViVU8oZ7UfEtFak3a60E4miYWkGdFM6TtDLT 3Wp2JFFoq0utLgbUQkaWcYVLzkFHs0AsG3bqkWJ9Y4o5MzbJYcMqyh4ee+ItFjZ3ffhOabHbVg+Gu zinJyH9LL0lJ4vk38wKzWXTliNmV8/givrFfHSad9vmlrKf3kaVxbfEmZtG2dzmYx12EGsEg42EdP qI4PuLaw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1enU1k-0008OV-Lx; Sun, 18 Feb 2018 18:49:32 +0000 Received: from mail-wm0-x244.google.com ([2a00:1450:400c:c09::244]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1enTxu-0006Qh-I5; Sun, 18 Feb 2018 18:45:48 +0000 Received: by mail-wm0-x244.google.com with SMTP id k87so11410004wmi.0; Sun, 18 Feb 2018 10:45:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=LYJXMg3lM2PrTtjV7yQumN9eBE0WlxIfnJ0kZukdIWM=; b=Ym5RsO2NrxpGWT4RaIDgre8TkY/EtWJiZaqTSuBdOEz3uB7dwiyxlxGyqSuX2/pULg WE+xTO7DhzzigawKhpRDH+/jvMyiUL5LKgj+z9Mrhjv5ZQqGfQQTKk1gPWcSieNrB9VA iNr9Z44GZhqBjbJlpuD1dHEbvQzLLEZfH31kVmEPbKWrMM8QZfm/0vvIoB1XftBH1YU2 rVF2p9UAE9ffJJL323mhM9ZB91gBghgcnXskD3JIsxtn1SV5IaaPr1Q9iPa2woOAq5mJ eHhcnkp5zeSf84GX7AWUETDa5cDrijS8RXjitQeVyjgww/U6KaAcRGnFsuQ0lZanCprm 9TLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=LYJXMg3lM2PrTtjV7yQumN9eBE0WlxIfnJ0kZukdIWM=; b=MSKSz7zJzWvMFkmVaQhKLL9fbq0jisqal7sLjYtSklr8xa6XFYHARbaKZ/SDeFTpwy but7+OLVnBMb5NFKzYqY8Em8jvPOnbwV4lt7M2lyhiA+LI/OU9g+QoSQ1eVa/0Gtf0uO 1nzo55vaD0PTozzuvcbG9trnwd47VkOkM+EqKAYWD9pRESyf4AIqwq1LqFSe+MYKYbv2 DVmpTJCd3zDuFPwVMzg7gu6CV7DC1pCUoBblZW9CxYoN5IB5bg9DvjHhFF25gSx9BB6y 2uEBJDVSrfS+Z3NWCA+bnIAL+is8USKzIyyzdp1fqlu0lmn7hgFdq+/YRsiFn3CRW1DK bphw== X-Gm-Message-State: APf1xPDhc6SOCPeKkS/W6awWsdU2sf+YPAUkQahukK17BFwaCq3R9ZdB UwXwpFiDTuZBSON1BUtPEy4= X-Google-Smtp-Source: AH8x225K+E9kP2PU1HTIqjv0hSonCRwRZuU0GD7NWuXwtqpFLSt8d7QwipNkJqwzc493H8VLYGLsZA== X-Received: by 10.28.245.25 with SMTP id t25mr8843333wmh.77.1518979522283; Sun, 18 Feb 2018 10:45:22 -0800 (PST) Received: from blackbox.darklights.net (p200300DCD7404304DD6DB7B324975560.dip0.t-ipconnect.de. [2003:dc:d740:4304:dd6d:b7b3:2497:5560]) by smtp.googlemail.com with ESMTPSA id 63sm22860290wms.46.2018.02.18.10.45.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 18 Feb 2018 10:45:21 -0800 (PST) From: Martin Blumenstingl To: linux-usb@vger.kernel.org, mathias.nyman@intel.com, arnd@arndb.de, gregkh@linuxfoundation.org, felipe.balbi@linux.intel.com Subject: [PATCH usb-next v10 3/8] usb: core: add a wrapper for the USB PHYs on the HCD Date: Sun, 18 Feb 2018 19:44:59 +0100 Message-Id: <20180218184504.3331-4-martin.blumenstingl@googlemail.com> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180218184504.3331-1-martin.blumenstingl@googlemail.com> References: <20180218184504.3331-1-martin.blumenstingl@googlemail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180218_104534_721787_3B61E2C5 X-CRM114-Status: GOOD ( 17.86 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, Chunfeng Yun , Peter.Chen@nxp.com, Martin Blumenstingl , narmstrong@baylibre.com, yixun.lan@amlogic.com, robh+dt@kernel.org, jonathanh@nvidia.com, linux@prisktech.co.nz, matthias.bgg@gmail.com, thierry.reding@gmail.com, linux-mediatek@lists.infradead.org, linux-amlogic@lists.infradead.org, linux-tegra@vger.kernel.org, stern@rowland.harvard.edu, linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Many SoC platforms have separate devices for the USB PHY which are registered through the generic PHY framework. These PHYs have to be enabled to make the USB controller actually work. They also have to be disabled again on shutdown/suspend. Currently (at least) the following HCI platform drivers are using custom code to obtain all PHYs via devicetree for the roothub/controller and disable/enable them when required: - ehci-platform.c has ehci_platform_power_{on,off} - xhci-mtk.c has xhci_mtk_phy_{init,exit,power_on,power_off} - ohci-platform.c has ohci_platform_power_{on,off} With this new wrapper the USB PHYs can be specified directly in the USB controller's devicetree node (just like on the drivers listed above). This allows SoCs like the Amlogic Meson GXL family to operate correctly once this is wired up correctly. These SoCs use a dwc3 controller and require all USB PHYs to be initialized (if one of the USB PHYs it not initialized then none of USB port works at all). Signed-off-by: Martin Blumenstingl Tested-by: Yixun Lan Cc: Neil Armstrong Cc: Chunfeng Yun --- drivers/usb/core/Makefile | 2 +- drivers/usb/core/phy.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/core/phy.h | 7 ++ 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/core/phy.c create mode 100644 drivers/usb/core/phy.h diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 92c9cefb4317..18e874b0441e 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile @@ -6,7 +6,7 @@ usbcore-y := usb.o hub.o hcd.o urb.o message.o driver.o usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o usbcore-y += devio.o notify.o generic.o quirks.o devices.o -usbcore-y += port.o +usbcore-y += phy.o port.o usbcore-$(CONFIG_OF) += of.o usbcore-$(CONFIG_USB_PCI) += hcd-pci.o diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c new file mode 100644 index 000000000000..09b7c43c0ea4 --- /dev/null +++ b/drivers/usb/core/phy.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * A wrapper for multiple PHYs which passes all phy_* function calls to + * multiple (actual) PHY devices. This is comes handy when initializing + * all PHYs on a HCD and to keep them all in the same state. + * + * Copyright (C) 2018 Martin Blumenstingl + */ + +#include +#include +#include +#include + +#include "phy.h" + +struct usb_phy_roothub { + struct phy *phy; + struct list_head list; +}; + +static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev) +{ + struct usb_phy_roothub *roothub_entry; + + roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL); + if (!roothub_entry) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&roothub_entry->list); + + return roothub_entry; +} + +static int usb_phy_roothub_add_phy(struct device *dev, int index, + struct list_head *list) +{ + struct usb_phy_roothub *roothub_entry; + struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index); + + if (IS_ERR_OR_NULL(phy)) { + if (!phy || PTR_ERR(phy) == -ENODEV) + return 0; + else + return PTR_ERR(phy); + } + + roothub_entry = usb_phy_roothub_alloc(dev); + if (IS_ERR(roothub_entry)) + return PTR_ERR(roothub_entry); + + roothub_entry->phy = phy; + + list_add_tail(&roothub_entry->list, list); + + return 0; +} + +struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev) +{ + struct usb_phy_roothub *phy_roothub; + struct usb_phy_roothub *roothub_entry; + struct list_head *head; + int i, num_phys, err; + + num_phys = of_count_phandle_with_args(dev->of_node, "phys", + "#phy-cells"); + if (num_phys <= 0) + return NULL; + + phy_roothub = usb_phy_roothub_alloc(dev); + if (IS_ERR(phy_roothub)) + return phy_roothub; + + for (i = 0; i < num_phys; i++) { + err = usb_phy_roothub_add_phy(dev, i, &phy_roothub->list); + if (err) + goto err_out; + } + + head = &phy_roothub->list; + + list_for_each_entry(roothub_entry, head, list) { + err = phy_init(roothub_entry->phy); + if (err) + goto err_exit_phys; + } + + return phy_roothub; + +err_exit_phys: + list_for_each_entry_continue_reverse(roothub_entry, head, list) + phy_exit(roothub_entry->phy); + +err_out: + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(usb_phy_roothub_init); + +int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub) +{ + struct usb_phy_roothub *roothub_entry; + struct list_head *head; + int err, ret = 0; + + if (!phy_roothub) + return 0; + + head = &phy_roothub->list; + + list_for_each_entry(roothub_entry, head, list) { + err = phy_exit(roothub_entry->phy); + if (err) + ret = ret; + } + + return ret; +} +EXPORT_SYMBOL_GPL(usb_phy_roothub_exit); + +int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub) +{ + struct usb_phy_roothub *roothub_entry; + struct list_head *head; + int err; + + if (!phy_roothub) + return 0; + + head = &phy_roothub->list; + + list_for_each_entry(roothub_entry, head, list) { + err = phy_power_on(roothub_entry->phy); + if (err) + goto err_out; + } + + return 0; + +err_out: + list_for_each_entry_continue_reverse(roothub_entry, head, list) + phy_power_off(roothub_entry->phy); + + return err; +} +EXPORT_SYMBOL_GPL(usb_phy_roothub_power_on); + +void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub) +{ + struct usb_phy_roothub *roothub_entry; + + if (!phy_roothub) + return; + + list_for_each_entry_reverse(roothub_entry, &phy_roothub->list, list) + phy_power_off(roothub_entry->phy); +} +EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off); diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h new file mode 100644 index 000000000000..6fde59bfbff8 --- /dev/null +++ b/drivers/usb/core/phy.h @@ -0,0 +1,7 @@ +struct usb_phy_roothub; + +struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev); +int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub); + +int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub); +void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub);