Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions components/drivers/phye/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ menuconfig RT_USING_PHYE
This framework will be of use only to devices that use
external PHY (PHY functionality is not embedded within the controller).

config RT_PHYE_GENERIC_USB
bool "Generic USB"
depends on RT_USING_PHYE
help
Enable support for generic USB PHY devices that follow the
"usb-nop-xceiv" device tree binding. This driver provides basic
PHY operations including reset, power management, and clock control
for USB PHY hardware.

if RT_USING_PHYE
osource "$(SOC_DM_PHYE_DIR)/Kconfig"
endif
3 changes: 3 additions & 0 deletions components/drivers/phye/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ CPPPATH = [cwd + '/../include']

src = ['phye.c']

if GetDepend(['RT_PHYE_GENERIC_USB']):
src += ['phye-generic-usb.c']

group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)

Return('group')
232 changes: 232 additions & 0 deletions components/drivers/phye/phye-generic-usb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/*
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 [PR Title/PR 标题]: Title format does not follow RT-Thread standards / 标题格式不符合 RT-Thread 标准

English: The PR title should follow the format: [module][subsystem] Description in lowercase. The current title uses uppercase "DM/PHYE" instead of lowercase, and the description is not specific enough.

Current title: [DM/PHYE] Support USB generic PHYE.
Suggested title: [drivers][phye] Add generic USB PHY driver

中文: PR 标题应遵循格式:小写的 [模块][子系统] 描述。当前标题使用了大写的 "DM/PHYE" 而非小写,且描述不够具体。

当前标题:[DM/PHYE] Support USB generic PHYE.
建议标题:[drivers][phye] Add generic USB PHY driver

Copilot generated this review using guidance from repository custom instructions.
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-10-24 GuEe-GUI first version
*/

#include <rtdevice.h>
#include <rtthread.h>

#define DBG_TAG "phye.generic.usb"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

struct generic_usb_phy
{
struct rt_phye parent;

rt_base_t rst_pin;
rt_uint8_t rst_active_val;

struct rt_clk *clk;
struct rt_regulator *vcc;
struct rt_regulator *vbus;
};

#define raw_to_generic_usb_phy(raw) rt_container_of(raw, struct generic_usb_phy, parent)

static rt_err_t generic_usb_phy_reset(struct rt_phye *phye)
{
struct generic_usb_phy *usb_phy = raw_to_generic_usb_phy(phye);

if (usb_phy->rst_pin == PIN_NONE)
{
return RT_EOK;
}

rt_pin_mode(usb_phy->rst_pin, PIN_MODE_OUTPUT);

rt_pin_write(usb_phy->rst_pin, usb_phy->rst_active_val);
rt_hw_us_delay(15000);

rt_pin_write(usb_phy->rst_pin, !usb_phy->rst_active_val);
rt_hw_us_delay(20000);

return RT_EOK;
}

static rt_err_t generic_usb_phy_power_on(struct rt_phye *phye)
{
rt_err_t err;
struct generic_usb_phy *usb_phy = raw_to_generic_usb_phy(phye);

if (usb_phy->vcc && (err = rt_regulator_enable(usb_phy->vcc)))
{
return err;
}

if ((err = rt_clk_prepare_enable(usb_phy->clk)))
{
if (usb_phy->vcc)
{
rt_regulator_disable(usb_phy->vcc);
}

return err;
}

return generic_usb_phy_reset(phye);
}

static rt_err_t generic_usb_phy_power_off(struct rt_phye *phye)
{
rt_err_t err;
struct generic_usb_phy *usb_phy = raw_to_generic_usb_phy(phye);

if (usb_phy->vcc && (err = rt_regulator_disable(usb_phy->vcc)))
{
return err;
}

rt_clk_disable_unprepare(usb_phy->clk);

return RT_EOK;
}

static const struct rt_phye_ops generic_usb_phy_ops =
{
.reset = generic_usb_phy_reset,
.power_on = generic_usb_phy_power_on,
.power_off = generic_usb_phy_power_off,
};

static void generic_usb_phy_free(struct generic_usb_phy *usb_phy)
{
if (!rt_is_err_or_null(usb_phy->clk))
{
rt_clk_put(usb_phy->clk);
}

if (!rt_is_err_or_null(usb_phy->vcc))
{
rt_regulator_put(usb_phy->vcc);
}

if (!rt_is_err_or_null(usb_phy->vbus))
{
rt_regulator_put(usb_phy->vbus);
}

rt_free(usb_phy);
}

static rt_err_t generic_usb_phy_probe(struct rt_platform_device *pdev)
{
rt_err_t err;
rt_uint32_t rate;
struct rt_phye *phy;
struct rt_device *dev = &pdev->parent;
struct generic_usb_phy *usb_phy = rt_calloc(1, sizeof(*usb_phy));

if (!usb_phy)
{
return -RT_ENOMEM;
}

usb_phy->rst_pin = rt_pin_get_named_pin(dev, "reset", 0,
RT_NULL, &usb_phy->rst_active_val);

if (usb_phy->rst_pin < 0 && usb_phy->rst_pin != PIN_NONE)
{
err = usb_phy->rst_pin;
goto _fail;
}

usb_phy->clk = rt_clk_get_by_name(dev, "main_clk");

if (rt_is_err(usb_phy->clk))
{
err = rt_ptr_err(usb_phy->clk);
goto _fail;
}

if (!rt_dm_dev_prop_read_u32(dev, "clock-frequency", &rate))
{
if ((err = rt_clk_set_rate(usb_phy->clk, rate)))
{
goto _fail;
}
}

usb_phy->vcc = rt_regulator_get(dev, "vcc");

if (rt_is_err(usb_phy->vcc))
{
err = rt_ptr_err(usb_phy->vcc);
goto _fail;
}

usb_phy->vbus = rt_regulator_get(dev, "vbus");

if (rt_is_err(usb_phy->vbus))
{
err = rt_ptr_err(usb_phy->vbus);
goto _fail;
}

if (usb_phy->vbus && (err = rt_regulator_enable(usb_phy->vbus)))
{
goto _fail;
}

dev->user_data = usb_phy;

phy = &usb_phy->parent;
phy->dev = dev;
phy->ops = &generic_usb_phy_ops;

if ((err = rt_phye_register(phy)))
{
goto _fail;
}

return RT_EOK;

_fail:
generic_usb_phy_free(usb_phy);

return err;
}

static rt_err_t generic_usb_phy_remove(struct rt_platform_device *pdev)
{
struct generic_usb_phy *usb_phy = pdev->parent.user_data;

rt_phye_unregister(&usb_phy->parent);

if (usb_phy->vbus)
{
rt_regulator_disable(usb_phy->vbus);
}

generic_usb_phy_free(usb_phy);

return RT_EOK;
}

static const struct rt_ofw_node_id generic_usb_phy_ofw_ids[] =
{
{ .compatible = "usb-nop-xceiv" },
{ /* sentinel */ }
};

static struct rt_platform_driver generic_usb_phy_driver =
{
.name = "phy-generic-usb",
.ids = generic_usb_phy_ofw_ids,

.probe = generic_usb_phy_probe,
.remove = generic_usb_phy_remove,
};

static int generic_usb_phy_drv_register(void)
{
rt_platform_driver_register(&generic_usb_phy_driver);

return 0;
}
INIT_PLATFORM_EXPORT(generic_usb_phy_drv_register);