From: Vinod Koul <vkoul@kernel.org>
To: Icenowy Zheng <zhengxingda@iscas.ac.cn>
Cc: Drew Fustini <fustini@kernel.org>, Guo Ren <guoren@kernel.org>,
Fu Wei <wefu@redhat.com>,
Michael Turquette <mturquette@baylibre.com>,
Stephen Boyd <sboyd@kernel.org>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Neil Armstrong <neil.armstrong@linaro.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Paul Walmsley <pjw@kernel.org>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Alexandre Ghiti <alex@ghiti.fr>,
Jisheng Zhang <jszhang@kernel.org>,
Philipp Zabel <p.zabel@pengutronix.de>,
linux-riscv@lists.infradead.org, linux-clk@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-gpio@vger.kernel.org, linux-phy@lists.infradead.org,
linux-usb@vger.kernel.org, Icenowy Zheng <uwu@icenowy.me>,
Han Gao <rabenda.cn@gmail.com>, Yao Zi <ziyao@disroot.org>
Subject: Re: [PATCH 05/12] phy: add a driver for T-Head TH1520 USB PHY
Date: Sun, 10 May 2026 13:14:17 +0530 [thread overview]
Message-ID: <agA3URhGA1u6R7LD@vaman> (raw)
In-Reply-To: <20260507081710.4090814-6-zhengxingda@iscas.ac.cn>
On 07-05-26, 16:17, Icenowy Zheng wrote:
> The USB PHY on T-Head TH1520 SoC is a Synopsys USB 3.0 FemtoPHY, with
> some PHY parameters exported as another system controller along with it.
>
> As a few PHY parameters' default value isn't ready to work, add a driver
> configuring them before letting the PHY run, in addition to
> clock/reset/regulator management.
Is there any dependency on the rest of series, if not please split up!
Some warnings flagged by sashiko, please check
https://sashiko.dev/#/patchset/20260507081710.4090814-1-zhengxingda%40iscas.ac.cn
>
> Signed-off-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
> ---
> drivers/phy/Kconfig | 1 +
> drivers/phy/Makefile | 1 +
> drivers/phy/thead/Kconfig | 12 ++
> drivers/phy/thead/Makefile | 2 +
> drivers/phy/thead/phy-th1520-usb.c | 197 +++++++++++++++++++++++++++++
> 5 files changed, 213 insertions(+)
> create mode 100644 drivers/phy/thead/Kconfig
> create mode 100644 drivers/phy/thead/Makefile
> create mode 100644 drivers/phy/thead/phy-th1520-usb.c
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 227b9a4c612e8..ea1a52e14b839 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -164,6 +164,7 @@ source "drivers/phy/st/Kconfig"
> source "drivers/phy/starfive/Kconfig"
> source "drivers/phy/sunplus/Kconfig"
> source "drivers/phy/tegra/Kconfig"
> +source "drivers/phy/thead/Kconfig"
> source "drivers/phy/ti/Kconfig"
> source "drivers/phy/xilinx/Kconfig"
>
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index f49d83f00a3d8..4604522548c91 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -48,5 +48,6 @@ obj-$(CONFIG_GENERIC_PHY) += allwinner/ \
> starfive/ \
> sunplus/ \
> tegra/ \
> + thead/ \
> ti/ \
> xilinx/
> diff --git a/drivers/phy/thead/Kconfig b/drivers/phy/thead/Kconfig
> new file mode 100644
> index 0000000000000..14012db5973c4
> --- /dev/null
> +++ b/drivers/phy/thead/Kconfig
> @@ -0,0 +1,12 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config PHY_TH1520_USB
> + tristate "USB PHY driver for T-Head TH1520 SoC"
> + depends on ARCH_THEAD || COMPILE_TEST
> + depends on COMMON_CLK
> + depends on HAS_IOMEM
> + depends on OF
> + depends on RESET_CONTROLLER
> + select GENERIC_PHY
> + default ARCH_THEAD
Why should this be default?
> + help
> + Enable support for the USB PHY on the T-Head TH1520 SoC.
> diff --git a/drivers/phy/thead/Makefile b/drivers/phy/thead/Makefile
> new file mode 100644
> index 0000000000000..5b459bc7004bd
> --- /dev/null
> +++ b/drivers/phy/thead/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_PHY_TH1520_USB) += phy-th1520-usb.o
> diff --git a/drivers/phy/thead/phy-th1520-usb.c b/drivers/phy/thead/phy-th1520-usb.c
> new file mode 100644
> index 0000000000000..c87bd779bbb74
> --- /dev/null
> +++ b/drivers/phy/thead/phy-th1520-usb.c
> @@ -0,0 +1,197 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Institute of Software, Chinese Academy of Sciences (ISCAS)
> + *
> + * Authors:
> + * Icenowy Zheng <zhengxingda@iscas.ac.cn>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> +
> +#define USB_SYSCON_OFFSET 0xf000
> +
> +/* All the below registers are in the USB syscon region */
> +#define USB_CLK_GATE_STS 0x0
> +#define USB_LOGIC_ANALYZER_TRACE_STS0 0x4
> +#define USB_LOGIC_ANALYZER_TRACE_STS1 0x8
> +#define USB_GPIO 0xc
> +#define USB_DEBUG_STS0 0x10
> +#define USB_DEBUG_STS1 0x14
> +#define USB_DEBUG_STS2 0x18
> +#define USBCTL_CLK_CTRL0 0x1c
> +#define USBPHY_CLK_CTRL1 0x20
> +#define USBPHY_TEST_CTRL0 0x24
> +#define USBPHY_TEST_CTRL1 0x28
> +#define USBPHY_TEST_CTRL2 0x2c
> +#define USBPHY_TEST_CTRL3 0x30
> +#define USB_SSP_EN 0x34
> +#define USB_HADDR_SEL 0x38
> +#define USB_SYS 0x3c
> +#define USB_HOST_STATUS 0x40
> +#define USB_HOST_CTRL 0x44
> +#define USBPHY_HOST_CTRL 0x48
> +#define USBPHY_HOST_STATUS 0x4c
> +#define USB_TEST_REG0 0x50
> +#define USB_TEST_REG1 0x54
> +#define USB_TEST_REG2 0x58
> +#define USB_TEST_REG3 0x5c
Why do need these test registers, they seem unused?
> +
> +#define USB_SYS_COMMONONN BIT(0)
> +
> +#define USB_SSP_EN_REF_SSP_EN BIT(0)
> +
> +struct th1520_usb_phy {
> + struct platform_device *pdev;
> + struct phy *phy;
> + struct regmap *regmap;
> + struct clk *ref_clk;
> + struct reset_control *phy_reset;
> +};
> +
> +static int th1520_usb_phy_init(struct phy *phy)
> +{
> + struct th1520_usb_phy *th1520_phy = phy_get_drvdata(phy);
> + int ret;
> +
> + ret = clk_prepare_enable(th1520_phy->ref_clk);
> + if (ret)
> + return ret;
> +
> + ret = reset_control_assert(th1520_phy->phy_reset);
> + if (ret)
> + goto err_disable_clk;
> +
> + /*
> + * Do some initial PHY setup:
> + * - Set COMMONONN to allow the PHY to automatically power down.
> + * - Set REF_SSP_EN to enable feeding reference clock to SuperSpeed
> + * PHY clock PLL.
> + */
> + regmap_set_bits(th1520_phy->regmap, USB_SYS, USB_SYS_COMMONONN);
> + regmap_set_bits(th1520_phy->regmap, USB_SSP_EN, USB_SSP_EN_REF_SSP_EN);
> +
> + ret = reset_control_deassert(th1520_phy->phy_reset);
> + if (ret)
> + goto err_disable_clk;
> +
> + udelay(10);
> +
> + return 0;
> +
> +err_disable_clk:
> + clk_disable_unprepare(th1520_phy->ref_clk);
> + return ret;
> +}
> +
> +static int th1520_usb_phy_exit(struct phy *phy)
> +{
> + struct th1520_usb_phy *th1520_phy = phy_get_drvdata(phy);
> + int ret;
> +
> + ret = reset_control_assert(th1520_phy->phy_reset);
> + if (ret)
> + return ret;
> +
> + clk_disable_unprepare(th1520_phy->ref_clk);
> +
> + return 0;
> +}
> +
> +static const struct phy_ops th1520_usb_phy_ops = {
> + .init = th1520_usb_phy_init,
> + .exit = th1520_usb_phy_exit,
> + .owner = THIS_MODULE,
> +};
> +
> +static const struct regmap_config phy_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = USB_TEST_REG3,
> +};
> +
> +static int th1520_usb_phy_probe(struct platform_device *pdev)
> +{
> + struct phy_provider *phy_provider;
> + struct device *dev = &pdev->dev;
> + struct th1520_usb_phy *th1520_phy;
> + struct reset_control *bus_reset;
> + void __iomem *base;
> + int ret;
> +
> + th1520_phy = devm_kzalloc(dev, sizeof(*th1520_phy), GFP_KERNEL);
> + if (!th1520_phy)
> + return -ENOMEM;
> +
> + th1520_phy->pdev = pdev;
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + th1520_phy->ref_clk = devm_clk_get(dev, "ref");
> + if (IS_ERR(th1520_phy->ref_clk))
> + return PTR_ERR(th1520_phy->ref_clk);
> +
> + /* De-assert the bus reset and leave it that way */
> + bus_reset = devm_reset_control_get_exclusive_deasserted(dev, "bus");
> + if (IS_ERR(bus_reset))
> + return PTR_ERR(bus_reset);
> +
> + th1520_phy->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
> + if (IS_ERR(th1520_phy->phy_reset))
> + return PTR_ERR(th1520_phy->phy_reset);
> +
> + /*
> + * Schematics of several boards (Lichee Module 4A/Milk-V Meles)
> + * describe this power rail as always-on.
> + */
> + ret = devm_regulator_get_enable(dev, "avdd33-usb3");
> + if (ret)
> + return ret;
> +
> + th1520_phy->regmap = devm_regmap_init_mmio_clk(dev, "bus",
> + base + USB_SYSCON_OFFSET,
> + &phy_regmap_config);
> + if (IS_ERR(th1520_phy->regmap))
> + return dev_err_probe(dev, PTR_ERR(th1520_phy->regmap),
> + "Failed to init regmap\n");
> +
> + th1520_phy->phy = devm_phy_create(dev, dev->of_node, &th1520_usb_phy_ops);
> + if (IS_ERR(th1520_phy->phy)) {
> + dev_err(dev, "failed to create PHY\n");
> + return PTR_ERR(th1520_phy->phy);
> + }
> +
> + phy_set_drvdata(th1520_phy->phy, th1520_phy);
> +
> + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> + return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static const struct of_device_id th1520_usb_phy_of_table[] = {
> + { .compatible = "thead,th1520-usb-phy" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, th1520_usb_phy_of_table);
> +
> +static struct platform_driver th1520_usb_phy_driver = {
> + .driver = {
> + .name = "th1520-usb-phy",
> + .of_match_table = th1520_usb_phy_of_table,
> + },
> + .probe = th1520_usb_phy_probe,
> +};
> +
> +module_platform_driver(th1520_usb_phy_driver);
> +
> +MODULE_DESCRIPTION("T-Head TH1520 USB PHY driver");
> +MODULE_LICENSE("GPL");
> --
> 2.52.0
--
~Vinod
WARNING: multiple messages have this Message-ID (diff)
From: Vinod Koul <vkoul@kernel.org>
To: Icenowy Zheng <zhengxingda@iscas.ac.cn>
Cc: Drew Fustini <fustini@kernel.org>, Guo Ren <guoren@kernel.org>,
Fu Wei <wefu@redhat.com>,
Michael Turquette <mturquette@baylibre.com>,
Stephen Boyd <sboyd@kernel.org>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Neil Armstrong <neil.armstrong@linaro.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Paul Walmsley <pjw@kernel.org>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Alexandre Ghiti <alex@ghiti.fr>,
Jisheng Zhang <jszhang@kernel.org>,
Philipp Zabel <p.zabel@pengutronix.de>,
linux-riscv@lists.infradead.org, linux-clk@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-gpio@vger.kernel.org, linux-phy@lists.infradead.org,
linux-usb@vger.kernel.org, Icenowy Zheng <uwu@icenowy.me>,
Han Gao <rabenda.cn@gmail.com>, Yao Zi <ziyao@disroot.org>
Subject: Re: [PATCH 05/12] phy: add a driver for T-Head TH1520 USB PHY
Date: Sun, 10 May 2026 13:14:17 +0530 [thread overview]
Message-ID: <agA3URhGA1u6R7LD@vaman> (raw)
In-Reply-To: <20260507081710.4090814-6-zhengxingda@iscas.ac.cn>
On 07-05-26, 16:17, Icenowy Zheng wrote:
> The USB PHY on T-Head TH1520 SoC is a Synopsys USB 3.0 FemtoPHY, with
> some PHY parameters exported as another system controller along with it.
>
> As a few PHY parameters' default value isn't ready to work, add a driver
> configuring them before letting the PHY run, in addition to
> clock/reset/regulator management.
Is there any dependency on the rest of series, if not please split up!
Some warnings flagged by sashiko, please check
https://sashiko.dev/#/patchset/20260507081710.4090814-1-zhengxingda%40iscas.ac.cn
>
> Signed-off-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
> ---
> drivers/phy/Kconfig | 1 +
> drivers/phy/Makefile | 1 +
> drivers/phy/thead/Kconfig | 12 ++
> drivers/phy/thead/Makefile | 2 +
> drivers/phy/thead/phy-th1520-usb.c | 197 +++++++++++++++++++++++++++++
> 5 files changed, 213 insertions(+)
> create mode 100644 drivers/phy/thead/Kconfig
> create mode 100644 drivers/phy/thead/Makefile
> create mode 100644 drivers/phy/thead/phy-th1520-usb.c
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 227b9a4c612e8..ea1a52e14b839 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -164,6 +164,7 @@ source "drivers/phy/st/Kconfig"
> source "drivers/phy/starfive/Kconfig"
> source "drivers/phy/sunplus/Kconfig"
> source "drivers/phy/tegra/Kconfig"
> +source "drivers/phy/thead/Kconfig"
> source "drivers/phy/ti/Kconfig"
> source "drivers/phy/xilinx/Kconfig"
>
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index f49d83f00a3d8..4604522548c91 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -48,5 +48,6 @@ obj-$(CONFIG_GENERIC_PHY) += allwinner/ \
> starfive/ \
> sunplus/ \
> tegra/ \
> + thead/ \
> ti/ \
> xilinx/
> diff --git a/drivers/phy/thead/Kconfig b/drivers/phy/thead/Kconfig
> new file mode 100644
> index 0000000000000..14012db5973c4
> --- /dev/null
> +++ b/drivers/phy/thead/Kconfig
> @@ -0,0 +1,12 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config PHY_TH1520_USB
> + tristate "USB PHY driver for T-Head TH1520 SoC"
> + depends on ARCH_THEAD || COMPILE_TEST
> + depends on COMMON_CLK
> + depends on HAS_IOMEM
> + depends on OF
> + depends on RESET_CONTROLLER
> + select GENERIC_PHY
> + default ARCH_THEAD
Why should this be default?
> + help
> + Enable support for the USB PHY on the T-Head TH1520 SoC.
> diff --git a/drivers/phy/thead/Makefile b/drivers/phy/thead/Makefile
> new file mode 100644
> index 0000000000000..5b459bc7004bd
> --- /dev/null
> +++ b/drivers/phy/thead/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_PHY_TH1520_USB) += phy-th1520-usb.o
> diff --git a/drivers/phy/thead/phy-th1520-usb.c b/drivers/phy/thead/phy-th1520-usb.c
> new file mode 100644
> index 0000000000000..c87bd779bbb74
> --- /dev/null
> +++ b/drivers/phy/thead/phy-th1520-usb.c
> @@ -0,0 +1,197 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Institute of Software, Chinese Academy of Sciences (ISCAS)
> + *
> + * Authors:
> + * Icenowy Zheng <zhengxingda@iscas.ac.cn>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> +
> +#define USB_SYSCON_OFFSET 0xf000
> +
> +/* All the below registers are in the USB syscon region */
> +#define USB_CLK_GATE_STS 0x0
> +#define USB_LOGIC_ANALYZER_TRACE_STS0 0x4
> +#define USB_LOGIC_ANALYZER_TRACE_STS1 0x8
> +#define USB_GPIO 0xc
> +#define USB_DEBUG_STS0 0x10
> +#define USB_DEBUG_STS1 0x14
> +#define USB_DEBUG_STS2 0x18
> +#define USBCTL_CLK_CTRL0 0x1c
> +#define USBPHY_CLK_CTRL1 0x20
> +#define USBPHY_TEST_CTRL0 0x24
> +#define USBPHY_TEST_CTRL1 0x28
> +#define USBPHY_TEST_CTRL2 0x2c
> +#define USBPHY_TEST_CTRL3 0x30
> +#define USB_SSP_EN 0x34
> +#define USB_HADDR_SEL 0x38
> +#define USB_SYS 0x3c
> +#define USB_HOST_STATUS 0x40
> +#define USB_HOST_CTRL 0x44
> +#define USBPHY_HOST_CTRL 0x48
> +#define USBPHY_HOST_STATUS 0x4c
> +#define USB_TEST_REG0 0x50
> +#define USB_TEST_REG1 0x54
> +#define USB_TEST_REG2 0x58
> +#define USB_TEST_REG3 0x5c
Why do need these test registers, they seem unused?
> +
> +#define USB_SYS_COMMONONN BIT(0)
> +
> +#define USB_SSP_EN_REF_SSP_EN BIT(0)
> +
> +struct th1520_usb_phy {
> + struct platform_device *pdev;
> + struct phy *phy;
> + struct regmap *regmap;
> + struct clk *ref_clk;
> + struct reset_control *phy_reset;
> +};
> +
> +static int th1520_usb_phy_init(struct phy *phy)
> +{
> + struct th1520_usb_phy *th1520_phy = phy_get_drvdata(phy);
> + int ret;
> +
> + ret = clk_prepare_enable(th1520_phy->ref_clk);
> + if (ret)
> + return ret;
> +
> + ret = reset_control_assert(th1520_phy->phy_reset);
> + if (ret)
> + goto err_disable_clk;
> +
> + /*
> + * Do some initial PHY setup:
> + * - Set COMMONONN to allow the PHY to automatically power down.
> + * - Set REF_SSP_EN to enable feeding reference clock to SuperSpeed
> + * PHY clock PLL.
> + */
> + regmap_set_bits(th1520_phy->regmap, USB_SYS, USB_SYS_COMMONONN);
> + regmap_set_bits(th1520_phy->regmap, USB_SSP_EN, USB_SSP_EN_REF_SSP_EN);
> +
> + ret = reset_control_deassert(th1520_phy->phy_reset);
> + if (ret)
> + goto err_disable_clk;
> +
> + udelay(10);
> +
> + return 0;
> +
> +err_disable_clk:
> + clk_disable_unprepare(th1520_phy->ref_clk);
> + return ret;
> +}
> +
> +static int th1520_usb_phy_exit(struct phy *phy)
> +{
> + struct th1520_usb_phy *th1520_phy = phy_get_drvdata(phy);
> + int ret;
> +
> + ret = reset_control_assert(th1520_phy->phy_reset);
> + if (ret)
> + return ret;
> +
> + clk_disable_unprepare(th1520_phy->ref_clk);
> +
> + return 0;
> +}
> +
> +static const struct phy_ops th1520_usb_phy_ops = {
> + .init = th1520_usb_phy_init,
> + .exit = th1520_usb_phy_exit,
> + .owner = THIS_MODULE,
> +};
> +
> +static const struct regmap_config phy_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = USB_TEST_REG3,
> +};
> +
> +static int th1520_usb_phy_probe(struct platform_device *pdev)
> +{
> + struct phy_provider *phy_provider;
> + struct device *dev = &pdev->dev;
> + struct th1520_usb_phy *th1520_phy;
> + struct reset_control *bus_reset;
> + void __iomem *base;
> + int ret;
> +
> + th1520_phy = devm_kzalloc(dev, sizeof(*th1520_phy), GFP_KERNEL);
> + if (!th1520_phy)
> + return -ENOMEM;
> +
> + th1520_phy->pdev = pdev;
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + th1520_phy->ref_clk = devm_clk_get(dev, "ref");
> + if (IS_ERR(th1520_phy->ref_clk))
> + return PTR_ERR(th1520_phy->ref_clk);
> +
> + /* De-assert the bus reset and leave it that way */
> + bus_reset = devm_reset_control_get_exclusive_deasserted(dev, "bus");
> + if (IS_ERR(bus_reset))
> + return PTR_ERR(bus_reset);
> +
> + th1520_phy->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
> + if (IS_ERR(th1520_phy->phy_reset))
> + return PTR_ERR(th1520_phy->phy_reset);
> +
> + /*
> + * Schematics of several boards (Lichee Module 4A/Milk-V Meles)
> + * describe this power rail as always-on.
> + */
> + ret = devm_regulator_get_enable(dev, "avdd33-usb3");
> + if (ret)
> + return ret;
> +
> + th1520_phy->regmap = devm_regmap_init_mmio_clk(dev, "bus",
> + base + USB_SYSCON_OFFSET,
> + &phy_regmap_config);
> + if (IS_ERR(th1520_phy->regmap))
> + return dev_err_probe(dev, PTR_ERR(th1520_phy->regmap),
> + "Failed to init regmap\n");
> +
> + th1520_phy->phy = devm_phy_create(dev, dev->of_node, &th1520_usb_phy_ops);
> + if (IS_ERR(th1520_phy->phy)) {
> + dev_err(dev, "failed to create PHY\n");
> + return PTR_ERR(th1520_phy->phy);
> + }
> +
> + phy_set_drvdata(th1520_phy->phy, th1520_phy);
> +
> + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> + return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static const struct of_device_id th1520_usb_phy_of_table[] = {
> + { .compatible = "thead,th1520-usb-phy" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, th1520_usb_phy_of_table);
> +
> +static struct platform_driver th1520_usb_phy_driver = {
> + .driver = {
> + .name = "th1520-usb-phy",
> + .of_match_table = th1520_usb_phy_of_table,
> + },
> + .probe = th1520_usb_phy_probe,
> +};
> +
> +module_platform_driver(th1520_usb_phy_driver);
> +
> +MODULE_DESCRIPTION("T-Head TH1520 USB PHY driver");
> +MODULE_LICENSE("GPL");
> --
> 2.52.0
--
~Vinod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
WARNING: multiple messages have this Message-ID (diff)
From: Vinod Koul <vkoul@kernel.org>
To: Icenowy Zheng <zhengxingda@iscas.ac.cn>
Cc: Drew Fustini <fustini@kernel.org>,
Michael Turquette <mturquette@baylibre.com>,
Guo Ren <guoren@kernel.org>, Jisheng Zhang <jszhang@kernel.org>,
linux-phy@lists.infradead.org, linux-riscv@lists.infradead.org,
linux-clk@vger.kernel.org, Rob Herring <robh@kernel.org>,
Alexandre Ghiti <alex@ghiti.fr>,
devicetree@vger.kernel.org, Conor Dooley <conor+dt@kernel.org>,
Albert Ou <aou@eecs.berkeley.edu>, Yao Zi <ziyao@disroot.org>,
linux-gpio@vger.kernel.org, Paul Walmsley <pjw@kernel.org>,
Neil Armstrong <neil.armstrong@linaro.org>,
Stephen Boyd <sboyd@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
Palmer Dabbelt <palmer@dabbelt.com>,
Philipp Zabel <p.zabel@pengutronix.de>,
Han Gao <rabenda.cn@gmail.com>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Fu Wei <wefu@redhat.com>
Subject: Re: [PATCH 05/12] phy: add a driver for T-Head TH1520 USB PHY
Date: Sun, 10 May 2026 13:14:17 +0530 [thread overview]
Message-ID: <agA3URhGA1u6R7LD@vaman> (raw)
In-Reply-To: <20260507081710.4090814-6-zhengxingda@iscas.ac.cn>
On 07-05-26, 16:17, Icenowy Zheng wrote:
> The USB PHY on T-Head TH1520 SoC is a Synopsys USB 3.0 FemtoPHY, with
> some PHY parameters exported as another system controller along with it.
>
> As a few PHY parameters' default value isn't ready to work, add a driver
> configuring them before letting the PHY run, in addition to
> clock/reset/regulator management.
Is there any dependency on the rest of series, if not please split up!
Some warnings flagged by sashiko, please check
https://sashiko.dev/#/patchset/20260507081710.4090814-1-zhengxingda%40iscas.ac.cn
>
> Signed-off-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
> ---
> drivers/phy/Kconfig | 1 +
> drivers/phy/Makefile | 1 +
> drivers/phy/thead/Kconfig | 12 ++
> drivers/phy/thead/Makefile | 2 +
> drivers/phy/thead/phy-th1520-usb.c | 197 +++++++++++++++++++++++++++++
> 5 files changed, 213 insertions(+)
> create mode 100644 drivers/phy/thead/Kconfig
> create mode 100644 drivers/phy/thead/Makefile
> create mode 100644 drivers/phy/thead/phy-th1520-usb.c
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 227b9a4c612e8..ea1a52e14b839 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -164,6 +164,7 @@ source "drivers/phy/st/Kconfig"
> source "drivers/phy/starfive/Kconfig"
> source "drivers/phy/sunplus/Kconfig"
> source "drivers/phy/tegra/Kconfig"
> +source "drivers/phy/thead/Kconfig"
> source "drivers/phy/ti/Kconfig"
> source "drivers/phy/xilinx/Kconfig"
>
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index f49d83f00a3d8..4604522548c91 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -48,5 +48,6 @@ obj-$(CONFIG_GENERIC_PHY) += allwinner/ \
> starfive/ \
> sunplus/ \
> tegra/ \
> + thead/ \
> ti/ \
> xilinx/
> diff --git a/drivers/phy/thead/Kconfig b/drivers/phy/thead/Kconfig
> new file mode 100644
> index 0000000000000..14012db5973c4
> --- /dev/null
> +++ b/drivers/phy/thead/Kconfig
> @@ -0,0 +1,12 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config PHY_TH1520_USB
> + tristate "USB PHY driver for T-Head TH1520 SoC"
> + depends on ARCH_THEAD || COMPILE_TEST
> + depends on COMMON_CLK
> + depends on HAS_IOMEM
> + depends on OF
> + depends on RESET_CONTROLLER
> + select GENERIC_PHY
> + default ARCH_THEAD
Why should this be default?
> + help
> + Enable support for the USB PHY on the T-Head TH1520 SoC.
> diff --git a/drivers/phy/thead/Makefile b/drivers/phy/thead/Makefile
> new file mode 100644
> index 0000000000000..5b459bc7004bd
> --- /dev/null
> +++ b/drivers/phy/thead/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_PHY_TH1520_USB) += phy-th1520-usb.o
> diff --git a/drivers/phy/thead/phy-th1520-usb.c b/drivers/phy/thead/phy-th1520-usb.c
> new file mode 100644
> index 0000000000000..c87bd779bbb74
> --- /dev/null
> +++ b/drivers/phy/thead/phy-th1520-usb.c
> @@ -0,0 +1,197 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Institute of Software, Chinese Academy of Sciences (ISCAS)
> + *
> + * Authors:
> + * Icenowy Zheng <zhengxingda@iscas.ac.cn>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> +
> +#define USB_SYSCON_OFFSET 0xf000
> +
> +/* All the below registers are in the USB syscon region */
> +#define USB_CLK_GATE_STS 0x0
> +#define USB_LOGIC_ANALYZER_TRACE_STS0 0x4
> +#define USB_LOGIC_ANALYZER_TRACE_STS1 0x8
> +#define USB_GPIO 0xc
> +#define USB_DEBUG_STS0 0x10
> +#define USB_DEBUG_STS1 0x14
> +#define USB_DEBUG_STS2 0x18
> +#define USBCTL_CLK_CTRL0 0x1c
> +#define USBPHY_CLK_CTRL1 0x20
> +#define USBPHY_TEST_CTRL0 0x24
> +#define USBPHY_TEST_CTRL1 0x28
> +#define USBPHY_TEST_CTRL2 0x2c
> +#define USBPHY_TEST_CTRL3 0x30
> +#define USB_SSP_EN 0x34
> +#define USB_HADDR_SEL 0x38
> +#define USB_SYS 0x3c
> +#define USB_HOST_STATUS 0x40
> +#define USB_HOST_CTRL 0x44
> +#define USBPHY_HOST_CTRL 0x48
> +#define USBPHY_HOST_STATUS 0x4c
> +#define USB_TEST_REG0 0x50
> +#define USB_TEST_REG1 0x54
> +#define USB_TEST_REG2 0x58
> +#define USB_TEST_REG3 0x5c
Why do need these test registers, they seem unused?
> +
> +#define USB_SYS_COMMONONN BIT(0)
> +
> +#define USB_SSP_EN_REF_SSP_EN BIT(0)
> +
> +struct th1520_usb_phy {
> + struct platform_device *pdev;
> + struct phy *phy;
> + struct regmap *regmap;
> + struct clk *ref_clk;
> + struct reset_control *phy_reset;
> +};
> +
> +static int th1520_usb_phy_init(struct phy *phy)
> +{
> + struct th1520_usb_phy *th1520_phy = phy_get_drvdata(phy);
> + int ret;
> +
> + ret = clk_prepare_enable(th1520_phy->ref_clk);
> + if (ret)
> + return ret;
> +
> + ret = reset_control_assert(th1520_phy->phy_reset);
> + if (ret)
> + goto err_disable_clk;
> +
> + /*
> + * Do some initial PHY setup:
> + * - Set COMMONONN to allow the PHY to automatically power down.
> + * - Set REF_SSP_EN to enable feeding reference clock to SuperSpeed
> + * PHY clock PLL.
> + */
> + regmap_set_bits(th1520_phy->regmap, USB_SYS, USB_SYS_COMMONONN);
> + regmap_set_bits(th1520_phy->regmap, USB_SSP_EN, USB_SSP_EN_REF_SSP_EN);
> +
> + ret = reset_control_deassert(th1520_phy->phy_reset);
> + if (ret)
> + goto err_disable_clk;
> +
> + udelay(10);
> +
> + return 0;
> +
> +err_disable_clk:
> + clk_disable_unprepare(th1520_phy->ref_clk);
> + return ret;
> +}
> +
> +static int th1520_usb_phy_exit(struct phy *phy)
> +{
> + struct th1520_usb_phy *th1520_phy = phy_get_drvdata(phy);
> + int ret;
> +
> + ret = reset_control_assert(th1520_phy->phy_reset);
> + if (ret)
> + return ret;
> +
> + clk_disable_unprepare(th1520_phy->ref_clk);
> +
> + return 0;
> +}
> +
> +static const struct phy_ops th1520_usb_phy_ops = {
> + .init = th1520_usb_phy_init,
> + .exit = th1520_usb_phy_exit,
> + .owner = THIS_MODULE,
> +};
> +
> +static const struct regmap_config phy_regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .max_register = USB_TEST_REG3,
> +};
> +
> +static int th1520_usb_phy_probe(struct platform_device *pdev)
> +{
> + struct phy_provider *phy_provider;
> + struct device *dev = &pdev->dev;
> + struct th1520_usb_phy *th1520_phy;
> + struct reset_control *bus_reset;
> + void __iomem *base;
> + int ret;
> +
> + th1520_phy = devm_kzalloc(dev, sizeof(*th1520_phy), GFP_KERNEL);
> + if (!th1520_phy)
> + return -ENOMEM;
> +
> + th1520_phy->pdev = pdev;
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + th1520_phy->ref_clk = devm_clk_get(dev, "ref");
> + if (IS_ERR(th1520_phy->ref_clk))
> + return PTR_ERR(th1520_phy->ref_clk);
> +
> + /* De-assert the bus reset and leave it that way */
> + bus_reset = devm_reset_control_get_exclusive_deasserted(dev, "bus");
> + if (IS_ERR(bus_reset))
> + return PTR_ERR(bus_reset);
> +
> + th1520_phy->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
> + if (IS_ERR(th1520_phy->phy_reset))
> + return PTR_ERR(th1520_phy->phy_reset);
> +
> + /*
> + * Schematics of several boards (Lichee Module 4A/Milk-V Meles)
> + * describe this power rail as always-on.
> + */
> + ret = devm_regulator_get_enable(dev, "avdd33-usb3");
> + if (ret)
> + return ret;
> +
> + th1520_phy->regmap = devm_regmap_init_mmio_clk(dev, "bus",
> + base + USB_SYSCON_OFFSET,
> + &phy_regmap_config);
> + if (IS_ERR(th1520_phy->regmap))
> + return dev_err_probe(dev, PTR_ERR(th1520_phy->regmap),
> + "Failed to init regmap\n");
> +
> + th1520_phy->phy = devm_phy_create(dev, dev->of_node, &th1520_usb_phy_ops);
> + if (IS_ERR(th1520_phy->phy)) {
> + dev_err(dev, "failed to create PHY\n");
> + return PTR_ERR(th1520_phy->phy);
> + }
> +
> + phy_set_drvdata(th1520_phy->phy, th1520_phy);
> +
> + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> + return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static const struct of_device_id th1520_usb_phy_of_table[] = {
> + { .compatible = "thead,th1520-usb-phy" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, th1520_usb_phy_of_table);
> +
> +static struct platform_driver th1520_usb_phy_driver = {
> + .driver = {
> + .name = "th1520-usb-phy",
> + .of_match_table = th1520_usb_phy_of_table,
> + },
> + .probe = th1520_usb_phy_probe,
> +};
> +
> +module_platform_driver(th1520_usb_phy_driver);
> +
> +MODULE_DESCRIPTION("T-Head TH1520 USB PHY driver");
> +MODULE_LICENSE("GPL");
> --
> 2.52.0
--
~Vinod
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2026-05-10 7:44 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-07 8:16 [PATCH 00/12] Add TH1520 USB support Icenowy Zheng
2026-05-07 8:16 ` Icenowy Zheng
2026-05-07 8:16 ` Icenowy Zheng
2026-05-07 8:16 ` [PATCH 01/12] dt-bindings: clock: thead: add TH1520 MISC subsys clock controller Icenowy Zheng
2026-05-07 8:16 ` Icenowy Zheng
2026-05-07 8:16 ` Icenowy Zheng
2026-05-07 17:26 ` Conor Dooley
2026-05-07 17:26 ` Conor Dooley
2026-05-07 17:26 ` Conor Dooley
2026-05-07 8:17 ` [PATCH 02/12] clk: thead: th1520-ap: add support for MISC subsys clocks Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` [PATCH 03/12] riscv: dts: thead: add device tree node for MISC clock controller Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` [PATCH 04/12] dt-bindings: phy: add binding for T-Head TH1520 USB PHY Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 17:26 ` Conor Dooley
2026-05-07 17:26 ` Conor Dooley
2026-05-07 17:26 ` Conor Dooley
2026-05-07 8:17 ` [PATCH 05/12] phy: add a driver " Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-10 7:44 ` Vinod Koul [this message]
2026-05-10 7:44 ` Vinod Koul
2026-05-10 7:44 ` Vinod Koul
2026-05-10 9:17 ` Icenowy Zheng
2026-05-10 9:17 ` Icenowy Zheng
2026-05-10 9:17 ` Icenowy Zheng
2026-05-11 16:16 ` Vinod Koul
2026-05-11 16:16 ` Vinod Koul
2026-05-11 16:16 ` Vinod Koul
2026-05-07 8:17 ` [PATCH 06/12] riscv: dts: thead: add device nodes for USB Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` [PATCH 07/12] dt-bindings: gpio: dwapb: allow GPIO hogs Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 17:25 ` Conor Dooley
2026-05-07 17:25 ` Conor Dooley
2026-05-07 17:25 ` Conor Dooley
2026-05-07 8:17 ` [PATCH 08/12] dt-bindings: usb: vialab,vl817: allow ports property Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 17:25 ` Conor Dooley
2026-05-07 17:25 ` Conor Dooley
2026-05-07 17:25 ` Conor Dooley
2026-05-07 8:17 ` [PATCH 09/12] riscv: dts: thead: lpi4a: sort nodes Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` [PATCH 10/12] riscv: dts: thead: Add TH1520 I2C nodes Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` [PATCH 11/12] riscv: dts: thead: Add Lichee Pi 4A IO expansions Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` [PATCH 12/12] riscv: dts: thead: enable USB3 ports on Lichee Pi 4A Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-07 8:17 ` Icenowy Zheng
2026-05-11 10:54 ` (subset) [PATCH 00/12] Add TH1520 USB support Bartosz Golaszewski
2026-05-11 10:54 ` Bartosz Golaszewski
2026-05-11 10:54 ` Bartosz Golaszewski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=agA3URhGA1u6R7LD@vaman \
--to=vkoul@kernel.org \
--cc=alex@ghiti.fr \
--cc=aou@eecs.berkeley.edu \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=fustini@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=guoren@kernel.org \
--cc=jszhang@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=linux-riscv@lists.infradead.org \
--cc=linux-usb@vger.kernel.org \
--cc=mturquette@baylibre.com \
--cc=neil.armstrong@linaro.org \
--cc=p.zabel@pengutronix.de \
--cc=palmer@dabbelt.com \
--cc=pjw@kernel.org \
--cc=rabenda.cn@gmail.com \
--cc=robh@kernel.org \
--cc=sboyd@kernel.org \
--cc=uwu@icenowy.me \
--cc=wefu@redhat.com \
--cc=zhengxingda@iscas.ac.cn \
--cc=ziyao@disroot.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.