mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-03-27 17:45:13 +08:00
[DM/PHYE] Support USB generic PHYE.
Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
components/drivers/phye/phye-generic-usb.c
Normal file
232
components/drivers/phye/phye-generic-usb.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* 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);
|
||||
Reference in New Issue
Block a user