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);
}
}
+static int
+ar8216_phy_read(struct ar8xxx_priv *priv, int addr, int regnum)
+{
+ u32 t, val = 0xffff;
+ int err;
+
+ if (addr >= AR8216_NUM_PORTS)
+ return 0xffff;
+ t = (regnum << AR8216_MDIO_CTRL_REG_ADDR_S) |
+ (addr << AR8216_MDIO_CTRL_PHY_ADDR_S) |
+ AR8216_MDIO_CTRL_MASTER_EN |
+ AR8216_MDIO_CTRL_BUSY |
+ AR8216_MDIO_CTRL_CMD_READ;
+
+ ar8xxx_write(priv, AR8216_REG_MDIO_CTRL, t);
+ err = ar8xxx_reg_wait(priv, AR8216_REG_MDIO_CTRL,
+ AR8216_MDIO_CTRL_BUSY, 0, 5);
+ if (!err)
+ val = ar8xxx_read(priv, AR8216_REG_MDIO_CTRL);
+
+ return val & AR8216_MDIO_CTRL_DATA_M;
+}
+
+static int
+ar8216_phy_write(struct ar8xxx_priv *priv, int addr, int regnum, u16 val)
+{
+ u32 t;
+ int ret;
+
+ if (addr >= AR8216_NUM_PORTS)
+ return -EINVAL;
+
+ t = (addr << AR8216_MDIO_CTRL_PHY_ADDR_S) |
+ (regnum << AR8216_MDIO_CTRL_REG_ADDR_S) |
+ AR8216_MDIO_CTRL_MASTER_EN |
+ AR8216_MDIO_CTRL_BUSY |
+ AR8216_MDIO_CTRL_CMD_WRITE |
+ val;
+
+ ar8xxx_write(priv, AR8216_REG_MDIO_CTRL, t);
+ ret = ar8xxx_reg_wait(priv, AR8216_REG_MDIO_CTRL,
+ AR8216_MDIO_CTRL_BUSY, 0, 5);
+
+ return ret;
+}
+
static int
ar8229_hw_init(struct ar8xxx_priv *priv)
{
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,
.hw_init = ar8229_hw_init,
.init_globals = ar8229_init_globals,
.init_port = ar8229_init_port,
+ .phy_read = ar8216_phy_read,
+ .phy_write = ar8216_phy_write,
.setup_port = ar8236_setup_port,
.read_port_status = ar8216_read_port_status,
.atu_flush = ar8216_atu_flush,
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);
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);
+
+ if (of_property_read_bool(priv->pdev->of_node, "qca,phy4-mii-enable")) {
+ priv->port4_phy = true;
+ swdev->ports--;
+ }
+
ret = register_switch(swdev, NULL);
if (ret)
goto free_priv;
unregister_switch(&priv->dev);
ar8xxx_mib_stop(priv);
+ if(priv->sw_mii_bus)
+ mdiobus_unregister(priv->sw_mii_bus);
ar8xxx_free(priv);
}