From patchwork Tue Jul 25 15:43:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugen Hristev X-Patchwork-Id: 1812722 X-Patchwork-Delegate: eugen.hristev@microchip.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=collabora.com header.i=@collabora.com header.a=rsa-sha256 header.s=mail header.b=ivQORRbF; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4R9LtF4cVMz1yYc for ; Wed, 26 Jul 2023 01:44:05 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 5A1268679A; Tue, 25 Jul 2023 17:43:52 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=collabora.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=collabora.com header.i=@collabora.com header.b="ivQORRbF"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8D2BE86789; Tue, 25 Jul 2023 17:43:42 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from madras.collabora.co.uk (madras.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e5ab]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id EC93A86795 for ; Tue, 25 Jul 2023 17:43:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=collabora.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=eugen.hristev@collabora.com Received: from eugen-station.. (unknown [82.76.24.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: ehristev) by madras.collabora.co.uk (Postfix) with ESMTPSA id 0FAC36606F9F; Tue, 25 Jul 2023 16:43:35 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1690299815; bh=fQY5BNhkbwWHDKeA/a0Vhey68Wz5D8QR5jE5H1VWikA=; h=From:To:Cc:Subject:Date:From; b=ivQORRbFs6trrJpANanBhfXMzvnGHx2ihbJRrgcJKG5B3xPjCaWLLe4HK3HCqCjBk 8iWmq6jI2ArEkzolcT+zN3W1yjLtPsT089ojMboAXq8tW1jqdXj8zI0ULTDXSCNWaU gS9ujft9pB6DIVOO8V1CBZ2Yn1YMXW3iILg5l+BG3JIS2+I4nidFzTAtv9hsWBDCFB JNdnWpDhS6CaugYDUrjbgeIHvngTEIuN95ejr88rorPrNVBGOYuArOjHUdqDWaiBe0 VNWuCgcbS8nMqLkUoDEGM3ZJJnwX5qssljCxPipR1dihDtEa2CVwhB00TrXwPsGBnt MmMcJn8CaDJoA== From: Eugen Hristev To: marex@denx.de Cc: u-boot@lists.denx.de, eugen.hristev@collabora.com, mihai.sain@microchip.com, Sergiu Moga Subject: [PATCH v5 1/3] phy: at91: Add support for the USB 2.0 PHY's of SAMA7 Date: Tue, 25 Jul 2023 18:43:15 +0300 Message-Id: <20230725154317.663337-1-eugen.hristev@collabora.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Sergiu Moga In order to have USB functionality, drivers for SAMA7's USB 2.0 PHY's have been added. There is one driver for UTMI clock's SFR and RESET required functionalities and one for its three possible subclocks of the phy's themselves. In order for this layout to properly work in conjunction with CCF and DT, the former driver will also act as a clock provider for the three phy's with the help of a custom hook into the driver's of_xlate method. Signed-off-by: Sergiu Moga Tested-by: Mihai Sain Reviewed-by: Marek Vasut --- v1 -> v2: - use *_bulk API's v2 -> v3: - use if (CONFIG_IS_ENABLED(...)) v3->v4: - none v4->v5 - add Rb Marek drivers/phy/Kconfig | 10 ++ drivers/phy/Makefile | 1 + drivers/phy/phy-sama7-usb.c | 90 +++++++++++++ drivers/phy/phy-sama7-utmi-clk.c | 216 +++++++++++++++++++++++++++++++ 4 files changed, 317 insertions(+) create mode 100644 drivers/phy/phy-sama7-usb.c create mode 100644 drivers/phy/phy-sama7-utmi-clk.c diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 7a2d54f71d21..999f9793fa3f 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -281,6 +281,16 @@ config PHY_XILINX_ZYNQMP Enable this to support ZynqMP High Speed Gigabit Transceiver that is part of ZynqMP SoC. +config PHY_MICROCHIP_SAMA7_USB + tristate "Microchip SAMA7 USB 2.0 PHY" + depends on PHY && ARCH_AT91 + help + Enable this to support SAMA7 USB 2.0 PHY. + + The USB 2.0 PHY integrates high-speed, full-speed and low-speed + termination and signal switching. With a single resistor, it + requires minimal external components. + source "drivers/phy/rockchip/Kconfig" source "drivers/phy/cadence/Kconfig" source "drivers/phy/ti/Kconfig" diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index aca365d219c4..0b609768774a 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o obj-$(CONFIG_PHY_NPCM_USB) += phy-npcm-usb.o obj-$(CONFIG_PHY_IMX8MQ_USB) += phy-imx8mq-usb.o obj-$(CONFIG_PHY_XILINX_ZYNQMP) += phy-zynqmp.o +obj-$(CONFIG_PHY_MICROCHIP_SAMA7_USB) += phy-sama7-utmi-clk.o phy-sama7-usb.o obj-y += cadence/ obj-y += ti/ obj-y += qcom/ diff --git a/drivers/phy/phy-sama7-usb.c b/drivers/phy/phy-sama7-usb.c new file mode 100644 index 000000000000..200324d81281 --- /dev/null +++ b/drivers/phy/phy-sama7-usb.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Support for Atmel/Microchip USB PHY's. + * + * Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries + * + * Author: Sergiu Moga + */ + +#include +#include +#include +#include +#include +#include + +struct sama7_usb_phy { + struct clk *uclk; + struct regmap *sfr; + int port; +}; + +static int sama7_usb_phy_init(struct phy *phy) +{ + struct sama7_usb_phy *sama7_phy = dev_get_priv(phy->dev); + int port = sama7_phy->port; + + regmap_update_bits(sama7_phy->sfr, SAMA7_SFR_UTMI0R(port), + SAMA7_SFR_UTMI_RX_TX_PREEM_AMP_TUNE_1X, + SAMA7_SFR_UTMI_RX_TX_PREEM_AMP_TUNE_1X); + + regmap_update_bits(sama7_phy->sfr, SAMA7_SFR_UTMI0R(port), + SAMA7_SFR_UTMI_RX_VBUS, + SAMA7_SFR_UTMI_RX_VBUS); + + return 0; +} + +static int sama7_phy_power_on(struct phy *phy) +{ + struct sama7_usb_phy *sama7_phy = dev_get_priv(phy->dev); + + clk_prepare_enable(sama7_phy->uclk); + + return 0; +} + +static int sama7_phy_power_off(struct phy *phy) +{ + struct sama7_usb_phy *sama7_phy = dev_get_priv(phy->dev); + + clk_disable_unprepare(sama7_phy->uclk); + + return 0; +} + +static int sama7_usb_phy_probe(struct udevice *dev) +{ + struct sama7_usb_phy *sama7_phy = dev_get_priv(dev); + + sama7_phy->uclk = devm_clk_get(dev, "utmi_clk"); + if (IS_ERR(sama7_phy->uclk)) + return PTR_ERR(sama7_phy->uclk); + + sama7_phy->sfr = syscon_regmap_lookup_by_phandle(dev, "sfr-phandle"); + if (IS_ERR(sama7_phy->sfr)) + return PTR_ERR(sama7_phy->sfr); + + return dev_read_u32(dev, "reg", &sama7_phy->port); +} + +static const struct phy_ops sama7_usb_phy_ops = { + .init = sama7_usb_phy_init, + .power_on = sama7_phy_power_on, + .power_off = sama7_phy_power_off, +}; + +static const struct udevice_id sama7_usb_phy_of_match[] = { + { .compatible = "microchip,sama7g5-usb-phy", }, + { }, +}; + +U_BOOT_DRIVER(sama7_usb_phy_driver) = { + .name = "sama7-usb-phy", + .id = UCLASS_PHY, + .of_match = sama7_usb_phy_of_match, + .ops = &sama7_usb_phy_ops, + .probe = sama7_usb_phy_probe, + .priv_auto = sizeof(struct sama7_usb_phy), +}; diff --git a/drivers/phy/phy-sama7-utmi-clk.c b/drivers/phy/phy-sama7-utmi-clk.c new file mode 100644 index 000000000000..2371b4341cd5 --- /dev/null +++ b/drivers/phy/phy-sama7-utmi-clk.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Support for Atmel/Microchip USB PHY's. + * + * Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries + * + * Author: Sergiu Moga + */ + +#include +#include +#include +#include +#include +#include +#include + +struct sama7_utmi_clk { + struct clk uclk; + struct regmap *regmap_sfr; + struct reset_ctl *reset; + u8 id; +}; + +#define to_sama7_utmi_clk(_c) container_of(_c, struct sama7_utmi_clk, uclk) + +#define UBOOT_DM_CLK_MICROCHIP_SAMA7G5_UTMI "sama7-utmi-clk" +#define UBOOT_DM_MICROCHIP_SAMA7G5_UTMI "sama7-utmi" +#define USB_RESET_NAME_MAX_LEN 16 + +#define AT91_TO_CLK_ID(_t, _i) (((_t) << 8) | ((_i) & 0xff)) + +/* + * UTMI clock description + * @n: clock name + * @p: clock parent name + * @id: clock id in RSTC_GRSTR + */ +static struct { + const char *n; + const char *p; + u8 id; +} sama7_utmick[] = { + { .n = "utmi1", .p = "utmick", .id = 0, }, + { .n = "utmi2", .p = "utmi1", .id = 1, }, + { .n = "utmi3", .p = "utmi1", .id = 2, }, +}; + +static int sama7_utmi_clk_enable(struct clk *clk) +{ + int ret; + + struct sama7_utmi_clk *utmi = to_sama7_utmi_clk(clk); + u8 id = utmi->id; + + ret = reset_assert(utmi->reset); + if (ret) + return ret; + + ret = regmap_update_bits(utmi->regmap_sfr, SAMA7_SFR_UTMI0R(id), + SAMA7_SFR_UTMI_COMMONON, 0); + if (ret < 0) + return ret; + + ret = reset_deassert(utmi->reset); + if (ret) + return ret; + + /* Datasheet states a minimum of 45 us before any USB operation */ + udelay(50); + + return 0; +} + +static int sama7_utmi_clk_disable(struct clk *clk) +{ + int ret; + struct sama7_utmi_clk *utmi = to_sama7_utmi_clk(clk); + u8 id = utmi->id; + + ret = reset_assert(utmi->reset); + if (ret) + return ret; + + regmap_update_bits(utmi->regmap_sfr, SAMA7_SFR_UTMI0R(id), + SAMA7_SFR_UTMI_COMMONON, SAMA7_SFR_UTMI_COMMONON); + + return 0; +} + +static ulong sama7_utmi_clk_get_rate(struct clk *clk) +{ + /* Return utmick's rate: 480MHz */ + return clk_get_parent_rate(clk); +} + +static const struct clk_ops sama7_utmi_clk_ops = { + .enable = sama7_utmi_clk_enable, + .disable = sama7_utmi_clk_disable, + .get_rate = sama7_utmi_clk_get_rate, +}; + +static struct clk* +sama7_utmi_clk_register(struct regmap *regmap_sfr, struct reset_ctl *reset, + const char *name, const char *parent_name, u8 id) +{ + struct clk *clk; + struct sama7_utmi_clk *utmi_clk; + int ret; + + if (!regmap_sfr || !reset || !name || !parent_name) + return ERR_PTR(-EINVAL); + + utmi_clk = kzalloc(sizeof(*utmi_clk), GFP_KERNEL); + if (!utmi_clk) + return ERR_PTR(-ENOMEM); + + utmi_clk->reset = reset; + utmi_clk->regmap_sfr = regmap_sfr; + utmi_clk->id = id; + + clk = &utmi_clk->uclk; + ret = clk_register(clk, UBOOT_DM_CLK_MICROCHIP_SAMA7G5_UTMI, + name, parent_name); + if (ret) { + kfree(utmi_clk); + clk = ERR_PTR(ret); + } + + clk_dm(AT91_TO_CLK_ID(USB_UTMI, utmi_clk->id), clk); + + return clk; +} + +static int sama7_utmi_probe(struct udevice *dev) +{ + struct clk *utmi_parent_clk, *utmi_clk[ARRAY_SIZE(sama7_utmick)]; + char name[USB_RESET_NAME_MAX_LEN]; + struct sama7_utmi_clk *uclk; + struct reset_ctl *phy_reset; + struct regmap *regmap_sfr; + int ret, i, j; + + utmi_parent_clk = devm_clk_get(dev, "utmi_clk"); + if (IS_ERR(utmi_parent_clk)) + return PTR_ERR(utmi_parent_clk); + + regmap_sfr = syscon_regmap_lookup_by_phandle(dev, "sfr-phandle"); + if (IS_ERR(regmap_sfr)) + return PTR_ERR(regmap_sfr); + + for (i = 0; i < ARRAY_SIZE(sama7_utmick); i++) { + snprintf(name, sizeof(name), "usb%d_reset", i); + phy_reset = devm_reset_control_get(dev, name); + if (IS_ERR(phy_reset)) { + ret = PTR_ERR(phy_reset); + goto err_uclk_register; + } + + utmi_clk[i] = sama7_utmi_clk_register(regmap_sfr, phy_reset, + sama7_utmick[i].n, + sama7_utmick[i].p, + sama7_utmick[i].id); + if (IS_ERR(utmi_clk[i])) { + ret = PTR_ERR(utmi_clk[i]); + goto err_uclk_register; + } + } + + return 0; + +err_uclk_register: + for (j = 0; j < i; j++) { + uclk = to_sama7_utmi_clk(utmi_clk[j]); + kfree(uclk); + } + + return ret; +}; + +static const struct udevice_id sama7_utmi_clk_dt_ids[] = { + { .compatible = "microchip,sama7g5-utmi-clk", }, + { /* sentinel */}, +}; + +static int utmi_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) +{ + if (args->args_count != 1) { + debug("UTMI: clk: Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + clk->id = AT91_TO_CLK_ID(USB_UTMI, args->args[0]); + + return 0; +} + +static const struct clk_ops sama7_utmi_ops = { + .of_xlate = utmi_clk_of_xlate, + .enable = ccf_clk_enable, + .disable = ccf_clk_disable, +}; + +U_BOOT_DRIVER(microhip_sama7g5_utmi_clk) = { + .name = UBOOT_DM_CLK_MICROCHIP_SAMA7G5_UTMI, + .id = UCLASS_CLK, + .ops = &sama7_utmi_clk_ops, +}; + +U_BOOT_DRIVER(microhip_sama7g5_utmi) = { + .name = UBOOT_DM_MICROCHIP_SAMA7G5_UTMI, + .of_match = sama7_utmi_clk_dt_ids, + .id = UCLASS_CLK, + .ops = &sama7_utmi_ops, + .probe = sama7_utmi_probe, +}; From patchwork Tue Jul 25 15:43:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugen Hristev X-Patchwork-Id: 1812720 X-Patchwork-Delegate: eugen.hristev@microchip.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=collabora.com header.i=@collabora.com header.a=rsa-sha256 header.s=mail header.b=NOsEASgC; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4R9Lst6Wmgz1yYc for ; Wed, 26 Jul 2023 01:43:46 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 39C4F866C1; Tue, 25 Jul 2023 17:43:44 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=collabora.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=collabora.com header.i=@collabora.com header.b="NOsEASgC"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1D4E7860AC; Tue, 25 Jul 2023 17:43:42 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from madras.collabora.co.uk (madras.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e5ab]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 68807867A4 for ; Tue, 25 Jul 2023 17:43:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=collabora.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=eugen.hristev@collabora.com Received: from eugen-station.. (unknown [82.76.24.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: ehristev) by madras.collabora.co.uk (Postfix) with ESMTPSA id 99A7D6607083; Tue, 25 Jul 2023 16:43:35 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1690299816; bh=aHpEOiGJSha0deOZKqQD8rp1LBmoBhYdzQ72hcTRow4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NOsEASgCXd4oyNBzBEzZwrFmQPCOX0sUTqNC4K/lnUJGeWQL8DH44sC8/S1uIs17Z Loek32viOo0fSG+Xs/feUyg8A9erjSiABSYP+vzeX2WNTr4Y/+Z4nff5FbC6nKjLZ/ /ICjiCcDpl/XpPn6sJHaf+w9Kp6Qn0mXKPvsqio8V9Rv/+xHB0tRofNwu3vhQK9OP9 E/Mb7lJXwVwEUK/ydAYCH101osFBs+ceDD+HS2PehkRl9XyE6tqeyzrzeMBb6g1PMA CJ9uGJcIu4HXOvJ1ULq8FpYq/zWk2xasNA5zP+S78/Ob+yGat2VRUMcNylDX4ALdit XGiyzG07QWh4A== From: Eugen Hristev To: marex@denx.de Cc: u-boot@lists.denx.de, eugen.hristev@collabora.com, mihai.sain@microchip.com, Sergiu Moga Subject: [PATCH v5 2/3] usb: ohci-at91: Enable OHCI functionality and register into DM Date: Tue, 25 Jul 2023 18:43:16 +0300 Message-Id: <20230725154317.663337-2-eugen.hristev@collabora.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230725154317.663337-1-eugen.hristev@collabora.com> References: <20230725154317.663337-1-eugen.hristev@collabora.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Sergiu Moga Register the OHCI driver into DM by properly initializing the required clocks and pins required by the DT node of OHCI. In order for the VBUS to stay enabled, a `child_pre_probe` method has been added to overcome the DM core disabling it in `usb_scan_device`: when the generic `device_probe` method is called, the pinctrl is processed once again, undoing whatever changes have been made in our driver's probe method. Furthermore, enable CONFIG_DM_GPIO whenever this driver and CONFIG_DM_USB are selected. Signed-off-by: Sergiu Moga Reviewed-by: Marek Vasut --- v1 -> v2: - squashed 3/4 into this patch - removed bool clocked - use *_blk API's - select DM_GPIO in Kconfig if DM_USB enabled - use dev_read_u32_default v2 -> v3: - check value of dev_read_addr - clk_disable in case of failure after at91_start_hc v3->v4: none v4->v5: add Rb Marek drivers/usb/host/Kconfig | 1 + drivers/usb/host/ohci-at91.c | 159 +++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1a883babf4c2..e9551a74bb23 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -437,6 +437,7 @@ config USB_ATMEL depends on ARCH_AT91 select SYS_USB_OHCI_CPU_INIT select USB_OHCI_NEW + select DM_GPIO if DM_USB choice prompt "Clock for OHCI" diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 9b955c1bd678..92d0ab7184c4 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -5,6 +5,9 @@ */ #include + +#if !(CONFIG_IS_ENABLED(DM_USB)) + #include int usb_cpu_init(void) @@ -62,3 +65,159 @@ int usb_cpu_init_fail(void) { return usb_cpu_stop(); } + +#else + +#include +#include +#include +#include +#include "ohci.h" + +#define AT91_MAX_USBH_PORTS 3 + +#define at91_for_each_port(index, ports) \ + for ((index) = 0; \ + (index) < min_t(u32, AT91_MAX_USBH_PORTS, (ports)); \ + (index)++) + +struct at91_usbh_data { + enum usb_init_type init_type; + struct gpio_desc vbus_pin[AT91_MAX_USBH_PORTS]; + u32 ports; /* number of ports on root hub */ +}; + +struct ohci_at91_priv { + ohci_t ohci; + struct clk_bulk clks; +}; + +static int at91_start_clock(struct ohci_at91_priv *ohci_at91) +{ + return clk_enable_bulk(&ohci_at91->clks); +} + +static int at91_stop_clock(struct ohci_at91_priv *ohci_at91) +{ + return clk_disable_bulk(&ohci_at91->clks); +} + +static void ohci_at91_set_power(struct at91_usbh_data *pdata, int port, + bool enable) +{ + if (!dm_gpio_is_valid(&pdata->vbus_pin[port])) + return; + + if (enable) + dm_gpio_set_dir_flags(&pdata->vbus_pin[port], + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + else + dm_gpio_set_dir_flags(&pdata->vbus_pin[port], 0); +} + +static int at91_start_hc(struct udevice *dev) +{ + struct ohci_at91_priv *ohci_at91 = dev_get_priv(dev); + + return at91_start_clock(ohci_at91); +} + +static int at91_stop_hc(struct udevice *dev) +{ + struct ohci_at91_priv *ohci_at91 = dev_get_priv(dev); + + return at91_stop_clock(ohci_at91); +} + +static int ohci_atmel_deregister(struct udevice *dev) +{ + struct at91_usbh_data *pdata = dev_get_plat(dev); + int ret, i; + + ret = at91_stop_hc(dev); + if (ret) + return ret; + + at91_for_each_port(i, pdata->ports) + ohci_at91_set_power(pdata, i, false); + + return ohci_deregister(dev); +} + +static int ohci_atmel_child_pre_probe(struct udevice *dev) +{ + struct udevice *ohci_controller = dev_get_parent(dev); + struct at91_usbh_data *pdata = dev_get_plat(ohci_controller); + int i; + + at91_for_each_port(i, pdata->ports) + ohci_at91_set_power(pdata, i, true); + + return 0; +} + +static int ohci_atmel_probe(struct udevice *dev) +{ + struct ohci_at91_priv *ohci_at91 = dev_get_priv(dev); + struct at91_usbh_data *pdata = dev_get_plat(dev); + struct ohci_regs *regs; + int ret; + u32 i; + + regs = (struct ohci_regs *)dev_read_addr(dev); + if (IS_ERR(regs)) { + ret = PTR_ERR(regs); + goto fail; + } + + pdata->ports = dev_read_u32_default(dev, "num-ports", 3); + + at91_for_each_port(i, pdata->ports) + gpio_request_by_name(dev, "atmel,vbus-gpio", i, + &pdata->vbus_pin[i], GPIOD_IS_OUT | + GPIOD_IS_OUT_ACTIVE); + + ret = clk_get_bulk(dev, &ohci_at91->clks); + if (ret) + goto fail; + + ret = clk_enable_bulk(&ohci_at91->clks); + if (ret) + goto fail; + + ret = at91_start_hc(dev); + if (ret) + goto fail; + + return ohci_register(dev, regs); + +fail: + at91_for_each_port(i, pdata->ports) + if (dm_gpio_is_valid(&pdata->vbus_pin[i])) + gpio_free(pdata->vbus_pin[i].offset); + + clk_disable_bulk(&ohci_at91->clks); + + return ret; +} + +static const struct udevice_id ohci_usb_ids[] = { + { .compatible = "atmel,at91rm9200-ohci", }, + { .compatible = "microchip,sama7g5-ohci", }, + { } +}; + +U_BOOT_DRIVER(ohci_atmel) = { + .name = "ohci_atmel", + .id = UCLASS_USB, + .of_match = ohci_usb_ids, + .probe = ohci_atmel_probe, + .remove = ohci_atmel_deregister, + .child_pre_probe = ohci_atmel_child_pre_probe, + .ops = &ohci_usb_ops, + .plat_auto = sizeof(struct at91_usbh_data), + .priv_auto = sizeof(struct ohci_at91_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; + +#endif /* CONFIG_IS_ENABLED(DM_USB) */ From patchwork Tue Jul 25 15:43:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugen Hristev X-Patchwork-Id: 1812721 X-Patchwork-Delegate: eugen.hristev@microchip.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=collabora.com header.i=@collabora.com header.a=rsa-sha256 header.s=mail header.b=TeRcv9qH; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4R9Lt43457z1yYc for ; Wed, 26 Jul 2023 01:43:56 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1BFFD8679D; Tue, 25 Jul 2023 17:43:49 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=collabora.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=collabora.com header.i=@collabora.com header.b="TeRcv9qH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 86EBB866C1; Tue, 25 Jul 2023 17:43:42 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from madras.collabora.co.uk (madras.collabora.co.uk [46.235.227.172]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 0CD4C867F7 for ; Tue, 25 Jul 2023 17:43:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=collabora.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=eugen.hristev@collabora.com Received: from eugen-station.. (unknown [82.76.24.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: ehristev) by madras.collabora.co.uk (Postfix) with ESMTPSA id 2C7AC6607108; Tue, 25 Jul 2023 16:43:36 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1690299816; bh=SdOgjX7TuK+7764xePqCaCWj0fI8g0hTHA5lpCitXqE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TeRcv9qHmwjGV2ziAzG+Y0CKhrY9r4NzTT9GFogNJDaapEZi0ozPM/tpULKPs7DHI +Cxl7jlWaGuc0DBChDjJnXQqMS8FYqHFUtSvwTZ/hENSgg0vurj5dFh0oZppC1Whua HQRytmx0hwGrUEL3AXJisfHGg/55Y9kcGtG3OuRveAcsttxJEWAyVqMTjTCtLENJMS PyiD/HsnYdDWzemM8T91gNnJGItg/Cdc8oF/aRCH+ko0DR1dhZsPHKk0VE6h7cvY6l +HGqDrPJJOypuKbvUlohOiw8rL7uTkQ9AsXm/70ZgU5edfYHr5hwT9Ruyldy6FK/so BE+Wf4mypRvKQ== From: Eugen Hristev To: marex@denx.de Cc: u-boot@lists.denx.de, eugen.hristev@collabora.com, mihai.sain@microchip.com, Sergiu Moga Subject: [PATCH v5 3/3] usb: ohci-at91: Add USB PHY functionality Date: Tue, 25 Jul 2023 18:43:17 +0300 Message-Id: <20230725154317.663337-3-eugen.hristev@collabora.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230725154317.663337-1-eugen.hristev@collabora.com> References: <20230725154317.663337-1-eugen.hristev@collabora.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Sergiu Moga Add the ability to enable/disable whatever USB PHY's are passed to the AT91 OHCI driver through DT. Signed-off-by: Sergiu Moga [eugen.hristev@collabora.com: rewrite error paths according to Marek's review] Signed-off-by: Eugen Hristev --- v1 -> v2: - use *_bulk API's v2 -> v3: - use if (CONFIG_IS_ENABLED(...)) v3 -> v4 [eugen.hristev@collabora.com: disable PHYs in at91_start_clock if clk_enable_bulk fails] v4->v5: [eugen.hristev@collabora.com: rewrite error paths according to Marek's review] drivers/usb/host/ohci-at91.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 92d0ab7184c4..4f4689745896 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -73,6 +73,7 @@ int usb_cpu_init_fail(void) #include #include #include "ohci.h" +#include #define AT91_MAX_USBH_PORTS 3 @@ -90,15 +91,36 @@ struct at91_usbh_data { struct ohci_at91_priv { ohci_t ohci; struct clk_bulk clks; + struct phy_bulk phys; }; static int at91_start_clock(struct ohci_at91_priv *ohci_at91) { - return clk_enable_bulk(&ohci_at91->clks); + int ret; + + if (CONFIG_IS_ENABLED(PHY_MICROCHIP_SAMA7_USB)) { + ret = generic_phy_power_on_bulk(&ohci_at91->phys); + if (ret) + return ret; + } + + ret = clk_enable_bulk(&ohci_at91->clks); + if (ret) + goto at91_start_clock_err; + + return 0; + +at91_start_clock_err: + generic_phy_power_off_bulk(&ohci_at91->phys); + + return ret; } static int at91_stop_clock(struct ohci_at91_priv *ohci_at91) { + if (CONFIG_IS_ENABLED(PHY_MICROCHIP_SAMA7_USB)) + generic_phy_power_off_bulk(&ohci_at91->phys); + return clk_disable_bulk(&ohci_at91->clks); } @@ -185,6 +207,16 @@ static int ohci_atmel_probe(struct udevice *dev) if (ret) goto fail; + if (CONFIG_IS_ENABLED(PHY_MICROCHIP_SAMA7_USB)) { + ret = generic_phy_get_bulk(dev, &ohci_at91->phys); + if (ret) + goto fail; + + ret = generic_phy_init_bulk(&ohci_at91->phys); + if (ret) + goto fail; + } + ret = at91_start_hc(dev); if (ret) goto fail;