博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MDIO总线相关_2
阅读量:4285 次
发布时间:2019-05-27

本文共 13161 字,大约阅读时间需要 43 分钟。

##这里主要是device端

在drivers/net/ethernet/中有各品牌的文件,一个品牌对应一个文件夹

一个文件夹下有多个文件,一个文件对应一个品牌下设备.

platform_driver_register(&smsc911x_driver)static struct platform_driver smsc911x_driver = {
.probe = smsc911x_drv_probe, .remove = smsc911x_drv_remove, .driver = {
.name = SMSC_CHIPNAME, .owner = THIS_MODULE, .pm = SMSC911X_PM_OPS, .of_match_table = of_match_ptr(smsc911x_dt_ids), },};

1/

smsc911x_drv_probe 一个设备对应一个文件

2/

smsc911x_drv_remove 一个设备对应一个文件

3/

.name	= SMSC_CHIPNAME "smsc911x"

4/

.pm	= SMSC911X_PM_OPS, 一个设备对应一系列操作

5/

static const struct of_device_id smsc911x_dt_ids[] = {
{
.compatible = "smsc,lan9115", }, {
/* sentinel */ }};

这个好像是platfrom里面的platform,应该和那个不对头.

估计是 phy_device,查找,果然有.但是找不到

继续分析这个

static struct platform_driver smsc911x_driver = {
.probe = smsc911x_drv_probe, .remove = smsc911x_drv_remove, .driver = {
.name = SMSC_CHIPNAME, .owner = THIS_MODULE, .pm = SMSC911X_PM_OPS, .of_match_table = of_match_ptr(smsc911x_dt_ids), },};/*** platform_match - bind platform device to platform driver.* @dev: device.* @drv: driver. ** Platform device IDs are assumed to be encoded like this:* "
", where
is a short description of the type of* device, like "pci" or "floppy", and
is the enumerated* instance of the device, like '0' or '42'. Driver IDs are simply* "
". So, extract the
from the platform_device structure,* and compare it against the name of the driver. Return whether they match* or not. */ static int platform_match(struct device *dev, struct device_driver *drv) { struct platform_device *pdev = to_platform_device(dev); struct platform_driver *pdrv = to_platform_driver(drv); /* Attempt an OF style match first */ if (of_driver_match_device(dev, drv)) return 1; /* Then try ACPI style match */ if (acpi_driver_match_device(dev, drv)) return 1; /* Then try to match against the id table */ if (pdrv->id_table) return platform_match_id(pdrv->id_table, pdev) != NULL; /* fall-back to driver name match */ return (strcmp(pdev->name, drv->name) == 0); }

不找platform了

我找到phy_device了

在drivers/of/of_mdio.c中

/***   of_mdiobus_register - Register mii_bus and create PHYs from the device tree    * @mdio: pointer to mii_bus *   @np: pointer to device_node of MDIO bus.     **   This function registers the mii_bus structure and registers a phy_device*   for each child node of @np.     */    int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)    {
struct phy_device *phy; struct device_node *child; const __be32 *paddr; u32 addr; bool is_c45, scanphys = false; int rc, i, len; /* Mask out all PHYs from auto probing. Instead the PHYs listed in * the device tree are populated after the bus has been registered */ mdio->phy_mask = ~0; /* Clear all the IRQ properties */ if (mdio->irq) for (i=0; i
irq[i] = PHY_POLL; mdio->dev.of_node = np; /* Register the MDIO bus */ rc = mdiobus_register(mdio); if (rc) return rc; /* Loop over the child nodes and register a phy_device for each one */ for_each_available_child_of_node(np, child) {
/* A PHY must have a reg property in the range [0-31] */ paddr = of_get_property(child, "reg", &len); if (!paddr || len < sizeof(*paddr)) {
scanphys = true; dev_err(&mdio->dev, "%s has invalid PHY address\n", child->full_name); continue; } addr = be32_to_cpup(paddr); if (addr >= 32) {
dev_err(&mdio->dev, "%s PHY address %i is too large\n", child->full_name, addr); continue; } if (mdio->irq) {
mdio->irq[addr] = irq_of_parse_and_map(child, 0); if (!mdio->irq[addr]) mdio->irq[addr] = PHY_POLL; } is_c45 = of_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); phy = get_phy_device(mdio, addr, is_c45); if (!phy || IS_ERR(phy)) {
dev_err(&mdio->dev, "cannot get PHY at address %i\n", addr); continue; } /* Associate the OF node with the device structure so it * can be looked up later */ of_node_get(child); phy->dev.of_node = child; /* All data is now stored in the phy struct; register it */ rc = phy_device_register(phy); if (rc) {
phy_device_free(phy); of_node_put(child); continue; } dev_dbg(&mdio->dev, "registered phy %s at address %i\n", child->name, addr); } if (!scanphys) return 0; /* auto scan for PHYs with empty reg property */ for_each_available_child_of_node(np, child) {
/* Skip PHYs with reg property set */ paddr = of_get_property(child, "reg", &len); if (paddr) continue; is_c45 = of_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
/* skip already registered PHYs */ if (mdio->phy_map[addr]) continue; /* be noisy to encourage people to set reg property */ dev_info(&mdio->dev, "scan phy %s at address %i\n", child->name, addr); phy = get_phy_device(mdio, addr, is_c45); if (!phy || IS_ERR(phy)) continue; if (mdio->irq) {
mdio->irq[addr] = irq_of_parse_and_map(child, 0); if (!mdio->irq[addr]) mdio->irq[addr] = PHY_POLL; } /* Associate the OF node with the device structure so it * can be looked up later */ of_node_get(child); phy->dev.of_node = child; /* All data is now stored in the phy struct; * register it */ rc = phy_device_register(phy); if (rc) {
phy_device_free(phy); of_node_put(child); continue; } dev_info(&mdio->dev, "registered phy %s at address %i\n", child->name, addr); break; } } return 0; } 其中paddr = of_get_property(child, "reg", &len); 其中addr = be32_to_cpup(paddr); 其中phy = get_phy_device(mdio, addr, is_c45);/*** 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* @is_c45: If true the PHY uses the 802.3 clause 45 protocol ** 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, bool is_c45) {
struct phy_c45_device_ids c45_ids = {
0}; struct phy_device *dev = NULL; u32 phy_id = 0; int r; r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids); if (r) return ERR_PTR(r); /* 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, is_c45, &c45_ids); return dev; }dev = phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);/*** 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* @is_c45: If true the PHY uses the 802.3 clause 45 protocol ** 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, bool is_c45) {
struct phy_c45_device_ids c45_ids = {
0}; struct phy_device *dev = NULL; u32 phy_id = 0; int r; r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids); if (r) return ERR_PTR(r); /* 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, is_c45, &c45_ids); return dev; }dev = phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, bool is_c45, struct phy_c45_device_ids *c45_ids){
struct phy_device *dev; /* We allocate the device, and initialize the * default values */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (NULL == dev) return (struct phy_device*) PTR_ERR((void*)-ENOMEM); dev->dev.release = phy_device_release; dev->speed = 0; dev->duplex = -1; dev->pause = dev->asym_pause = 0; dev->link = 1; dev->interface = PHY_INTERFACE_MODE_GMII; dev->autoneg = AUTONEG_ENABLE; dev->is_c45 = is_c45; dev->addr = addr; dev->phy_id = phy_id; if (c45_ids) dev->c45_ids = *c45_ids; dev->bus = bus; dev->dev.parent = bus->parent; dev->dev.bus = &mdio_bus_type; dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL; dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr); dev->state = PHY_DOWN; mutex_init(&dev->lock); INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); /* Request the appropriate module unconditionally; don't bother trying to do so only if it isn't already loaded, because that gets complicated. A hotplug event would have done an unconditional modprobe anyway. We don't do normal hotplug because it won't work for MDIO -- because it relies on the device staying around for long enough for the driver to get loaded. With MDIO, the NIC driver will get bored and give up as soon as it finds that there's no driver _already_ loaded. */ request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id)); device_initialize(&dev->dev); return dev;}

------------------然后分析最后一个函数

phy_device结构体/* phy_device: An instance of a PHY **   drv: Pointer to the driver for this PHY instance*   bus: Pointer to the bus this PHY is on*   dev: driver model device structure for this PHY*   phy_id: UID for this device found during discovery*   c45_ids: 802.3-c45 Device Identifers if is_c45.*   is_c45:  Set to true if this phy uses clause 45 addressing.*   state: state of the PHY for management purposes*   dev_flags: Device-specific flags used by the PHY driver.*   addr: Bus address of PHY*   link_timeout: The number of timer firings to wait before the*   giving up on the current attempt at acquiring a link*   irq: IRQ number of the PHY's interrupt (-1 if none)*   phy_timer: The timer for handling the state machine*   phy_queue: A work_queue for the interrupt*   attached_dev: The attached enet driver's device instance ptr*   adjust_link: Callback for the enet controller to respond to*   changes in the link state.*   adjust_state: Callback for the enet driver to respond to*   changes in the state machine.     **   speed, duplex, pause, supported, advertising, and*   autoneg are used like in mii_if_info     **   interrupts currently only supports enabled or disabled,*   but could be changed in the future to support enabling*   and disabling specific interrupts     **   Contains some infrastructure for polling and interrupt*   handling, as well as handling shifts in PHY hardware state     */    struct phy_device {
/* Information about the PHY type */ /* And management functions */ struct phy_driver *drv; struct mii_bus *bus; struct device dev; u32 phy_id; struct phy_c45_device_ids c45_ids; bool is_c45; enum phy_state state; u32 dev_flags; phy_interface_t interface; /* Bus address of the PHY (0-31) */ int addr; /* * forced speed & duplex (no autoneg) * partner speed & duplex & pause (autoneg) */ int speed; int duplex; int pause; int asym_pause; /* The most recently read link state */ int link; /* Enabled Interrupts */ u32 interrupts; /* Union of PHY and Attached devices' supported modes */ /* See mii.h for more info */ u32 supported; u32 advertising; int autoneg; int link_timeout; /* * Interrupt number for this PHY * -1 means no interrupt */ int irq; /* private data pointer */ /* For use by PHYs to maintain extra state */ void *priv; /* Interrupt and Polling infrastructure */ struct work_struct phy_queue; struct delayed_work state_queue; 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); };可以看到ID是get_phy_device函数给的 调用了get_phy_id得到的 r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids);

通过of_mdiobus_register找调用

Of_mdio.c (drivers\of): * of_mdiobus_register - Register mii_bus and create PHYs from the device treeOf_mdio.c (drivers\of):int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)Of_mdio.c (drivers\of):EXPORT_SYMBOL(of_mdiobus_register);Of_mdio.h (include\linux):extern int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np);Of_mdio.h (include\linux):static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)Mdio-gpio.c (drivers\net\phy):		ret = of_mdiobus_register(new_bus, pdev->dev.of_node);Mdio-mux.c (drivers\net\phy):		r = of_mdiobus_register(cb->mii_bus, child_bus_node);Mdio-octeon.c (drivers\net\phy):	err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);Mdio_bus.c (drivers\net\phy): * of_mdiobus_register(), the mii_bus cannot be found before it isMdio_bus.c (drivers\net\phy): * registered with of_mdiobus_register().应该不是上面的5行应该是下面的

转载地址:http://ivigi.baihongyu.com/

你可能感兴趣的文章
实战项目经验得到的常用linux命令(-)
查看>>
Mysql的设计规范和结构优化(-)
查看>>
查看是否安装mysql以及是否正在运行的mysql
查看>>
题目:在一个文件中有 10G 个整数,乱序排列,要求找出中位数。内存限制为 2G。只写出思路即可(内存限制为 2G的意思就是,可以使用2G的空间来运行程序,而不考虑这台机器上的其他软件的占用内存)。
查看>>
springboot注解中@controller和@restcontroller,以及@springbootApplication注解的区别和联系
查看>>
hbase 常用过滤器filter--------------------------有这篇文章就够了,舍我其谁!!!!
查看>>
【十问评估经营理念】
查看>>
Android调用天气预报的WebService简单例子
查看>>
出现An internal error occurred during: "Building workspace".的解决方法
查看>>
ext4.2入门简单小例子(button的事件--对话框的几种使用情况)
查看>>
nodejs:在windows系统中安装node.js 及第一个程序Hello World
查看>>
ExtJS 4.2心得和总结:布局系统详解(Ext.layout.container)
查看>>
数据结构几种排序算法详解和总结(java版)
查看>>
ExtJS4.2 登陆表单(Login)简单示例
查看>>
Node.js快速入门
查看>>
Node.js进行Web开发(一)--Express,路由控制,模板引擎
查看>>
阿里巴巴集团2014秋季校园招聘笔试题
查看>>
2014校园招聘_百度2014校园招聘
查看>>
2014校园招聘_华为2014校园招聘
查看>>
2014校园招聘_腾讯2014校园招聘
查看>>