summaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy_device.c
diff options
context:
space:
mode:
authorSascha Hauer2014-05-21 15:29:45 +0200
committerDavid S. Miller2014-05-22 21:43:02 +0200
commitde906af1cf8d5f2e9c461148577ac26dcdaea86e (patch)
tree4732496e85bf6845316ea9055605abf4b20dbda1 /drivers/net/phy/phy_device.c
parentnet: phy: genphy: Allow overwriting features (diff)
downloadkernel-qcow2-linux-de906af1cf8d5f2e9c461148577ac26dcdaea86e.tar.gz
kernel-qcow2-linux-de906af1cf8d5f2e9c461148577ac26dcdaea86e.tar.xz
kernel-qcow2-linux-de906af1cf8d5f2e9c461148577ac26dcdaea86e.zip
net: phy: make of_set_phy_supported work with genphy driver
of_set_phy_supported allows overwiting hardware capabilities of a phy with values from the devicetree. of_set_phy_supported is called right after phy_device_register in the assumption that phy_probe is called from phy_device_register and the features of the phy are already initialized. For the genphy driver this is not true, here phy_probe is called later during phy_connect time. phy_probe will then overwrite all settings done from of_set_phy_supported Fix this by moving of_set_phy_supported to the core phy code and calling it from phy_probe. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r--drivers/net/phy/phy_device.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index fc569eae7215..eb3b946bd8c0 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -33,6 +33,7 @@
#include <linux/mdio.h>
#include <linux/io.h>
#include <linux/uaccess.h>
+#include <linux/of.h>
#include <asm/irq.h>
@@ -1166,6 +1167,38 @@ static int gen10g_resume(struct phy_device *phydev)
return 0;
}
+static void of_set_phy_supported(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->dev.of_node;
+ u32 max_speed;
+
+ if (!IS_ENABLED(CONFIG_OF_MDIO))
+ return;
+
+ if (!node)
+ return;
+
+ if (!of_property_read_u32(node, "max-speed", &max_speed)) {
+ /* The default values for phydev->supported are provided by the PHY
+ * driver "features" member, we want to reset to sane defaults fist
+ * before supporting higher speeds.
+ */
+ phydev->supported &= PHY_DEFAULT_FEATURES;
+
+ switch (max_speed) {
+ default:
+ return;
+
+ case SPEED_1000:
+ phydev->supported |= PHY_1000BT_FEATURES;
+ case SPEED_100:
+ phydev->supported |= PHY_100BT_FEATURES;
+ case SPEED_10:
+ phydev->supported |= PHY_10BT_FEATURES;
+ }
+ }
+}
+
/**
* phy_probe - probe and init a PHY device
* @dev: device to probe and init
@@ -1200,7 +1233,8 @@ static int phy_probe(struct device *dev)
* or both of these values
*/
phydev->supported = phydrv->features;
- phydev->advertising = phydrv->features;
+ of_set_phy_supported(phydev);
+ phydev->advertising = phydev->supported;
/* Set the state to READY by default */
phydev->state = PHY_READY;