我们有一个嵌入式主板,其中以太网设备直接连接到交换机,两者之间没有phy.为了使事情变得更复杂,以太网设备的mdio总线连接到交换机的mdio进行控制.
我已设法使用固定的mdio/phy驱动程序启用以太网,并通过将交换机的默认配置与固定的phy匹配来工作.
我现在如何连接到mdio总线以更改开关设置?由于以太网设备附加的phy由固定的phy填充,我现在如何将真正的mdio总线连接到系统,以便我可以对其进行配置.似乎没有直接用户空间接口到mdio总线.我是否创建了一个假的以太网设备,其唯一目的是访问mdio总线或者以某种方式将它连接到以太网设备,然后将连接两个mdio总线?
PS:看起来物理mdio总线驱动程序找到了开关,但我该如何与它交谈?
该补丁允许我读取和写入系统中检测到的mdio设备中的所有寄存器.
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index dc92097..668150e 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -439,8 +439,85 @@ phy_id_show(struct device *dev, struct device_attribute *attr, char *buf) return sprintf(buf, "0x%.8lx\n", (unsigned long)phydev->phy_id); } +static ssize_t +mdio_reg_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct phy_device *phydev = to_phy_device(dev); + struct mii_bus* bus = phydev->bus; + int regnum; + int val; + + if (sscanf(attr->attr.name, "%d", ®num) != 1) + return -EINVAL; + + val = mdiobus_read(bus, phydev->addr, regnum); + if (val < 0) + return -EIO; + + return sprintf(buf, "0x%.4x\n", val); +} + +static ssize_t +mdio_reg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + struct phy_device *phydev = to_phy_device(dev); + struct mii_bus* bus = phydev->bus; + int regnum; + int val; + int err; + + if (sscanf(attr->attr.name, "%d", ®num) != 1) + return -EINVAL; + + if (sscanf(buf, "%d", &val) != 1) + return -EINVAL; + + if (val < 0 || val > 0xffff) + return -EINVAL; + + err = mdiobus_write(bus, phydev->addr, regnum, val); + if (err < 0) + return -EIO; + + return size; +} + +#define MDIO_REG(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), mdio_reg_show, mdio_reg_store) + static struct device_attribute mdio_dev_attrs[] = { __ATTR_RO(phy_id), + MDIO_REG(0), + MDIO_REG(1), + MDIO_REG(2), + MDIO_REG(3), + MDIO_REG(4), + MDIO_REG(5), + MDIO_REG(6), + MDIO_REG(7), + MDIO_REG(8), + MDIO_REG(9), + MDIO_REG(10), + MDIO_REG(11), + MDIO_REG(12), + MDIO_REG(13), + MDIO_REG(14), + MDIO_REG(15), + MDIO_REG(16), + MDIO_REG(17), + MDIO_REG(18), + MDIO_REG(19), + MDIO_REG(20), + MDIO_REG(21), + MDIO_REG(22), + MDIO_REG(23), + MDIO_REG(24), + MDIO_REG(25), + MDIO_REG(26), + MDIO_REG(27), + MDIO_REG(28), + MDIO_REG(29), + MDIO_REG(30), + MDIO_REG(31), __ATTR_NULL };
它扩展了已经存在的sysfs接口,每个mdio设备可以包含32个寄存器地址.由于mdio设备不是物理设备,因此它们不遵循phy标准,因此我不得不破解phy检测以允许所有设备出现:
--- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -339,9 +339,12 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45) if (r) return ERR_PTR(r); + /* BRM: this is patently not the case for our marvell switch */ +#if 0 /* If the phy_id is mostly Fs, there is no device there */ if ((phy_id & 0x1fffffff) == 0x1fffffff) return NULL; +#endif dev = phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);
希望这对其他人有帮助.