From mboxrd@z Thu Jan 1 00:00:00 1970 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6B550C61DC4 for ; Thu, 27 Aug 2026 16:00:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:Cc:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=/12E6gOj+UbxVaU0wxx8LTVimavE58t8UME2uZ4K5V8=; b=I9O5pEc1IdHsl7 Ztia7U8kffhxL58Hmzhr49/wODGKVf4pxBTRo0GDOOqEn2v4bsXt03LU26O9HiGiR9zvZTphTAhtt kNUZ7cnPxbNrvm9OnQRR4UeCb90y5HFHceocPZcgnClMKigQ6verKlL2tBjJ+bqAU7/wpx7rtss0u 77IkOPHEIQsBqKyS+eVY4j5ljUYGhxQfycqRr+fLuL6ePQ1KBHb4/f3SdTkAg4JOIaQZD0FclkdgB iKjFlQl0//nY7xJKRojwJtbl7WGhslX3KGVgyU3uaInPMAxc8s6EGisU1DVzrbilv0PA+gdx2pjxJ tsV0a4PkbtmTtyuvTZ2w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wzcWs-00000004HjI-02ZY; Thu, 27 Aug 2026 16:00:38 +0000 Received: from sea.source.kernel.org ([2600:3c0a:e001:78e:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wzcWq-00000004Hio-0kN4; Thu, 27 Aug 2026 16:00:36 +0000 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) by sea.source.kernel.org (Postfix) with ESMTP id D5F8A40BE8; Thu, 27 Aug 2026 16:00:35 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E0E831F000E9; Thu, 27 Aug 2026 16:00:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787846435; bh=mc9UqifGDes7aqOfgsJlG3V88rf8KQlsEq8wthV3IEk=; h=Date:From:To:Cc:Subject:References:In-Reply-To; b=QtrYgCCZ+k2VUTD2+vb3c3oCDpu0y0MrozeRvCXQQxFL4CH9XjueJ7EcjvDSvuJDN /1lWbHKCTRoU/QyUFkbf3bszPZHHMAadCQ3wgyrc+XaEDy0XdJXT0BteBZWXS6LqcO /g1hHlAvdJh2FjxgpKbb8mse83Lo+hNWLB7sYt141MJ+bEr/MQ0HnYu/WJr3hQ2usM 5WBXy173K3VJiJCvoeONgKfSFY7mC0kq/CIPE8Fc1I7d3giBaCl69vTGfXp6YhO7DC mBwNeP6hobSvVdVVsRjv30VyGRFouWWvBRHrsNzQnzVN2XB4w9fmEwU1/xRIXtfQne o7J5UGgmCzFlA== Date: Thu, 27 Aug 2026 21:30:31 +0530 From: Vinod Koul To: Marek Vasut Cc: linux-usb@vger.kernel.org, fabrice.gasnier@foss.st.com, Pankaj Dev , Rahul Kumar , Christian Bruel , Alexandre Torgue , Conor Dooley , Greg Kroah-Hartman , Krzysztof Kozlowski , Maxime Coquelin , Neil Armstrong , Rob Herring , Rosen Penev , Thinh Nguyen , devicetree@vger.kernel.org, kernel@dh-electronics.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com Subject: Re: [PATCH v3 2/9] phy: stm32: Add support for ST STM32MP25 USB2-FEMTO PHY Message-ID: References: <20260822074816.548662-1-marex@nabladev.com> <20260822074816.548662-3-marex@nabladev.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20260822074816.548662-3-marex@nabladev.com> X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org On 22-08-26, 09:46, Marek Vasut wrote: > From: Pankaj Dev > > Add USB2 PHY driver for STM32MP25 USB2 controllers, which includes the > USB2.0 host-only controller and USB 2.0 part of the DWC3 controller. > Two such PHYs in total are present in STM32MP25 SoC, they both are > slightly different, therefore they use different compatible string > to discern them. > > Signed-off-by: Pankaj Dev > Co-developed-by: Rahul Kumar > Signed-off-by: Rahul Kumar > Co-developed-by: Fabrice Gasnier > Signed-off-by: Fabrice Gasnier > Co-developed-by: Christian Bruel > Signed-off-by: Christian Bruel > Co-developed-by: Marek Vasut > Signed-off-by: Marek Vasut > --- > Cc: Alexandre Torgue > Cc: Christian Bruel > Cc: Conor Dooley > Cc: Fabrice Gasnier > Cc: Greg Kroah-Hartman > Cc: Krzysztof Kozlowski > Cc: Maxime Coquelin > Cc: Neil Armstrong > Cc: Pankaj Dev > Cc: Rahul Kumar > Cc: Rob Herring > Cc: Rosen Penev > Cc: Thinh Nguyen > Cc: Vinod Koul > Cc: devicetree@vger.kernel.org > Cc: kernel@dh-electronics.com > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-kernel@vger.kernel.org > Cc: linux-phy@lists.infradead.org > Cc: linux-stm32@st-md-mailman.stormreply.com > Cc: linux-usb@vger.kernel.org > --- > V2: - Fix up Sob/Cdb lines > - Operate PHY as a syscon subnode > V3: - Update copyright years > - Register two sets of clock, one 480 MHz PLL and one CMN > - Split PHY ops per PHY, since the PHY2 does not have set mode ops > - Fix up Sob/Cdb lines further > --- > drivers/phy/st/Kconfig | 10 + > drivers/phy/st/Makefile | 1 + > drivers/phy/st/phy-stm32-usb2phy.c | 406 +++++++++++++++++++++++++++++ > 3 files changed, 417 insertions(+) > create mode 100644 drivers/phy/st/phy-stm32-usb2phy.c > > diff --git a/drivers/phy/st/Kconfig b/drivers/phy/st/Kconfig > index 49206185e5633..2835bb67bca9e 100644 > --- a/drivers/phy/st/Kconfig > +++ b/drivers/phy/st/Kconfig > @@ -58,3 +58,13 @@ config PHY_STM32_USBPHYC > used by an HS USB Host controller, and the second one is shared > between an HS USB OTG controller and an HS USB Host controller, > selected by a USB switch. > + > +config PHY_STM32_USB2PHY > + tristate "STMicroelectronics STM32MP25 USB2.0 PHY Controller driver" > + depends on ARCH_STM32 || COMPILE_TEST > + depends on COMMON_CLK > + select GENERIC_PHY > + help > + Enable this to support the High-Speed USB 2.0 transceivers that are > + part of the STMicroelectronics STM32MP25 SoCs. The PHY itself is a > + Synopsys FEMTO-PHY. > diff --git a/drivers/phy/st/Makefile b/drivers/phy/st/Makefile > index cb80e954ea9f0..4945df5ed78a8 100644 > --- a/drivers/phy/st/Makefile > +++ b/drivers/phy/st/Makefile > @@ -5,3 +5,4 @@ obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o > obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o > obj-$(CONFIG_PHY_STM32_COMBOPHY) += phy-stm32-combophy.o > obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o > +obj-$(CONFIG_PHY_STM32_USB2PHY) += phy-stm32-usb2phy.o > diff --git a/drivers/phy/st/phy-stm32-usb2phy.c b/drivers/phy/st/phy-stm32-usb2phy.c > new file mode 100644 > index 0000000000000..8c68b2d208d73 > --- /dev/null > +++ b/drivers/phy/st/phy-stm32-usb2phy.c > @@ -0,0 +1,406 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * STMicroelectronics STM32 USB2 PHY Controller driver > + * Currently Only supported for STM32MP25 > + * > + * Copyright (C) 2022-2026 STMicroelectronics > + * Author(s): Pankaj Dev . > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define SYSCFG_USB2PHY2CR_USB2PHY2CMN BIT(2) > +#define SYSCFG_USB2PHY2CR_VBUSVALID BIT(4) > +#define SYSCFG_USB2PHY2CR_VBUSVLDEXTSEL BIT(5) > +#define SYSCFG_USB2PHY2CR_VBUSVLDEXT BIT(6) > + > +#define USBH_NUM_CLK 2 > + > +struct stm32_usb2phy { > + struct phy *phy; > + struct regmap *regmap; > + struct device *dev; > + struct reset_control *rstc; > + struct clk *phyref; > + struct regulator *vdd33; > + const struct stm32mp2_usb2phy_hw_data *hw_data; > + atomic_t en_refcnt; > + enum phy_mode mode; > + u32 cr_offset; > + bool is_init; > + struct clk_hw clkpll_hw; > + struct clk_hw clkcmn_hw; > + /* Must be last */ > + struct clk_hw_onecell_data onecell; > +}; > + > +struct stm32mp2_usb2phy_hw_data { > + u32 phyrefsel_mask; > + const struct phy_ops *phy_ops; > +}; > + > +static int stm32_usb2phy_enable(struct stm32_usb2phy *phy_dev) > +{ > + const struct stm32mp2_usb2phy_hw_data *phy_data = phy_dev->hw_data; > + unsigned int refsel; > + unsigned long rate; > + int ret; > + > + /* Check if a phy is already init or clkpll in use */ > + if (atomic_inc_return(&phy_dev->en_refcnt) > 1) > + return 0; > + > + rate = clk_get_rate(phy_dev->phyref); > + if (rate == 19200000) > + refsel = 0; > + else if (rate == 20000000) > + refsel = 1; > + else if (rate == 24000000) > + refsel = 2; > + else > + return -EINVAL; Would a switch not be better here? > + > + ret = regmap_update_bits(phy_dev->regmap, > + phy_dev->cr_offset, > + phy_data->phyrefsel_mask, > + field_prep(phy_data->phyrefsel_mask, refsel)); > + if (ret) > + return ret; > + > + ret = regulator_enable(phy_dev->vdd33); > + if (ret) > + return ret; > + > + ret = clk_prepare_enable(phy_dev->phyref); > + if (ret) > + goto error_regdis; > + > + ret = reset_control_deassert(phy_dev->rstc); > + if (ret) > + goto error_clkdis; > + > + return 0; > + > +error_clkdis: > + clk_disable_unprepare(phy_dev->phyref); > +error_regdis: > + regulator_disable(phy_dev->vdd33); > + > + return ret; > +} > + > +static int stm32_usb2phy_disable(struct stm32_usb2phy *phy_dev) > +{ > + int ret; > + > + /* Check if a phy is still init or clkpll in use */ > + if (atomic_dec_return(&phy_dev->en_refcnt) > 0) > + return 0; > + > + ret = reset_control_assert(phy_dev->rstc); > + if (ret) > + return ret; > + > + clk_disable_unprepare(phy_dev->phyref); > + > + return regulator_disable(phy_dev->vdd33); > +} > + > +static int stm32_usb2phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) > +{ > + struct stm32_usb2phy *phy_dev = phy_get_drvdata(phy); > + u32 mask = SYSCFG_USB2PHY2CR_USB2PHY2CMN | > + SYSCFG_USB2PHY2CR_VBUSVALID | > + SYSCFG_USB2PHY2CR_VBUSVLDEXT; > + u32 val = 0; > + int ret; > + > + if (mode == PHY_MODE_USB_HOST) { > + if (submode != USB_ROLE_NONE) > + val = SYSCFG_USB2PHY2CR_VBUSVALID; > + } else if (mode == PHY_MODE_USB_DEVICE) { > + val = SYSCFG_USB2PHY2CR_USB2PHY2CMN | > + SYSCFG_USB2PHY2CR_VBUSVLDEXTSEL; > + if (submode != USB_ROLE_NONE) > + val |= SYSCFG_USB2PHY2CR_VBUSVLDEXT; > + mask |= SYSCFG_USB2PHY2CR_VBUSVLDEXTSEL; > + } else { > + return -EINVAL; > + } > + > + ret = regmap_update_bits(phy_dev->regmap, phy_dev->cr_offset, mask, val); > + if (ret) > + return ret; > + > + phy_dev->mode = mode; > + > + return 0; > +} > + > +static int stm32_usb2phy1_init(struct phy *phy) > +{ > + struct stm32_usb2phy *phy_dev = phy_get_drvdata(phy); > + int ret; > + > + ret = stm32_usb2phy_enable(phy_dev); > + if (ret) > + return ret; > + > + phy_dev->is_init = true; > + > + return 0; > +} > + > +static int stm32_usb2phy2_init(struct phy *phy) > +{ > + struct stm32_usb2phy *phy_dev = phy_get_drvdata(phy); > + int ret; > + > + ret = stm32_usb2phy_enable(phy_dev); > + if (ret) > + return ret; > + > + if (phy_dev->mode != PHY_MODE_INVALID) { > + ret = stm32_usb2phy_set_mode(phy, phy_dev->mode, USB_ROLE_NONE); > + if (ret) { > + stm32_usb2phy_disable(phy_dev); > + return ret; > + } > + } so what is the diff b/w these two phys that we need to check invalid only here? -- ~Vinod -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy