AM335X+AR8031网卡驱动(二)

AM335X+AR8031网卡驱动(二)
mdiobus_scan()函数中调用的两个关键函数,完成设备驱动的注册
/**

  • get_phy_device - reads the specified PHY device and returns its @phy_device struct

  • @bus: the target MII bus

  • @addr: PHY address on the MII bus

  • Description: Reads the ID registers of the PHY at @addr on the

  • @bus, then allocates and returns the phy_device to represent it.
    */
    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);
    if ®
    return ERR_PTR®;
    /
    If the phy_id is mostly Fs, there is no device there /
    if ((phy_id & 0x1fffffff) == 0x1fffffff)
    return NULL;
    dev = phy_device_create(bus, addr, phy_id);
    return dev;
    }
    此函数主要是获取phy_device设备,紧接着调用phy_device_register()函数注册设备。
    /

  • phy_device_register - Register the phy device on the MDIO bus

  • @phydev: phy_device structure to be added to the MDIO bus
    */
    int phy_device_register(struct phy_device *phydev)
    {
    int err;

    /* Don’t register a phy if one is already registered at this

    • address */
      if (phydev->bus->phy_map[phydev->addr])
      return -EINVAL;
      phydev->bus->phy_map[phydev->addr] = phydev;

    /* Run all of the fixups for this PHY */
    phy_scan_fixups(phydev);

    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;
}
ti公司的mdio平台总线驱动如下
static int __init davinci_mdio_init(void)
{
return platform_driver_register(&davinci_mdio_driver);
}
platform_driver 结构体中的操作集合
static struct platform_driver davinci_mdio_driver = {
.driver = {
.name = “davinci_mdio”,
.owner = THIS_MODULE,
.pm = &davinci_mdio_pm_ops,
},
.probe = davinci_mdio_probe,
.remove = __devexit_p(davinci_mdio_remove),
};
由davinci_mdio_probe函数完成平台总线驱动的调用
static int __devinit davinci_mdio_probe(struct platform_device *pdev)
{
struct mdio_platform_data *pdata = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
struct davinci_mdio_data *data;
struct resource *res;
struct phy_device *phy;
int ret, addr;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
dev_err(dev, “failed to alloc device data\n”);
return -ENOMEM;
}
data->pdata = pdata ? (pdata) : default_pdata;
data->bus = mdiobus_alloc();
if (!data->bus) {
dev_err(dev, “failed to alloc mii bus\n”);
ret = -ENOMEM;
goto bail_out;
}
data->bus->name = dev_name(dev);
data->bus->read = davinci_mdio_read,//读操作
data->bus->write = davinci_mdio_write,//写操作
data->bus->reset = davinci_mdio_reset,//复位操作

data->bus->parent = dev;
data->bus->priv = data;
snprintf(data->bus->id, MII_BUS_ID_SIZE, “%x”, pdev->id);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
data->clk = clk_get(&pdev->dev, “fck”);
if (IS_ERR(data->clk)) {
data->clk = NULL;
dev_err(dev, “failed to get device clock\n”);
ret = PTR_ERR(data->clk);
goto bail_out;
}
dev_set_drvdata(dev, data);
data->dev = dev;
spin_lock_init(&data->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, “could not find register map resource\n”);
ret = -ENOENT;
goto bail_out;
}
res = devm_request_mem_region(dev, res->start, resource_size(res),
dev_name(dev));
if (!res) {
dev_err(dev, “could not allocate register map resource\n”);
ret = -ENXIO;
goto bail_out;
}
data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!data->regs) {
dev_err(dev, “could not map mdio registers\n”);
ret = -ENOMEM;
goto bail_out;
}
/
register the mii bus /
ret = mdiobus_register(data->bus);//注册驱动
if (ret)
goto bail_out;
/
scan and dump the bus */
for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
phy = data->bus->phy_map[addr];
if (phy) {
dev_info(dev, “phy[%d]: device %s, driver %s\n”,
phy->addr, dev_name(&phy->dev),
phy->drv ? phy->drv->name : “unknown”);
}
}
return 0;
bail_out:
if (data->bus)
mdiobus_free(data->bus);
if (data->clk)
clk_put(data->clk);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
kfree(data);
return ret;
}
接下来将会继续对phy芯片驱动做进一步分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值