From: Chuanhong Guo Date: Thu, 10 Jan 2019 11:30:35 +0000 (+0800) Subject: generic: ar8216: add support for separated mdio bus for phy access X-Git-Tag: v19.07.0-rc1~956 X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fopenwrt.git;a=commitdiff_plain;h=cc817392f4ec9c3c3cc04bd95952cf9222fd8ad1;ds=sidebyside generic: ar8216: add support for separated mdio bus for phy access Atheros FE switches have a builtin mdio master available for PHY accessing and on ar724x/ar933x builtin switches this mdio master is the only way of accessing PHYs. After this patch if there is phy_read/phy_write method available in ar8xxx_chip we register a separated mdio bus for accessing PHYs. Still adds support for mdio device probing only since this isn't needed for those switches registered using PHY probing. Signed-off-by: Chuanhong Guo --- diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 85f7c2ab85..e1c3dc95c3 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -190,7 +190,7 @@ ar8xxx_phy_init(struct ar8xxx_priv *priv) int i; struct mii_bus *bus; - bus = priv->mii_bus; + bus = priv->sw_mii_bus ?: priv->mii_bus; for (i = 0; i < AR8XXX_NUM_PHYS; i++) { if (priv->chip->phy_fixup) priv->chip->phy_fixup(priv, i); @@ -1683,6 +1683,21 @@ ar8xxx_sw_set_flush_port_arl_table(struct switch_dev *dev, return ret; } +static int +ar8xxx_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr) +{ + struct ar8xxx_priv *priv = bus->priv; + return priv->chip->phy_read(priv, phy_addr, reg_addr); +} + +static int +ar8xxx_phy_write(struct mii_bus *bus, int phy_addr, int reg_addr, + u16 reg_val) +{ + struct ar8xxx_priv *priv = bus->priv; + return priv->chip->phy_write(priv, phy_addr, reg_addr, reg_val); +} + static const struct switch_attr ar8xxx_sw_attr_globals[] = { { .type = SWITCH_TYPE_INT, @@ -2471,6 +2486,7 @@ ar8xxx_mdiodev_probe(struct mdio_device *mdiodev) const struct of_device_id *match; struct ar8xxx_priv *priv; struct switch_dev *swdev; + struct device_node *mdio_node; int ret; match = of_match_device(ar8xxx_mdiodev_of_match, &mdiodev->dev); @@ -2493,6 +2509,21 @@ ar8xxx_mdiodev_probe(struct mdio_device *mdiodev) if (ret) goto free_priv; + if (priv->chip->phy_read && priv->chip->phy_write) { + priv->sw_mii_bus = devm_mdiobus_alloc(&mdiodev->dev); + priv->sw_mii_bus->name = "ar8xxx-mdio"; + priv->sw_mii_bus->read = ar8xxx_phy_read; + priv->sw_mii_bus->write = ar8xxx_phy_write; + priv->sw_mii_bus->priv = priv; + priv->sw_mii_bus->parent = &mdiodev->dev; + snprintf(priv->sw_mii_bus->id, MII_BUS_ID_SIZE, "%s", + dev_name(&mdiodev->dev)); + mdio_node = of_get_child_by_name(priv->pdev->of_node, "mdio-bus"); + ret = of_mdiobus_register(priv->sw_mii_bus, mdio_node); + if (ret) + goto free_priv; + } + swdev = &priv->dev; swdev->alias = dev_name(&mdiodev->dev); ret = register_switch(swdev, NULL); @@ -2548,6 +2579,8 @@ ar8xxx_mdiodev_remove(struct mdio_device *mdiodev) unregister_switch(&priv->dev); ar8xxx_mib_stop(priv); + if(priv->sw_mii_bus) + mdiobus_unregister(priv->sw_mii_bus); ar8xxx_free(priv); } diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.h b/target/linux/generic/files/drivers/net/phy/ar8216.h index 4d2d8b5dbd..0444bf7f22 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.h +++ b/target/linux/generic/files/drivers/net/phy/ar8216.h @@ -433,6 +433,8 @@ struct ar8xxx_chip { u32 *status, enum arl_op op); int (*sw_hw_apply)(struct switch_dev *dev); void (*phy_rgmii_set)(struct ar8xxx_priv *priv, struct phy_device *phydev); + int (*phy_read)(struct ar8xxx_priv *priv, int addr, int regnum); + int (*phy_write)(struct ar8xxx_priv *priv, int addr, int regnum, u16 val); const struct ar8xxx_mib_desc *mib_decs; unsigned num_mibs; @@ -442,6 +444,7 @@ struct ar8xxx_chip { struct ar8xxx_priv { struct switch_dev dev; struct mii_bus *mii_bus; + struct mii_bus *sw_mii_bus; struct phy_device *phy; struct device *pdev;