diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 56eec40d01..0d950cd354 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -21,6 +21,7 @@ rsource "touch/Kconfig" rsource "graphic/Kconfig" rsource "hwcrypto/Kconfig" rsource "wlan/Kconfig" +rsource "phye/Kconfig" rsource "block/Kconfig" rsource "nvme/Kconfig" rsource "scsi/Kconfig" diff --git a/components/drivers/include/drivers/phye.h b/components/drivers/include/drivers/phye.h new file mode 100644 index 0000000000..3776cdeac9 --- /dev/null +++ b/components/drivers/include/drivers/phye.h @@ -0,0 +1,91 @@ +/* + * 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 + */ + +#ifndef __PHYE_H__ +#define __PHYE_H__ + +#include +#include + +enum rt_phye_mode +{ + RT_PHYE_MODE_INVALID, + RT_PHYE_MODE_USB_HOST, + RT_PHYE_MODE_USB_HOST_LS, + RT_PHYE_MODE_USB_HOST_FS, + RT_PHYE_MODE_USB_HOST_HS, + RT_PHYE_MODE_USB_HOST_SS, + RT_PHYE_MODE_USB_DEVICE, + RT_PHYE_MODE_USB_DEVICE_LS, + RT_PHYE_MODE_USB_DEVICE_FS, + RT_PHYE_MODE_USB_DEVICE_HS, + RT_PHYE_MODE_USB_DEVICE_SS, + RT_PHYE_MODE_USB_OTG, + RT_PHYE_MODE_UFS_HS_A, + RT_PHYE_MODE_UFS_HS_B, + RT_PHYE_MODE_PCIE, + RT_PHYE_MODE_ETHERNET, + RT_PHYE_MODE_MIPI_DPHY, + RT_PHYE_MODE_SATA, + RT_PHYE_MODE_LVDS, + RT_PHYE_MODE_DP, + + RT_PHYE_MODE_MAX, + + /* PCIe */ + RT_PHYE_MODE_PCIE_RC = RT_PHYE_MODE_MAX, + RT_PHYE_MODE_PCIE_EP, + RT_PHYE_MODE_PCIE_BIFURCATION, +}; + +struct rt_phye_ops; + +struct rt_phye +{ + struct rt_device *dev; + + const struct rt_phye_ops *ops; + + int init_count; + int power_count; + struct rt_spinlock lock; +}; + +struct rt_phye_ops +{ + rt_err_t (*init)(struct rt_phye *phye); + rt_err_t (*exit)(struct rt_phye *phye); + rt_err_t (*reset)(struct rt_phye *phye); + rt_err_t (*power_on)(struct rt_phye *phye); + rt_err_t (*power_off)(struct rt_phye *phye); + rt_err_t (*set_mode)(struct rt_phye *phye, enum rt_phye_mode mode, int submode); + rt_err_t (*ofw_parse)(struct rt_phye *phye, struct rt_ofw_cell_args *phye_args); +}; + +rt_err_t rt_phye_register(struct rt_phye *phye); +rt_err_t rt_phye_unregister(struct rt_phye *phye); + +rt_err_t rt_phye_init(struct rt_phye *phye); +rt_err_t rt_phye_exit(struct rt_phye *phye); +rt_err_t rt_phye_reset(struct rt_phye *phye); +rt_err_t rt_phye_power_on(struct rt_phye *phye); +rt_err_t rt_phye_power_off(struct rt_phye *phye); +rt_err_t rt_phye_set_mode(struct rt_phye *phye, enum rt_phye_mode mode, int submode); + +rt_inline rt_err_t rt_phye_set_mode_simple(struct rt_phye *phye, enum rt_phye_mode mode) +{ + return rt_phye_set_mode(phye, mode, RT_PHYE_MODE_INVALID); +} + +struct rt_phye *rt_phye_get_by_index(struct rt_device *dev, int index); +struct rt_phye *rt_phye_get_by_name(struct rt_device *dev, const char *id); +void rt_phye_put(struct rt_phye *phye); + +#endif /* __PHYE_H__ */ diff --git a/components/drivers/include/dt-bindings/phye/phye.h b/components/drivers/include/dt-bindings/phye/phye.h new file mode 100644 index 0000000000..54a9cce958 --- /dev/null +++ b/components/drivers/include/dt-bindings/phye/phye.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DT_BINDINGS_PHYE_H__ +#define __DT_BINDINGS_PHYE_H__ + +#define PHY_NONE 0 +#define PHY_TYPE_SATA 1 +#define PHY_TYPE_PCIE 2 +#define PHY_TYPE_USB2 3 +#define PHY_TYPE_USB3 4 +#define PHY_TYPE_UFS 5 +#define PHY_TYPE_DP 6 +#define PHY_TYPE_XPCS 7 +#define PHY_TYPE_SGMII 8 +#define PHY_TYPE_QSGMII 9 +#define PHY_TYPE_DPHY 10 +#define PHY_TYPE_CPHY 11 +#define PHY_TYPE_USXGMII 12 + +#endif /* __DT_BINDINGS_PHYE_H__ */ diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index 18a64e259c..ceb02485e3 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -67,6 +67,10 @@ extern "C" { #include "drivers/ofw_raw.h" #endif /* RT_USING_OFW */ +#ifdef RT_USING_PHYE +#include "drivers/phye.h" +#endif + #ifdef RT_USING_PIC #include "drivers/pic.h" #endif diff --git a/components/drivers/phye/Kconfig b/components/drivers/phye/Kconfig new file mode 100644 index 0000000000..c6672eee43 --- /dev/null +++ b/components/drivers/phye/Kconfig @@ -0,0 +1,11 @@ +menuconfig RT_USING_PHYE + bool "Using External Port Physical Layer (PHY) device drivers" + depends on RT_USING_DM + default n + help + This framework will be of use only to devices that use + external PHY (PHY functionality is not embedded within the controller). + +if RT_USING_PHYE + osource "$(SOC_DM_PHYE_DIR)/Kconfig" +endif diff --git a/components/drivers/phye/SConscript b/components/drivers/phye/SConscript new file mode 100644 index 0000000000..23deafed7c --- /dev/null +++ b/components/drivers/phye/SConscript @@ -0,0 +1,15 @@ +from building import * + +group = [] + +if not GetDepend(['RT_USING_PHYE']): + Return('group') + +cwd = GetCurrentDir() +CPPPATH = [cwd + '/../include'] + +src = ['phye.c'] + +group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/phye/phye.c b/components/drivers/phye/phye.c new file mode 100644 index 0000000000..7dc6709682 --- /dev/null +++ b/components/drivers/phye/phye.c @@ -0,0 +1,320 @@ +/* + * 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 + */ + +#define DBG_TAG "rtdm.phye" +#define DBG_LVL DBG_INFO +#include + +#include +#include + +rt_err_t rt_phye_register(struct rt_phye *phye) +{ + rt_err_t err; + + if (phye && phye->dev && phye->ops) + { + err = RT_EOK; + + rt_spin_lock_init(&phye->lock); + rt_dm_dev_bind_fwdata(phye->dev, RT_NULL, phye); + } + else + { + err = -RT_EINVAL; + } + + return err; +} + +rt_err_t rt_phye_unregister(struct rt_phye *phye) +{ + rt_err_t err; + + if (phye) + { + err = RT_EOK; + + rt_spin_lock(&phye->lock); + + if (phye->dev->ref_count) + { + err = -RT_EBUSY; + LOG_E("%s is busy in unregister", rt_dm_dev_get_name(phye->dev)); + } + + rt_dm_dev_unbind_fwdata(phye->dev, RT_NULL); + + rt_spin_unlock(&phye->lock); + } + else + { + err = -RT_EINVAL; + } + + return err; +} + +rt_err_t rt_phye_init(struct rt_phye *phye) +{ + rt_err_t err; + + if (!phye) + { + return RT_EOK; + } + + err = RT_EOK; + + rt_spin_lock(&phye->lock); + + if (phye->init_count == 0 && phye->ops->init) + { + if ((err = phye->ops->init(phye))) + { + goto _out_lock; + } + } + ++phye->init_count; + +_out_lock: + rt_spin_unlock(&phye->lock); + + return err; +} + +rt_err_t rt_phye_exit(struct rt_phye *phye) +{ + rt_err_t err; + + if (!phye) + { + return RT_EOK; + } + + err = RT_EOK; + + rt_spin_lock(&phye->lock); + + if (phye->init_count == 1 && phye->ops->exit) + { + if ((err = phye->ops->exit(phye))) + { + goto _out_lock; + } + } + if (phye->init_count) + { + --phye->init_count; + } + +_out_lock: + rt_spin_unlock(&phye->lock); + + return err; +} + +rt_err_t rt_phye_reset(struct rt_phye *phye) +{ + rt_err_t err; + + if (!phye) + { + return RT_EOK; + } + + err = RT_EOK; + + rt_spin_lock(&phye->lock); + + if (phye->ops->reset) + { + err = phye->ops->reset(phye); + } + + rt_spin_unlock(&phye->lock); + + return err; +} + +rt_err_t rt_phye_power_on(struct rt_phye *phye) +{ + rt_err_t err; + + if (!phye) + { + return RT_EOK; + } + + err = RT_EOK; + + rt_spin_lock(&phye->lock); + + if (phye->power_count == 0 && phye->ops->power_on) + { + if ((err = phye->ops->power_on(phye))) + { + goto _out_lock; + } + } + ++phye->power_count; + +_out_lock: + rt_spin_unlock(&phye->lock); + + return err; +} + +rt_err_t rt_phye_power_off(struct rt_phye *phye) +{ + rt_err_t err; + + if (!phye) + { + return RT_EOK; + } + + err = RT_EOK; + + rt_spin_lock(&phye->lock); + + if (phye->power_count == 1 && phye->ops->power_off) + { + if ((err = phye->ops->power_off(phye))) + { + goto _out_lock; + } + } + if (phye->power_count) + { + --phye->power_count; + } + +_out_lock: + rt_spin_unlock(&phye->lock); + + return err; +} + +rt_err_t rt_phye_set_mode(struct rt_phye *phye, enum rt_phye_mode mode, int submode) +{ + rt_err_t err; + + if (!phye) + { + return RT_EOK; + } + + if (mode < RT_PHYE_MODE_MAX && + (submode == RT_PHYE_MODE_INVALID || submode >= RT_PHYE_MODE_MAX)) + { + err = RT_EOK; + + rt_spin_lock(&phye->lock); + + if (phye->ops->set_mode) + { + err = phye->ops->set_mode(phye, mode, submode); + } + + rt_spin_unlock(&phye->lock); + } + else + { + err = -RT_EINVAL; + } + + return err; +} + +static struct rt_phye *ofw_phye_get_by_index(struct rt_ofw_node *np, int index) +{ + struct rt_phye *phye = RT_NULL; +#ifdef RT_USING_OFW + rt_err_t err; + struct rt_ofw_node *phye_np; + struct rt_ofw_cell_args phye_args; + + if (!rt_ofw_parse_phandle_cells(np, "phys", "#phy-cells", index, &phye_args)) + { + phye_np = phye_args.data; + + if (!rt_ofw_data(phye_np)) + { + rt_platform_ofw_request(phye_np); + } + + phye = rt_ofw_data(phye_np); + rt_ofw_node_put(phye_np); + + if (phye && phye->ops->ofw_parse) + { + if ((err = phye->ops->ofw_parse(phye, &phye_args))) + { + phye = rt_err_ptr(err); + } + } + } +#endif /* RT_USING_OFW */ + return phye; +} + +struct rt_phye *rt_phye_get_by_index(struct rt_device *dev, int index) +{ + struct rt_phye *phye = RT_NULL; + + if (!dev || index < 0) + { + return rt_err_ptr(-RT_EINVAL); + } + + if (dev->ofw_node) + { + phye = ofw_phye_get_by_index(dev->ofw_node, index); + } + + if (!rt_is_err_or_null(phye)) + { + rt_spin_lock(&phye->lock); + ++phye->dev->ref_count; + rt_spin_unlock(&phye->lock); + } + + return phye; +} + +struct rt_phye *rt_phye_get_by_name(struct rt_device *dev, const char *id) +{ + int index; + + if (!dev || !id) + { + return rt_err_ptr(-RT_EINVAL); + } + + index = rt_dm_dev_prop_index_of_string(dev, "phy-names", id); + + if (index >= 0) + { + return rt_phye_get_by_index(dev, index); + } + + return RT_NULL; +} + +void rt_phye_put(struct rt_phye *phye) +{ + if (phye) + { + rt_spin_lock(&phye->lock); + --phye->dev->ref_count; + rt_spin_unlock(&phye->lock); + } +}