summaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r--drivers/net/phy/phy.c177
1 files changed, 160 insertions, 17 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 60b5839b40..abd78b2c80 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -20,8 +20,6 @@
#include <linux/phy.h>
#include <linux/err.h>
-#define PHY_AN_TIMEOUT 10
-
static struct phy_driver genphy_driver;
/**
@@ -330,7 +328,7 @@ struct phy_device *of_phy_register_fixed_link(struct device_node *np,
static struct phy_device *of_mdio_find_phy(struct eth_device *edev)
{
- struct device_d *dev;
+ struct device *dev;
struct device_node *phy_node;
struct mii_bus *bus;
int addr;
@@ -338,16 +336,18 @@ static struct phy_device *of_mdio_find_phy(struct eth_device *edev)
if (!IS_ENABLED(CONFIG_OFDEVICE))
return NULL;
- if (!edev->parent || !edev->parent->device_node)
+ if (!edev->parent || !edev->parent->of_node)
return NULL;
- phy_node = of_parse_phandle(edev->parent->device_node, "phy-handle", 0);
+ phy_node = of_parse_phandle(edev->parent->of_node, "phy-handle", 0);
if (!phy_node)
- phy_node = of_parse_phandle(edev->parent->device_node, "phy", 0);
+ phy_node = of_parse_phandle(edev->parent->of_node, "phy", 0);
if (!phy_node)
- phy_node = of_parse_phandle(edev->parent->device_node, "phy-device", 0);
+ phy_node = of_parse_phandle(edev->parent->of_node,
+ "phy-device", 0);
if (!phy_node) {
- phy_node = of_get_child_by_name(edev->parent->device_node, "fixed-link");
+ phy_node = of_get_child_by_name(edev->parent->of_node,
+ "fixed-link");
if (phy_node)
return of_phy_register_fixed_link(phy_node, edev);
}
@@ -358,7 +358,7 @@ static struct phy_device *of_mdio_find_phy(struct eth_device *edev)
if (!of_property_read_u32(phy_node, "reg", &addr)) {
of_device_ensure_probed(phy_node->parent);
for_each_mii_bus(bus) {
- if (bus->parent->device_node == phy_node->parent) {
+ if (bus->dev.of_node == phy_node->parent) {
struct phy_device *phy = mdiobus_scan(bus, addr);
if (!IS_ERR(phy))
return phy;
@@ -367,7 +367,7 @@ static struct phy_device *of_mdio_find_phy(struct eth_device *edev)
}
bus_for_each_device(&mdio_bus_type, dev) {
- if (dev->device_node == phy_node)
+ if (dev->of_node == phy_node)
return container_of(dev, struct phy_device, dev);
}
@@ -462,7 +462,7 @@ int phy_device_connect(struct eth_device *edev, struct mii_bus *bus, int addr,
ret = -ENODEV;
out:
if (ret)
- puts("Unable to find a PHY (unknown ID?)\n");
+ dev_err(&edev->dev, "Unable to find a PHY (unknown ID?)\n");
return ret;
}
@@ -675,7 +675,7 @@ int genphy_aneg_done(struct phy_device *phydev)
/* Restart auto-negotiation if remote fault */
if (bmsr & BMSR_RFAULT) {
- puts("PHY remote fault detected\n"
+ dev_info(&phydev->dev, "PHY remote fault detected\n"
"PHY restarting auto-negotiation\n");
phy_write(phydev, MII_BMCR,
BMCR_ANENABLE | BMCR_ANRESTART);
@@ -819,14 +819,14 @@ int genphy_read_status(struct phy_device *phydev)
return 0;
}
-static inline void mmd_phy_indirect(struct phy_device *phydev, int prtad,
- int devad)
+static inline void mmd_phy_indirect(struct phy_device *phydev, int devad,
+ u16 regnum)
{
/* Write the desired MMD Devad */
phy_write(phydev, MII_MMD_CTRL, devad);
/* Write the desired MMD register address */
- phy_write(phydev, MII_MMD_DATA, prtad);
+ phy_write(phydev, MII_MMD_DATA, regnum);
/* Select the Function : DATA with no post increment */
phy_write(phydev, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
@@ -850,7 +850,10 @@ int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, int devad)
{
u32 ret;
- mmd_phy_indirect(phydev, prtad, devad);
+ phydev_warn(phydev, "%s is deprectated use phy_read_mmd instead\n",
+ __func__);
+
+ mmd_phy_indirect(phydev, devad, prtad);
/* Read the content of the MMD's selected register */
ret = phy_read(phydev, MII_MMD_DATA);
@@ -876,12 +879,150 @@ int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, int devad)
void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, int devad,
u16 data)
{
- mmd_phy_indirect(phydev, prtad, devad);
+ phydev_warn(phydev, "%s is deprectated use phy_write_mmd instead\n",
+ __func__);
+
+ mmd_phy_indirect(phydev, devad, prtad);
/* Write the data into MMD's selected register */
phy_write(phydev, MII_MMD_DATA, data);
}
+/**
+ * phy_modify_mmd_indirect - Convenience function for modifying a MMD register
+ * @phydev: phy device
+ * @prtad: MMD Address
+ * @devad: MMD DEVAD
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in @mask
+ *
+ */
+int phy_modify_mmd_indirect(struct phy_device *phydev, int prtad, int devad,
+ u16 mask, u16 set)
+{
+ int ret;
+
+ phydev_warn(phydev, "%s is deprectated use phy_modify_mmd instead\n",
+ __func__);
+
+ ret = phy_read_mmd_indirect(phydev, prtad, devad);
+ if (ret < 0)
+ return ret;
+
+ phy_write_mmd_indirect(phydev, prtad, devad, (ret & ~mask) | set);
+
+ return 0;
+}
+
+/**
+ * phy_read_mmd - Convenience function for reading a register
+ * from an MMD on a given PHY.
+ * @phydev: The phy_device struct
+ * @devad: The MMD to read from
+ * @regnum: The register on the MMD to read
+ *
+ * Same rules as for phy_read();
+ */
+int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
+{
+ struct mii_bus *bus = phydev->bus;
+ int phy_addr = phydev->addr;
+
+ if (regnum > (u16)~0 || devad > 32)
+ return -EINVAL;
+
+ if (phydev->is_c45) {
+ phydev_warn(phydev, "Clause45 is not supported yet\n");
+ return -EOPNOTSUPP;
+ }
+
+ mmd_phy_indirect(phydev, devad, regnum);
+
+ /* Read the content of the MMD's selected register */
+ return mdiobus_read(bus, phy_addr, MII_MMD_DATA);
+}
+EXPORT_SYMBOL(phy_read_mmd);
+
+/**
+ * phy_write_mmd - Convenience function for writing a register
+ * on an MMD on a given PHY.
+ * @phydev: The phy_device struct
+ * @devad: The MMD to read from
+ * @regnum: The register on the MMD to read
+ * @val: value to write to @regnum
+ *
+ * Same rules as for phy_write();
+ */
+int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
+{
+ struct mii_bus *bus = phydev->bus;
+ int phy_addr = phydev->addr;
+
+ if (regnum > (u16)~0 || devad > 32)
+ return -EINVAL;
+
+ if (phydev->is_c45) {
+ phydev_warn(phydev, "Clause45 is not supported yet\n");
+ return -EOPNOTSUPP;
+ }
+
+ mmd_phy_indirect(phydev, devad, regnum);
+
+ /* Write the data into MMD's selected register */
+ mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
+
+ return 0;
+}
+EXPORT_SYMBOL(phy_write_mmd);
+
+/**
+ * phy_modify_mmd_changed - Function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ *
+ * Returns negative errno, 0 if there was no change, and 1 in case of change
+ */
+int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int new, ret;
+
+ ret = phy_read_mmd(phydev, devad, regnum);
+ if (ret < 0)
+ return ret;
+
+ new = (ret & ~mask) | set;
+ if (new == ret)
+ return 0;
+
+ ret = phy_write_mmd(phydev, devad, regnum, new);
+
+ return ret < 0 ? ret : 1;
+}
+EXPORT_SYMBOL_GPL(phy_modify_mmd_changed);
+
+/**
+ * phy_modify_mmd - Convenience function for modifying a register on MMD
+ * @phydev: the phy_device struct
+ * @devad: the MMD containing register to modify
+ * @regnum: register number to modify
+ * @mask: bit mask of bits to clear
+ * @set: new value of bits set in mask to write to @regnum
+ */
+int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,
+ u16 mask, u16 set)
+{
+ int ret;
+
+ ret = phy_modify_mmd_changed(phydev, devad, regnum, mask, set);
+
+ return ret < 0 ? ret : 0;
+}
+EXPORT_SYMBOL_GPL(phy_modify_mmd);
+
int genphy_config_init(struct phy_device *phydev)
{
int val;
@@ -933,6 +1074,8 @@ int phy_driver_register(struct phy_driver *phydrv)
{
phydrv->drv.bus = &mdio_bus_type;
+ phydrv->is_phy = true;
+
if (!phydrv->config_init)
phydrv->config_init = genphy_config_init;