#define MIIM_88E151x_MODE_SGMII 1
#define MIIM_88E151x_RESET_OFFS 15
+#if IS_ENABLED(CONFIG_DM_ETH)
+static int marvell_read_page(struct phy_device *phydev)
+{
+ return phy_read(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE);
+}
+
+static int marvell_write_page(struct phy_device *phydev, int page)
+{
+ return phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, page);
+}
+
+/* Set and/or override some configuration registers based on the
+ * marvell,reg-init property stored in the of_node for the phydev.
+ *
+ * marvell,reg-init = <reg-page reg mask value>,...;
+ *
+ * There may be one or more sets of <reg-page reg mask value>:
+ *
+ * reg-page: which register bank to use.
+ * reg: the register.
+ * mask: if non-zero, ANDed with existing register value.
+ * value: ORed with the masked value and written to the regiser.
+ *
+ */
+static int marvell_of_reg_init(struct phy_device *phydev)
+{
+ const __be32 *prop;
+ int len, i, saved_page, current_page, ret = 0;
+
+ if (!ofnode_valid(phydev->node))
+ return 0;
+
+ prop = ofnode_get_property(phydev->node, "marvell,reg-init", &len);
+ if (!prop)
+ return 0;
+
+ saved_page = marvell_read_page(phydev);
+ if (saved_page < 0)
+ goto err;
+ current_page = saved_page;
+
+ len /= sizeof(*prop);
+ for (i = 0; i < len - 3; i += 4) {
+ u16 page = be32_to_cpup(prop + i);
+ u16 reg = be32_to_cpup(prop + i + 1);
+ u16 mask = be32_to_cpup(prop + i + 2);
+ u16 val_bits = be32_to_cpup(prop + i + 3);
+ int val;
+
+ if (page != current_page) {
+ current_page = page;
+ ret = marvell_write_page(phydev, page);
+ if (ret < 0)
+ goto err;
+ }
+
+ val = 0;
+ if (mask) {
+ val = phy_read(phydev, MDIO_DEVAD_NONE, reg);
+ if (val < 0) {
+ ret = val;
+ goto err;
+ }
+ val &= mask;
+ }
+ val |= val_bits;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, reg, val);
+ if (ret < 0)
+ goto err;
+ }
+
+err:
+ return marvell_write_page(phydev, saved_page);
+}
+#else
+static int marvell_of_reg_init(struct phy_device *phydev)
+{
+ return 0;
+}
+#endif /* CONFIG_DM_ETH */
+
static int m88e1xxx_phy_extread(struct phy_device *phydev, int addr,
int devaddr, int regnum)
{
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+ marvell_of_reg_init(phydev);
+
genphy_config_aneg(phydev);
return 0;
/* soft reset */
phy_reset(phydev);
+ marvell_of_reg_init(phydev);
+
genphy_config_aneg(phydev);
genphy_restart_aneg(phydev);
/* soft reset */
phy_reset(phydev);
+ marvell_of_reg_init(phydev);
+
genphy_config_aneg(phydev);
genphy_restart_aneg(phydev);
/* Change Page Number */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
+ marvell_of_reg_init(phydev);
+
return genphy_config_aneg(phydev);
}
{
int pg;
+ marvell_of_reg_init(phydev);
+
/* Configure the PHY */
genphy_config_aneg(phydev);
MIIM_M88E1145_RGMII_TX_DELAY;
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg);
+ marvell_of_reg_init(phydev);
+
genphy_config_aneg(phydev);
/* soft reset */
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
+ marvell_of_reg_init(phydev);
+
genphy_config_aneg(phydev);
phy_reset(phydev);
/* Ensure to return to page 0 */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000);
+ marvell_of_reg_init(phydev);
+
return genphy_config_aneg(phydev);
}
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x9140);
+ marvell_of_reg_init(phydev);
+
res = genphy_config_aneg(phydev);
if (res < 0)
return res;