* Re: [PATCH v6 1/6] phy: realtek: usb2: introduce vstatus/new_reg_req variables to driver data
From: sashiko-bot @ 2026-05-20 18:23 UTC (permalink / raw)
To: Rustam Adilov
Cc: neil.armstrong, robh, devicetree, olteanv, linux-phy, vkoul,
conor+dt
In-Reply-To: <20260520175728.720877-2-adilov@disroot.org>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but the driver fails to check the return value of `of_iomap()`, which can lead to a NULL pointer dereference.
- [High] This problem wasn't introduced by this patch, but incorrect pointer arithmetic on a `void __iomem *` pointer results in unaligned I/O memory accesses for multi-port setups.
- [High] This problem wasn't introduced by this patch, but I/O memory mappings created by `of_iomap()` are never unmapped, leading to resource leaks.
- [High] This problem wasn't introduced by this patch, but multi-port PHY configurations concurrently modify shared hardware registers without synchronization or a read-modify-write cycle.
--
commit 734507efb75a6be151dcde389bfc7f0e1df95132
Author: Rustam Adilov <adilov@disroot.org>
phy: realtek: usb2: introduce vstatus/new_reg_req variables to driver data
This commit introduces vstatus_offset, vstatus_busy, and new_reg_req variables
to the driver data to handle different register offsets and busy bit
definitions in the RTL9607C SoC. These variables are added to the existing
PHY configuration structures and assigned default values.
> diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
> index 248550ef98cab..bd9ee895b9f90 100644
> --- a/drivers/phy/realtek/phy-rtk-usb2.c
> +++ b/drivers/phy/realtek/phy-rtk-usb2.c
[ ... ]
> @@ -194,25 +200,26 @@ static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data)
> int ret = 0;
>
> /* write data to VStatusOut2 (data output to phy) */
> - writel((u32)data << shift_bits, reg_wrap_vstatus);
> + writel((u32)data << shift_bits,
> + reg_wrap_vstatus + phy_reg->vstatus_offset);
[Severity: High]
This is a pre-existing issue, but does writing directly to this register
without a read-modify-write cycle overwrite the configuration for other
ports?
In multi-port setups, all PHY instances appear to share this same base
address, and a direct writel() could clear the bits belonging to other PHYs.
Is there also a need for synchronization to prevent concurrent writes across
different ports?
>
> - ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
> + ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
> if (ret)
> return ret;
[ ... ]
> @@ -974,6 +982,9 @@ static int parse_phy_data(struct rtk_phy *rtk_phy)
> phy_parameter->phy_reg.reg_wrap_vstatus = of_iomap(np, 0);
> phy_parameter->phy_reg.reg_gusb2phyacc0 = of_iomap(np, 1) + index;
[Severity: High]
This isn't a bug introduced by this patch, but does the driver need to
check the return value of of_iomap() here?
If the mapping fails, this would leave the pointers as NULL and cause a
dereference during I/O operations.
[Severity: High]
This is a pre-existing issue, but does adding index directly to the
void __iomem * returned by of_iomap() result in exactly a 1-byte offset
when index > 0?
If so, this could cause an unaligned memory access fault on ARM
architectures. Should the index be scaled appropriately?
[Severity: High]
This is also a pre-existing issue, but does the driver leak these I/O
mappings?
The driver maps the memory here using of_iomap(), but there does not
appear to be a matching iounmap() in the driver cleanup paths. Would
using devm_of_iomap() prevent this leak?
> phy_parameter->phy_reg.vstatus_index = index;
> + phy_parameter->phy_reg.vstatus_offset = phy_cfg->vstatus_offset;
> + phy_parameter->phy_reg.vstatus_busy = phy_cfg->vstatus_busy;
> + phy_parameter->phy_reg.new_reg_req = phy_cfg->new_reg_req;
>
> if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock"))
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260520175728.720877-1-adilov@disroot.org?part=1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v6 6/6] phy: realtek: Make configs available for MACH_REALTEK_RTL
From: Rustam Adilov @ 2026-05-20 17:57 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, Philipp Zabel, linux-phy, devicetree,
linux-kernel
Cc: Rustam Adilov
In-Reply-To: <20260520175728.720877-1-adilov@disroot.org>
Add the MACH_REALTEK_RTL to the if statement to make the config
options available for Realtek RTL SoCs as well.
Signed-off-by: Rustam Adilov <adilov@disroot.org>
---
drivers/phy/realtek/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/realtek/Kconfig b/drivers/phy/realtek/Kconfig
index 75ac7e7c31ae..76f9215d8b94 100644
--- a/drivers/phy/realtek/Kconfig
+++ b/drivers/phy/realtek/Kconfig
@@ -3,7 +3,7 @@
# Phy drivers for Realtek platforms
#
-if ARCH_REALTEK || COMPILE_TEST
+if ARCH_REALTEK || MACH_REALTEK_RTL || COMPILE_TEST
config PHY_RTK_RTD_USB2PHY
tristate "Realtek RTD USB2 PHY Transceiver Driver"
@@ -29,4 +29,4 @@ config PHY_RTK_RTD_USB3PHY
DWC3 USB IP. This driver will do the PHY initialization
of the parameters.
-endif # ARCH_REALTEK || COMPILE_TEST
+endif # ARCH_REALTEK || MACH_REALTEK_RTL || COMPILE_TEST
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v6 2/6] phy: realtek: usb2: introduce read and write functions to driver data
From: Rustam Adilov @ 2026-05-20 17:57 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, Philipp Zabel, linux-phy, devicetree,
linux-kernel
Cc: Rustam Adilov, Michael Zavertkin
In-Reply-To: <20260520175728.720877-1-adilov@disroot.org>
RTL9607C is a big endian SoC with little endian USB host controller but
vstatus register is from big endian memory region and thus existing
writel doesn't work. It needs either __raw_writel or iowrite32be
instead.
To handle this situation, introduce read and write function to the
driver data and create a default variation for the current RTD SoCs.
Assign the existing phy configuration for RTD SoCs to the default
read and write function.
Co-developed-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Rustam Adilov <adilov@disroot.org>
---
drivers/phy/realtek/phy-rtk-usb2.c | 40 ++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
index bd9ee895b9f9..a9e29d2f7e6f 100644
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -67,6 +67,9 @@ struct phy_reg {
int vstatus_offset;
u32 vstatus_busy;
u32 new_reg_req;
+
+ u32 (*read)(void __iomem *reg);
+ void (*write)(u32 val, void __iomem *reg);
};
struct phy_data {
@@ -102,6 +105,9 @@ struct phy_cfg {
int vstatus_offset;
u32 vstatus_busy;
u32 new_reg_req;
+
+ u32 (*read)(void __iomem *reg);
+ void (*write)(u32 val, void __iomem *reg);
};
struct phy_parameter {
@@ -128,6 +134,16 @@ struct rtk_phy {
struct dentry *debug_dir;
};
+static u32 rtk_usb2phy_read(void __iomem *reg)
+{
+ return readl(reg);
+}
+
+static void rtk_usb2phy_write(u32 val, void __iomem *reg)
+{
+ writel(val, reg);
+}
+
/* mapping 0xE0 to 0 ... 0xE7 to 7, 0xF0 to 8 ,,, 0xF7 to 15 */
static inline int page_addr_to_array_index(u8 addr)
{
@@ -200,8 +216,8 @@ static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data)
int ret = 0;
/* write data to VStatusOut2 (data output to phy) */
- writel((u32)data << shift_bits,
- reg_wrap_vstatus + phy_reg->vstatus_offset);
+ phy_reg->write((u32)data << shift_bits,
+ reg_wrap_vstatus + phy_reg->vstatus_offset);
ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
@@ -985,6 +1001,8 @@ static int parse_phy_data(struct rtk_phy *rtk_phy)
phy_parameter->phy_reg.vstatus_offset = phy_cfg->vstatus_offset;
phy_parameter->phy_reg.vstatus_busy = phy_cfg->vstatus_busy;
phy_parameter->phy_reg.new_reg_req = phy_cfg->new_reg_req;
+ phy_parameter->phy_reg.read = phy_cfg->read;
+ phy_parameter->phy_reg.write = phy_cfg->write;
if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock"))
phy_parameter->inverse_hstx_sync_clock = true;
@@ -1099,6 +1117,8 @@ static const struct phy_cfg rtd1295_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1395_phy_cfg = {
@@ -1126,6 +1146,8 @@ static const struct phy_cfg rtd1395_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1395_phy_cfg_2port = {
@@ -1153,6 +1175,8 @@ static const struct phy_cfg rtd1395_phy_cfg_2port = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1619_phy_cfg = {
@@ -1178,6 +1202,8 @@ static const struct phy_cfg rtd1619_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1319_phy_cfg = {
@@ -1207,6 +1233,8 @@ static const struct phy_cfg rtd1319_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1312c_phy_cfg = {
@@ -1235,6 +1263,8 @@ static const struct phy_cfg rtd1312c_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1619b_phy_cfg = {
@@ -1263,6 +1293,8 @@ static const struct phy_cfg rtd1619b_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1319d_phy_cfg = {
@@ -1291,6 +1323,8 @@ static const struct phy_cfg rtd1319d_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct phy_cfg rtd1315e_phy_cfg = {
@@ -1320,6 +1354,8 @@ static const struct phy_cfg rtd1315e_phy_cfg = {
.vstatus_offset = 0,
.vstatus_busy = PHY_VSTS_BUSY,
.new_reg_req = PHY_NEW_REG_REQ,
+ .read = rtk_usb2phy_read,
+ .write = rtk_usb2phy_write,
};
static const struct of_device_id usbphy_rtk_dt_match[] = {
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v6 5/6] phy: realtek: usb2: add support for RTL9607C USB2 PHY
From: Rustam Adilov @ 2026-05-20 17:57 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, Philipp Zabel, linux-phy, devicetree,
linux-kernel
Cc: Rustam Adilov, Michael Zavertkin
In-Reply-To: <20260520175728.720877-1-adilov@disroot.org>
Add support for the usb2 phy of RTL9607C series based SoCs.
Add the macros and phy config struct for rtl9607.
RTL9607C requires to clear a "force host disconnect" bit in the
specific register (which is at an offset from reg_wrap_vstatus)
before proceeding with phy parameter writes. Since it belongs into
the vstatus register region, it requires the use of added read and
write helper functions.
Add the bool variable to the driver data struct and hide this whole
procedure under the if statement that checks this new variable.
Add the appropriate big endian read and write functions for rtl9607
and assign them to its phy config struct.
Co-developed-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Rustam Adilov <adilov@disroot.org>
---
drivers/phy/realtek/phy-rtk-usb2.c | 58 ++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
index 16c5fc3191de..69f0f5279b5e 100644
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -26,6 +26,12 @@
#define PHY_VCTRL_SHIFT 8
#define PHY_REG_DATA_MASK 0xff
+#define PHY_9607_VSTS_BUSY BIT(17)
+#define PHY_9607_NEW_REG_REQ BIT(13)
+
+#define PHY_9607_FORCE_DISCONNECT_REG 0x10
+#define PHY_9607_FORCE_DISCONNECT_BIT BIT(5)
+
#define GET_LOW_NIBBLE(addr) ((addr) & 0x0f)
#define GET_HIGH_NIBBLE(addr) (((addr) & 0xf0) >> 4)
@@ -109,6 +115,7 @@ struct phy_cfg {
u32 (*read)(void __iomem *reg);
void (*write)(u32 val, void __iomem *reg);
+ bool force_host_disconnect;
};
struct phy_parameter {
@@ -146,6 +153,16 @@ static void rtk_usb2phy_write(u32 val, void __iomem *reg)
writel(val, reg);
}
+static u32 rtk_usb2phy_read_be(void __iomem *reg)
+{
+ return ioread32be(reg);
+}
+
+static void rtk_usb2phy_write_be(u32 val, void __iomem *reg)
+{
+ iowrite32be(val, reg);
+}
+
/* mapping 0xE0 to 0 ... 0xE7 to 7, 0xF0 to 8 ,,, 0xF7 to 15 */
static inline int page_addr_to_array_index(u8 addr)
{
@@ -600,6 +617,19 @@ static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
goto do_toggle;
}
+ if (phy_cfg->force_host_disconnect) {
+ /* disable force-host-disconnect */
+ void __iomem *vstatus = phy_reg->reg_wrap_vstatus;
+ u32 temp;
+
+ temp = phy_reg->read(vstatus + PHY_9607_FORCE_DISCONNECT_REG);
+
+ temp &= ~PHY_9607_FORCE_DISCONNECT_BIT;
+ phy_reg->write(temp, vstatus + PHY_9607_FORCE_DISCONNECT_REG);
+
+ usleep_range(10000, 11000);
+ }
+
/* Set page 0 */
phy_data_page = phy_cfg->page0;
rtk_phy_set_page(phy_reg, 0);
@@ -1374,6 +1404,33 @@ static const struct phy_cfg rtd1315e_phy_cfg = {
.write = rtk_usb2phy_write,
};
+static const struct phy_cfg rtl9607_phy_cfg = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [0] = {0xe0, 0x95},
+ [4] = {0xe4, 0x6a},
+ [12] = {0xf3, 0x31}, },
+ .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE,
+ .page1 = { [0] = {0xe0, 0x26}, },
+ .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+ .page2 = { [7] = {0xe7, 0x33}, },
+ .num_phy = 1,
+ .check_efuse_version = CHECK_EFUSE_V2,
+ .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
+ .dc_driving_mask = 0x1f,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = true,
+ .do_toggle = true,
+ .driving_updated_for_dev_dis = 0x8,
+ .is_double_sensitivity_mode = true,
+ .vstatus_offset = 0xc,
+ .vstatus_busy = PHY_9607_VSTS_BUSY,
+ .new_reg_req = PHY_9607_NEW_REG_REQ,
+ .read = rtk_usb2phy_read_be,
+ .write = rtk_usb2phy_write_be,
+ .force_host_disconnect = true,
+};
+
static const struct of_device_id usbphy_rtk_dt_match[] = {
{ .compatible = "realtek,rtd1295-usb2phy", .data = &rtd1295_phy_cfg },
{ .compatible = "realtek,rtd1312c-usb2phy", .data = &rtd1312c_phy_cfg },
@@ -1384,6 +1441,7 @@ static const struct of_device_id usbphy_rtk_dt_match[] = {
{ .compatible = "realtek,rtd1395-usb2phy-2port", .data = &rtd1395_phy_cfg_2port },
{ .compatible = "realtek,rtd1619-usb2phy", .data = &rtd1619_phy_cfg },
{ .compatible = "realtek,rtd1619b-usb2phy", .data = &rtd1619b_phy_cfg },
+ { .compatible = "realtek,rtl9607-usb2phy", .data = &rtl9607_phy_cfg },
{},
};
MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v6 4/6] phy: realtek: usb2: introduce reset controller struct
From: Rustam Adilov @ 2026-05-20 17:57 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, Philipp Zabel, linux-phy, devicetree,
linux-kernel
Cc: Rustam Adilov, Michael Zavertkin
In-Reply-To: <20260520175728.720877-1-adilov@disroot.org>
In RTL9607C, there is so called "IP Enable Controller" which resemble
reset controller with reset lines and is used for various things like
USB, PCIE, GMAC and such.
Introduce the reset_control struct to this driver to handle deasserting
usb2 phy reset line.
Make use of the function devm_reset_control_array_get_optional_exclusive()
function to get the reset controller and since existing RTD SoCs don't
specify the resets we can have a cleaner code.
Since the vendor usb driver developed by Realtek doesn't assert the reset
line (or in their case clear the register bit), we can reasonably assume
reset_control_assert is not needed here.
Co-developed-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Rustam Adilov <adilov@disroot.org>
---
drivers/phy/realtek/phy-rtk-usb2.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
index a9e29d2f7e6f..16c5fc3191de 100644
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -17,6 +17,7 @@
#include <linux/sys_soc.h>
#include <linux/mfd/syscon.h>
#include <linux/phy/phy.h>
+#include <linux/reset.h>
#include <linux/usb.h>
/* GUSB2PHYACCn register */
@@ -130,6 +131,7 @@ struct rtk_phy {
struct phy_cfg *phy_cfg;
int num_phy;
struct phy_parameter *phy_parameter;
+ struct reset_control *phy_rst;
struct dentry *debug_dir;
};
@@ -676,6 +678,15 @@ static int rtk_phy_init(struct phy *phy)
if (!rtk_phy)
return -EINVAL;
+ if (rtk_phy->phy_rst) {
+ ret = reset_control_deassert(rtk_phy->phy_rst);
+
+ if (ret)
+ return ret;
+
+ usleep_range(5000, 6000);
+ }
+
for (i = 0; i < rtk_phy->num_phy; i++)
ret = do_rtk_phy_init(rtk_phy, i);
@@ -1059,6 +1070,11 @@ static int rtk_usb2phy_probe(struct platform_device *pdev)
rtk_phy->num_phy = phy_cfg->num_phy;
+ rtk_phy->phy_rst = devm_reset_control_array_get_optional_exclusive(dev);
+ if (IS_ERR(rtk_phy->phy_rst))
+ return dev_err_probe(dev, PTR_ERR(rtk_phy->phy_rst),
+ "usb2 phy resets are not working\n");
+
ret = parse_phy_data(rtk_phy);
if (ret)
goto err;
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v6 1/6] phy: realtek: usb2: introduce vstatus/new_reg_req variables to driver data
From: Rustam Adilov @ 2026-05-20 17:57 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, Philipp Zabel, linux-phy, devicetree,
linux-kernel
Cc: Rustam Adilov, Michael Zavertkin
In-Reply-To: <20260520175728.720877-1-adilov@disroot.org>
In RTL9607C SoC, the vstatus register is located at a certain offset from
the base and so introduce the vstatus_offset to handle it.
Busy bit of the vstatus and new_reg_req bit are also different and so
introduce these variables to the driver data as well.
Add these variables to the pre-existing phy cfg structs for RTD SoCs and
assign them the default values.
Co-developed-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Michael Zavertkin <misha.zavertkin@mail.ru>
Signed-off-by: Rustam Adilov <adilov@disroot.org>
---
drivers/phy/realtek/phy-rtk-usb2.c | 68 +++++++++++++++++++++++-------
1 file changed, 53 insertions(+), 15 deletions(-)
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
index 248550ef98ca..bd9ee895b9f9 100644
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -64,6 +64,9 @@ struct phy_reg {
void __iomem *reg_wrap_vstatus;
void __iomem *reg_gusb2phyacc0;
int vstatus_index;
+ int vstatus_offset;
+ u32 vstatus_busy;
+ u32 new_reg_req;
};
struct phy_data {
@@ -96,6 +99,9 @@ struct phy_cfg {
bool do_toggle_driving;
bool use_default_parameter;
bool is_double_sensitivity_mode;
+ int vstatus_offset;
+ u32 vstatus_busy;
+ u32 new_reg_req;
};
struct phy_parameter {
@@ -162,21 +168,21 @@ static char rtk_phy_read(struct phy_reg *phy_reg, char addr)
addr -= OFFEST_PHY_READ;
/* polling until VBusy == 0 */
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return (char)ret;
- /* VCtrl = low nibble of addr, and set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ /* VCtrl = low nibble of addr, and set phy_reg->new_reg_req */
+ val = phy_reg->new_reg_req | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return (char)ret;
- /* VCtrl = high nibble of addr, and set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ /* VCtrl = high nibble of addr, and set phy_reg->new_reg_req */
+ val = phy_reg->new_reg_req | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return (char)ret;
@@ -194,25 +200,26 @@ static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data)
int ret = 0;
/* write data to VStatusOut2 (data output to phy) */
- writel((u32)data << shift_bits, reg_wrap_vstatus);
+ writel((u32)data << shift_bits,
+ reg_wrap_vstatus + phy_reg->vstatus_offset);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return ret;
- /* VCtrl = low nibble of addr, set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ /* VCtrl = low nibble of addr, set phy_reg->new_reg_req */
+ val = phy_reg->new_reg_req | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return ret;
- /* VCtrl = high nibble of addr, set PHY_NEW_REG_REQ */
- val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ /* VCtrl = high nibble of addr, set phy_reg->new_reg_req */
+ val = phy_reg->new_reg_req | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
writel(val, reg_gusb2phyacc0);
- ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, phy_reg->vstatus_busy, 0);
if (ret)
return ret;
@@ -957,6 +964,7 @@ static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
static int parse_phy_data(struct rtk_phy *rtk_phy)
{
+ struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
struct device *dev = rtk_phy->dev;
struct device_node *np = dev->of_node;
struct phy_parameter *phy_parameter;
@@ -974,6 +982,9 @@ static int parse_phy_data(struct rtk_phy *rtk_phy)
phy_parameter->phy_reg.reg_wrap_vstatus = of_iomap(np, 0);
phy_parameter->phy_reg.reg_gusb2phyacc0 = of_iomap(np, 1) + index;
phy_parameter->phy_reg.vstatus_index = index;
+ phy_parameter->phy_reg.vstatus_offset = phy_cfg->vstatus_offset;
+ phy_parameter->phy_reg.vstatus_busy = phy_cfg->vstatus_busy;
+ phy_parameter->phy_reg.new_reg_req = phy_cfg->new_reg_req;
if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock"))
phy_parameter->inverse_hstx_sync_clock = true;
@@ -1085,6 +1096,9 @@ static const struct phy_cfg rtd1295_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = false,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1395_phy_cfg = {
@@ -1109,6 +1123,9 @@ static const struct phy_cfg rtd1395_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = false,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1395_phy_cfg_2port = {
@@ -1133,6 +1150,9 @@ static const struct phy_cfg rtd1395_phy_cfg_2port = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = false,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1619_phy_cfg = {
@@ -1155,6 +1175,9 @@ static const struct phy_cfg rtd1619_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = false,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1319_phy_cfg = {
@@ -1181,6 +1204,9 @@ static const struct phy_cfg rtd1319_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1312c_phy_cfg = {
@@ -1206,6 +1232,9 @@ static const struct phy_cfg rtd1312c_phy_cfg = {
.driving_updated_for_dev_dis = 0xf,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1619b_phy_cfg = {
@@ -1231,6 +1260,9 @@ static const struct phy_cfg rtd1619b_phy_cfg = {
.driving_updated_for_dev_dis = 0x8,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1319d_phy_cfg = {
@@ -1256,6 +1288,9 @@ static const struct phy_cfg rtd1319d_phy_cfg = {
.driving_updated_for_dev_dis = 0x8,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct phy_cfg rtd1315e_phy_cfg = {
@@ -1282,6 +1317,9 @@ static const struct phy_cfg rtd1315e_phy_cfg = {
.driving_updated_for_dev_dis = 0x8,
.use_default_parameter = false,
.is_double_sensitivity_mode = true,
+ .vstatus_offset = 0,
+ .vstatus_busy = PHY_VSTS_BUSY,
+ .new_reg_req = PHY_NEW_REG_REQ,
};
static const struct of_device_id usbphy_rtk_dt_match[] = {
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v6 3/6] dt-bindings: phy: realtek,usb2phy.yaml: extend for resets and RTL9607C support
From: Rustam Adilov @ 2026-05-20 17:57 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, Philipp Zabel, linux-phy, devicetree,
linux-kernel
Cc: Rustam Adilov, Krzysztof Kozlowski
In-Reply-To: <20260520175728.720877-1-adilov@disroot.org>
Add the "realtek,rtl9607-usb2phy" compatible for USB2 PHY on the RTL9607C
SoC series.
Add a resets property to properties to describe the usb2phy reset line.
In RTL9607C, USB2 PHY reset line is from "IP Enable controller" which is
multipurpose and handle activating various SoC peripherals.
It is unclear whether RTD SoCs have something similar to that so set
the resets to false for these devices.
RTL9607C requires the "resets" to be specified so add the corresponding
if check for the "realtek,rtl9607-usb2phy" compatible.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Rustam Adilov <adilov@disroot.org>
---
.../bindings/phy/realtek,usb2phy.yaml | 25 ++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/phy/realtek,usb2phy.yaml b/Documentation/devicetree/bindings/phy/realtek,usb2phy.yaml
index 9911ada39ee7..7b50833c8e19 100644
--- a/Documentation/devicetree/bindings/phy/realtek,usb2phy.yaml
+++ b/Documentation/devicetree/bindings/phy/realtek,usb2phy.yaml
@@ -11,7 +11,8 @@ maintainers:
- Stanley Chang <stanley_chang@realtek.com>
description: |
- Realtek USB 2.0 PHY support the digital home center (DHC) RTD series SoCs.
+ Realtek USB 2.0 PHY support the digital home center (DHC) RTD and
+ RTL9607C series SoCs.
The USB 2.0 PHY driver is designed to support the XHCI controller. The SoCs
support multiple XHCI controllers. One PHY device node maps to one XHCI
controller.
@@ -57,6 +58,12 @@ description: |
XHCI controller#1 -- usb2phy -- phy#0
XHCI controller#2 -- usb2phy -- phy#0
+ RTL9607C SoCs USB
+ The USB architecture includes OHCI and EHCI controllers.
+ Both of them map to one USB2.0 PHY.
+ OHCI controller#0 -- usb2phy -- phy#0
+ EHCI controller#0 -- usb2phy -- phy#0
+
properties:
compatible:
enum:
@@ -69,6 +76,7 @@ properties:
- realtek,rtd1395-usb2phy-2port
- realtek,rtd1619-usb2phy
- realtek,rtd1619b-usb2phy
+ - realtek,rtl9607-usb2phy
reg:
items:
@@ -130,6 +138,9 @@ properties:
minimum: -8
maximum: 8
+ resets:
+ maxItems: 1
+
required:
- compatible
- reg
@@ -157,6 +168,18 @@ allOf:
then:
properties:
realtek,driving-level-compensate: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - realtek,rtl9607-usb2phy
+ then:
+ required:
+ - resets
+ else:
+ properties:
+ resets: false
additionalProperties: false
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v6 0/6] phy: realtek: usb2: support for RTL9607C USB2 PHY
From: Rustam Adilov @ 2026-05-20 17:57 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stanley Chang, Philipp Zabel, linux-phy, devicetree,
linux-kernel
Cc: Rustam Adilov
This patch series for Realtek USB2 PHY driver adds support for RTL9607C
USB2 PHY.
RTL9607C is a big endian MIPS CPU which is quite far from RTD series SoCs
supported by realtek usb2 phy driver, but the phy initilization is found
to be very indentical in most areas.
Most of the code was based on the Realtek's usb driver from the GPL tarball
in [1] and adjusted to fit into the realtek usb2 phy driver code format.
The patch series was split into smaller patches that add/change something
in the driver that are not exactly related to RTL9607C and that also
helps for easier review. That also means, patch 5 depends on all the prior
patches that come before it.
USB2 PHY on RTL9607C is primarly used for its internal OHCI/EHCI controllers.
Tested on my RTL9607C based machine as a backport to 6.18 linux in OpenWrt.
[1] - https://github.com/jameywine/GPL-for-GP3000/blob/main/linux-5.10.x/arch/mips/rtl9607c/usb.c
---
Changelog in v6:
Driver has been refactored with enabled SWAP_IO_SPACE config in mind.
- Patch 1
- fixed one line exceeding 80 columns.
- Patch 2
- changed to use the introduced read/write functions for reg_wrap_vstatus
instead of reg_gusb2phyacc0.
- Patch 3
- properly added the review tag from v4 of patch series.
- Patch 5
- fixed the lines exceeding 80 columns.
- changed msleep(10) to usleep_range(10000, 11000).
- changed the read and write functions to use ioread32be instead of __le32
now that we are using them for reg_wrap_vstatus.
- Link to v5: https://lore.kernel.org/linux-phy/20260420191941.81834-1-adilov@disroot.org/
Changelog in v5:
Mostly addressing LLM review
- Patch 1
- changed int to u32 type for new_reg_req and vstatus_busy data fields.
- changed comments in rtk_phy_read/write from PHY_NEW_REG_REQ to phy_reg->new_reg_req.
- Patch 2
- explained readl/writel native endianess issue in more detail.
- explained why vstatus register doesn't need byte swapping.
- Patch 4
- moved reset_control_deassert to rtk_phy_init function to keep it outside of for loop.
- changed msleep(5) to usleep_range(5000, 6000).
- explained why reset_control_assert is not needed.
- Patch 5
- explained readl/writel native endianess issue here as well.
- explained why FORCE_DISCONNECT_REG doesn't need byte swapping.
- Link to v4: https://lore.kernel.org/linux-phy/20260406181228.25892-1-adilov@disroot.org/
Changelog in v4:
- Patch 2
- moved the le variations of read/write functions to Patch 5 where it is actually used because
otherwise, it results in unused errors when only Patch 2 is applied.
- updated the commit message to to point the reason for le32 wrappers around readl/writel.
- Patch 3
- added "Reviewed by Krzysztof Kozlowski"
- Patch 5
- updated the commit message to include the addition of little endian read/write functions from
Patch 2.
- Link to v3: https://lore.kernel.org/linux-phy/20260402154414.196012-1-adilov@disroot.org/
Changelog in v3:
- Patch 2
- renamed phy read and functions to "rtk_usb2phy" to not collide with networking API functions
- fixed the sparse warnings by creating intermidiate "tmp" variable and then pass it to writel
- sligtly adjusted commit message to instead use "default read" not "default phy_read"
- Patch 4
- added the check for reset_control_deassert() just in case
- changed mdelay(5) to msleep(5)
- changed dev_err and return combo with one dev_err_probe for phy_rst
- Patch 5
- changed mdelay(10) under force_host_disconnect to msleep(10)
- removed struct fields with false like force_host_disconnect and more in rtl9607_phy_cfg
- Patch 6
- updated the #endif commend to now include MACH_REALTEK_RTL to reflect if on top
- Link to v2: https://lore.kernel.org/linux-phy/20260327160638.15134-1-adilov@disroot.org/
Changelog in v2:
- Patch 3
- removed the line about OHCI/EHCI controllers from description.
- set the resets to false for RTD SoC devices and changed the
commit message to reflect that.
- Link to v1: https://lore.kernel.org/linux-phy/20260326193419.48419-1-adilov@disroot.org/
Rustam Adilov (6):
phy: realtek: usb2: introduce vstatus/new_reg_req variables to driver
data
phy: realtek: usb2: introduce read and write functions to driver data
dt-bindings: phy: realtek,usb2phy.yaml: extend for resets and RTL9607C
support
phy: realtek: usb2: introduce reset controller struct
phy: realtek: usb2: add support for RTL9607C USB2 PHY
phy: realtek: Make configs available for MACH_REALTEK_RTL
.../bindings/phy/realtek,usb2phy.yaml | 25 ++-
drivers/phy/realtek/Kconfig | 4 +-
drivers/phy/realtek/phy-rtk-usb2.c | 178 ++++++++++++++++--
3 files changed, 189 insertions(+), 18 deletions(-)
--
2.54.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v2] phy: exynos5-usbdrd: Remove error print for devm_add_action_or_reset()
From: Tudor Ambarus @ 2026-05-20 17:06 UTC (permalink / raw)
To: Waqar Hameed, Vinod Koul, Kishon Vijay Abraham I,
Krzysztof Kozlowski, Alim Akhtar
Cc: kernel, linux-phy, linux-arm-kernel, linux-samsung-soc,
linux-kernel, Peter Griffin, André Draszik, Juan Yescas
In-Reply-To: <pndjysynn55.a.out@axis.com>
On 5/20/26 5:58 PM, Waqar Hameed wrote:
> On Fri, Oct 10, 2025 at 15:39 +0200 Waqar Hameed <waqar.hameed@axis.com> wrote:
>
>> On Tue, Aug 05, 2025 at 11:33 +0200 Waqar Hameed <waqar.hameed@axis.com> wrote:
>
> [...]
>
>> Friendly ping incoming!
>
> Friendly ping 2 incoming!
>
> This will be the last ping for the original patch [1]. I'll interpret
> the silence as a NACK (though it would preferable to get an explicit
The patch is fine, I think it just slipped through the cracks:
Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
> one...). All other patches in the previous patch series has been merged
> [2].
>
> [1] https://lore.kernel.org/all/pnd34a6m7tc.a.out@axis.com/
> [2] https://lore.kernel.org/all/pnd7c0s6ji2.fsf@axis.com/
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH RFC v4 5/9] phy: qcom: qmp-pcie: Refactor pipe clk register and parse_dt helpers
From: Dmitry Baryshkov @ 2026-05-20 16:25 UTC (permalink / raw)
To: Qiang Yu
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Bjorn Andersson, Konrad Dybcio,
linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <20260518-link_mode_0519-v4-5-269cd73cc5d1@oss.qualcomm.com>
On Mon, May 18, 2026 at 10:47:16PM -0700, Qiang Yu wrote:
> Some QMP PCIe PHY hardware blocks can be split into multiple sub-PHYs
> under a single DT node, each requiring its own pipe clock registration and
> DT resource mapping. The current helpers are tightly coupled to a single
> qmp_pcie instance, which prevents reuse across sub-PHY instances.
>
> Refactor __phy_pipe_clk_register() as a generic helper and reduce
> phy_pipe_clk_register() to a thin wrapper around it. Similarly, extract
> qmp_pcie_parse_dt_common() from qmp_pcie_parse_dt() to hold the register-
> mapping and pipe-clock setup that will be shared between sub-PHY instances,
> with pipe clock names parameterised per instance.
>
> This is a preparatory step before adding multi-PHY support. No functional
> change for existing platforms.
>
> Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 76 ++++++++++++++++++--------------
> 1 file changed, 44 insertions(+), 32 deletions(-)
I'd suggest splitting the Glymur PHY to a separate driver. Otherwise we
end up having too many single-platform, single-device specifics which
don't apply to other platforms.
--
With best wishes
Dmitry
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v8 phy-next 15/31] drm/rockchip: dw_hdmi: avoid direct dereference of phy->dev.of_node
From: Vladimir Oltean @ 2026-05-20 15:20 UTC (permalink / raw)
To: Heiko Stuebner
Cc: linux-phy, Vinod Koul, Neil Armstrong, dri-devel, freedreno,
linux-arm-kernel, linux-arm-msm, linux-can, linux-gpio, linux-ide,
linux-kernel, linux-media, linux-pci, linux-renesas-soc,
linux-riscv, linux-rockchip, linux-samsung-soc, linux-scsi,
linux-sunxi, linux-tegra, linux-usb, netdev, spacemit,
UNGLinuxDriver, Sandy Huang, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter
In-Reply-To: <3758596.1xdlsreqCQ@phil>
Hi Heiko,
On Wed, May 20, 2026 at 04:21:24PM +0200, Heiko Stuebner wrote:
> Hi Vladimir,
>
> Am Dienstag, 5. Mai 2026, 12:05:07 Mitteleuropäische Sommerzeit schrieb Vladimir Oltean:
> > The dw_hdmi-rockchip driver validates pixel clock rates against the
> > HDMI PHY's internal clock provider on certain SoCs like RK3328.
> > This is currently achieved by dereferencing hdmi->phy->dev.of_node
> > to obtain the provider node, which violates the Generic PHY API's
> > encapsulation (the goal is for struct phy to be an opaque pointer
> > with a hidden definition, to be interacted with only using API
> > functions or NULL pointer checks, for the case where optional variants
> > of phy_get() did not find a PHY).
> >
> > Refactor dw_hdmi_rockchip_bind() to perform a manual phandle lookup
> > on the "hdmi" PHY index within the controller's DT node. This provides
> > a parallel path to the clock provider's OF node without relying on the
> > internal structure of the struct phy handle.
> >
> > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> > Reviewed-by: Heiko Stueber <heiko@sntech.de>
>
> there is now already more stuff depending on this change [0], and
> the change itself also is sort of independent of the whole
> phy-series. And somehow this series itself sadly hasn't gotten
> much review yet.
>
> So would you be ok with me just picking this one patch for the
> drm-misc-tree?
>
>
> Thanks
> Heiko
>
> [0] https://lore.kernel.org/dri-devel/20260518193748.2482823-1-jonas@kwiboo.se/
I am currently out of office, so I can't look very closely, but yes,
I did agree with Vinod to try to reduce the size of this series by
submitting some of the changes this cycle to individual subsystems, and
the cross-tree remainder the following cycle. So yes, feel free to pick
from this series and I'll submit to dri-devel whatever remains when I
return to this activity.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v8 0/5] airoha: an7581: USB support
From: Christian Marangi @ 2026-05-20 15:14 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul, Neil Armstrong,
Lorenzo Bianconi, Felix Fietkau, linux-clk, devicetree,
linux-kernel, linux-arm-kernel, linux-phy
In-Reply-To: <20260520150912.11614-1-ansuelsmth@gmail.com>
On Wed, May 20, 2026 at 05:09:05PM +0200, Christian Marangi wrote:
> This is a major rework of the old v2 series.
>
> The SoC always support USB 2.0 but for USB 3.0 it needs additional
> configuration for the Serdes port. Such port can be either configured
> for USB usage or for PCIe lines or HSGMII and these are configured
> in the SCU space.
>
> The previous implementation of a dedicated SSR driver was too
> complex and fragile for the simple task of configuring a register
> hence it was dropped and the handling is entirely in the PHY driver.
>
> Everything was reducted to the dt-bindings to describe the Serdes line.
>
> Also the property for the PHY are renamed to a more suitable name and
> everything is now mandatory to simplify the implementation.
> (the PHY are always present and active on the SoC)
>
> Also other unrelated patch are dropped from this series.
>
> Changes v8:
> - Squash header to clk Documentation patch
> - Address comments from AI Bot
>
> Changes v7:
> - Rework to double PHY implementation
> (suggested by Rob)
> Now the clk driver expose a PHY for Serdes port
> USB PHY driver selects it
> - Rebase on top of linux-next
> Link: https://lore.kernel.org/all/20260306190156.22297-1-ansuelsmth@gmail.com/
Typo for the link. It's:
Link: https://lore.kernel.org/all/20260519220813.28468-1-ansuelsmth@gmail.com/
>
> Changes v6:
> - Fix kernel test robot (sparse warning)
> Link: https://lore.kernel.org/all/20260306190156.22297-1-ansuelsmth@gmail.com/
>
> Changes v5:
> - Add Ack and Review tag from Connor
> - Implement Ethernet support in the USB driver
> (testing support for this Serdes on a special reference board)
> - Use an7581 prefix for USB PHY driver
> Link: https://lore.kernel.org/all/20251107160251.2307088-1-ansuelsmth@gmail.com/
>
> Changes v4:
> - Rename PCIe and USB PHY to AN7581
> - Drop airoha,scu (handled directly in driver)
> - Drop dt-bindings for monitor clock in favor of raw values
> - Better describe the usage of airoha,usb3-serdes
> - Simplify values of dt-bindings SSR SERDES
> Link: https://lore.kernel.org/all/20251107160251.2307088-1-ansuelsmth@gmail.com/
>
> Changes v3:
> - Drop clk changes
> - Drop SSR driver
> - Rename property in Documentation
> - Simplify PHY handling
> - Move SSR handling inside the PHY driver
> Link: https://lore.kernel.org/all/20251029173713.7670-1-ansuelsmth@gmail.com/
>
> Changes v2:
> - Drop changes for simple-mfd
> - Rework PHY node structure to single node
> - Drop port-id property in favor of serdes-port and
> usb2-monitor-clock-sel
> - Make the SSR driver probe from the clock driver
>
> Christian Marangi (5):
> dt-bindings: clock: airoha: Add PHY binding for Serdes port
> dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
> clk: en7523: Add support for selecting the Serdes port in SCU
> phy: move and rename Airoha PCIe PHY driver to dedicated directory
> phy: airoha: Add support for Airoha AN7581 USB PHY
>
> .../bindings/clock/airoha,en7523-scu.yaml | 9 +
> .../bindings/phy/airoha,an7581-usb-phy.yaml | 62 ++
> MAINTAINERS | 11 +-
> drivers/clk/Kconfig | 1 +
> drivers/clk/clk-en7523.c | 216 ++++++-
> drivers/phy/Kconfig | 11 +-
> drivers/phy/Makefile | 4 +-
> drivers/phy/airoha/Kconfig | 24 +
> drivers/phy/airoha/Makefile | 4 +
> .../phy-an7581-pcie-regs.h} | 2 +-
> .../phy-an7581-pcie.c} | 6 +-
> drivers/phy/airoha/phy-an7581-usb.c | 554 ++++++++++++++++++
> include/dt-bindings/soc/airoha,scu-ssr.h | 11 +
> 13 files changed, 894 insertions(+), 21 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
> create mode 100644 drivers/phy/airoha/Kconfig
> create mode 100644 drivers/phy/airoha/Makefile
> rename drivers/phy/{phy-airoha-pcie-regs.h => airoha/phy-an7581-pcie-regs.h} (99%)
> rename drivers/phy/{phy-airoha-pcie.c => airoha/phy-an7581-pcie.c} (99%)
> create mode 100644 drivers/phy/airoha/phy-an7581-usb.c
> create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h
>
> --
> 2.53.0
>
--
Ansuel
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v8 5/5] phy: airoha: Add support for Airoha AN7581 USB PHY
From: Christian Marangi @ 2026-05-20 15:09 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Christian Marangi, Vinod Koul,
Neil Armstrong, Lorenzo Bianconi, Felix Fietkau, linux-clk,
devicetree, linux-kernel, linux-arm-kernel, linux-phy
In-Reply-To: <20260520150912.11614-1-ansuelsmth@gmail.com>
Add support for Airoha AN7581 USB PHY driver. AN7581 supports up to 2
USB port with USB 2.0 mode always supported and USB 3.0 mode available
only if the Serdes port is correctly configured for USB 3.0.
If the USB 3.0 mode is not configured, the modes needs to be also
disabled in the xHCI node or the driver will report unsable clock and
fail probe.
For USB 2.0 Slew Rate calibration, airoha,usb2-monitor-clk-sel is
mandatory and is used to select the monitor clock for calibration.
Normally it's 1 for USB port 1 and 2 for USB port 2.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
MAINTAINERS | 1 +
drivers/phy/airoha/Kconfig | 11 +
drivers/phy/airoha/Makefile | 1 +
drivers/phy/airoha/phy-an7581-usb.c | 554 ++++++++++++++++++++++++++++
4 files changed, 567 insertions(+)
create mode 100644 drivers/phy/airoha/phy-an7581-usb.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 7bea8c620da8..2f05faa44503 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -776,6 +776,7 @@ M: Christian Marangi <ansuelsmth@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
+F: drivers/phy/airoha/phy-an7581-usb.c
AIRSPY MEDIA DRIVER
L: linux-media@vger.kernel.org
diff --git a/drivers/phy/airoha/Kconfig b/drivers/phy/airoha/Kconfig
index 9a1b625a7701..634448ee39b5 100644
--- a/drivers/phy/airoha/Kconfig
+++ b/drivers/phy/airoha/Kconfig
@@ -11,3 +11,14 @@ config PHY_AIROHA_AN7581_PCIE
Say Y here to add support for Airoha AN7581 PCIe PHY driver.
This driver create the basic PHY instance and provides initialize
callback for PCIe GEN3 port.
+
+config PHY_AIROHA_AN7581_USB
+ tristate "Airoha AN7581 USB PHY Driver"
+ depends on ARCH_AIROHA || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ select REGMAP_MMIO
+ help
+ Say 'Y' here to add support for Airoha AN7581 USB PHY driver.
+ This driver create the basic PHY instance and provides initialize
+ callback for USB port.
diff --git a/drivers/phy/airoha/Makefile b/drivers/phy/airoha/Makefile
index 912f3e11a061..944bf842deba 100644
--- a/drivers/phy/airoha/Makefile
+++ b/drivers/phy/airoha/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_AIROHA_AN7581_PCIE) += phy-an7581-pcie.o
+obj-$(CONFIG_PHY_AIROHA_AN7581_USB) += phy-an7581-usb.o
diff --git a/drivers/phy/airoha/phy-an7581-usb.c b/drivers/phy/airoha/phy-an7581-usb.c
new file mode 100644
index 000000000000..af20f5cb4ed1
--- /dev/null
+++ b/drivers/phy/airoha/phy-an7581-usb.c
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Christian Marangi <ansuelsmth@gmail.com>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/soc/airoha,scu-ssr.h>
+#include <linux/bitfield.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* U2PHY */
+#define AIROHA_USB_PHY_FMCR0 0x100
+#define AIROHA_USB_PHY_MONCLK_SEL GENMASK(27, 26)
+#define AIROHA_USB_PHY_MONCLK_SEL0 FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x0)
+#define AIROHA_USB_PHY_MONCLK_SEL1 FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x1)
+#define AIROHA_USB_PHY_MONCLK_SEL2 FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x2)
+#define AIROHA_USB_PHY_MONCLK_SEL3 FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x3)
+#define AIROHA_USB_PHY_FREQDET_EN BIT(24)
+#define AIROHA_USB_PHY_CYCLECNT GENMASK(23, 0)
+#define AIROHA_USB_PHY_FMMONR0 0x10c
+#define AIROHA_USB_PHY_USB_FM_OUT GENMASK(31, 0)
+#define AIROHA_USB_PHY_FMMONR1 0x110
+#define AIROHA_USB_PHY_FRCK_EN BIT(8)
+
+#define AIROHA_USB_PHY_USBPHYACR4 0x310
+#define AIROHA_USB_PHY_USB20_FS_CR GENMASK(10, 8)
+#define AIROHA_USB_PHY_USB20_FS_CR_MAX FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x0)
+#define AIROHA_USB_PHY_USB20_FS_CR_NORMAL FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x2)
+#define AIROHA_USB_PHY_USB20_FS_CR_SMALLER FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x4)
+#define AIROHA_USB_PHY_USB20_FS_CR_MIN FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x6)
+#define AIROHA_USB_PHY_USB20_FS_SR GENMASK(2, 0)
+#define AIROHA_USB_PHY_USB20_FS_SR_MAX FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x0)
+#define AIROHA_USB_PHY_USB20_FS_SR_NORMAL FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x2)
+#define AIROHA_USB_PHY_USB20_FS_SR_SMALLER FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x4)
+#define AIROHA_USB_PHY_USB20_FS_SR_MIN FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x6)
+#define AIROHA_USB_PHY_USBPHYACR5 0x314
+#define AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN BIT(15)
+#define AIROHA_USB_PHY_USB20_HSTX_SRCTRL GENMASK(14, 12)
+#define AIROHA_USB_PHY_USBPHYACR6 0x318
+#define AIROHA_USB_PHY_USB20_BC11_SW_EN BIT(23)
+#define AIROHA_USB_PHY_USB20_DISCTH GENMASK(7, 4)
+#define AIROHA_USB_PHY_USB20_DISCTH_400 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x0)
+#define AIROHA_USB_PHY_USB20_DISCTH_420 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x1)
+#define AIROHA_USB_PHY_USB20_DISCTH_440 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x2)
+#define AIROHA_USB_PHY_USB20_DISCTH_460 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x3)
+#define AIROHA_USB_PHY_USB20_DISCTH_480 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x4)
+#define AIROHA_USB_PHY_USB20_DISCTH_500 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x5)
+#define AIROHA_USB_PHY_USB20_DISCTH_520 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x6)
+#define AIROHA_USB_PHY_USB20_DISCTH_540 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x7)
+#define AIROHA_USB_PHY_USB20_DISCTH_560 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x8)
+#define AIROHA_USB_PHY_USB20_DISCTH_580 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x9)
+#define AIROHA_USB_PHY_USB20_DISCTH_600 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xa)
+#define AIROHA_USB_PHY_USB20_DISCTH_620 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xb)
+#define AIROHA_USB_PHY_USB20_DISCTH_640 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xc)
+#define AIROHA_USB_PHY_USB20_DISCTH_660 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xd)
+#define AIROHA_USB_PHY_USB20_DISCTH_680 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xe)
+#define AIROHA_USB_PHY_USB20_DISCTH_700 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xf)
+#define AIROHA_USB_PHY_USB20_SQTH GENMASK(3, 0)
+#define AIROHA_USB_PHY_USB20_SQTH_85 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x0)
+#define AIROHA_USB_PHY_USB20_SQTH_90 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x1)
+#define AIROHA_USB_PHY_USB20_SQTH_95 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x2)
+#define AIROHA_USB_PHY_USB20_SQTH_100 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x3)
+#define AIROHA_USB_PHY_USB20_SQTH_105 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x4)
+#define AIROHA_USB_PHY_USB20_SQTH_110 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x5)
+#define AIROHA_USB_PHY_USB20_SQTH_115 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x6)
+#define AIROHA_USB_PHY_USB20_SQTH_120 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x7)
+#define AIROHA_USB_PHY_USB20_SQTH_125 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x8)
+#define AIROHA_USB_PHY_USB20_SQTH_130 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x9)
+#define AIROHA_USB_PHY_USB20_SQTH_135 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xa)
+#define AIROHA_USB_PHY_USB20_SQTH_140 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xb)
+#define AIROHA_USB_PHY_USB20_SQTH_145 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xc)
+#define AIROHA_USB_PHY_USB20_SQTH_150 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xd)
+#define AIROHA_USB_PHY_USB20_SQTH_155 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xe)
+#define AIROHA_USB_PHY_USB20_SQTH_160 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xf)
+
+#define AIROHA_USB_PHY_U2PHYDTM1 0x36c
+#define AIROHA_USB_PHY_FORCE_IDDIG BIT(9)
+#define AIROHA_USB_PHY_IDDIG BIT(1)
+
+#define AIROHA_USB_PHY_GPIO_CTLD 0x80c
+#define AIROHA_USB_PHY_C60802_GPIO_CTLD GENMASK(31, 0)
+#define AIROHA_USB_PHY_SSUSB_IP_SW_RST BIT(31)
+#define AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN BIT(30)
+#define AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST BIT(29)
+#define AIROHA_USB_PHY_SSUSB_SW_RST BIT(28)
+
+#define AIROHA_USB_PHY_U3_PHYA_REG0 0xb00
+#define AIROHA_USB_PHY_SSUSB_BG_DIV GENMASK(29, 28)
+#define AIROHA_USB_PHY_SSUSB_BG_DIV_2 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x0)
+#define AIROHA_USB_PHY_SSUSB_BG_DIV_4 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x1)
+#define AIROHA_USB_PHY_SSUSB_BG_DIV_8 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x2)
+#define AIROHA_USB_PHY_SSUSB_BG_DIV_16 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x3)
+#define AIROHA_USB_PHY_U3_PHYA_REG1 0xb04
+#define AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE GENMASK(25, 10)
+#define AIROHA_USB_PHY_U3_PHYA_REG6 0xb18
+#define AIROHA_USB_PHY_SSUSB_CDR_RESERVE GENMASK(31, 24)
+#define AIROHA_USB_PHY_U3_PHYA_REG8 0xb20
+#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY GENMASK(7, 6)
+#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x0)
+#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_64 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x1)
+#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_128 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x2)
+#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_216 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x3)
+
+#define AIROHA_USB_PHY_U3_PHYA_DA_REG19 0xc38
+#define AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3 GENMASK(15, 0)
+
+#define AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT 1024
+#define AIROHA_USB_PHY_REF_CK 20
+#define AIROHA_USB_PHY_U2_SR_COEF 28
+#define AIROHA_USB_PHY_U2_SR_COEF_DIVISOR 1000
+
+#define AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION 0x5
+#define AIROHA_USB_PHY_FREQDET_SLEEP 1000 /* 1ms */
+#define AIROHA_USB_PHY_FREQDET_TIMEOUT (AIROHA_USB_PHY_FREQDET_SLEEP * 10)
+
+struct an7581_usb_phy_instance {
+ struct phy *phy;
+ u32 type;
+};
+
+enum an7581_usb_phy_instance_type {
+ AIROHA_PHY_USB2,
+ AIROHA_PHY_USB3,
+
+ AIROHA_PHY_USB_MAX,
+};
+
+struct an7581_usb_phy_priv {
+ struct device *dev;
+ struct regmap *regmap;
+
+ unsigned int monclk_sel;
+
+ struct phy *serdes_phy;
+ struct an7581_usb_phy_instance *phys[AIROHA_PHY_USB_MAX];
+};
+
+static void an7581_usb_phy_u2_slew_rate_calibration(struct an7581_usb_phy_priv *priv)
+{
+ u32 fm_out = 0;
+ u32 srctrl;
+
+ /* Enable HS TX SR calibration */
+ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
+ AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
+
+ usleep_range(1000, 1500);
+
+ /* Enable Free run clock */
+ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
+ AIROHA_USB_PHY_FRCK_EN);
+
+ /* Select Monitor Clock */
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+ AIROHA_USB_PHY_MONCLK_SEL,
+ FIELD_PREP(AIROHA_USB_PHY_MONCLK_SEL,
+ priv->monclk_sel));
+
+ /* Set cyclecnt */
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+ AIROHA_USB_PHY_CYCLECNT,
+ FIELD_PREP(AIROHA_USB_PHY_CYCLECNT,
+ AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT));
+
+ /* Enable Frequency meter */
+ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+ AIROHA_USB_PHY_FREQDET_EN);
+
+ /* Timeout can happen and we will apply workaround at the end */
+ regmap_read_poll_timeout(priv->regmap, AIROHA_USB_PHY_FMMONR0, fm_out,
+ fm_out, AIROHA_USB_PHY_FREQDET_SLEEP,
+ AIROHA_USB_PHY_FREQDET_TIMEOUT);
+
+ /* Disable Frequency meter */
+ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
+ AIROHA_USB_PHY_FREQDET_EN);
+
+ /* Disable Free run clock */
+ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
+ AIROHA_USB_PHY_FRCK_EN);
+
+ /* Disable HS TX SR calibration */
+ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
+ AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
+
+ usleep_range(1000, 1500);
+
+ /* Frequency was not detected, use default SR calibration value */
+ if (!fm_out) {
+ srctrl = AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION;
+ dev_err(priv->dev, "Frequency not detected, using default SR calibration.\n");
+ } else {
+ /* (1024 / FM_OUT) * REF_CK * U2_SR_COEF (round to the nearest digits) */
+ srctrl = AIROHA_USB_PHY_REF_CK * AIROHA_USB_PHY_U2_SR_COEF;
+ srctrl = (srctrl * AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT) / fm_out;
+ srctrl = DIV_ROUND_CLOSEST(srctrl, AIROHA_USB_PHY_U2_SR_COEF_DIVISOR);
+ dev_dbg(priv->dev, "SR calibration applied: %x\n", srctrl);
+ }
+
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
+ AIROHA_USB_PHY_USB20_HSTX_SRCTRL,
+ FIELD_PREP(AIROHA_USB_PHY_USB20_HSTX_SRCTRL, srctrl));
+}
+
+static void an7581_usb_phy_u2_init(struct an7581_usb_phy_priv *priv)
+{
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4,
+ AIROHA_USB_PHY_USB20_FS_CR,
+ AIROHA_USB_PHY_USB20_FS_CR_MIN);
+
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4,
+ AIROHA_USB_PHY_USB20_FS_SR,
+ AIROHA_USB_PHY_USB20_FS_SR_NORMAL);
+
+ /* FIXME: evaluate if needed */
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+ AIROHA_USB_PHY_USB20_SQTH,
+ AIROHA_USB_PHY_USB20_SQTH_130);
+
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+ AIROHA_USB_PHY_USB20_DISCTH,
+ AIROHA_USB_PHY_USB20_DISCTH_600);
+
+ /* Enable the USB port and then disable after calibration */
+ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+ AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+ an7581_usb_phy_u2_slew_rate_calibration(priv);
+
+ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+ AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+ usleep_range(1000, 1500);
+}
+
+/*
+ * USB 3.0 mode can only work if USB serdes is correctly set.
+ * This is validated in xLate function.
+ */
+static void an7581_usb_phy_u3_init(struct an7581_usb_phy_priv *priv)
+{
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG8,
+ AIROHA_USB_PHY_SSUSB_CDR_RST_DLY,
+ AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32);
+
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG6,
+ AIROHA_USB_PHY_SSUSB_CDR_RESERVE,
+ FIELD_PREP(AIROHA_USB_PHY_SSUSB_CDR_RESERVE, 0xe));
+
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG0,
+ AIROHA_USB_PHY_SSUSB_BG_DIV,
+ AIROHA_USB_PHY_SSUSB_BG_DIV_4);
+
+ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG1,
+ FIELD_PREP(AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE, 0x600));
+
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_DA_REG19,
+ AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3,
+ FIELD_PREP(AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3, 0x43));
+}
+
+static int an7581_usb_phy_init(struct phy *phy)
+{
+ struct an7581_usb_phy_instance *instance = phy_get_drvdata(phy);
+ struct an7581_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+ int ret;
+
+ switch (instance->type) {
+ case PHY_TYPE_USB2:
+ an7581_usb_phy_u2_init(priv);
+ break;
+ case PHY_TYPE_USB3:
+ ret = phy_set_mode(priv->serdes_phy, PHY_MODE_USB_DEVICE_SS);
+ if (ret)
+ return ret;
+
+ an7581_usb_phy_u3_init(priv);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int an7581_usb_phy_u2_power_on(struct an7581_usb_phy_priv *priv)
+{
+ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+ AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+ usleep_range(1000, 1500);
+
+ return 0;
+}
+
+static int an7581_usb_phy_u3_power_on(struct an7581_usb_phy_priv *priv)
+{
+ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD,
+ AIROHA_USB_PHY_SSUSB_IP_SW_RST |
+ AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN |
+ AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST |
+ AIROHA_USB_PHY_SSUSB_SW_RST);
+
+ usleep_range(1000, 1500);
+
+ return 0;
+}
+
+static int an7581_usb_phy_power_on(struct phy *phy)
+{
+ struct an7581_usb_phy_instance *instance = phy_get_drvdata(phy);
+ struct an7581_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+ switch (instance->type) {
+ case PHY_TYPE_USB2:
+ an7581_usb_phy_u2_power_on(priv);
+ break;
+ case PHY_TYPE_USB3:
+ an7581_usb_phy_u3_power_on(priv);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int an7581_usb_phy_u2_power_off(struct an7581_usb_phy_priv *priv)
+{
+ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
+ AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+ usleep_range(1000, 1500);
+
+ return 0;
+}
+
+static int an7581_usb_phy_u3_power_off(struct an7581_usb_phy_priv *priv)
+{
+ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD,
+ AIROHA_USB_PHY_SSUSB_IP_SW_RST |
+ AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST);
+
+ usleep_range(1000, 1500);
+
+ return 0;
+}
+
+static int an7581_usb_phy_power_off(struct phy *phy)
+{
+ struct an7581_usb_phy_instance *instance = phy_get_drvdata(phy);
+ struct an7581_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+ switch (instance->type) {
+ case PHY_TYPE_USB2:
+ an7581_usb_phy_u2_power_off(priv);
+ break;
+ case PHY_TYPE_USB3:
+ an7581_usb_phy_u3_power_off(priv);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int an7581_usb_phy_u2_set_mode(struct an7581_usb_phy_priv *priv,
+ enum phy_mode mode)
+{
+ u32 val;
+
+ /*
+ * For Device and Host mode, enable force IDDIG.
+ * For Device set IDDIG, for Host clear IDDIG.
+ * For OTG disable force and clear IDDIG bit while at it.
+ */
+ switch (mode) {
+ case PHY_MODE_USB_DEVICE:
+ val = AIROHA_USB_PHY_FORCE_IDDIG |
+ AIROHA_USB_PHY_IDDIG;
+ break;
+ case PHY_MODE_USB_HOST:
+ val = AIROHA_USB_PHY_FORCE_IDDIG;
+ break;
+ case PHY_MODE_USB_OTG:
+ val = 0;
+ break;
+ default:
+ return 0;
+ }
+
+ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U2PHYDTM1,
+ AIROHA_USB_PHY_FORCE_IDDIG |
+ AIROHA_USB_PHY_IDDIG, val);
+
+ return 0;
+}
+
+static int an7581_usb_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct an7581_usb_phy_instance *instance = phy_get_drvdata(phy);
+ struct an7581_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+ switch (instance->type) {
+ case PHY_TYPE_USB2:
+ return an7581_usb_phy_u2_set_mode(priv, mode);
+ default:
+ return 0;
+ }
+}
+
+static struct phy *an7581_usb_phy_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct an7581_usb_phy_priv *priv = dev_get_drvdata(dev);
+ struct an7581_usb_phy_instance *instance = NULL;
+ unsigned int index, phy_type;
+
+ if (args->args_count != 1) {
+ dev_err(dev, "invalid number of cells in 'phy' property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ phy_type = args->args[0];
+ if (!(phy_type == PHY_TYPE_USB2 || phy_type == PHY_TYPE_USB3)) {
+ dev_err(dev, "unsupported device type: %d\n", phy_type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ for (index = 0; index < AIROHA_PHY_USB_MAX; index++)
+ if (priv->phys[index] &&
+ phy_type == priv->phys[index]->type) {
+ instance = priv->phys[index];
+ break;
+ }
+
+ if (!instance) {
+ dev_err(dev, "failed to find appropriate phy\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return instance->phy;
+}
+
+static const struct phy_ops airoha_phy = {
+ .init = an7581_usb_phy_init,
+ .power_on = an7581_usb_phy_power_on,
+ .power_off = an7581_usb_phy_power_off,
+ .set_mode = an7581_usb_phy_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static const struct regmap_config an7581_usb_phy_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int an7581_usb_phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct an7581_usb_phy_priv *priv;
+ struct device *dev = &pdev->dev;
+ unsigned int index;
+ void __iomem *base;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+
+ ret = of_property_read_u32(dev->of_node, "airoha,usb2-monitor-clk-sel",
+ &priv->monclk_sel);
+ if (ret)
+ return dev_err_probe(dev, ret, "Monitor clock selection is mandatory for USB PHY calibration\n");
+
+ if (priv->monclk_sel > 3)
+ return dev_err_probe(dev, -EINVAL, "only 4 Monitor clock are selectable on the SoC\n");
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ priv->regmap = devm_regmap_init_mmio(dev, base, &an7581_usb_phy_regmap_config);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
+ platform_set_drvdata(pdev, priv);
+
+ for (index = 0; index < AIROHA_PHY_USB_MAX; index++) {
+ struct an7581_usb_phy_instance *instance;
+ u32 phy_type;
+
+ switch (index) {
+ case AIROHA_PHY_USB2:
+ phy_type = PHY_TYPE_USB2;
+ break;
+ case AIROHA_PHY_USB3:
+ phy_type = PHY_TYPE_USB3;
+ break;
+ }
+
+ if (phy_type == PHY_TYPE_USB3) {
+ priv->serdes_phy = devm_phy_get(dev, NULL);
+ if (IS_ERR(priv->serdes_phy))
+ return dev_err_probe(dev, PTR_ERR(priv->serdes_phy), "missing serdes phy for USB 3.0\n");
+ }
+
+ instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+ if (!instance)
+ return -ENOMEM;
+
+ instance->type = phy_type;
+ priv->phys[index] = instance;
+
+ instance->phy = devm_phy_create(dev, NULL, &airoha_phy);
+ if (IS_ERR(instance->phy))
+ return dev_err_probe(dev, PTR_ERR(instance->phy), "failed to create phy\n");
+
+ phy_set_drvdata(instance->phy, instance);
+ }
+
+ phy_provider = devm_of_phy_provider_register(&pdev->dev, an7581_usb_phy_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id airoha_phy_id_table[] = {
+ { .compatible = "airoha,an7581-usb-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, airoha_phy_id_table);
+
+static struct platform_driver an7581_usb_driver = {
+ .probe = an7581_usb_phy_probe,
+ .driver = {
+ .name = "airoha-an7581-usb-phy",
+ .of_match_table = airoha_phy_id_table,
+ },
+};
+
+module_platform_driver(an7581_usb_driver);
+
+MODULE_DESCRIPTION("Airoha AN7581 USB PHY driver");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_LICENSE("GPL");
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v8 3/5] clk: en7523: Add support for selecting the Serdes port in SCU
From: Christian Marangi @ 2026-05-20 15:09 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Christian Marangi, Vinod Koul,
Neil Armstrong, Lorenzo Bianconi, Felix Fietkau, linux-clk,
devicetree, linux-kernel, linux-arm-kernel, linux-phy
In-Reply-To: <20260520150912.11614-1-ansuelsmth@gmail.com>
In the SCU register for clock and reset, there are also some register to
select the Serdes port mode. The Airoha AN7581 SoC have 4 different Serdes
that can switch between PCIe, USB or Ethernet mode.
Add a simple PHY provider that expose the .set_mode OP to toggle the
requested mode for the Serdes port.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/Kconfig | 1 +
drivers/clk/clk-en7523.c | 216 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 214 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index b2efbe9f6acb..e60a824b5117 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -221,6 +221,7 @@ config COMMON_CLK_EN7523
bool "Clock driver for Airoha/EcoNet SoC system clocks"
depends on OF
depends on ARCH_AIROHA || ECONET || COMPILE_TEST
+ select GENERIC_PHY
default ARCH_AIROHA
help
This driver provides the fixed clocks and gates present on Airoha
diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index 1ab0e2eca5d3..d4b73c5f15b9 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -6,14 +6,18 @@
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
#include <dt-bindings/clock/en7523-clk.h>
#include <dt-bindings/reset/airoha,en7523-reset.h>
#include <dt-bindings/reset/airoha,en7581-reset.h>
#include <dt-bindings/clock/econet,en751221-scu.h>
#include <dt-bindings/reset/econet,en751221-scu.h>
+#include <dt-bindings/soc/airoha,scu-ssr.h>
#define RST_NR_PER_BANK 32
@@ -40,9 +44,22 @@
#define REG_HIR_MASK GENMASK(31, 16)
/* EN7581 */
#define REG_NP_SCU_PCIC 0x88
+#define REG_NP_SCU_SSR3 0x94
+#define REG_SSUSB_HSGMII_SEL_MASK BIT(29)
+#define REG_SSUSB_HSGMII_SEL_HSGMII FIELD_PREP_CONST(REG_SSUSB_HSGMII_SEL_MASK, 0x0)
+#define REG_SSUSB_HSGMII_SEL_USB FIELD_PREP_CONST(REG_SSUSB_HSGMII_SEL_MASK, 0x1)
#define REG_NP_SCU_SSTR 0x9c
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
+#define REG_PCIE_XSI0_SEL_PCIE FIELD_PREP_CONST(REG_PCIE_XSI0_SEL_MASK, 0x0)
+#define REG_PCIE_XSI0_SEL_XFI FIELD_PREP_CONST(REG_PCIE_XSI0_SEL_MASK, 0x1)
+#define REG_PCIE_XSI0_SEL_HSGMII FIELD_PREP_CONST(REG_PCIE_XSI0_SEL_MASK, 0x2)
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
+#define REG_PCIE_XSI1_SEL_PCIE FIELD_PREP_CONST(REG_PCIE_XSI1_SEL_MASK, 0x0)
+#define REG_PCIE_XSI1_SEL_XFI FIELD_PREP_CONST(REG_PCIE_XSI1_SEL_MASK, 0x1)
+#define REG_PCIE_XSI1_SEL_HSGMII FIELD_PREP_CONST(REG_PCIE_XSI1_SEL_MASK, 0x2)
+#define REG_USB_PCIE_SEL_MASK BIT(3)
+#define REG_USB_PCIE_SEL_PCIE FIELD_PREP_CONST(REG_USB_PCIE_SEL_MASK, 0x0)
+#define REG_USB_PCIE_SEL_USB FIELD_PREP_CONST(REG_USB_PCIE_SEL_MASK, 0x1)
#define REG_CRYPTO_CLKSRC2 0x20c
/* EN751221 */
#define EN751221_REG_SPI_DIV 0x0cc
@@ -81,6 +98,8 @@ enum en_hir {
HIR_MAX = 14,
};
+#define EN_SERDES_PHY_NUM 4
+
struct en_clk_desc {
int id;
const char *name;
@@ -113,6 +132,18 @@ struct en_rst_data {
struct reset_controller_dev rcdev;
};
+struct en_serdes_phy_instance {
+ struct phy *phy;
+ unsigned int serdes_port;
+};
+
+struct en_clk_priv {
+ void __iomem *base;
+ /* protect SCU register */
+ spinlock_t lock;
+ struct en_serdes_phy_instance *serdes_phys[EN_SERDES_PHY_NUM];
+};
+
struct en_clk_soc_data {
u32 num_clocks;
const struct clk_ops pcie_ops;
@@ -830,12 +861,179 @@ static int en7581_reset_register(struct device *dev, void __iomem *base,
return devm_reset_controller_register(dev, &rst_data->rcdev);
}
+static int en7581_serdes_phy_set_mode(struct phy *phy, enum phy_mode mode,
+ int submode)
+{
+ struct en_serdes_phy_instance *instance = phy_get_drvdata(phy);
+ struct en_clk_priv *priv = dev_get_drvdata(phy->dev.parent);
+ u32 reg, mask, sel, val;
+ unsigned long flags;
+
+ switch (instance->serdes_port) {
+ case AIROHA_SCU_SERDES_PCIE1:
+ reg = REG_NP_SCU_SSTR;
+ mask = REG_PCIE_XSI0_SEL_MASK;
+
+ if (mode != PHY_MODE_ETHERNET && mode != PHY_MODE_PCIE)
+ return -EINVAL;
+
+ if (mode == PHY_MODE_ETHERNET) {
+ switch (submode) {
+ case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_10GBASER:
+ sel = REG_PCIE_XSI0_SEL_XFI;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ sel = REG_PCIE_XSI0_SEL_HSGMII;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ sel = REG_PCIE_XSI0_SEL_PCIE;
+ }
+
+ break;
+ case AIROHA_SCU_SERDES_PCIE2:
+ reg = REG_NP_SCU_SSTR;
+ mask = REG_PCIE_XSI1_SEL_MASK;
+
+ if (mode != PHY_MODE_ETHERNET && mode != PHY_MODE_PCIE)
+ return -EINVAL;
+
+ if (mode == PHY_MODE_ETHERNET) {
+ switch (submode) {
+ case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_10GBASER:
+ sel = REG_PCIE_XSI1_SEL_XFI;
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ sel = REG_PCIE_XSI1_SEL_HSGMII;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ sel = REG_PCIE_XSI1_SEL_PCIE;
+ }
+
+ break;
+ case AIROHA_SCU_SERDES_USB1:
+ reg = REG_NP_SCU_SSR3;
+ mask = REG_SSUSB_HSGMII_SEL_MASK;
+
+ if (mode != PHY_MODE_ETHERNET && mode != PHY_MODE_USB_DEVICE &&
+ mode != PHY_MODE_USB_DEVICE_SS)
+ return -EINVAL;
+
+ if (mode == PHY_MODE_ETHERNET)
+ sel = REG_SSUSB_HSGMII_SEL_HSGMII;
+ else
+ sel = REG_SSUSB_HSGMII_SEL_USB;
+
+ break;
+ case AIROHA_SCU_SERDES_USB2:
+ reg = REG_NP_SCU_SSTR;
+ mask = REG_USB_PCIE_SEL_MASK;
+
+ if (mode != PHY_MODE_PCIE && mode != PHY_MODE_USB_DEVICE &&
+ mode != PHY_MODE_USB_DEVICE_SS)
+ return -EINVAL;
+
+ if (mode == PHY_MODE_PCIE)
+ sel = REG_USB_PCIE_SEL_PCIE;
+ else
+ sel = REG_USB_PCIE_SEL_USB;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ val = readl(priv->base + reg);
+ val &= ~mask;
+ val |= sel;
+ writel(val, priv->base + reg);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static const struct phy_ops en7581_serdes_phy_ops = {
+ .set_mode = en7581_serdes_phy_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *en7581_serdes_phy_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct en_clk_priv *priv = dev_get_drvdata(dev);
+ struct en_serdes_phy_instance *instance;
+ unsigned int serdes_port;
+
+ if (args->args_count != 1) {
+ dev_err(dev, "invalid number of cells in 'phy' property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ serdes_port = args->args[0];
+ if (serdes_port >= EN_SERDES_PHY_NUM) {
+ dev_err(dev, "invalid serdes port: %d\n", serdes_port);
+ return ERR_PTR(-EINVAL);
+ }
+
+ instance = priv->serdes_phys[serdes_port];
+ if (!instance) {
+ dev_err(dev, "failed to find appropriate serdes phy\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return instance->phy;
+}
+
+static int en7581_serdes_phy_register(struct device *dev)
+{
+ struct en_clk_priv *priv = dev_get_drvdata(dev);
+ struct phy_provider *phy_provider;
+ int i;
+
+ for (i = 0; i < EN_SERDES_PHY_NUM; i++) {
+ struct en_serdes_phy_instance *instance;
+
+ instance = devm_kzalloc(dev, sizeof(*instance),
+ GFP_KERNEL);
+ if (!instance)
+ return -ENOMEM;
+
+ instance->phy = devm_phy_create(dev, NULL,
+ &en7581_serdes_phy_ops);
+ if (IS_ERR(instance->phy))
+ return dev_err_probe(dev, PTR_ERR(instance->phy), "failed to create phy\n");
+
+ instance->serdes_port = i;
+ priv->serdes_phys[i] = instance;
+
+ phy_set_drvdata(instance->phy, instance);
+ }
+
+ phy_provider = devm_of_phy_provider_register(dev, en7581_serdes_phy_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
static int en7581_clk_hw_init(struct platform_device *pdev,
struct clk_hw_onecell_data *clk_data)
{
+ struct en_clk_priv *priv = platform_get_drvdata(pdev);
struct regmap *map;
void __iomem *base;
u32 val;
+ int ret;
map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
if (IS_ERR(map))
@@ -845,6 +1043,8 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
if (IS_ERR(base))
return PTR_ERR(base);
+ priv->base = base;
+
en7581_register_clocks(&pdev->dev, clk_data, map, base);
val = readl(base + REG_NP_SCU_SSTR);
@@ -853,9 +1053,12 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
val = readl(base + REG_NP_SCU_PCIC);
writel(val | 3, base + REG_NP_SCU_PCIC);
- return en7581_reset_register(&pdev->dev, base, en7581_rst_map,
- ARRAY_SIZE(en7581_rst_map),
- en7581_rst_ofs);
+ ret = en7581_reset_register(&pdev->dev, base, en7581_rst_map,
+ ARRAY_SIZE(en7581_rst_map), en7581_rst_ofs);
+ if (ret)
+ return ret;
+
+ return en7581_serdes_phy_register(&pdev->dev);
}
static enum en_hir get_hw_id(void __iomem *np_base)
@@ -962,16 +1165,23 @@ static int en7523_clk_probe(struct platform_device *pdev)
struct device_node *node = pdev->dev.of_node;
const struct en_clk_soc_data *soc_data;
struct clk_hw_onecell_data *clk_data;
+ struct en_clk_priv *priv;
int r;
soc_data = device_get_match_data(&pdev->dev);
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
clk_data = devm_kzalloc(&pdev->dev,
struct_size(clk_data, hws, soc_data->num_clocks),
GFP_KERNEL);
if (!clk_data)
return -ENOMEM;
+ platform_set_drvdata(pdev, priv);
+
clk_data->num = soc_data->num_clocks;
r = soc_data->hw_init(pdev, clk_data);
if (r)
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v8 4/5] phy: move and rename Airoha PCIe PHY driver to dedicated directory
From: Christian Marangi @ 2026-05-20 15:09 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Christian Marangi, Vinod Koul,
Neil Armstrong, Lorenzo Bianconi, Felix Fietkau, linux-clk,
devicetree, linux-kernel, linux-arm-kernel, linux-phy
In-Reply-To: <20260520150912.11614-1-ansuelsmth@gmail.com>
To keep the generic PHY directory tidy, move the PCIe PHY driver for
Airoha AN7581 SoC to a dedicated directory.
Also rename the driver and add the relevant SoC name to the .c and .h
file in preparation for support of PCIe and USB PHY driver for Airoha
AN7583 SoC that use a completely different implementation and
calibration for PHYs and will have their own dedicated drivers.
The rename permits to better identify the specific usage of the driver
in the future once the airoha PHY directory will have multiple driver
for multiple SoC.
The config is changed from PHY_AIROHA_PCIE to PHY_AIROHA_AN7581_PCIE.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
MAINTAINERS | 4 ++--
drivers/phy/Kconfig | 11 +----------
drivers/phy/Makefile | 4 ++--
drivers/phy/airoha/Kconfig | 13 +++++++++++++
drivers/phy/airoha/Makefile | 3 +++
.../phy-an7581-pcie-regs.h} | 2 +-
.../{phy-airoha-pcie.c => airoha/phy-an7581-pcie.c} | 6 +++---
7 files changed, 25 insertions(+), 18 deletions(-)
create mode 100644 drivers/phy/airoha/Kconfig
create mode 100644 drivers/phy/airoha/Makefile
rename drivers/phy/{phy-airoha-pcie-regs.h => airoha/phy-an7581-pcie-regs.h} (99%)
rename drivers/phy/{phy-airoha-pcie.c => airoha/phy-an7581-pcie.c} (99%)
diff --git a/MAINTAINERS b/MAINTAINERS
index 932044785a39..7bea8c620da8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -759,8 +759,8 @@ M: Lorenzo Bianconi <lorenzo@kernel.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml
-F: drivers/phy/phy-airoha-pcie-regs.h
-F: drivers/phy/phy-airoha-pcie.c
+F: drivers/phy/airoha/phy-an7581-pcie-regs.h
+F: drivers/phy/airoha/phy-an7581-pcie.c
AIROHA SPI SNFI DRIVER
M: Lorenzo Bianconi <lorenzo@kernel.org>
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 227b9a4c612e..f9cd765a3ccc 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -46,16 +46,6 @@ config GENERIC_PHY_MIPI_DPHY
Provides a number of helpers a core functions for MIPI D-PHY
drivers to us.
-config PHY_AIROHA_PCIE
- tristate "Airoha PCIe-PHY Driver"
- depends on ARCH_AIROHA || COMPILE_TEST
- depends on OF
- select GENERIC_PHY
- help
- Say Y here to add support for Airoha PCIe PHY driver.
- This driver create the basic PHY instance and provides initialize
- callback for PCIe GEN3 port.
-
config PHY_CAN_TRANSCEIVER
tristate "CAN transceiver PHY"
select GENERIC_PHY
@@ -133,6 +123,7 @@ config PHY_XGENE
help
This option enables support for APM X-Gene SoC multi-purpose PHY.
+source "drivers/phy/airoha/Kconfig"
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/apple/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index f49d83f00a3d..84062279fa63 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_PHY_COMMON_PROPS) += phy-common-props.o
obj-$(CONFIG_PHY_COMMON_PROPS_TEST) += phy-common-props-test.o
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
-obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o
obj-$(CONFIG_PHY_GOOGLE_USB) += phy-google-usb.o
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o
@@ -17,7 +16,8 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_PHY_SNPS_EUSB2) += phy-snps-eusb2.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
-obj-$(CONFIG_GENERIC_PHY) += allwinner/ \
+obj-$(CONFIG_GENERIC_PHY) += airoha/ \
+ allwinner/ \
amlogic/ \
apple/ \
broadcom/ \
diff --git a/drivers/phy/airoha/Kconfig b/drivers/phy/airoha/Kconfig
new file mode 100644
index 000000000000..9a1b625a7701
--- /dev/null
+++ b/drivers/phy/airoha/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Phy drivers for Airoha devices
+#
+config PHY_AIROHA_AN7581_PCIE
+ tristate "Airoha AN7581 PCIe-PHY Driver"
+ depends on ARCH_AIROHA || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ help
+ Say Y here to add support for Airoha AN7581 PCIe PHY driver.
+ This driver create the basic PHY instance and provides initialize
+ callback for PCIe GEN3 port.
diff --git a/drivers/phy/airoha/Makefile b/drivers/phy/airoha/Makefile
new file mode 100644
index 000000000000..912f3e11a061
--- /dev/null
+++ b/drivers/phy/airoha/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_PHY_AIROHA_AN7581_PCIE) += phy-an7581-pcie.o
diff --git a/drivers/phy/phy-airoha-pcie-regs.h b/drivers/phy/airoha/phy-an7581-pcie-regs.h
similarity index 99%
rename from drivers/phy/phy-airoha-pcie-regs.h
rename to drivers/phy/airoha/phy-an7581-pcie-regs.h
index 58572c793722..b938a7b468fe 100644
--- a/drivers/phy/phy-airoha-pcie-regs.h
+++ b/drivers/phy/airoha/phy-an7581-pcie-regs.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2024 AIROHA Inc
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
diff --git a/drivers/phy/phy-airoha-pcie.c b/drivers/phy/airoha/phy-an7581-pcie.c
similarity index 99%
rename from drivers/phy/phy-airoha-pcie.c
rename to drivers/phy/airoha/phy-an7581-pcie.c
index 56e9ade8a9fd..81ddf0e7638b 100644
--- a/drivers/phy/phy-airoha-pcie.c
+++ b/drivers/phy/airoha/phy-an7581-pcie.c
@@ -13,7 +13,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include "phy-airoha-pcie-regs.h"
+#include "phy-an7581-pcie-regs.h"
#define LEQ_LEN_CTRL_MAX_VAL 7
#define FREQ_LOCK_MAX_ATTEMPT 10
@@ -1279,12 +1279,12 @@ MODULE_DEVICE_TABLE(of, airoha_pcie_phy_of_match);
static struct platform_driver airoha_pcie_phy_driver = {
.probe = airoha_pcie_phy_probe,
.driver = {
- .name = "airoha-pcie-phy",
+ .name = "airoha-an7581-pcie-phy",
.of_match_table = airoha_pcie_phy_of_match,
},
};
module_platform_driver(airoha_pcie_phy_driver);
-MODULE_DESCRIPTION("Airoha PCIe PHY driver");
+MODULE_DESCRIPTION("Airoha AN7581 PCIe PHY driver");
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
MODULE_LICENSE("GPL");
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v8 2/5] dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
From: Christian Marangi @ 2026-05-20 15:09 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Christian Marangi, Vinod Koul,
Neil Armstrong, Lorenzo Bianconi, Felix Fietkau, linux-clk,
devicetree, linux-kernel, linux-arm-kernel, linux-phy
In-Reply-To: <20260520150912.11614-1-ansuelsmth@gmail.com>
Add documentation for Airoha AN7581 USB PHY that describe the USB PHY
for the USB controller.
Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
always supported. The USB 3.0 mode is optional and depends on the Serdes
mode currently configured on the system for the relevant USB port.
To correctly calibrate, the USB 2.0 port require correct value in
"airoha,usb2-monitor-clk-sel" property. Both the 2 USB 2.0 port permit
selecting one of the 4 monitor clock for calibration (internal clock not
exposed to the system) but each port have only one of the 4 actually
connected in HW hence the correct value needs to be specified in DT
based on board and the physical port. Normally it's monitor clock 1 for
USB1 and monitor clock 2 for USB2.
To correctly setup the Serdes mode attached to the USB 3.0 mode, a phys
property is required with the phandle pointing to the correct Serdes port
provided by the SCU node.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
.../bindings/phy/airoha,an7581-usb-phy.yaml | 62 +++++++++++++++++++
MAINTAINERS | 6 ++
2 files changed, 68 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
diff --git a/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
new file mode 100644
index 000000000000..f561cf2a8103
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/airoha,an7581-usb-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN7581 SoC USB PHY
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+
+description: >
+ The Airoha AN7581 SoC USB PHY describes the USB PHY for the USB controller.
+
+ Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
+ always supported. The USB 3.0 mode is optional and depends on the Serdes
+ mode currently configured on the system for the relevant USB port.
+
+properties:
+ compatible:
+ const: airoha,an7581-usb-phy
+
+ reg:
+ maxItems: 1
+
+ airoha,usb2-monitor-clk-sel:
+ description: Describe what oscillator across the available 4
+ should be selected for USB 2.0 Slew Rate calibration.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1, 2, 3]
+
+ phys:
+ items:
+ - description: phandle to Serdes PHY
+
+ '#phy-cells':
+ description: The cell contains the mode, PHY_TYPE_USB2 or PHY_TYPE_USB3,
+ as defined in dt-bindings/phy/phy.h.
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - airoha,usb2-monitor-clk-sel
+ - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/soc/airoha,scu-ssr.h>
+
+ phy@1fac0000 {
+ compatible = "airoha,an7581-usb-phy";
+ reg = <0x1fac0000 0x10000>;
+
+ airoha,usb2-monitor-clk-sel = <1>;
+ phys = <&scu AIROHA_SCU_SERDES_USB1>;
+
+ #phy-cells = <1>;
+ };
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 21c0ef0b9ce5..932044785a39 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -771,6 +771,12 @@ S: Maintained
F: Documentation/devicetree/bindings/spi/airoha,en7581-snand.yaml
F: drivers/spi/spi-airoha-snfi.c
+AIROHA USB PHY DRIVER
+M: Christian Marangi <ansuelsmth@gmail.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
+
AIRSPY MEDIA DRIVER
L: linux-media@vger.kernel.org
S: Orphan
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v8 1/5] dt-bindings: clock: airoha: Add PHY binding for Serdes port
From: Christian Marangi @ 2026-05-20 15:09 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Christian Marangi, Vinod Koul,
Neil Armstrong, Lorenzo Bianconi, Felix Fietkau, linux-clk,
devicetree, linux-kernel, linux-arm-kernel, linux-phy
In-Reply-To: <20260520150912.11614-1-ansuelsmth@gmail.com>
Add PHY cell property for Serdes port selection. Currently supported only
for Airoha AN7581 SoC, that support up to 4 Serdes port.
The Serdes port can support both PCIe, USB3 or Ethernet mode.
- PCIe1 Serdes can support PCIe or Ethernet mode.
- PCIe2 Serdes can support PCIe or Ethernet mode.
- USB1 Serdes can support USB3 or HSGMII mode.
- USB2 Serdes can support USB3 or PCIe mode.
Add bindings to permit correct reference of the Serdes ports in DT.
Values are just symbolic and enumerates the Serdes port with a specific
number for precise reference.
The available Serdes port can be selected following the dt-binding header
in [2].
[2] <include/dt-bindings/soc/airoha,scu-ssr.h>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
.../devicetree/bindings/clock/airoha,en7523-scu.yaml | 9 +++++++++
include/dt-bindings/soc/airoha,scu-ssr.h | 11 +++++++++++
2 files changed, 20 insertions(+)
create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h
diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
index eb24a5687639..913ddc16182b 100644
--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
@@ -23,6 +23,7 @@ description: |
All these identifiers can be found in:
[1]: <include/dt-bindings/clock/en7523-clk.h>.
+ [2]: <include/dt-bindings/soc/airoha,scu-ssr.h>.
The clocks are provided inside a system controller node.
@@ -50,6 +51,12 @@ properties:
description: ID of the controller reset line
const: 1
+ '#phy-cells':
+ description:
+ The first cell indicates the serdes phy number, see [2] for the
+ available serdes port.
+ const: 1
+
required:
- compatible
- reg
@@ -65,6 +72,8 @@ allOf:
reg:
minItems: 2
+ '#phy-cells': false
+
- if:
properties:
compatible:
diff --git a/include/dt-bindings/soc/airoha,scu-ssr.h b/include/dt-bindings/soc/airoha,scu-ssr.h
new file mode 100644
index 000000000000..33c64844ada3
--- /dev/null
+++ b/include/dt-bindings/soc/airoha,scu-ssr.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef __DT_BINDINGS_AIROHA_SCU_SSR_H
+#define __DT_BINDINGS_AIROHA_SCU_SSR_H
+
+#define AIROHA_SCU_SERDES_PCIE1 0
+#define AIROHA_SCU_SERDES_PCIE2 1
+#define AIROHA_SCU_SERDES_USB1 2
+#define AIROHA_SCU_SERDES_USB2 3
+
+#endif /* __DT_BINDINGS_AIROHA_SCU_SSR_H */
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v8 0/5] airoha: an7581: USB support
From: Christian Marangi @ 2026-05-20 15:09 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Brian Masney, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Christian Marangi, Vinod Koul,
Neil Armstrong, Lorenzo Bianconi, Felix Fietkau, linux-clk,
devicetree, linux-kernel, linux-arm-kernel, linux-phy
This is a major rework of the old v2 series.
The SoC always support USB 2.0 but for USB 3.0 it needs additional
configuration for the Serdes port. Such port can be either configured
for USB usage or for PCIe lines or HSGMII and these are configured
in the SCU space.
The previous implementation of a dedicated SSR driver was too
complex and fragile for the simple task of configuring a register
hence it was dropped and the handling is entirely in the PHY driver.
Everything was reducted to the dt-bindings to describe the Serdes line.
Also the property for the PHY are renamed to a more suitable name and
everything is now mandatory to simplify the implementation.
(the PHY are always present and active on the SoC)
Also other unrelated patch are dropped from this series.
Changes v8:
- Squash header to clk Documentation patch
- Address comments from AI Bot
Changes v7:
- Rework to double PHY implementation
(suggested by Rob)
Now the clk driver expose a PHY for Serdes port
USB PHY driver selects it
- Rebase on top of linux-next
Link: https://lore.kernel.org/all/20260306190156.22297-1-ansuelsmth@gmail.com/
Changes v6:
- Fix kernel test robot (sparse warning)
Link: https://lore.kernel.org/all/20260306190156.22297-1-ansuelsmth@gmail.com/
Changes v5:
- Add Ack and Review tag from Connor
- Implement Ethernet support in the USB driver
(testing support for this Serdes on a special reference board)
- Use an7581 prefix for USB PHY driver
Link: https://lore.kernel.org/all/20251107160251.2307088-1-ansuelsmth@gmail.com/
Changes v4:
- Rename PCIe and USB PHY to AN7581
- Drop airoha,scu (handled directly in driver)
- Drop dt-bindings for monitor clock in favor of raw values
- Better describe the usage of airoha,usb3-serdes
- Simplify values of dt-bindings SSR SERDES
Link: https://lore.kernel.org/all/20251107160251.2307088-1-ansuelsmth@gmail.com/
Changes v3:
- Drop clk changes
- Drop SSR driver
- Rename property in Documentation
- Simplify PHY handling
- Move SSR handling inside the PHY driver
Link: https://lore.kernel.org/all/20251029173713.7670-1-ansuelsmth@gmail.com/
Changes v2:
- Drop changes for simple-mfd
- Rework PHY node structure to single node
- Drop port-id property in favor of serdes-port and
usb2-monitor-clock-sel
- Make the SSR driver probe from the clock driver
Christian Marangi (5):
dt-bindings: clock: airoha: Add PHY binding for Serdes port
dt-bindings: phy: Add documentation for Airoha AN7581 USB PHY
clk: en7523: Add support for selecting the Serdes port in SCU
phy: move and rename Airoha PCIe PHY driver to dedicated directory
phy: airoha: Add support for Airoha AN7581 USB PHY
.../bindings/clock/airoha,en7523-scu.yaml | 9 +
.../bindings/phy/airoha,an7581-usb-phy.yaml | 62 ++
MAINTAINERS | 11 +-
drivers/clk/Kconfig | 1 +
drivers/clk/clk-en7523.c | 216 ++++++-
drivers/phy/Kconfig | 11 +-
drivers/phy/Makefile | 4 +-
drivers/phy/airoha/Kconfig | 24 +
drivers/phy/airoha/Makefile | 4 +
.../phy-an7581-pcie-regs.h} | 2 +-
.../phy-an7581-pcie.c} | 6 +-
drivers/phy/airoha/phy-an7581-usb.c | 554 ++++++++++++++++++
include/dt-bindings/soc/airoha,scu-ssr.h | 11 +
13 files changed, 894 insertions(+), 21 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
create mode 100644 drivers/phy/airoha/Kconfig
create mode 100644 drivers/phy/airoha/Makefile
rename drivers/phy/{phy-airoha-pcie-regs.h => airoha/phy-an7581-pcie-regs.h} (99%)
rename drivers/phy/{phy-airoha-pcie.c => airoha/phy-an7581-pcie.c} (99%)
create mode 100644 drivers/phy/airoha/phy-an7581-usb.c
create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 3/5] phy: qualcomm: qmp-combo: Add preliminary USB4 support
From: Dmitry Baryshkov @ 2026-05-20 15:06 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Konrad Dybcio, Vinod Koul, Neil Armstrong, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, linux-kernel,
linux-phy, linux-arm-msm, devicetree, usb4-upstream,
Raghavendra Thoorpu, Mika Westerberg, Sven Peter
In-Reply-To: <6fb112ae-5919-4c8f-a915-4538d14284da@oss.qualcomm.com>
On Tue, May 19, 2026 at 10:12:06AM +0200, Konrad Dybcio wrote:
> On 5/18/26 5:38 PM, Dmitry Baryshkov wrote:
> > On Mon, May 18, 2026 at 04:15:16PM +0200, Konrad Dybcio wrote:
> >> On 5/18/26 3:57 PM, Dmitry Baryshkov wrote:
> >>> On Mon, May 18, 2026 at 12:29:50PM +0200, Konrad Dybcio wrote:
> >>>> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>>>
> >>>> Some Combo PHYs (so far only on SC8280XP, X1E80100 and Glymur), come in
> >>>> a flavor called USB43DP, which as the name implies, features USB4, USB3
> >>>> and DP signal processing capabilities. In that architecture, USB3 and
> >>>> USB4 PHYs share the same USB_PLL while featuring separate logic spaces.
> >>>> The DP part is roughly the same as on the instances without USB4.
> >>>>
> >>>> The USB4 and USB3/DP operation modes of the PHY are mutually exclusive.
> >>>> Only one USB protocol (and flavor of pipe clock) can be active at a
> >>>> given moment (not to be confused with USB3 not being able to be
> >>>> tunneled as USB4 packets - that of course remains possible).
> >>>> The DP PLL is still used for clocking tunneled DP links. It may be
> >>>> turned off to save power when no tunnels are active, but that's left as
> >>>> a TODO item for now.
> >>>>
> >>>> Due to the nature of USB4, the Type-C handling happens entirely inside
> >>>> the Host Router, and as such the QMPPHY's mux_set() function is
> >>>> nullified for the period when USB4 PHY remains active. This is strictly
> >>>> necessary, as the Host Router driver is going to excercise manual
> >>>> control over the USB4 PHY's power state, which is needed by the suspend
> >>>> and resume flows. Failure to control that synchronously with other
> >>>> parts of the code results in a SoC crash by unlocked access.
> >>>>
> >>>> Because of that, a new struct phy is spawned to expose the USB4 mode,
> >>>> along with a .set_mode callback to allow toggling between USB4 and TBT3
> >>>> submodes.
> >>>>
> >>>> Thunderbolt 3, having a number of differences vs USB4, requires a
> >>>> couple specific overrides, pertaining to electrical characteristics,
> >>>> which are easily accommodated for.
> >>>>
> >>>> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> >>>> ---
> >>>> drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 392 ++++++++++++++++++++++++------
> >>>> 1 file changed, 322 insertions(+), 70 deletions(-)
> >>>>
> >>>
> >>> Overall it looks good. The major question (after looking at TODOs), do
> >>> we need a separate submode for USB+DP / TBT+DP?
> >>
> >> The problem space is as follows:
> >>
> >> After a TBT (collectively TBT3+ and USB4) link has been established and
> >> we have a link partner, we may (based on the HW capabilities and user
> >> config, such as kernel params but not only) start or stop a DP tunnel at
> >> runtime. On Qualcomm hardware, the PHY is kept in USB4 mode and its DP
> >> AUX lines are not used (instead, the encapsulated DP AUX packets are r/w
> >> entirely within the USB4 subsystem via a pair of FIFOs that Linux sees
> >> as a separate DP AUX host)
> >
> > So far so good. But I still don't grok if having a DP-over-USB4 is a
> > separate submode or not. I.e. I see code (and TODOs) to detect and
> > handle DP going on and off. Would it be better if we specify that
> > explicitly?
>
> I really don't want to end up in a situation like we have with:
>
> $ rg _USB include/linux/phy/phy.h
> 29: PHY_MODE_USB_HOST,
> 30: PHY_MODE_USB_HOST_LS,
> 31: PHY_MODE_USB_HOST_FS,
> 32: PHY_MODE_USB_HOST_HS,
> 33: PHY_MODE_USB_HOST_SS,
> 34: PHY_MODE_USB_DEVICE,
> 35: PHY_MODE_USB_DEVICE_LS,
> 36: PHY_MODE_USB_DEVICE_FS,
> 37: PHY_MODE_USB_DEVICE_HS,
> 38: PHY_MODE_USB_DEVICE_SS,
> 39: PHY_MODE_USB_OTG,
>
> >> Then, on hamoa/glymur specifically, any of the 3 USB4-capable DP hosts
> >> can be muxed to either of the 2 DPIN ports on any of the 3 USB4 routers
> >> (and each of these routers is hardwired to one of the PHYs).
> >>
> >> To underline, we have 3 DP producers and 6 consumers. If there's e.g. a
> >> super high-res display at one of the physical ports, or a long
> >> daisy-chain, we may need to use 2 DPTXes to service 1 receptacle. Then,
> >> we would only need one of the PHYs (associated with the router that's
> >> wired to that port) to provide a DP clock.
> >>
> >> This, along with the normal (logical or physical) present/absent status
> >> can change at runtime. My plan is to use phy_set_opts(dp_tunelling=true)
> >> or something along those lines to toggle that bit as necessary
> >
> > I don't see phy_set_opts(). So maybe a submode then...
>
> Sorry, I misremembered the name. The function is phy_configure(), and it
> takes a union phy_configure_opts, hence the confusion
So, phy_configure() will be called for the DP PHY to set the DP opts,
but how do you plan to determine if DP is on or not? Or do you plan to
add phy_tbt_configure_opts ?
Another obvious option would be to set the flag if DP PHY is being tuned
on / off. I don't know if that fulfills your needs.
>
> Konrad
--
With best wishes
Dmitry
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v2] phy: exynos5-usbdrd: Remove error print for devm_add_action_or_reset()
From: Waqar Hameed @ 2026-05-20 14:58 UTC (permalink / raw)
To: Vinod Koul, Kishon Vijay Abraham I, Krzysztof Kozlowski,
Alim Akhtar
Cc: kernel, linux-phy, linux-arm-kernel, linux-samsung-soc,
linux-kernel
In-Reply-To: <pnd7bx2j2pi.a.out@axis.com>
On Fri, Oct 10, 2025 at 15:39 +0200 Waqar Hameed <waqar.hameed@axis.com> wrote:
> On Tue, Aug 05, 2025 at 11:33 +0200 Waqar Hameed <waqar.hameed@axis.com> wrote:
[...]
> Friendly ping incoming!
Friendly ping 2 incoming!
This will be the last ping for the original patch [1]. I'll interpret
the silence as a NACK (though it would preferable to get an explicit
one...). All other patches in the previous patch series has been merged
[2].
[1] https://lore.kernel.org/all/pnd34a6m7tc.a.out@axis.com/
[2] https://lore.kernel.org/all/pnd7c0s6ji2.fsf@axis.com/
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v8 phy-next 15/31] drm/rockchip: dw_hdmi: avoid direct dereference of phy->dev.of_node
From: Heiko Stuebner @ 2026-05-20 14:21 UTC (permalink / raw)
To: linux-phy, Vladimir Oltean
Cc: Vinod Koul, Neil Armstrong, dri-devel, freedreno,
linux-arm-kernel, linux-arm-msm, linux-can, linux-gpio, linux-ide,
linux-kernel, linux-media, linux-pci, linux-renesas-soc,
linux-riscv, linux-rockchip, linux-samsung-soc, linux-scsi,
linux-sunxi, linux-tegra, linux-usb, netdev, spacemit,
UNGLinuxDriver, Sandy Huang, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter
In-Reply-To: <20260505100523.1922388-16-vladimir.oltean@nxp.com>
Hi Vladimir,
Am Dienstag, 5. Mai 2026, 12:05:07 Mitteleuropäische Sommerzeit schrieb Vladimir Oltean:
> The dw_hdmi-rockchip driver validates pixel clock rates against the
> HDMI PHY's internal clock provider on certain SoCs like RK3328.
> This is currently achieved by dereferencing hdmi->phy->dev.of_node
> to obtain the provider node, which violates the Generic PHY API's
> encapsulation (the goal is for struct phy to be an opaque pointer
> with a hidden definition, to be interacted with only using API
> functions or NULL pointer checks, for the case where optional variants
> of phy_get() did not find a PHY).
>
> Refactor dw_hdmi_rockchip_bind() to perform a manual phandle lookup
> on the "hdmi" PHY index within the controller's DT node. This provides
> a parallel path to the clock provider's OF node without relying on the
> internal structure of the struct phy handle.
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> Reviewed-by: Heiko Stueber <heiko@sntech.de>
there is now already more stuff depending on this change [0], and
the change itself also is sort of independent of the whole
phy-series. And somehow this series itself sadly hasn't gotten
much review yet.
So would you be ok with me just picking this one patch for the
drm-misc-tree?
Thanks
Heiko
[0] https://lore.kernel.org/dri-devel/20260518193748.2482823-1-jonas@kwiboo.se/
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH RESEND v8 00/10] SPMI: Implement sub-devices and migrate drivers
From: AngeloGioacchino Del Regno @ 2026-05-20 11:51 UTC (permalink / raw)
To: Jonathan Cameron
Cc: dlechner, nuno.sa, andy, arnd, gregkh, srini, vkoul,
neil.armstrong, sre, sboyd, krzk, dmitry.baryshkov, quic_wcheng,
melody.olvera, quic_nsekar, ivo.ivanov.ivanov1, abelvesa,
luca.weiss, konrad.dybcio, mitltlatltl, krishna.kurapati,
linux-arm-msm, linux-iio, linux-kernel, linux-phy, linux-pm,
kernel
In-Reply-To: <20260511141743.251a47e4@jic23-huawei>
On 5/11/26 15:17, Jonathan Cameron wrote:
> On Mon, 11 May 2026 12:07:55 +0200
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> wrote:
>
> Hi Angelo,
>
> Why the resend? If marking a series with that I expect to see it
> called out as first thing in the cover letter.
>
Right, forgot to mention why.
The v8 was sent on January 2026, I pinged maintainers to pick it on
March 2026, even if this was fully reviewed by multiple people nobody
picked anything here.
....and I've resent it because pinging multiple times didn't work, and
because the series got old all that much. :-)
Regards,
Angelo
> Jonathan
>
>> Changes in v8:
>> - Renamed *res to *sub_sdev in devm_spmi_subdevice_remove() (Andy)
>> - Changed kerneldoc wording to "error pointer" for function
>> spmi_subdevice_alloc_and_add() (Andy)
>> - Shuffled around some assignments in spmi_subdevice_alloc_and_add() (Andy)
>> - Used device_property_read_u32() instead of of_property_read_u32()
>> in all of the migrated drivers (Andy)
>> - Changed .max_register field in all of the migrated drivers from
>> 0x100 to 0xff (Andy)
>> - Kept `sta1` declaration in reversed xmas tree order in function
>> iadc_poll_wait_eoc() of qcom-spmi-iadc.c (Andy)
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v15 7/9] drm/rockchip: cdn-dp: Add multiple bridges to support PHY port selection
From: Heiko Stuebner @ 2026-05-20 11:12 UTC (permalink / raw)
To: Heikki Krogerus, Greg Kroah-Hartman, Dmitry Baryshkov, Peter Chen,
Luca Ceresoli, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Vinod Koul, Kishon Vijay Abraham I, Sandy Huang, Andy Yan,
Yubing Zhang, Frank Wang, Andrzej Hajda, Neil Armstrong,
Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Amit Sunil Dhamne, Dragan Simic, Johan Jonker,
Diederik de Haas, Peter Robinson, Hugh Cole-Baker, Chaoyi Chen
Cc: linux-usb, devicetree, linux-kernel, linux-phy, linux-arm-kernel,
linux-rockchip, dri-devel, Chaoyi Chen
In-Reply-To: <20260304094152.92-8-kernel@airkyi.com>
Am Mittwoch, 4. März 2026, 10:41:50 Mitteleuropäische Sommerzeit schrieb Chaoyi Chen:
> From: Chaoyi Chen <chaoyi.chen@rock-chips.com>
>
> The RK3399 has two USB/DP combo PHY and one CDN-DP controller. And
> the CDN-DP can be switched to output to one of the PHYs. If both ports
> are plugged into DP, DP will select the first port for output.
>
> This patch adds support for multiple bridges, enabling users to flexibly
> select the output port. For each PHY port, a separate encoder and bridge
> are registered.
>
> The change is based on the DRM AUX HPD bridge, rather than the
> extcon approach. This requires the DT to correctly describe the
> connections between the first bridge in bridge chain and DP
> controller. For example, the bridge chain may be like this:
>
> PHY aux birdge -> fsa4480 analog audio switch bridge ->
> onnn,nb7vpq904m USB reminder bridge -> USB-C controller AUX HPD bridge
>
> In this case, the connection relationships among the PHY aux bridge
> and the DP contorller need to be described in DT.
>
> In addition, the cdn_dp_parse_next_bridge_dt() will parses it and
> determines whether to register one or two bridges.
>
> Since there is only one DP controller, only one of the PHY ports can
> output at a time. The key is how to switch between different PHYs,
> which is handled by cdn_dp_switch_port() and cdn_dp_enable().
>
> There are two cases:
>
> 1. Neither bridge is enabled. In this case, both bridges can
> independently read the EDID, and the PHY port may switch before
> reading the EDID.
>
> 2. One bridge is already enabled. In this case, other bridges are not
> allowed to read the EDID. So we will try to return the cached EDID.
>
> Since the scenario of two ports plug in at the same time is rare,
> I don't have a board which support two TypeC connector to test this.
> Therefore, I tested forced switching on a single PHY port, as well as
> output using a fake PHY port alongside a real PHY port.
>
> Signed-off-by: Chaoyi Chen <chaoyi.chen@rock-chips.com>
> Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v15 6/9] drm/rockchip: cdn-dp: Support handle lane info without extcon
From: Heiko Stuebner @ 2026-05-20 11:10 UTC (permalink / raw)
To: Heikki Krogerus, Greg Kroah-Hartman, Dmitry Baryshkov, Peter Chen,
Luca Ceresoli, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Vinod Koul, Kishon Vijay Abraham I, Sandy Huang, Andy Yan,
Yubing Zhang, Frank Wang, Andrzej Hajda, Neil Armstrong,
Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Amit Sunil Dhamne, Dragan Simic, Johan Jonker,
Diederik de Haas, Peter Robinson, Hugh Cole-Baker, Chaoyi Chen
Cc: linux-usb, devicetree, linux-kernel, linux-phy, linux-arm-kernel,
linux-rockchip, dri-devel, Chaoyi Chen
In-Reply-To: <20260304094152.92-7-kernel@airkyi.com>
Am Mittwoch, 4. März 2026, 10:41:49 Mitteleuropäische Sommerzeit schrieb Chaoyi Chen:
> From: Chaoyi Chen <chaoyi.chen@rock-chips.com>
>
> This patch add support for get PHY lane info without help of extcon.
>
> There is no extcon needed if the Type-C controller is present. In this
> case, the lane info can be get from PHY instead of extcon.
>
> The extcon device should still be supported if Type-C controller is
> not present.
>
> Signed-off-by: Chaoyi Chen <chaoyi.chen@rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v15 9/9] arm64: dts: rockchip: rk3399-evb-ind: Add support for DisplayPort
From: Heiko Stuebner @ 2026-05-20 11:06 UTC (permalink / raw)
To: Heikki Krogerus, Greg Kroah-Hartman, Dmitry Baryshkov, Peter Chen,
Luca Ceresoli, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Vinod Koul, Kishon Vijay Abraham I, Sandy Huang, Andy Yan,
Yubing Zhang, Frank Wang, Andrzej Hajda, Neil Armstrong,
Robert Foss, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Amit Sunil Dhamne, Dragan Simic, Johan Jonker,
Diederik de Haas, Peter Robinson, Hugh Cole-Baker, Chaoyi Chen
Cc: linux-usb, devicetree, linux-kernel, linux-phy, linux-arm-kernel,
linux-rockchip, dri-devel, Chaoyi Chen
In-Reply-To: <20260304094152.92-10-kernel@airkyi.com>
Am Mittwoch, 4. März 2026, 10:41:52 Mitteleuropäische Sommerzeit schrieb Chaoyi Chen:
> From: Chaoyi Chen <chaoyi.chen@rock-chips.com>
>
> The RK3399 EVB IND board has a Type-C interface DisplayPort.
> It use fusb302 chip as Type-C controller.
>
> fusb302 chip ---> USB/DP PHY0 <----> CDN-DP controller
>
> Signed-off-by: Chaoyi Chen <chaoyi.chen@rock-chips.com>
Apart from what I replied to the cover-letter, it might be
nice to split this into
- patch adding the fusb and general type-c parts
- patch adding the dp altmode
To make each part a bit shorter.
Heiko
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox