diff options
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/dp83640.c | 32 | ||||
-rw-r--r-- | drivers/net/phy/mdio-sun4i.c | 3 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 11 | ||||
-rw-r--r-- | drivers/net/phy/phy_device.c | 57 |
4 files changed, 64 insertions, 39 deletions
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 547725f..98e7cbf 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -437,7 +437,10 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp, if (on) { gpio_num = gpio_tab[EXTTS0_GPIO + index]; evnt |= (gpio_num & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT; - evnt |= EVNT_RISE; + if (rq->extts.flags & PTP_FALLING_EDGE) + evnt |= EVNT_FALL; + else + evnt |= EVNT_RISE; } ext_write(0, phydev, PAGE5, PTP_EVNT, evnt); return 0; @@ -1003,11 +1006,6 @@ static int dp83640_probe(struct phy_device *phydev) } else list_add_tail(&dp83640->list, &clock->phylist); - if (clock->chosen && !list_empty(&clock->phylist)) - recalibrate(clock); - else - enable_broadcast(dp83640->phydev, clock->page, 1); - dp83640_clock_put(clock); return 0; @@ -1058,6 +1056,21 @@ static void dp83640_remove(struct phy_device *phydev) kfree(dp83640); } +static int dp83640_config_init(struct phy_device *phydev) +{ + struct dp83640_private *dp83640 = phydev->priv; + struct dp83640_clock *clock = dp83640->clock; + + if (clock->chosen && !list_empty(&clock->phylist)) + recalibrate(clock); + else + enable_broadcast(phydev, clock->page, 1); + + enable_status_frames(phydev, true); + ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE); + return 0; +} + static int dp83640_ack_interrupt(struct phy_device *phydev) { int err = phy_read(phydev, MII_DP83640_MISR); @@ -1195,11 +1208,6 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) mutex_lock(&dp83640->clock->extreg_lock); - if (dp83640->hwts_tx_en || dp83640->hwts_rx_en) { - enable_status_frames(phydev, true); - ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE); - } - ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0); ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0); @@ -1281,6 +1289,7 @@ static void dp83640_txtstamp(struct phy_device *phydev, } /* fall through */ case HWTSTAMP_TX_ON: + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; skb_queue_tail(&dp83640->tx_queue, skb); schedule_work(&dp83640->ts_work); break; @@ -1330,6 +1339,7 @@ static struct phy_driver dp83640_driver = { .flags = PHY_HAS_INTERRUPT, .probe = dp83640_probe, .remove = dp83640_remove, + .config_init = dp83640_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, .ack_interrupt = dp83640_ack_interrupt, diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c index bb88bc7..9367acc 100644 --- a/drivers/net/phy/mdio-sun4i.c +++ b/drivers/net/phy/mdio-sun4i.c @@ -170,6 +170,9 @@ static int sun4i_mdio_remove(struct platform_device *pdev) } static const struct of_device_id sun4i_mdio_dt_ids[] = { + { .compatible = "allwinner,sun4i-a10-mdio" }, + + /* Deprecated */ { .compatible = "allwinner,sun4i-mdio" }, { } }; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 19c9eca..76d96b9 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -164,9 +164,9 @@ static const struct phy_setting settings[] = { * of that setting. Returns the index of the last setting if * none of the others match. */ -static inline int phy_find_setting(int speed, int duplex) +static inline unsigned int phy_find_setting(int speed, int duplex) { - int idx = 0; + unsigned int idx = 0; while (idx < ARRAY_SIZE(settings) && (settings[idx].speed != speed || settings[idx].duplex != duplex)) @@ -185,7 +185,7 @@ static inline int phy_find_setting(int speed, int duplex) * the mask in features. Returns the index of the last setting * if nothing else matches. */ -static inline int phy_find_valid(int idx, u32 features) +static inline unsigned int phy_find_valid(unsigned int idx, u32 features) { while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features)) idx++; @@ -204,7 +204,7 @@ static inline int phy_find_valid(int idx, u32 features) static void phy_sanitize_settings(struct phy_device *phydev) { u32 features = phydev->supported; - int idx; + unsigned int idx; /* Sanitize settings based on PHY capabilities */ if ((features & SUPPORTED_Autoneg) == 0) @@ -954,7 +954,8 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) (phydev->interface == PHY_INTERFACE_MODE_RGMII))) { int eee_lp, eee_cap, eee_adv; u32 lp, cap, adv; - int idx, status; + int status; + unsigned int idx; /* Read phy status to properly get the right settings */ status = phy_read_status(phydev); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 4b03e63..2f6989b 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -683,10 +683,9 @@ EXPORT_SYMBOL(phy_detach); int phy_suspend(struct phy_device *phydev) { struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver); - struct ethtool_wolinfo wol; + struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; /* If the device has WOL enabled, we cannot suspend the PHY */ - wol.cmd = ETHTOOL_GWOL; phy_ethtool_get_wol(phydev, &wol); if (wol.wolopts) return -EBUSY; @@ -719,7 +718,7 @@ int phy_resume(struct phy_device *phydev) static int genphy_config_advert(struct phy_device *phydev) { u32 advertise; - int oldadv, adv; + int oldadv, adv, bmsr; int err, changed = 0; /* Only allow advertising what this PHY supports */ @@ -744,26 +743,36 @@ static int genphy_config_advert(struct phy_device *phydev) changed = 1; } + bmsr = phy_read(phydev, MII_BMSR); + if (bmsr < 0) + return bmsr; + + /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all + * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a + * logical 1. + */ + if (!(bmsr & BMSR_ESTATEN)) + return changed; + /* Configure gigabit if it's supported */ + adv = phy_read(phydev, MII_CTRL1000); + if (adv < 0) + return adv; + + oldadv = adv; + adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); + if (phydev->supported & (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)) { - adv = phy_read(phydev, MII_CTRL1000); - if (adv < 0) - return adv; - - oldadv = adv; - adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); adv |= ethtool_adv_to_mii_ctrl1000_t(advertise); - - if (adv != oldadv) { - err = phy_write(phydev, MII_CTRL1000, adv); - - if (err < 0) - return err; + if (adv != oldadv) changed = 1; - } } + err = phy_write(phydev, MII_CTRL1000, adv); + if (err < 0) + return err; + return changed; } @@ -906,6 +915,8 @@ int genphy_read_status(struct phy_device *phydev) int err; int lpa; int lpagb = 0; + int common_adv; + int common_adv_gb = 0; /* Update the link, but return if there was an error */ err = genphy_update_link(phydev); @@ -927,7 +938,7 @@ int genphy_read_status(struct phy_device *phydev) phydev->lp_advertising = mii_stat1000_to_ethtool_lpa_t(lpagb); - lpagb &= adv << 2; + common_adv_gb = lpagb & adv << 2; } lpa = phy_read(phydev, MII_LPA); @@ -940,25 +951,25 @@ int genphy_read_status(struct phy_device *phydev) if (adv < 0) return adv; - lpa &= adv; + common_adv = lpa & adv; phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; phydev->pause = 0; phydev->asym_pause = 0; - if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { + if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) { phydev->speed = SPEED_1000; - if (lpagb & LPA_1000FULL) + if (common_adv_gb & LPA_1000FULL) phydev->duplex = DUPLEX_FULL; - } else if (lpa & (LPA_100FULL | LPA_100HALF)) { + } else if (common_adv & (LPA_100FULL | LPA_100HALF)) { phydev->speed = SPEED_100; - if (lpa & LPA_100FULL) + if (common_adv & LPA_100FULL) phydev->duplex = DUPLEX_FULL; } else - if (lpa & LPA_10FULL) + if (common_adv & LPA_10FULL) phydev->duplex = DUPLEX_FULL; if (phydev->duplex == DUPLEX_FULL) { |