]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - drivers/net/phy/marvell.c
net: phy: marvell: mv88e6390 temperature sensor reading
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / phy / marvell.c
index 82104edca393b9b6662a18ef8ea0bdd8d3bb057d..22d9bc9c33a4bce864505babe6b3060348542a62 100644 (file)
@@ -83,7 +83,7 @@
 #define MII_88E1121_PHY_MSCR_REG       21
 #define MII_88E1121_PHY_MSCR_RX_DELAY  BIT(5)
 #define MII_88E1121_PHY_MSCR_TX_DELAY  BIT(4)
-#define MII_88E1121_PHY_MSCR_DELAY_MASK        (~(BIT(5) | BIT(4)))
+#define MII_88E1121_PHY_MSCR_DELAY_MASK        (BIT(5) | BIT(4))
 
 #define MII_88E1121_MISC_TEST                          0x1a
 #define MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK      0x1f00
 #define MII_88E1510_TEMP_SENSOR                0x1b
 #define MII_88E1510_TEMP_SENSOR_MASK   0xff
 
+#define MII_88E6390_MISC_TEST          0x1b
+#define MII_88E6390_MISC_TEST_SAMPLE_1S                0
+#define MII_88E6390_MISC_TEST_SAMPLE_10MS      BIT(14)
+#define MII_88E6390_MISC_TEST_SAMPLE_DISABLE   BIT(15)
+#define MII_88E6390_MISC_TEST_SAMPLE_ENABLE    0
+#define MII_88E6390_MISC_TEST_SAMPLE_MASK      (0x3 << 14)
+
+#define MII_88E6390_TEMP_SENSOR                0x1c
+#define MII_88E6390_TEMP_SENSOR_MASK   0xff
+#define MII_88E6390_TEMP_SENSOR_SAMPLES 10
+
 #define MII_88E1318S_PHY_MSCR1_REG     16
 #define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6)
 
@@ -177,27 +188,19 @@ struct marvell_priv {
        struct device *hwmon_dev;
 };
 
-static int marvell_get_page(struct phy_device *phydev)
+static int marvell_read_page(struct phy_device *phydev)
 {
-       return phy_read(phydev, MII_MARVELL_PHY_PAGE);
+       return __phy_read(phydev, MII_MARVELL_PHY_PAGE);
 }
 
-static int marvell_set_page(struct phy_device *phydev, int page)
+static int marvell_write_page(struct phy_device *phydev, int page)
 {
-       return phy_write(phydev, MII_MARVELL_PHY_PAGE, page);
+       return __phy_write(phydev, MII_MARVELL_PHY_PAGE, page);
 }
 
-static int marvell_get_set_page(struct phy_device *phydev, int page)
+static int marvell_set_page(struct phy_device *phydev, int page)
 {
-       int oldpage = marvell_get_page(phydev);
-
-       if (oldpage < 0)
-               return oldpage;
-
-       if (page != oldpage)
-               return marvell_set_page(phydev, page);
-
-       return 0;
+       return phy_write(phydev, MII_MARVELL_PHY_PAGE, page);
 }
 
 static int marvell_ack_interrupt(struct phy_device *phydev)
@@ -399,7 +402,7 @@ static int m88e1111_config_aneg(struct phy_device *phydev)
 static int marvell_of_reg_init(struct phy_device *phydev)
 {
        const __be32 *paddr;
-       int len, i, saved_page, current_page, ret;
+       int len, i, saved_page, current_page, ret = 0;
 
        if (!phydev->mdio.dev.of_node)
                return 0;
@@ -409,12 +412,11 @@ static int marvell_of_reg_init(struct phy_device *phydev)
        if (!paddr || len < (4 * sizeof(*paddr)))
                return 0;
 
-       saved_page = marvell_get_page(phydev);
+       saved_page = phy_save_page(phydev);
        if (saved_page < 0)
-               return saved_page;
+               goto err;
        current_page = saved_page;
 
-       ret = 0;
        len /= sizeof(*paddr);
        for (i = 0; i < len - 3; i += 4) {
                u16 page = be32_to_cpup(paddr + i);
@@ -425,14 +427,14 @@ static int marvell_of_reg_init(struct phy_device *phydev)
 
                if (page != current_page) {
                        current_page = page;
-                       ret = marvell_set_page(phydev, page);
+                       ret = marvell_write_page(phydev, page);
                        if (ret < 0)
                                goto err;
                }
 
                val = 0;
                if (mask) {
-                       val = phy_read(phydev, reg);
+                       val = __phy_read(phydev, reg);
                        if (val < 0) {
                                ret = val;
                                goto err;
@@ -441,17 +443,12 @@ static int marvell_of_reg_init(struct phy_device *phydev)
                }
                val |= val_bits;
 
-               ret = phy_write(phydev, reg, val);
+               ret = __phy_write(phydev, reg, val);
                if (ret < 0)
                        goto err;
        }
 err:
-       if (current_page != saved_page) {
-               i = marvell_set_page(phydev, saved_page);
-               if (ret == 0)
-                       ret = i;
-       }
-       return ret;
+       return phy_restore_page(phydev, saved_page, ret);
 }
 #else
 static int marvell_of_reg_init(struct phy_device *phydev)
@@ -462,34 +459,21 @@ static int marvell_of_reg_init(struct phy_device *phydev)
 
 static int m88e1121_config_aneg_rgmii_delays(struct phy_device *phydev)
 {
-       int err, oldpage, mscr;
-
-       oldpage = marvell_get_set_page(phydev, MII_MARVELL_MSCR_PAGE);
-       if (oldpage < 0)
-               return oldpage;
-
-       mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG);
-       if (mscr < 0) {
-               err = mscr;
-               goto out;
-       }
-
-       mscr &= MII_88E1121_PHY_MSCR_DELAY_MASK;
+       int mscr;
 
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
-               mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
-                        MII_88E1121_PHY_MSCR_TX_DELAY);
+               mscr MII_88E1121_PHY_MSCR_RX_DELAY |
+                      MII_88E1121_PHY_MSCR_TX_DELAY;
        else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
-               mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
+               mscr = MII_88E1121_PHY_MSCR_RX_DELAY;
        else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
-               mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
-
-       err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
-
-out:
-       marvell_set_page(phydev, oldpage);
+               mscr = MII_88E1121_PHY_MSCR_TX_DELAY;
+       else
+               mscr = 0;
 
-       return err;
+       return phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
+                               MII_88E1121_PHY_MSCR_REG,
+                               MII_88E1121_PHY_MSCR_DELAY_MASK, mscr);
 }
 
 static int m88e1121_config_aneg(struct phy_device *phydev)
@@ -498,7 +482,7 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
 
        if (phy_interface_is_rgmii(phydev)) {
                err = m88e1121_config_aneg_rgmii_delays(phydev);
-               if (err)
+               if (err < 0)
                        return err;
        }
 
@@ -515,20 +499,11 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
 
 static int m88e1318_config_aneg(struct phy_device *phydev)
 {
-       int err, oldpage, mscr;
-
-       oldpage = marvell_get_set_page(phydev, MII_MARVELL_MSCR_PAGE);
-       if (oldpage < 0)
-               return oldpage;
-
-       mscr = phy_read(phydev, MII_88E1318S_PHY_MSCR1_REG);
-       mscr |= MII_88E1318S_PHY_MSCR1_PAD_ODD;
-
-       err = phy_write(phydev, MII_88E1318S_PHY_MSCR1_REG, mscr);
-       if (err < 0)
-               return err;
+       int err;
 
-       err = marvell_set_page(phydev, oldpage);
+       err = phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
+                              MII_88E1318S_PHY_MSCR1_REG,
+                              0, MII_88E1318S_PHY_MSCR1_PAD_ODD);
        if (err < 0)
                return err;
 
@@ -700,19 +675,14 @@ static int m88e1116r_config_init(struct phy_device *phydev)
 
 static int m88e3016_config_init(struct phy_device *phydev)
 {
-       int reg;
+       int ret;
 
        /* Enable Scrambler and Auto-Crossover */
-       reg = phy_read(phydev, MII_88E3016_PHY_SPEC_CTRL);
-       if (reg < 0)
-               return reg;
-
-       reg &= ~MII_88E3016_DISABLE_SCRAMBLER;
-       reg |= MII_88E3016_AUTO_MDIX_CROSSOVER;
-
-       reg = phy_write(phydev, MII_88E3016_PHY_SPEC_CTRL, reg);
-       if (reg < 0)
-               return reg;
+       ret = phy_modify(phydev, MII_88E3016_PHY_SPEC_CTRL,
+                        MII_88E3016_DISABLE_SCRAMBLER,
+                        MII_88E3016_AUTO_MDIX_CROSSOVER);
+       if (ret < 0)
+               return ret;
 
        return marvell_config_init(phydev);
 }
@@ -721,42 +691,33 @@ static int m88e1111_config_init_hwcfg_mode(struct phy_device *phydev,
                                           u16 mode,
                                           int fibre_copper_auto)
 {
-       int temp;
-
-       temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
-       if (temp < 0)
-               return temp;
-
-       temp &= ~(MII_M1111_HWCFG_MODE_MASK |
-                 MII_M1111_HWCFG_FIBER_COPPER_AUTO |
-                 MII_M1111_HWCFG_FIBER_COPPER_RES);
-       temp |= mode;
-
        if (fibre_copper_auto)
-               temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
+               mode |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
 
-       return phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+       return phy_modify(phydev, MII_M1111_PHY_EXT_SR,
+                         MII_M1111_HWCFG_MODE_MASK |
+                         MII_M1111_HWCFG_FIBER_COPPER_AUTO |
+                         MII_M1111_HWCFG_FIBER_COPPER_RES,
+                         mode);
 }
 
 static int m88e1111_config_init_rgmii_delays(struct phy_device *phydev)
 {
-       int temp;
-
-       temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
-       if (temp < 0)
-               return temp;
+       int delay;
 
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
-               temp |= (MII_M1111_RGMII_RX_DELAY | MII_M1111_RGMII_TX_DELAY);
+               delay = MII_M1111_RGMII_RX_DELAY | MII_M1111_RGMII_TX_DELAY;
        } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
-               temp &= ~MII_M1111_RGMII_TX_DELAY;
-               temp |= MII_M1111_RGMII_RX_DELAY;
+               delay = MII_M1111_RGMII_RX_DELAY;
        } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
-               temp &= ~MII_M1111_RGMII_RX_DELAY;
-               temp |= MII_M1111_RGMII_TX_DELAY;
+               delay = MII_M1111_RGMII_TX_DELAY;
+       } else {
+               delay = 0;
        }
 
-       return phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
+       return phy_modify(phydev, MII_M1111_PHY_EXT_CR,
+                         MII_M1111_RGMII_RX_DELAY | MII_M1111_RGMII_TX_DELAY,
+                         delay);
 }
 
 static int m88e1111_config_init_rgmii(struct phy_device *phydev)
@@ -802,7 +763,7 @@ static int m88e1111_config_init_rtbi(struct phy_device *phydev)
        int err;
 
        err = m88e1111_config_init_rgmii_delays(phydev);
-       if (err)
+       if (err < 0)
                return err;
 
        err = m88e1111_config_init_hwcfg_mode(
@@ -829,7 +790,7 @@ static int m88e1111_config_init(struct phy_device *phydev)
 
        if (phy_interface_is_rgmii(phydev)) {
                err = m88e1111_config_init_rgmii(phydev);
-               if (err)
+               if (err < 0)
                        return err;
        }
 
@@ -854,20 +815,15 @@ static int m88e1111_config_init(struct phy_device *phydev)
 
 static int m88e1121_config_init(struct phy_device *phydev)
 {
-       int err, oldpage;
-
-       oldpage = marvell_get_set_page(phydev, MII_MARVELL_LED_PAGE);
-       if (oldpage < 0)
-               return oldpage;
+       int err;
 
        /* Default PHY LED config: LED[0] .. Link, LED[1] .. Activity */
-       err = phy_write(phydev, MII_88E1121_PHY_LED_CTRL,
-                       MII_88E1121_PHY_LED_DEF);
+       err = phy_write_paged(phydev, MII_MARVELL_LED_PAGE,
+                             MII_88E1121_PHY_LED_CTRL,
+                             MII_88E1121_PHY_LED_DEF);
        if (err < 0)
                return err;
 
-       marvell_set_page(phydev, oldpage);
-
        /* Set marvell,reg-init configuration from device tree */
        return marvell_config_init(phydev);
 }
@@ -875,7 +831,6 @@ static int m88e1121_config_init(struct phy_device *phydev)
 static int m88e1510_config_init(struct phy_device *phydev)
 {
        int err;
-       int temp;
 
        /* SGMII-to-Copper mode initialization */
        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
@@ -887,16 +842,15 @@ static int m88e1510_config_init(struct phy_device *phydev)
                        return err;
 
                /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */
-               temp = phy_read(phydev, MII_88E1510_GEN_CTRL_REG_1);
-               temp &= ~MII_88E1510_GEN_CTRL_REG_1_MODE_MASK;
-               temp |= MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII;
-               err = phy_write(phydev, MII_88E1510_GEN_CTRL_REG_1, temp);
+               err = phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1,
+                                MII_88E1510_GEN_CTRL_REG_1_MODE_MASK,
+                                MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII);
                if (err < 0)
                        return err;
 
                /* PHY reset is necessary after changing MODE[2:0] */
-               temp |= MII_88E1510_GEN_CTRL_REG_1_RESET;
-               err = phy_write(phydev, MII_88E1510_GEN_CTRL_REG_1, temp);
+               err = phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1, 0,
+                                MII_88E1510_GEN_CTRL_REG_1_RESET);
                if (err < 0)
                        return err;
 
@@ -1002,7 +956,6 @@ static int m88e1149_config_init(struct phy_device *phydev)
 
 static int m88e1145_config_init_rgmii(struct phy_device *phydev)
 {
-       int temp;
        int err;
 
        err = m88e1111_config_init_rgmii_delays(phydev);
@@ -1014,15 +967,9 @@ static int m88e1145_config_init_rgmii(struct phy_device *phydev)
                if (err < 0)
                        return err;
 
-               temp = phy_read(phydev, 0x1e);
-               if (temp < 0)
-                       return temp;
-
-               temp &= 0xf03f;
-               temp |= 2 << 9; /* 36 ohm */
-               temp |= 2 << 6; /* 39 ohm */
-
-               err = phy_write(phydev, 0x1e, temp);
+               err = phy_modify(phydev, 0x1e, 0x0fc0,
+                                2 << 9 | /* 36 ohm */
+                                2 << 6); /* 39 ohm */
                if (err < 0)
                        return err;
 
@@ -1398,100 +1345,98 @@ static int m88e1121_did_interrupt(struct phy_device *phydev)
 static void m88e1318_get_wol(struct phy_device *phydev,
                             struct ethtool_wolinfo *wol)
 {
+       int oldpage, ret = 0;
+
        wol->supported = WAKE_MAGIC;
        wol->wolopts = 0;
 
-       if (marvell_set_page(phydev, MII_MARVELL_WOL_PAGE) < 0)
-               return;
+       oldpage = phy_select_page(phydev, MII_MARVELL_WOL_PAGE);
+       if (oldpage < 0)
+               goto error;
 
-       if (phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL) &
-           MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE)
+       ret = __phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
+       if (ret & MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE)
                wol->wolopts |= WAKE_MAGIC;
 
-       if (marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE) < 0)
-               return;
+error:
+       phy_restore_page(phydev, oldpage, ret);
 }
 
 static int m88e1318_set_wol(struct phy_device *phydev,
                            struct ethtool_wolinfo *wol)
 {
-       int err, oldpage, temp;
+       int err = 0, oldpage;
 
-       oldpage = marvell_get_page(phydev);
+       oldpage = phy_save_page(phydev);
+       if (oldpage < 0)
+               goto error;
 
        if (wol->wolopts & WAKE_MAGIC) {
                /* Explicitly switch to page 0x00, just to be sure */
-               err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
+               err = marvell_write_page(phydev, MII_MARVELL_COPPER_PAGE);
                if (err < 0)
-                       return err;
+                       goto error;
 
                /* Enable the WOL interrupt */
-               temp = phy_read(phydev, MII_88E1318S_PHY_CSIER);
-               temp |= MII_88E1318S_PHY_CSIER_WOL_EIE;
-               err = phy_write(phydev, MII_88E1318S_PHY_CSIER, temp);
+               err = __phy_modify(phydev, MII_88E1318S_PHY_CSIER, 0,
+                                  MII_88E1318S_PHY_CSIER_WOL_EIE);
                if (err < 0)
-                       return err;
+                       goto error;
 
-               err = marvell_set_page(phydev, MII_MARVELL_LED_PAGE);
+               err = marvell_write_page(phydev, MII_MARVELL_LED_PAGE);
                if (err < 0)
-                       return err;
+                       goto error;
 
                /* Setup LED[2] as interrupt pin (active low) */
-               temp = phy_read(phydev, MII_88E1318S_PHY_LED_TCR);
-               temp &= ~MII_88E1318S_PHY_LED_TCR_FORCE_INT;
-               temp |= MII_88E1318S_PHY_LED_TCR_INTn_ENABLE;
-               temp |= MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW;
-               err = phy_write(phydev, MII_88E1318S_PHY_LED_TCR, temp);
+               err = __phy_modify(phydev, MII_88E1318S_PHY_LED_TCR,
+                                  MII_88E1318S_PHY_LED_TCR_FORCE_INT,
+                                  MII_88E1318S_PHY_LED_TCR_INTn_ENABLE |
+                                  MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW);
                if (err < 0)
-                       return err;
+                       goto error;
 
-               err = marvell_set_page(phydev, MII_MARVELL_WOL_PAGE);
+               err = marvell_write_page(phydev, MII_MARVELL_WOL_PAGE);
                if (err < 0)
-                       return err;
+                       goto error;
 
                /* Store the device address for the magic packet */
-               err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD2,
+               err = __phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD2,
                                ((phydev->attached_dev->dev_addr[5] << 8) |
                                 phydev->attached_dev->dev_addr[4]));
                if (err < 0)
-                       return err;
-               err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD1,
+                       goto error;
+               err = __phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD1,
                                ((phydev->attached_dev->dev_addr[3] << 8) |
                                 phydev->attached_dev->dev_addr[2]));
                if (err < 0)
-                       return err;
-               err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD0,
+                       goto error;
+               err = __phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD0,
                                ((phydev->attached_dev->dev_addr[1] << 8) |
                                 phydev->attached_dev->dev_addr[0]));
                if (err < 0)
-                       return err;
+                       goto error;
 
                /* Clear WOL status and enable magic packet matching */
-               temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
-               temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS;
-               temp |= MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE;
-               err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp);
+               err = __phy_modify(phydev, MII_88E1318S_PHY_WOL_CTRL, 0,
+                                  MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS |
+                                  MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE);
                if (err < 0)
-                       return err;
+                       goto error;
        } else {
-               err = marvell_set_page(phydev, MII_MARVELL_WOL_PAGE);
+               err = marvell_write_page(phydev, MII_MARVELL_WOL_PAGE);
                if (err < 0)
-                       return err;
+                       goto error;
 
                /* Clear WOL status and disable magic packet matching */
-               temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
-               temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS;
-               temp &= ~MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE;
-               err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp);
+               err = __phy_modify(phydev, MII_88E1318S_PHY_WOL_CTRL,
+                                  MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE,
+                                  MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS);
                if (err < 0)
-                       return err;
+                       goto error;
        }
 
-       err = marvell_set_page(phydev, oldpage);
-       if (err < 0)
-               return err;
-
-       return 0;
+error:
+       return phy_restore_page(phydev, oldpage, err);
 }
 
 static int marvell_get_sset_count(struct phy_device *phydev)
@@ -1519,14 +1464,10 @@ static u64 marvell_get_stat(struct phy_device *phydev, int i)
 {
        struct marvell_hw_stat stat = marvell_hw_stats[i];
        struct marvell_priv *priv = phydev->priv;
-       int oldpage, val;
+       int val;
        u64 ret;
 
-       oldpage = marvell_get_set_page(phydev, stat.page);
-       if (oldpage < 0)
-               return UINT64_MAX;
-
-       val = phy_read(phydev, stat.reg);
+       val = phy_read_paged(phydev, stat.page, stat.reg);
        if (val < 0) {
                ret = UINT64_MAX;
        } else {
@@ -1535,8 +1476,6 @@ static u64 marvell_get_stat(struct phy_device *phydev, int i)
                ret = priv->stats[i];
        }
 
-       marvell_set_page(phydev, oldpage);
-
        return ret;
 }
 
@@ -1553,51 +1492,44 @@ static void marvell_get_stats(struct phy_device *phydev,
 static int m88e1121_get_temp(struct phy_device *phydev, long *temp)
 {
        int oldpage;
-       int ret;
+       int ret = 0;
        int val;
 
        *temp = 0;
 
-       mutex_lock(&phydev->lock);
-
-       oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
-       if (oldpage < 0) {
-               mutex_unlock(&phydev->lock);
-               return oldpage;
-       }
+       oldpage = phy_select_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
+       if (oldpage < 0)
+               goto error;
 
        /* Enable temperature sensor */
-       ret = phy_read(phydev, MII_88E1121_MISC_TEST);
+       ret = __phy_read(phydev, MII_88E1121_MISC_TEST);
        if (ret < 0)
                goto error;
 
-       ret = phy_write(phydev, MII_88E1121_MISC_TEST,
-                       ret | MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
+       ret = __phy_write(phydev, MII_88E1121_MISC_TEST,
+                         ret | MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
        if (ret < 0)
                goto error;
 
        /* Wait for temperature to stabilize */
        usleep_range(10000, 12000);
 
-       val = phy_read(phydev, MII_88E1121_MISC_TEST);
+       val = __phy_read(phydev, MII_88E1121_MISC_TEST);
        if (val < 0) {
                ret = val;
                goto error;
        }
 
        /* Disable temperature sensor */
-       ret = phy_write(phydev, MII_88E1121_MISC_TEST,
-                       ret & ~MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
+       ret = __phy_write(phydev, MII_88E1121_MISC_TEST,
+                         ret & ~MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
        if (ret < 0)
                goto error;
 
        *temp = ((val & MII_88E1121_MISC_TEST_TEMP_MASK) - 5) * 5000;
 
 error:
-       marvell_set_page(phydev, oldpage);
-       mutex_unlock(&phydev->lock);
-
-       return ret;
+       return phy_restore_page(phydev, oldpage, ret);
 }
 
 static int m88e1121_hwmon_read(struct device *dev,
@@ -1671,118 +1603,64 @@ static const struct hwmon_chip_info m88e1121_hwmon_chip_info = {
 
 static int m88e1510_get_temp(struct phy_device *phydev, long *temp)
 {
-       int oldpage;
        int ret;
 
        *temp = 0;
 
-       mutex_lock(&phydev->lock);
-
-       oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
-       if (oldpage < 0) {
-               mutex_unlock(&phydev->lock);
-               return oldpage;
-       }
-
-       ret = phy_read(phydev, MII_88E1510_TEMP_SENSOR);
+       ret = phy_read_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
+                            MII_88E1510_TEMP_SENSOR);
        if (ret < 0)
-               goto error;
+               return ret;
 
        *temp = ((ret & MII_88E1510_TEMP_SENSOR_MASK) - 25) * 1000;
 
-error:
-       marvell_set_page(phydev, oldpage);
-       mutex_unlock(&phydev->lock);
-
-       return ret;
+       return 0;
 }
 
 static int m88e1510_get_temp_critical(struct phy_device *phydev, long *temp)
 {
-       int oldpage;
        int ret;
 
        *temp = 0;
 
-       mutex_lock(&phydev->lock);
-
-       oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
-       if (oldpage < 0) {
-               mutex_unlock(&phydev->lock);
-               return oldpage;
-       }
-
-       ret = phy_read(phydev, MII_88E1121_MISC_TEST);
+       ret = phy_read_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
+                            MII_88E1121_MISC_TEST);
        if (ret < 0)
-               goto error;
+               return ret;
 
        *temp = (((ret & MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK) >>
                  MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT) * 5) - 25;
        /* convert to mC */
        *temp *= 1000;
 
-error:
-       marvell_set_page(phydev, oldpage);
-       mutex_unlock(&phydev->lock);
-
-       return ret;
+       return 0;
 }
 
 static int m88e1510_set_temp_critical(struct phy_device *phydev, long temp)
 {
-       int oldpage;
-       int ret;
-
-       mutex_lock(&phydev->lock);
-
-       oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
-       if (oldpage < 0) {
-               mutex_unlock(&phydev->lock);
-               return oldpage;
-       }
-
-       ret = phy_read(phydev, MII_88E1121_MISC_TEST);
-       if (ret < 0)
-               goto error;
-
        temp = temp / 1000;
        temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f);
-       ret = phy_write(phydev, MII_88E1121_MISC_TEST,
-                       (ret & ~MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK) |
-                       (temp << MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT));
-
-error:
-       marvell_set_page(phydev, oldpage);
-       mutex_unlock(&phydev->lock);
 
-       return ret;
+       return phy_modify_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
+                               MII_88E1121_MISC_TEST,
+                               MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK,
+                               temp << MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT);
 }
 
 static int m88e1510_get_temp_alarm(struct phy_device *phydev, long *alarm)
 {
-       int oldpage;
        int ret;
 
        *alarm = false;
 
-       mutex_lock(&phydev->lock);
-
-       oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
-       if (oldpage < 0) {
-               mutex_unlock(&phydev->lock);
-               return oldpage;
-       }
-
-       ret = phy_read(phydev, MII_88E1121_MISC_TEST);
+       ret = phy_read_paged(phydev, MII_MARVELL_MISC_TEST_PAGE,
+                            MII_88E1121_MISC_TEST);
        if (ret < 0)
-               goto error;
-       *alarm = !!(ret & MII_88E1510_MISC_TEST_TEMP_IRQ);
+               return ret;
 
-error:
-       marvell_set_page(phydev, oldpage);
-       mutex_unlock(&phydev->lock);
+       *alarm = !!(ret & MII_88E1510_MISC_TEST_TEMP_IRQ);
 
-       return ret;
+       return 0;
 }
 
 static int m88e1510_hwmon_read(struct device *dev,
@@ -1871,6 +1749,123 @@ static const struct hwmon_chip_info m88e1510_hwmon_chip_info = {
        .info = m88e1510_hwmon_info,
 };
 
+static int m88e6390_get_temp(struct phy_device *phydev, long *temp)
+{
+       int sum = 0;
+       int oldpage;
+       int ret = 0;
+       int i;
+
+       *temp = 0;
+
+       oldpage = phy_select_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
+       if (oldpage < 0)
+               goto error;
+
+       /* Enable temperature sensor */
+       ret = __phy_read(phydev, MII_88E6390_MISC_TEST);
+       if (ret < 0)
+               goto error;
+
+       ret = ret & ~MII_88E6390_MISC_TEST_SAMPLE_MASK;
+       ret |= MII_88E6390_MISC_TEST_SAMPLE_ENABLE |
+               MII_88E6390_MISC_TEST_SAMPLE_1S;
+
+       ret = __phy_write(phydev, MII_88E6390_MISC_TEST, ret);
+       if (ret < 0)
+               goto error;
+
+       /* Wait for temperature to stabilize */
+       usleep_range(10000, 12000);
+
+       /* Reading the temperature sense has an errata. You need to read
+        * a number of times and take an average.
+        */
+       for (i = 0; i < MII_88E6390_TEMP_SENSOR_SAMPLES; i++) {
+               ret = __phy_read(phydev, MII_88E6390_TEMP_SENSOR);
+               if (ret < 0)
+                       goto error;
+               sum += ret & MII_88E6390_TEMP_SENSOR_MASK;
+       }
+
+       sum /= MII_88E6390_TEMP_SENSOR_SAMPLES;
+       *temp = (sum  - 75) * 1000;
+
+       /* Disable temperature sensor */
+       ret = __phy_read(phydev, MII_88E6390_MISC_TEST);
+       if (ret < 0)
+               goto error;
+
+       ret = ret & ~MII_88E6390_MISC_TEST_SAMPLE_MASK;
+       ret |= MII_88E6390_MISC_TEST_SAMPLE_DISABLE;
+
+       ret = __phy_write(phydev, MII_88E6390_MISC_TEST, ret);
+
+error:
+       phy_restore_page(phydev, oldpage, ret);
+
+       return ret;
+}
+
+static int m88e6390_hwmon_read(struct device *dev,
+                              enum hwmon_sensor_types type,
+                              u32 attr, int channel, long *temp)
+{
+       struct phy_device *phydev = dev_get_drvdata(dev);
+       int err;
+
+       switch (attr) {
+       case hwmon_temp_input:
+               err = m88e6390_get_temp(phydev, temp);
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return err;
+}
+
+static umode_t m88e6390_hwmon_is_visible(const void *data,
+                                        enum hwmon_sensor_types type,
+                                        u32 attr, int channel)
+{
+       if (type != hwmon_temp)
+               return 0;
+
+       switch (attr) {
+       case hwmon_temp_input:
+               return 0444;
+       default:
+               return 0;
+       }
+}
+
+static u32 m88e6390_hwmon_temp_config[] = {
+       HWMON_T_INPUT,
+       0
+};
+
+static const struct hwmon_channel_info m88e6390_hwmon_temp = {
+       .type = hwmon_temp,
+       .config = m88e6390_hwmon_temp_config,
+};
+
+static const struct hwmon_channel_info *m88e6390_hwmon_info[] = {
+       &m88e1121_hwmon_chip,
+       &m88e6390_hwmon_temp,
+       NULL
+};
+
+static const struct hwmon_ops m88e6390_hwmon_hwmon_ops = {
+       .is_visible = m88e6390_hwmon_is_visible,
+       .read = m88e6390_hwmon_read,
+};
+
+static const struct hwmon_chip_info m88e6390_hwmon_chip_info = {
+       .ops = &m88e6390_hwmon_hwmon_ops,
+       .info = m88e6390_hwmon_info,
+};
+
 static int marvell_hwmon_name(struct phy_device *phydev)
 {
        struct marvell_priv *priv = phydev->priv;
@@ -1917,6 +1912,11 @@ static int m88e1510_hwmon_probe(struct phy_device *phydev)
 {
        return marvell_hwmon_probe(phydev, &m88e1510_hwmon_chip_info);
 }
+
+static int m88e6390_hwmon_probe(struct phy_device *phydev)
+{
+       return marvell_hwmon_probe(phydev, &m88e6390_hwmon_chip_info);
+}
 #else
 static int m88e1121_hwmon_probe(struct phy_device *phydev)
 {
@@ -1927,6 +1927,11 @@ static int m88e1510_hwmon_probe(struct phy_device *phydev)
 {
        return 0;
 }
+
+static int m88e6390_hwmon_probe(struct phy_device *phydev)
+{
+       return 0;
+}
 #endif
 
 static int marvell_probe(struct phy_device *phydev)
@@ -1964,6 +1969,17 @@ static int m88e1510_probe(struct phy_device *phydev)
        return m88e1510_hwmon_probe(phydev);
 }
 
+static int m88e6390_probe(struct phy_device *phydev)
+{
+       int err;
+
+       err = marvell_probe(phydev);
+       if (err)
+               return err;
+
+       return m88e6390_hwmon_probe(phydev);
+}
+
 static struct phy_driver marvell_drivers[] = {
        {
                .phy_id = MARVELL_PHY_ID_88E1101,
@@ -1974,11 +1990,12 @@ static struct phy_driver marvell_drivers[] = {
                .probe = marvell_probe,
                .config_init = &marvell_config_init,
                .config_aneg = &m88e1101_config_aneg,
-               .read_status = &genphy_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -1992,11 +2009,12 @@ static struct phy_driver marvell_drivers[] = {
                .probe = marvell_probe,
                .config_init = &m88e1111_config_init,
                .config_aneg = &marvell_config_aneg,
-               .read_status = &genphy_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2015,6 +2033,8 @@ static struct phy_driver marvell_drivers[] = {
                .config_intr = &marvell_config_intr,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2028,11 +2048,12 @@ static struct phy_driver marvell_drivers[] = {
                .probe = marvell_probe,
                .config_init = &m88e1118_config_init,
                .config_aneg = &m88e1118_config_aneg,
-               .read_status = &genphy_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2052,6 +2073,8 @@ static struct phy_driver marvell_drivers[] = {
                .did_interrupt = &m88e1121_did_interrupt,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2073,6 +2096,8 @@ static struct phy_driver marvell_drivers[] = {
                .set_wol = &m88e1318_set_wol,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2091,6 +2116,8 @@ static struct phy_driver marvell_drivers[] = {
                .config_intr = &marvell_config_intr,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2104,11 +2131,12 @@ static struct phy_driver marvell_drivers[] = {
                .probe = marvell_probe,
                .config_init = &m88e1149_config_init,
                .config_aneg = &m88e1118_config_aneg,
-               .read_status = &genphy_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2122,11 +2150,12 @@ static struct phy_driver marvell_drivers[] = {
                .probe = marvell_probe,
                .config_init = &m88e1111_config_init,
                .config_aneg = &marvell_config_aneg,
-               .read_status = &genphy_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2139,12 +2168,12 @@ static struct phy_driver marvell_drivers[] = {
                .flags = PHY_HAS_INTERRUPT,
                .probe = marvell_probe,
                .config_init = &m88e1116r_config_init,
-               .config_aneg = &genphy_config_aneg,
-               .read_status = &genphy_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2166,6 +2195,8 @@ static struct phy_driver marvell_drivers[] = {
                .set_wol = &m88e1318_set_wol,
                .resume = &marvell_resume,
                .suspend = &marvell_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2186,6 +2217,8 @@ static struct phy_driver marvell_drivers[] = {
                .did_interrupt = &m88e1121_did_interrupt,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2205,6 +2238,8 @@ static struct phy_driver marvell_drivers[] = {
                .did_interrupt = &m88e1121_did_interrupt,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2216,7 +2251,6 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_BASIC_FEATURES,
                .flags = PHY_HAS_INTERRUPT,
                .probe = marvell_probe,
-               .config_aneg = &genphy_config_aneg,
                .config_init = &m88e3016_config_init,
                .aneg_done = &marvell_aneg_done,
                .read_status = &marvell_read_status,
@@ -2225,6 +2259,8 @@ static struct phy_driver marvell_drivers[] = {
                .did_interrupt = &m88e1121_did_interrupt,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,
@@ -2235,7 +2271,7 @@ static struct phy_driver marvell_drivers[] = {
                .name = "Marvell 88E6390",
                .features = PHY_GBIT_FEATURES,
                .flags = PHY_HAS_INTERRUPT,
-               .probe = m88e1510_probe,
+               .probe = m88e6390_probe,
                .config_init = &marvell_config_init,
                .config_aneg = &m88e1510_config_aneg,
                .read_status = &marvell_read_status,
@@ -2244,6 +2280,8 @@ static struct phy_driver marvell_drivers[] = {
                .did_interrupt = &m88e1121_did_interrupt,
                .resume = &genphy_resume,
                .suspend = &genphy_suspend,
+               .read_page = marvell_read_page,
+               .write_page = marvell_write_page,
                .get_sset_count = marvell_get_sset_count,
                .get_strings = marvell_get_strings,
                .get_stats = marvell_get_stats,