设为首页 加入收藏

TOP

PHY驱动调试之 ---PHY设备驱动(三)(一)
2023-07-23 13:30:24 】 浏览:75
Tags:PHY ---PHY

1. 前言

 内核版本:linux 4.9.225,以freescale为例。(部分内容待修改和补充,不一定准确)

2. 概述

上一篇文章讲了控制器的驱动使用的是platform总线的连接方式,本节要讲的PHY设备驱动是基于device、driver、bus的连接方式

其驱动涉及如下几个重要部分:

  • 总线 - sturct mii_bus (mii stand for media independent interface)
  • 设备 - struct phy_device
  • 驱动 - struct phy_driver

关于PHY设备的创建和注册已经在上一篇控制器的probe函数中有过详细的描述(需要注意的是:phy设备不像i2c/spi有一个board_info函数进行设备的添加,而是直接读取phy中的寄存器<根据IEEE的规定,PHY芯片的前16个寄存器的内容必须是固定的>),本节就不再描述;本节主要讲解总线、设备、驱动模型中剩下的mdio_bus总线PHY设备对应的驱动

3. mdio_bus总线

3.1 总线注册的入口函数

# linux-4.9.225\drivers\net\phy\phy_device.c
static int __init phy_init(void)
{
	int rc;

	rc = mdio_bus_init(); //mdio_bus总线的注册
	if (rc)
		return rc;

	rc = phy_drivers_register(genphy_driver,ARRAY_SIZE(genphy_driver), THIS_MODULE); //通用PHY驱动
	if (rc)
		mdio_bus_exit();

	return rc;
}

subsys_initcall(phy_init); 

subsys_initcall(phy_init) 这行的作用非常重要,这一行就决定了内核在启动的时候会调用该函数,注册完了之后紧接着又注册一个通用的PHY驱动。关于intcall的机制请参见我之前写的专题:linux内核链接脚本vmlinux.lds分析续篇之 --- initcall机制(十三)

3.2 总线注册函数--- mdio_bus_init解析

# linux-4.9.225\drivers\net\phy\mdio_bus.c
static struct class mdio_bus_class = {
	.name		= "mdio_bus",
	.dev_release	= mdiobus_release,
};

static int mdio_bus_match(struct device *dev, struct device_driver *drv)
{
	struct mdio_device *mdio = to_mdio_device(dev);

	if (of_driver_match_device(dev, drv))
		return 1;

	if (mdio->bus_match)
		return mdio->bus_match(dev, drv);

	return 0;
}

struct bus_type mdio_bus_type = {
	.name		= "mdio_bus",     //总线名称
	.match		= mdio_bus_match, //用来匹配总线上设备和驱动的函数
	.pm		= MDIO_BUS_PM_OPS,
};
EXPORT_SYMBOL(mdio_bus_type);

int __init mdio_bus_init(void)
{
	int ret;

	ret = class_register(&mdio_bus_class); //注册设备类 (在linux设备模型中,我再仔细讲这个类的概念)
	if (!ret) {
		ret = bus_register(&mdio_bus_type);//总线注册
		if (ret)
			class_unregister(&mdio_bus_class);
	}

	return ret;
}

其中
(1) class_register(&mdio_bus_class)执行后会有以下设备类:

  • /sys/class/mdio_bus

(2)bus_register(&mdio_bus_type)执行后会有以下总线类型:

  • /sys/bus/mdio_bus

3.3 总线中的match函数解析

/**
 * mdio_bus_match - determine if given MDIO driver supports the given
 *		    MDIO device
 * @dev: target MDIO device
 * @drv: given MDIO driver
 *
 * Description: Given a MDIO device, and a MDIO driver, return 1 if
 *   the driver supports the device.  Otherwise, return 0. This may
 *   require calling the devices own match function, since different classes
 *   of MDIO devices have different match criteria.
 */
static int mdio_bus_match(struct device *dev, struct device_driver *drv)
{
	struct mdio_device *mdio = to_mdio_device(dev);

	if (of_driver_match_device(dev, drv))
		return 1;

	if (mdio->bus_match)               //实现匹配的函数
		return mdio->bus_match(dev, drv);

	return 0;
}

4. 设备驱动的注册

在phy_init函数中不仅注册了mdio_bus总线,还注册了一个通用的PHY驱动作为缺省的内核PHY驱动,但是如果PHY芯片的内部寄存器和802.3定义的并不一样或者需要特殊的功能配置以实现更强的功能,这就需要专有的驱动。关于通用PHY驱动的知识,网上有一大堆讲解,本节就不再重复的去描述。

对于市场上存在的主流PHY品牌,一般在内核源码 drivers\net\phy目录下都有对应的驱动。本节主要以realtek RTL8211F为例,讲述PHY的驱动,代码如下:

# linux-4.9.225\drivers\net\phy\realtek.c
static struct phy_driver realtek_drvs[] = {
	......
	, {
		.phy_id		= 0x001cc916,
		.name		= "RTL8211F Gigabit Ethernet",
		.phy_id_mask	= 0x001fffff,
		.features	= PHY_GBIT_FEATURES,
		.flags		= PHY_HAS_INTERRUPT,
		.config_aneg	= &ge
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇UBOOT编译--- include/config.h、.. 下一篇UBOOT编译--- include/config/aut..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目