三星 USB 2.0 PHY 适配层¶
1. 描述¶
三星 SoC 中的 USB 2.0 PHY 模块的架构在许多 SoC 中相似。尽管存在相似之处,但事实证明很难创建一个适合所有这些 PHY 控制器的驱动程序。通常,差异很小,并且存在于 PHY 寄存器的特定位中。在某些罕见的情况下,必须更改寄存器写入的顺序或 PHY 上电过程。此适配层是在拥有单独的驱动程序和拥有一个添加了对许多特殊情况的支持的单个驱动程序之间的一种折衷方案。
2. 文件描述¶
- phy-samsung-usb2.c
这是适配层的主文件。此文件包含探测函数,并为通用 PHY 框架提供两个回调。这两个回调用于打开和关闭 phy 的电源。它们执行在所有版本的 PHY 模块上都必须完成的通用工作。根据选择的 SoC,它们会执行特定于 SoC 的回调。特定的 SoC 版本通过选择适当的兼容字符串来选择。此外,此文件包含特定 SoC 的 struct of_device_id 定义。
- phy-samsung-usb2.h
这是包含文件。它声明了此驱动程序使用的结构。此外,它应包含用于描述特定 SoC 的结构的 extern 声明。
3. 支持的 SoC¶
要支持新的 SoC,应在 drivers/phy 目录中添加一个新文件。每个 SoC 的配置都存储在 struct samsung_usb2_phy_config 的实例中
struct samsung_usb2_phy_config {
const struct samsung_usb2_common_phy *phys;
int (*rate_to_clk)(unsigned long, u32 *);
unsigned int num_phys;
bool has_mode_switch;
};
num_phys 是驱动程序处理的 phy 的数量。*phys 是一个数组,其中包含每个 phy 的配置。has_mode_switch 属性是一个布尔标志,用于确定 SoC 是否在单对引脚上具有 USB 主机和设备。如果是,则必须修改特殊寄存器以更改这些引脚在 USB 设备或主机模块之间的内部路由。
例如,Exynos 4210 的配置如下
const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = {
.has_mode_switch = 0,
.num_phys = EXYNOS4210_NUM_PHYS,
.phys = exynos4210_phys,
.rate_to_clk = exynos4210_rate_to_clk,
}
int (*rate_to_clk)(unsigned long, u32 *)
rate_to_clk 回调是将用作 PHY 模块的参考时钟的时钟速率转换为应写入硬件寄存器的值的回调。
exynos4210_phys 配置数组如下
static const struct samsung_usb2_common_phy exynos4210_phys[] = {
{
.label = "device",
.id = EXYNOS4210_DEVICE,
.power_on = exynos4210_power_on,
.power_off = exynos4210_power_off,
},
{
.label = "host",
.id = EXYNOS4210_HOST,
.power_on = exynos4210_power_on,
.power_off = exynos4210_power_off,
},
{
.label = "hsic0",
.id = EXYNOS4210_HSIC0,
.power_on = exynos4210_power_on,
.power_off = exynos4210_power_off,
},
{
.label = "hsic1",
.id = EXYNOS4210_HSIC1,
.power_on = exynos4210_power_on,
.power_off = exynos4210_power_off,
},
{},
};
int (*power_on)(struct samsung_usb2_phy_instance *); int (*power_off)(struct samsung_usb2_phy_instance *);
这两个回调用于通过修改适当的寄存器来打开和关闭 phy 的电源。
对驱动程序的最终更改是在 phy-samsung-usb2.c 文件中添加适当的兼容值。对于 Exynos 4210,以下行已添加到 struct of_device_id samsung_usb2_phy_of_match[] 数组中
#ifdef CONFIG_PHY_EXYNOS4210_USB2
{
.compatible = "samsung,exynos4210-usb2-phy",
.data = &exynos4210_usb2_phy_config,
},
#endif
为了向驱动程序添加更大的灵活性,Kconfig 文件允许在编译后的驱动程序中包含对选定 SoC 的支持。Exynos 4210 的 Kconfig 条目如下
config PHY_EXYNOS4210_USB2
bool "Support for Exynos 4210"
depends on PHY_SAMSUNG_USB2
depends on CPU_EXYNOS4210
help
Enable USB PHY support for Exynos 4210. This option requires that
Samsung USB 2.0 PHY driver is enabled and means that support for this
particular SoC is compiled in the driver. In case of Exynos 4210 four
phys are available - device, host, HSCI0 and HSCI1.
支持新 SoC 的新创建的文件也必须添加到 Makefile 中。对于 Exynos 4210,添加的行如下
obj-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
完成这些步骤后,对新 SoC 的支持应该就绪。