X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/25b268205aa390668fa889ad3148b5054ca53bbd..69776356230d6afbb5017945e4053f98cabf6496:/target/linux/generic/files/drivers/net/phy/ar8216.c?ds=sidebyside diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 57088a974..1183cbc52 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -48,6 +48,8 @@ struct ar8216_priv { bool port4_phy; char buf[80]; + bool init; + /* all fields below are cleared on reset */ bool vlan; u16 vlan_id[AR8X16_MAX_VLANS]; @@ -75,14 +77,20 @@ static u32 ar8216_mii_read(struct ar8216_priv *priv, int reg) { struct phy_device *phy = priv->phy; + struct mii_bus *bus = phy->bus; u16 r1, r2, page; u16 lo, hi; split_addr((u32) reg, &r1, &r2, &page); - mdiobus_write(phy->bus, 0x18, 0, page); + + mutex_lock(&bus->mdio_lock); + + bus->write(bus, 0x18, 0, page); msleep(1); /* wait for the page switch to propagate */ - lo = mdiobus_read(phy->bus, 0x10 | r2, r1); - hi = mdiobus_read(phy->bus, 0x10 | r2, r1 + 1); + lo = bus->read(bus, 0x10 | r2, r1); + hi = bus->read(bus, 0x10 | r2, r1 + 1); + + mutex_unlock(&bus->mdio_lock); return (hi << 16) | lo; } @@ -91,17 +99,22 @@ static void ar8216_mii_write(struct ar8216_priv *priv, int reg, u32 val) { struct phy_device *phy = priv->phy; + struct mii_bus *bus = phy->bus; u16 r1, r2, r3; u16 lo, hi; split_addr((u32) reg, &r1, &r2, &r3); - mdiobus_write(phy->bus, 0x18, 0, r3); - msleep(1); /* wait for the page switch to propagate */ - lo = val & 0xffff; hi = (u16) (val >> 16); - mdiobus_write(phy->bus, 0x10 | r2, r1 + 1, hi); - mdiobus_write(phy->bus, 0x10 | r2, r1, lo); + + mutex_lock(&bus->mdio_lock); + + bus->write(bus, 0x18, 0, r3); + msleep(1); /* wait for the page switch to propagate */ + bus->write(bus, 0x10 | r2, r1 + 1, hi); + bus->write(bus, 0x10 | r2, r1, lo); + + mutex_unlock(&bus->mdio_lock); } static u32 @@ -550,7 +563,7 @@ ar8216_hw_apply(struct switch_dev *dev) ar8216_vtu_op(priv, AR8216_VTU_OP_FLUSH, 0); memset(portmask, 0, sizeof(portmask)); - if (priv->vlan) { + if (!priv->init) { /* calculate the port destination masks and load vlans * into the vlan translation unit */ for (j = 0; j < AR8X16_MAX_VLANS; j++) { @@ -630,10 +643,10 @@ ar8236_hw_init(struct ar8216_priv *priv) { /* Initialize the PHYs */ bus = priv->phy->bus; for (i = 0; i < 5; i++) { - bus->write(bus, i, MII_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | - ADVERTISE_PAUSE_ASYM); - bus->write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); + mdiobus_write(bus, i, MII_ADVERTISE, + ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); } msleep(1000); @@ -877,6 +890,8 @@ ar8216_config_init(struct phy_device *pdev) goto done; } + priv->init = true; + if (priv->chip == AR8316) { ret = ar8316_hw_init(priv); if (ret) { @@ -912,6 +927,8 @@ ar8216_config_init(struct phy_device *pdev) dev->netdev_ops = &priv->ndo; } + priv->init = false; + done: return ret; } @@ -987,7 +1004,7 @@ ar8216_remove(struct phy_device *pdev) static struct phy_driver ar8216_driver = { .phy_id = 0x004d0000, - .name = "Atheros AR8216/AR8316/AR8326", + .name = "Atheros AR8216/AR8236/AR8316", .phy_id_mask = 0xffff0000, .features = PHY_BASIC_FEATURES, .probe = ar8216_probe,