[Arm-dev] [PATCH v1 73/87] net, phy, apci: Allow to initialize Marvell phy in the ACPI way.

Thu Aug 13 13:19:10 UTC 2015
Vadim Lomovtsev <Vadim.Lomovtsev at caviumnetworks.com>

From: Tomasz Nowicki <tomasz.nowicki at linaro.org>

Signed-off-by: Tomasz Nowicki <tomasz.nowicki at linaro.org>
Signed-off-by: Vadim Lomovtsev <Vadim.Lomovtsev at caviumnetworks.com>
---
 drivers/net/phy/marvell.c | 118 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 99 insertions(+), 19 deletions(-)

diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index f721444..c07a5fc 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -33,6 +33,7 @@
 #include <linux/phy.h>
 #include <linux/marvell_phy.h>
 #include <linux/of.h>
+#include <linux/acpi.h>
 
 #include <linux/io.h>
 #include <asm/irq.h>
@@ -226,20 +227,6 @@ static int marvell_config_aneg(struct phy_device *phydev)
 }
 
 #ifdef CONFIG_OF_MDIO
-/*
- * 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 *paddr;
@@ -306,6 +293,99 @@ static int marvell_of_reg_init(struct phy_device *phydev)
 }
 #endif /* CONFIG_OF_MDIO */
 
+#ifdef CONFIG_ACPI
+static int marvell_acpi_reg_init(struct phy_device *phydev)
+{
+	const union acpi_object *items;
+	const union acpi_object *obj;
+	int len, i, saved_page, current_page, page_changed, ret;
+
+	ret = acpi_dev_get_property_array(ACPI_COMPANION(&phydev->dev),
+			"marvell,reg-init", ACPI_TYPE_ANY, &obj);
+	if (ret)
+		return 0;
+
+	saved_page = phy_read(phydev, MII_MARVELL_PHY_PAGE);
+	if (saved_page < 0)
+		return saved_page;
+	page_changed = 0;
+	current_page = saved_page;
+
+	items = obj->package.elements;
+	len = obj->package.count;
+	ret = 0;
+	for (i = 0; i < len - 3; i += 4) {
+		u16 reg_page = items[i].integer.value;
+		u16 reg = items[i + 1].integer.value;
+		u16 mask = items[i + 2].integer.value;
+		u16 val_bits = items[i + 3].integer.value;
+		int val;
+
+		if (reg_page != current_page) {
+			current_page = reg_page;
+			page_changed = 1;
+			ret = phy_write(phydev, MII_MARVELL_PHY_PAGE, reg_page);
+			if (ret < 0)
+				goto err;
+		}
+
+		val = 0;
+		if (mask) {
+			val = phy_read(phydev, reg);
+			if (val < 0) {
+				ret = val;
+				goto err;
+			}
+			val &= mask;
+		}
+		val |= val_bits;
+
+		ret = phy_write(phydev, reg, val);
+		if (ret < 0)
+			goto err;
+
+	}
+err:
+	if (page_changed) {
+		i = phy_write(phydev, MII_MARVELL_PHY_PAGE, saved_page);
+		if (ret == 0)
+			ret = i;
+	}
+	return ret;
+}
+#else
+static int marvell_acpi_reg_init(struct phy_device *phydev)
+{
+	return 0;
+}
+#endif /* CONFIG_ACPI */
+
+/*
+ * 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_reg_init(struct phy_device *phydev)
+{
+	int ret;
+
+	if (phydev->dev.of_node)
+		ret = marvell_of_reg_init(phydev);
+	else
+		ret = marvell_acpi_reg_init(phydev);
+
+	return ret;
+}
+
 static int m88e1121_config_aneg(struct phy_device *phydev)
 {
 	int err, oldpage, mscr;
@@ -390,7 +470,7 @@ static int m88e1510_config_aneg(struct phy_device *phydev)
 	if (err < 0)
 		return err;
 
-	return marvell_of_reg_init(phydev);
+	return marvell_reg_init(phydev);
 }
 
 static int m88e1116r_config_init(struct phy_device *phydev)
@@ -552,7 +632,7 @@ static int m88e1111_config_init(struct phy_device *phydev)
 			return err;
 	}
 
-	err = marvell_of_reg_init(phydev);
+	err = marvell_reg_init(phydev);
 	if (err < 0)
 		return err;
 
@@ -603,7 +683,7 @@ static int m88e1118_config_init(struct phy_device *phydev)
 	if (err < 0)
 		return err;
 
-	err = marvell_of_reg_init(phydev);
+	err = marvell_reg_init(phydev);
 	if (err < 0)
 		return err;
 
@@ -629,7 +709,7 @@ static int m88e1149_config_init(struct phy_device *phydev)
 	if (err < 0)
 		return err;
 
-	err = marvell_of_reg_init(phydev);
+	err = marvell_reg_init(phydev);
 	if (err < 0)
 		return err;
 
@@ -715,7 +795,7 @@ static int m88e1145_config_init(struct phy_device *phydev)
 			return err;
 	}
 
-	err = marvell_of_reg_init(phydev);
+	err = marvell_reg_init(phydev);
 	if (err < 0)
 		return err;
 
-- 
2.4.3