SOC可以对PHY 进行配置或者读取PHY 相关状态,这个就需要 PHY 内部寄存器去实现了。PHY 芯片寄存器地址空间为 5位(支持访问32个寄存器).IEEE 定义了0~15这 16个寄存器的功能。而 16~31这16 个寄存器由厂商自行实现。
就是说不管你用的哪个厂家的 PHY 芯片,其中 0~15 这 16 个寄存器是一模一样的。仅靠这16个寄存器是完全可以驱动起 PHY 芯片的,至少能保证基本的网络数据通信,因此 Linux 内核有通用 PHY 驱动。所以 一般情况下,如果不需要使用PHY厂家提供的自定义的寄存器配置实现一些个性化的功能,那么PHY驱动就基本不需要修改。
如 寄存器0是PHY控制寄存器,通过Control Register可以对PHY的主要工作状态进行设置。 寄存器1是PHY状态寄存器,主要包含PHY的状态信息。等等 具体可以去找具体的寄存器信息,这里不做详细叙述。
如:
MAC控制器通过MDIO总线来管理phy设备,mdio总线与i2c总线类似,可以一个主机对应多个从设备,每个从设备都有地址。mdio最多接32个phy设备。
对应的目录是/sys/mdio,在/sys/mdio/devices目录中会有挂载在mdio的phy设备,在/sys/mdio/drivers中会有phy设备的驱动。
如:
 /sys/bus/mdio_bus/devices/stmmac-0:00 
其中 stmmac-0:00 表示 PHY 地址是 0。
该命令会读取 0~31 的所有寄存器,所以可以查看对应的寄存器值
cat /sys/bus/mdio_bus/devices/stmmac-0:00/phy_registers
root@OpenSDT:/sys/devices/platform/fe300000.ethernet/mdio_bus/stmmac-0/stmmac-0:00# cat phy_registers
 0: 0x1140
 1: 0x7989
 2: 0x1c
 3: 0xc982
 4: 0x1e1
 5: 0x0
 6: 0x64
 7: 0x2001
 8: 0x0
 9: 0xe00
10: 0x0
11: 0x0
12: 0x0
13: 0x0
14: 0x0
15: 0x2000
16: 0x23
17: 0x0
18: 0xffff
19: 0x0
20: 0x0
21: 0x0
22: 0xf00
23: 0xf00
24: 0x19c
25: 0x40
26: 0x5000
27: 0x802a
28: 0x0
29: 0x220
30: 0x0
31: 0x0
root@OpenSDT:/sys/devices/platform/fe300000.ethernet/mdio_bus/stmmac-0/stmmac-0:00# 
drivers\net\phy\phy_device.c
static struct phy_driver genphy_driver = {
	.phy_id		= 0xffffffff,
	.phy_id_mask	= 0xffffffff,
	.name		= "Generic PHY",
	.soft_reset	= genphy_no_soft_reset,
	.config_init	= genphy_config_init,
	.features	= PHY_GBIT_FEATURES | SUPPORTED_MII |
			  SUPPORTED_AUI | SUPPORTED_FIBRE |
			  SUPPORTED_BNC,
	.aneg_done	= genphy_aneg_done,
	.suspend	= genphy_suspend,
	.resume		= genphy_resume,
	.set_loopback   = genphy_loopback,
};
static int __init phy_init(void)
{
	int rc;
	//mdio 总线初始化注册:
	/*
		注册:
		/sys/class/mdio_bus
		/sys/bus/mdio_bus
	*/
	rc = mdio_bus_init();
	if (rc)
		return rc;
	//注册 名为    "Generic 10G PHY" phy驱动 到 mdio 总线
	rc = phy_driver_register(&genphy_10g_driver, THIS_MODULE);
	if (rc)
		goto err_10g;
	//注册 名为   "Generic PHY" phy驱动 到 mdio 总线
	rc = phy_driver_register(&genphy_driver, THIS_MODULE);
	if (rc) {
		phy_driver_unregister(&genphy_10g_driver);
err_10g:
		mdio_bus_exit();
	}
	return rc;
}
static void __exit phy_exit(void)
{
	phy_driver_unregister(&genphy_10g_driver);
	phy_driver_unregister(&genphy_driver);
	mdio_bus_exit();
}
subsys_initcall(phy_init);
module_exit(phy_exit);
\drivers\net\phy\mdio_bus.c
// sys/class/mdio_bus
static struct class mdio_bus_class = {
	.name		= "mdio_bus",
	.dev_release	= mdiobus_release,
};
// /sys/bus/mdio_bus
struct bus_type mdio_bus_type = {
	.name		= "mdio_bus",
	.match		= mdio_bus_match,
	.uevent		= mdio_uevent,
};
EXPORT_SYMBOL(mdio_bus_type);
int __init mdio_bus_init(void)
{
	int ret;
	// 即 /sys/class/mdio_bus
	ret = class_register(&mdio_bus_class);
	if (!ret) {
		
		//即 /sys/bus/mdio_bus
		ret = bus_register(&mdio_bus_type);
		if (ret)
			class_unregister(&mdio_bus_class);
	}
	return ret;
}
EXPORT_SYMBOL_GPL(mdio_bus_init);
int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
{
	int retval;
/*
//phy 驱动
struct phy_driver
	.name		= "Generic PHY",
	 //MDIO 驱动通用部分
	 struct mdio_driver_common mdiodrv;-----+
											|
											|
											+---struct mdio_driver_common mdiodrv;
													int flags  |= MDIO_DEVICE_IS_PHY
													struct device_driver driver;
														.name		= "Generic PHY",
														//总线													//mdio 总线
														struct bus_type		*bus;-------------------------------struct bus_type mdio_bus_type = {
														int (*probe) (struct device *dev); = phy_probe              .name		= "mdio_bus",
														...                                                       	.match		= mdio_bus_match,
                                                                                                                  	.uevent		= mdio_uevent,
																													struct subsys_private *p;
																														//相关的驱动程序列表
																														struct kset *drivers_kset;
*/
	new_driver->mdiodrv.flags |= MDIO_DEVICE_IS_PHY;
	new_driver->mdiodrv.driver.name = new_driver->name;
	new_driver->mdiodrv.driver.bus = &mdio_bus_type;
	new_driver->mdiodrv.driver.probe = phy_probe;
	new_driver->mdiodrv.driver.remove = phy_remove;
	new_driver->mdiodrv.driver.owner = owner;
	new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS;
	retval = driver_register(&new_driver->mdiodrv.driver);
	if (retval) {
		pr_err("%s: Error %d in registering driver\n",
		       new_driver->name, retval);
		return retval;
	}
	pr_debug("%s: Registered new driver\n", new_driver->name);
	return 0;
}
EXPORT_SYMBOL(phy_driver_register);
所以 phy 驱动注册部分主要做了如下工作:
1 创建 初始化 struct phy_driver
 2 设置struct phy_driver ,
 如所在的名为“mdio_bus” 的mdio_bus_type 总线
 如 匹配成功后的 probe()函数
 …
 3 注册 phy_driver

至此
 phy_driver注册成功了,那就差phy_device的注册。看代码就知道 phy_device的注册不依靠设备树,而是在GMAC控制器注册时候 在其中的mdiobus_register中会注册phy_device 。


















