AM335X+AR8031网卡驱动(一)

AM335X+AR8031网卡驱动(一)
最近项目中所使用的AR8031网卡总是会间断性的失去连接,为此,对AR8031的网卡驱动做了一些总结和分析,希望以此抛砖引玉,有更好的想法可以与大家一起在此分享交流。
AR8031介绍:
AR8031支持10/100/1000Mbps的传输速度,支持RGMII和SGNII,通过MDIO总线进行管理,定义了三类寄存器,分别是MII寄存器,debug寄存器,MDIO寄存器,例如如果想往MMD3的寄存器0写入数据0x8000,则需要经过如下几个步骤
1.写0x03到寄存器0xD,0xD=0x03,(function=address,设置器件地址)
2.写0x0到寄存器0xE,0xE=0x0,(设置寄存器的偏移地址)
3.写0x4003到寄存器0xD,0xD=0x4003,(function=data,保持设备的地址)
4.读寄存器0xE,0xE=来自MMD3的寄存器0的值
5.写0x8000到寄存器0xE,0xE=0x8000,(写0x8000到MMD3寄存器0中)
Mdio总线:
1.结构体:

struct mii_bus {
const char *name;
char id[MII_BUS_ID_SIZE];
void *priv;
int (*read)(struct mii_bus *bus, int phy_id, int regnum);
int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val);
int (*reset)(struct mii_bus bus);
/

* A lock to ensure that only one thing can read/write
* the MDIO bus at a time
*/
struct mutex mdio_lock;
struct device parent;
enum {
MDIOBUS_ALLOCATED = 1,
MDIOBUS_REGISTERED,
MDIOBUS_UNREGISTERED,
MDIOBUS_RELEASED,
} state;
struct device dev;
/
list of all PHYs on bus */
struct phy_device phy_map[PHY_MAX_ADDR];
/
PHY addresses to be ignored when probing /
u32 phy_mask;
/

* Pointer to an array of interrupts, each PHY’s
* interrupt at the index matching its address
*/
int *irq;
};
2.初始化:
int __init mdio_bus_init(void)
{
int ret;
ret = class_register(&mdio_bus_class);
if (!ret) {
ret = bus_register(&mdio_bus_type);
if (ret)
class_unregister(&mdio_bus_class);
}
}
3.设备类结构体
static struct class mdio_bus_class = {
.name = “mdio_bus”,
.dev_release = mdiobus_release,
};
4.总线类结构体:
struct bus_type mdio_bus_type = {
.name = “mdio_bus”,
.match = mdio_bus_match,
.pm = MDIO_BUS_PM_OPS,
};
5.mdio总线注册:
a.分配总线内存空间
struct mii_bus *mdiobus_alloc(void)
{
struct mii_bus *bus;
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (bus != NULL)
bus->state = MDIOBUS_ALLOCATED;
return bus;
}
b.注册mdio设备驱动
int mdiobus_register(struct mii_bus *bus)
{
int i, err;
if (NULL == bus || NULL == bus->name ||
NULL == bus->read ||
NULL == bus->write)
return -EINVAL;
BUG_ON(bus->state != MDIOBUS_ALLOCATED &&
bus->state != MDIOBUS_UNREGISTERED);
bus->dev.parent = bus->parent;
bus->dev.class = &mdio_bus_class;
bus->dev.groups = NULL;
dev_set_name(&bus->dev, “%s”, bus->id);
err = device_register(&bus->dev);
if (err) {
printk(KERN_ERR “mii_bus %s failed to register\n”, bus->id);
return -EINVAL;
}
mutex_init(&bus->mdio_lock);
if (bus->reset)
bus->reset(bus);
for (i = 0; i < PHY_MAX_ADDR; i++) {
if ((bus->phy_mask & (1 << i)) == 0) {
struct phy_device *phydev;
phydev = mdiobus_scan(bus, i);
if (IS_ERR(phydev)) {
err = PTR_ERR(phydev);
goto error;
}
}
}
bus->state = MDIOBUS_REGISTERED;
pr_info("%s: probed\n", bus->name);
return 0;
error:
while (–i >= 0) {
if (bus->phy_map[i])
device_unregister(&bus->phy_map[i]->dev);
}
device_del(&bus->dev);
return err;
}
重点是:mdiobus_scan(函数)
struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
{
struct phy_device *phydev;
int err;
phydev = get_phy_device(bus, addr);//先获取phy设备
if (IS_ERR(phydev) || phydev == NULL)
return phydev;
err = phy_device_register(phydev);//注册phy设备
if (err) {
phy_device_free(phydev);
return NULL;
}
return phydev;
}
下一节将对phy芯片AR8031的驱动进行讲解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值