一.结构体
1.PHY设备
struct phy_device {
struct phy_driver *drv; //PHY设备驱动
struct mii_bus *bus; //对应的MII总线
struct device dev; //设备文件
u32 phy_id; //PHY ID
enum phy_state state; //PHY状态
u32 dev_flags;
phy_interface_t interface; //PHY接口
int addr; //PHY 总线地址(0~31)
int speed; //速度
int duplex; //双工模式
int pause; //停止
int asym_pause; //
int link;
u32 interrupts; //中断使能标志
u32 supported;
u32 advertising;
int autoneg;
int link_timeout; //026
int irq; //中断号
void *priv; //私有数据
struct work_struct phy_queue; //PHY工作队列
struct delayed_work state_queue; //PHY延时工作队列
atomic_t irq_disable;
struct mutex lock;
struct net_device *attached_dev; //网络设备
void (*adjust_link)(struct net_device *dev);
void (*adjust_state)(struct net_device *dev);
};
2.PHY驱动
struct phy_driver {
u32 phy_id; //PHY ID
char *name; //PHY名
unsigned int phy_id_mask;
u32 features; //特性
u32 flags; //标记
int (*config_init)(struct phy_device *phydev); //配置初始化
int (*probe)(struct phy_device *phydev); //探测到 probe方法
int (*suspend)(struct phy_device *phydev); //唤醒
int (*resume)(struct phy_device *phydev); //挂起
int (*config_aneg)(struct phy_device *phydev); //支援(Auto-negotiation)配置
int (*read_status)(struct phy_device *phydev); //读支援(Auto-negotiation)状态
int (*ack_interrupt)(struct phy_device *phydev); //清中断
int (*config_intr)(struct phy_device *phydev); //使能/禁用 中断
int (*did_interrupt)(struct phy_device *phydev); //判断是否由中断
void (*remove)(struct phy_device *phydev); //移除
int (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr); //时间戳处理
bool (*rxtstamp)(struct phy_device *dev, struct sk_buff *skb, int type); //接收时间戳
void (*txtstamp)(struct phy_device *dev, struct sk_buff *skb, int type); //发送时间戳
struct device_driver driver; //设备驱动文件
};
二.设备与驱动的注册函数
1.注册PHY设备
int phy_device_register(struct phy_device *phydev)
{
int err;
if (phydev->bus->phy_map[phydev->addr]) //判断PHY是否已经给注册了
return -EINVAL;
phydev->bus->phy_map[phydev->addr] = phydev; //添加PHY到总线的phy_map里
phy_scan_fixups(phydev); //执行匹配的fixups
err = device_register(&phydev->dev); //注册设备
if (err) {
pr_err("phy %d failed to register\n", phydev->addr);
goto out;
}
return 0;
out:
phydev->bus->phy_map[phydev->addr] = NULL;
return err;
}
EXPORT_SYMBOL(phy_device_register);
PHY的设备一般是动态注册的在注册之前一般会调用get_phy_device函数
struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
{
struct phy_device *dev = NULL;
u32 phy_id;
int r;
r = get_phy_id(bus, addr, &phy_id); //获取PHY ID
if (r)
return ERR_PTR(r);
if ((phy_id & 0x1fffffff) == 0x1fffffff)
return NULL;
dev = phy_device_create(bus, addr, phy_id); //创建PHY设备
return dev;
}
EXPORT_SYMBOL(get_phy_device);
获取PHY ID
int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
{
int phy_reg;
//调用PHY的总线也就是mii总线的读方法获取PHY ID
phy_reg = bus->read(bus, addr, MII_PHYSID1); //获取PHYS ID1命令
if (phy_reg < 0)
return -EIO;
*phy_id = (phy_reg & 0xffff) << 16;
phy_reg = bus->read(bus, addr, MII_PHYSID2); //获取PHYS ID1命令
if (phy_reg < 0)
return -EIO;
*phy_id |= (phy_reg & 0xffff);
return 0;
}
EXPORT_SYMBOL(get_phy_id);
创建PHY设备