aboutsummaryrefslogtreecommitdiff
path: root/include/phy.h
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-05-08 22:46:31 -0400
committerTom Rini <trini@konsulko.com>2019-05-08 22:46:31 -0400
commiteb511984e90423dd3b5ee3a614f040fa353ee9aa (patch)
treedb02d1f61d07dc438bf6de99b1f681505e493007 /include/phy.h
parent504bf790da08db9b4a443566cf6ef577f9c7996a (diff)
parent6314d1c8c035d1c4d14ea1ffd133f25385edd067 (diff)
Merge branch 'master' of git://git.denx.de/u-boot-net
- Various PHY fixes / enhancements. - TI K2G fixes
Diffstat (limited to 'include/phy.h')
-rw-r--r--include/phy.h70
1 files changed, 70 insertions, 0 deletions
diff --git a/include/phy.h b/include/phy.h
index f23ca63f3b..d01435d1aa 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -101,6 +101,14 @@ struct phy_driver {
int (*readext)(struct phy_device *phydev, int addr, int devad, int reg);
int (*writeext)(struct phy_device *phydev, int addr, int devad, int reg,
u16 val);
+
+ /* Phy specific driver override for reading a MMD register */
+ int (*read_mmd)(struct phy_device *phydev, int devad, int reg);
+
+ /* Phy specific driver override for writing a MMD register */
+ int (*write_mmd)(struct phy_device *phydev, int devad, int reg,
+ u16 val);
+
struct list_head list;
};
@@ -165,6 +173,68 @@ static inline int phy_write(struct phy_device *phydev, int devad, int regnum,
return bus->write(bus, phydev->addr, devad, regnum, val);
}
+static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad,
+ int regnum)
+{
+ /* Write the desired MMD Devad */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad);
+
+ /* Write the desired MMD register address */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum);
+
+ /* Select the Function : DATA with no post increment */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL,
+ (devad | MII_MMD_CTRL_NOINCR));
+}
+
+static inline int phy_read_mmd(struct phy_device *phydev, int devad,
+ int regnum)
+{
+ struct phy_driver *drv = phydev->drv;
+
+ if (regnum > (u16)~0 || devad > 32)
+ return -EINVAL;
+
+ /* driver-specific access */
+ if (drv->read_mmd)
+ return drv->read_mmd(phydev, devad, regnum);
+
+ /* direct C45 / C22 access */
+ if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
+ devad == MDIO_DEVAD_NONE || !devad)
+ return phy_read(phydev, devad, regnum);
+
+ /* indirect C22 access */
+ phy_mmd_start_indirect(phydev, devad, regnum);
+
+ /* Read the content of the MMD's selected register */
+ return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA);
+}
+
+static inline int phy_write_mmd(struct phy_device *phydev, int devad,
+ int regnum, u16 val)
+{
+ struct phy_driver *drv = phydev->drv;
+
+ if (regnum > (u16)~0 || devad > 32)
+ return -EINVAL;
+
+ /* driver-specific access */
+ if (drv->write_mmd)
+ return drv->write_mmd(phydev, devad, regnum, val);
+
+ /* direct C45 / C22 access */
+ if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
+ devad == MDIO_DEVAD_NONE || !devad)
+ return phy_write(phydev, devad, regnum, val);
+
+ /* indirect C22 access */
+ phy_mmd_start_indirect(phydev, devad, regnum);
+
+ /* Write the data into MMD's selected register */
+ return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val);
+}
+
#ifdef CONFIG_PHYLIB_10G
extern struct phy_driver gen10g_driver;