[OpenWrt-Devel] [PATCH 1/2] kernel: move at803x phy patch to generic

Roman Yeryomin leroi.lists at gmail.com
Sat Dec 19 19:30:26 EST 2015


Signed-off-by: Roman Yeryomin <roman at advem.lv>
---
 ...t-phy-at803x-allow-to-configure-via-pdata.patch | 180 ---------------------
 ...t-phy-at803x-allow-to-configure-via-pdata.patch | 180 +++++++++++++++++++++
 ...t-phy-at803x-allow-to-configure-via-pdata.patch | 180 +++++++++++++++++++++
 ...t-phy-at803x-allow-to-configure-via-pdata.patch | 180 +++++++++++++++++++++
 ...t-phy-at803x-allow-to-configure-via-pdata.patch | 180 +++++++++++++++++++++
 5 files changed, 720 insertions(+), 180 deletions(-)
 delete mode 100644 target/linux/ar71xx/patches-4.1/425-net-phy-at803x-allow-to-configure-via-pdata.patch
 create mode 100644 target/linux/generic/patches-3.18/734-net-phy-at803x-allow-to-configure-via-pdata.patch
 create mode 100644 target/linux/generic/patches-4.1/734-net-phy-at803x-allow-to-configure-via-pdata.patch
 create mode 100644 target/linux/generic/patches-4.3/734-net-phy-at803x-allow-to-configure-via-pdata.patch
 create mode 100644 target/linux/generic/patches-4.4/734-net-phy-at803x-allow-to-configure-via-pdata.patch

diff --git a/target/linux/ar71xx/patches-4.1/425-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/ar71xx/patches-4.1/425-net-phy-at803x-allow-to-configure-via-pdata.patch
deleted file mode 100644
index 53abcc3..0000000
--- a/target/linux/ar71xx/patches-4.1/425-net-phy-at803x-allow-to-configure-via-pdata.patch
+++ /dev/null
@@ -1,180 +0,0 @@
---- a/drivers/net/phy/at803x.c
-+++ b/drivers/net/phy/at803x.c
-@@ -12,12 +12,14 @@
-  */
- 
- #include <linux/phy.h>
-+#include <linux/mdio.h>
- #include <linux/module.h>
- #include <linux/string.h>
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/of_gpio.h>
- #include <linux/gpio/consumer.h>
-+#include <linux/platform_data/phy-at803x.h>
- 
- #define AT803X_INTR_ENABLE			0x12
- #define AT803X_INTR_STATUS			0x13
-@@ -34,8 +36,16 @@
- #define AT803X_INER				0x0012
- #define AT803X_INER_INIT			0xec00
- #define AT803X_INSR				0x0013
-+
-+#define AT803X_PCS_SMART_EEE_CTRL3			0x805D
-+#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK	0x3
-+#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT	12
-+#define AT803X_SMART_EEE_CTRL3_LPI_EN			BIT(8)
-+
- #define AT803X_DEBUG_ADDR			0x1D
- #define AT803X_DEBUG_DATA			0x1E
-+#define AT803X_DBG0_REG				0x00
-+#define AT803X_DEBUG_RGMII_RX_CLK_DLY		BIT(8)
- #define AT803X_DEBUG_SYSTEM_MODE_CTRL		0x05
- #define AT803X_DEBUG_RGMII_TX_CLK_DLY		BIT(8)
- 
-@@ -50,6 +60,7 @@ MODULE_LICENSE("GPL");
- struct at803x_priv {
- 	bool phy_reset:1;
- 	struct gpio_desc *gpiod_reset;
-+	int prev_speed;
- };
- 
- struct at803x_context {
-@@ -61,6 +72,43 @@ struct at803x_context {
- 	u16 led_control;
- };
- 
-+static u16
-+at803x_dbg_reg_rmw(struct phy_device *phydev, u16 reg, u16 clear, u16 set)
-+{
-+	struct mii_bus *bus = phydev->bus;
-+	int val;
-+
-+	mutex_lock(&bus->mdio_lock);
-+
-+	bus->write(bus, phydev->addr, AT803X_DEBUG_ADDR, reg);
-+	val = bus->read(bus, phydev->addr, AT803X_DEBUG_DATA);
-+	if (val < 0) {
-+		val = 0xffff;
-+		goto out;
-+	}
-+
-+	val &= ~clear;
-+	val |= set;
-+	bus->write(bus, phydev->addr, AT803X_DEBUG_DATA, val);
-+
-+out:
-+	mutex_unlock(&bus->mdio_lock);
-+	return val;
-+}
-+
-+static inline void
-+at803x_dbg_reg_set(struct phy_device *phydev, u16 reg, u16 set)
-+{
-+	at803x_dbg_reg_rmw(phydev, reg, 0, set);
-+}
-+
-+static inline void
-+at803x_dbg_reg_clr(struct phy_device *phydev, u16 reg, u16 clear)
-+{
-+	at803x_dbg_reg_rmw(phydev, reg, clear, 0);
-+}
-+
-+
- /* save relevant PHY registers to private copy */
- static void at803x_context_save(struct phy_device *phydev,
- 				struct at803x_context *context)
-@@ -209,8 +257,16 @@ static int at803x_probe(struct phy_devic
- 	return 0;
- }
- 
-+static void at803x_disable_smarteee(struct phy_device *phydev)
-+{
-+	phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3,
-+		1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT);
-+	phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
-+}
-+
- static int at803x_config_init(struct phy_device *phydev)
- {
-+	struct at803x_platform_data *pdata;
- 	int ret;
- 
- 	ret = genphy_config_init(phydev);
-@@ -228,6 +284,26 @@ static int at803x_config_init(struct phy
- 			return ret;
- 	}
- 
-+	pdata = dev_get_platdata(&phydev->dev);
-+	if (pdata) {
-+		if (pdata->disable_smarteee)
-+			at803x_disable_smarteee(phydev);
-+
-+		if (pdata->enable_rgmii_rx_delay)
-+			at803x_dbg_reg_set(phydev, AT803X_DBG0_REG,
-+				AT803X_DEBUG_RGMII_RX_CLK_DLY);
-+		else
-+			at803x_dbg_reg_clr(phydev, AT803X_DBG0_REG,
-+				AT803X_DEBUG_RGMII_RX_CLK_DLY);
-+
-+		if (pdata->enable_rgmii_tx_delay)
-+			at803x_dbg_reg_set(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
-+				AT803X_DEBUG_RGMII_TX_CLK_DLY);
-+		else
-+			at803x_dbg_reg_clr(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
-+				AT803X_DEBUG_RGMII_TX_CLK_DLY);
-+	}
-+
- 	return 0;
- }
- 
-@@ -259,6 +335,8 @@ static int at803x_config_intr(struct phy
- static void at803x_link_change_notify(struct phy_device *phydev)
- {
- 	struct at803x_priv *priv = phydev->priv;
-+	struct at803x_platform_data *pdata;
-+	pdata = dev_get_platdata(&phydev->dev);
- 
- 	/*
- 	 * Conduct a hardware reset for AT8030 every time a link loss is
-@@ -289,6 +367,26 @@ static void at803x_link_change_notify(st
- 			priv->phy_reset = false;
- 		}
- 	}
-+	if (pdata && pdata->fixup_rgmii_tx_delay &&
-+	    phydev->speed != priv->prev_speed) {
-+		switch (phydev->speed) {
-+		case SPEED_10:
-+		case SPEED_100:
-+			at803x_dbg_reg_set(phydev,
-+				AT803X_DEBUG_SYSTEM_MODE_CTRL,
-+				AT803X_DEBUG_RGMII_TX_CLK_DLY);
-+			break;
-+		case SPEED_1000:
-+			at803x_dbg_reg_clr(phydev,
-+				AT803X_DEBUG_SYSTEM_MODE_CTRL,
-+				AT803X_DEBUG_RGMII_TX_CLK_DLY);
-+			break;
-+		default:
-+			break;
-+		}
-+
-+		priv->prev_speed = phydev->speed;
-+	}
- }
- 
- static struct phy_driver at803x_driver[] = {
---- /dev/null
-+++ b/include/linux/platform_data/phy-at803x.h
-@@ -0,0 +1,11 @@
-+#ifndef _PHY_AT803X_PDATA_H
-+#define _PHY_AT803X_PDATA_H
-+
-+struct at803x_platform_data {
-+	int disable_smarteee:1;
-+	int enable_rgmii_tx_delay:1;
-+	int enable_rgmii_rx_delay:1;
-+	int fixup_rgmii_tx_delay:1;
-+};
-+
-+#endif /* _PHY_AT803X_PDATA_H */
diff --git a/target/linux/generic/patches-3.18/734-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/generic/patches-3.18/734-net-phy-at803x-allow-to-configure-via-pdata.patch
new file mode 100644
index 0000000..53abcc3
--- /dev/null
+++ b/target/linux/generic/patches-3.18/734-net-phy-at803x-allow-to-configure-via-pdata.patch
@@ -0,0 +1,180 @@
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -12,12 +12,14 @@
+  */
+ 
+ #include <linux/phy.h>
++#include <linux/mdio.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/of_gpio.h>
+ #include <linux/gpio/consumer.h>
++#include <linux/platform_data/phy-at803x.h>
+ 
+ #define AT803X_INTR_ENABLE			0x12
+ #define AT803X_INTR_STATUS			0x13
+@@ -34,8 +36,16 @@
+ #define AT803X_INER				0x0012
+ #define AT803X_INER_INIT			0xec00
+ #define AT803X_INSR				0x0013
++
++#define AT803X_PCS_SMART_EEE_CTRL3			0x805D
++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK	0x3
++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT	12
++#define AT803X_SMART_EEE_CTRL3_LPI_EN			BIT(8)
++
+ #define AT803X_DEBUG_ADDR			0x1D
+ #define AT803X_DEBUG_DATA			0x1E
++#define AT803X_DBG0_REG				0x00
++#define AT803X_DEBUG_RGMII_RX_CLK_DLY		BIT(8)
+ #define AT803X_DEBUG_SYSTEM_MODE_CTRL		0x05
+ #define AT803X_DEBUG_RGMII_TX_CLK_DLY		BIT(8)
+ 
+@@ -50,6 +60,7 @@ MODULE_LICENSE("GPL");
+ struct at803x_priv {
+ 	bool phy_reset:1;
+ 	struct gpio_desc *gpiod_reset;
++	int prev_speed;
+ };
+ 
+ struct at803x_context {
+@@ -61,6 +72,43 @@ struct at803x_context {
+ 	u16 led_control;
+ };
+ 
++static u16
++at803x_dbg_reg_rmw(struct phy_device *phydev, u16 reg, u16 clear, u16 set)
++{
++	struct mii_bus *bus = phydev->bus;
++	int val;
++
++	mutex_lock(&bus->mdio_lock);
++
++	bus->write(bus, phydev->addr, AT803X_DEBUG_ADDR, reg);
++	val = bus->read(bus, phydev->addr, AT803X_DEBUG_DATA);
++	if (val < 0) {
++		val = 0xffff;
++		goto out;
++	}
++
++	val &= ~clear;
++	val |= set;
++	bus->write(bus, phydev->addr, AT803X_DEBUG_DATA, val);
++
++out:
++	mutex_unlock(&bus->mdio_lock);
++	return val;
++}
++
++static inline void
++at803x_dbg_reg_set(struct phy_device *phydev, u16 reg, u16 set)
++{
++	at803x_dbg_reg_rmw(phydev, reg, 0, set);
++}
++
++static inline void
++at803x_dbg_reg_clr(struct phy_device *phydev, u16 reg, u16 clear)
++{
++	at803x_dbg_reg_rmw(phydev, reg, clear, 0);
++}
++
++
+ /* save relevant PHY registers to private copy */
+ static void at803x_context_save(struct phy_device *phydev,
+ 				struct at803x_context *context)
+@@ -209,8 +257,16 @@ static int at803x_probe(struct phy_devic
+ 	return 0;
+ }
+ 
++static void at803x_disable_smarteee(struct phy_device *phydev)
++{
++	phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3,
++		1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT);
++	phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
++}
++
+ static int at803x_config_init(struct phy_device *phydev)
+ {
++	struct at803x_platform_data *pdata;
+ 	int ret;
+ 
+ 	ret = genphy_config_init(phydev);
+@@ -228,6 +284,26 @@ static int at803x_config_init(struct phy
+ 			return ret;
+ 	}
+ 
++	pdata = dev_get_platdata(&phydev->dev);
++	if (pdata) {
++		if (pdata->disable_smarteee)
++			at803x_disable_smarteee(phydev);
++
++		if (pdata->enable_rgmii_rx_delay)
++			at803x_dbg_reg_set(phydev, AT803X_DBG0_REG,
++				AT803X_DEBUG_RGMII_RX_CLK_DLY);
++		else
++			at803x_dbg_reg_clr(phydev, AT803X_DBG0_REG,
++				AT803X_DEBUG_RGMII_RX_CLK_DLY);
++
++		if (pdata->enable_rgmii_tx_delay)
++			at803x_dbg_reg_set(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++		else
++			at803x_dbg_reg_clr(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++	}
++
+ 	return 0;
+ }
+ 
+@@ -259,6 +335,8 @@ static int at803x_config_intr(struct phy
+ static void at803x_link_change_notify(struct phy_device *phydev)
+ {
+ 	struct at803x_priv *priv = phydev->priv;
++	struct at803x_platform_data *pdata;
++	pdata = dev_get_platdata(&phydev->dev);
+ 
+ 	/*
+ 	 * Conduct a hardware reset for AT8030 every time a link loss is
+@@ -289,6 +367,26 @@ static void at803x_link_change_notify(st
+ 			priv->phy_reset = false;
+ 		}
+ 	}
++	if (pdata && pdata->fixup_rgmii_tx_delay &&
++	    phydev->speed != priv->prev_speed) {
++		switch (phydev->speed) {
++		case SPEED_10:
++		case SPEED_100:
++			at803x_dbg_reg_set(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		case SPEED_1000:
++			at803x_dbg_reg_clr(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		default:
++			break;
++		}
++
++		priv->prev_speed = phydev->speed;
++	}
+ }
+ 
+ static struct phy_driver at803x_driver[] = {
+--- /dev/null
++++ b/include/linux/platform_data/phy-at803x.h
+@@ -0,0 +1,11 @@
++#ifndef _PHY_AT803X_PDATA_H
++#define _PHY_AT803X_PDATA_H
++
++struct at803x_platform_data {
++	int disable_smarteee:1;
++	int enable_rgmii_tx_delay:1;
++	int enable_rgmii_rx_delay:1;
++	int fixup_rgmii_tx_delay:1;
++};
++
++#endif /* _PHY_AT803X_PDATA_H */
diff --git a/target/linux/generic/patches-4.1/734-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/generic/patches-4.1/734-net-phy-at803x-allow-to-configure-via-pdata.patch
new file mode 100644
index 0000000..53abcc3
--- /dev/null
+++ b/target/linux/generic/patches-4.1/734-net-phy-at803x-allow-to-configure-via-pdata.patch
@@ -0,0 +1,180 @@
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -12,12 +12,14 @@
+  */
+ 
+ #include <linux/phy.h>
++#include <linux/mdio.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/of_gpio.h>
+ #include <linux/gpio/consumer.h>
++#include <linux/platform_data/phy-at803x.h>
+ 
+ #define AT803X_INTR_ENABLE			0x12
+ #define AT803X_INTR_STATUS			0x13
+@@ -34,8 +36,16 @@
+ #define AT803X_INER				0x0012
+ #define AT803X_INER_INIT			0xec00
+ #define AT803X_INSR				0x0013
++
++#define AT803X_PCS_SMART_EEE_CTRL3			0x805D
++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK	0x3
++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT	12
++#define AT803X_SMART_EEE_CTRL3_LPI_EN			BIT(8)
++
+ #define AT803X_DEBUG_ADDR			0x1D
+ #define AT803X_DEBUG_DATA			0x1E
++#define AT803X_DBG0_REG				0x00
++#define AT803X_DEBUG_RGMII_RX_CLK_DLY		BIT(8)
+ #define AT803X_DEBUG_SYSTEM_MODE_CTRL		0x05
+ #define AT803X_DEBUG_RGMII_TX_CLK_DLY		BIT(8)
+ 
+@@ -50,6 +60,7 @@ MODULE_LICENSE("GPL");
+ struct at803x_priv {
+ 	bool phy_reset:1;
+ 	struct gpio_desc *gpiod_reset;
++	int prev_speed;
+ };
+ 
+ struct at803x_context {
+@@ -61,6 +72,43 @@ struct at803x_context {
+ 	u16 led_control;
+ };
+ 
++static u16
++at803x_dbg_reg_rmw(struct phy_device *phydev, u16 reg, u16 clear, u16 set)
++{
++	struct mii_bus *bus = phydev->bus;
++	int val;
++
++	mutex_lock(&bus->mdio_lock);
++
++	bus->write(bus, phydev->addr, AT803X_DEBUG_ADDR, reg);
++	val = bus->read(bus, phydev->addr, AT803X_DEBUG_DATA);
++	if (val < 0) {
++		val = 0xffff;
++		goto out;
++	}
++
++	val &= ~clear;
++	val |= set;
++	bus->write(bus, phydev->addr, AT803X_DEBUG_DATA, val);
++
++out:
++	mutex_unlock(&bus->mdio_lock);
++	return val;
++}
++
++static inline void
++at803x_dbg_reg_set(struct phy_device *phydev, u16 reg, u16 set)
++{
++	at803x_dbg_reg_rmw(phydev, reg, 0, set);
++}
++
++static inline void
++at803x_dbg_reg_clr(struct phy_device *phydev, u16 reg, u16 clear)
++{
++	at803x_dbg_reg_rmw(phydev, reg, clear, 0);
++}
++
++
+ /* save relevant PHY registers to private copy */
+ static void at803x_context_save(struct phy_device *phydev,
+ 				struct at803x_context *context)
+@@ -209,8 +257,16 @@ static int at803x_probe(struct phy_devic
+ 	return 0;
+ }
+ 
++static void at803x_disable_smarteee(struct phy_device *phydev)
++{
++	phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3,
++		1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT);
++	phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
++}
++
+ static int at803x_config_init(struct phy_device *phydev)
+ {
++	struct at803x_platform_data *pdata;
+ 	int ret;
+ 
+ 	ret = genphy_config_init(phydev);
+@@ -228,6 +284,26 @@ static int at803x_config_init(struct phy
+ 			return ret;
+ 	}
+ 
++	pdata = dev_get_platdata(&phydev->dev);
++	if (pdata) {
++		if (pdata->disable_smarteee)
++			at803x_disable_smarteee(phydev);
++
++		if (pdata->enable_rgmii_rx_delay)
++			at803x_dbg_reg_set(phydev, AT803X_DBG0_REG,
++				AT803X_DEBUG_RGMII_RX_CLK_DLY);
++		else
++			at803x_dbg_reg_clr(phydev, AT803X_DBG0_REG,
++				AT803X_DEBUG_RGMII_RX_CLK_DLY);
++
++		if (pdata->enable_rgmii_tx_delay)
++			at803x_dbg_reg_set(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++		else
++			at803x_dbg_reg_clr(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++	}
++
+ 	return 0;
+ }
+ 
+@@ -259,6 +335,8 @@ static int at803x_config_intr(struct phy
+ static void at803x_link_change_notify(struct phy_device *phydev)
+ {
+ 	struct at803x_priv *priv = phydev->priv;
++	struct at803x_platform_data *pdata;
++	pdata = dev_get_platdata(&phydev->dev);
+ 
+ 	/*
+ 	 * Conduct a hardware reset for AT8030 every time a link loss is
+@@ -289,6 +367,26 @@ static void at803x_link_change_notify(st
+ 			priv->phy_reset = false;
+ 		}
+ 	}
++	if (pdata && pdata->fixup_rgmii_tx_delay &&
++	    phydev->speed != priv->prev_speed) {
++		switch (phydev->speed) {
++		case SPEED_10:
++		case SPEED_100:
++			at803x_dbg_reg_set(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		case SPEED_1000:
++			at803x_dbg_reg_clr(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		default:
++			break;
++		}
++
++		priv->prev_speed = phydev->speed;
++	}
+ }
+ 
+ static struct phy_driver at803x_driver[] = {
+--- /dev/null
++++ b/include/linux/platform_data/phy-at803x.h
+@@ -0,0 +1,11 @@
++#ifndef _PHY_AT803X_PDATA_H
++#define _PHY_AT803X_PDATA_H
++
++struct at803x_platform_data {
++	int disable_smarteee:1;
++	int enable_rgmii_tx_delay:1;
++	int enable_rgmii_rx_delay:1;
++	int fixup_rgmii_tx_delay:1;
++};
++
++#endif /* _PHY_AT803X_PDATA_H */
diff --git a/target/linux/generic/patches-4.3/734-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/generic/patches-4.3/734-net-phy-at803x-allow-to-configure-via-pdata.patch
new file mode 100644
index 0000000..53abcc3
--- /dev/null
+++ b/target/linux/generic/patches-4.3/734-net-phy-at803x-allow-to-configure-via-pdata.patch
@@ -0,0 +1,180 @@
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -12,12 +12,14 @@
+  */
+ 
+ #include <linux/phy.h>
++#include <linux/mdio.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/of_gpio.h>
+ #include <linux/gpio/consumer.h>
++#include <linux/platform_data/phy-at803x.h>
+ 
+ #define AT803X_INTR_ENABLE			0x12
+ #define AT803X_INTR_STATUS			0x13
+@@ -34,8 +36,16 @@
+ #define AT803X_INER				0x0012
+ #define AT803X_INER_INIT			0xec00
+ #define AT803X_INSR				0x0013
++
++#define AT803X_PCS_SMART_EEE_CTRL3			0x805D
++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK	0x3
++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT	12
++#define AT803X_SMART_EEE_CTRL3_LPI_EN			BIT(8)
++
+ #define AT803X_DEBUG_ADDR			0x1D
+ #define AT803X_DEBUG_DATA			0x1E
++#define AT803X_DBG0_REG				0x00
++#define AT803X_DEBUG_RGMII_RX_CLK_DLY		BIT(8)
+ #define AT803X_DEBUG_SYSTEM_MODE_CTRL		0x05
+ #define AT803X_DEBUG_RGMII_TX_CLK_DLY		BIT(8)
+ 
+@@ -50,6 +60,7 @@ MODULE_LICENSE("GPL");
+ struct at803x_priv {
+ 	bool phy_reset:1;
+ 	struct gpio_desc *gpiod_reset;
++	int prev_speed;
+ };
+ 
+ struct at803x_context {
+@@ -61,6 +72,43 @@ struct at803x_context {
+ 	u16 led_control;
+ };
+ 
++static u16
++at803x_dbg_reg_rmw(struct phy_device *phydev, u16 reg, u16 clear, u16 set)
++{
++	struct mii_bus *bus = phydev->bus;
++	int val;
++
++	mutex_lock(&bus->mdio_lock);
++
++	bus->write(bus, phydev->addr, AT803X_DEBUG_ADDR, reg);
++	val = bus->read(bus, phydev->addr, AT803X_DEBUG_DATA);
++	if (val < 0) {
++		val = 0xffff;
++		goto out;
++	}
++
++	val &= ~clear;
++	val |= set;
++	bus->write(bus, phydev->addr, AT803X_DEBUG_DATA, val);
++
++out:
++	mutex_unlock(&bus->mdio_lock);
++	return val;
++}
++
++static inline void
++at803x_dbg_reg_set(struct phy_device *phydev, u16 reg, u16 set)
++{
++	at803x_dbg_reg_rmw(phydev, reg, 0, set);
++}
++
++static inline void
++at803x_dbg_reg_clr(struct phy_device *phydev, u16 reg, u16 clear)
++{
++	at803x_dbg_reg_rmw(phydev, reg, clear, 0);
++}
++
++
+ /* save relevant PHY registers to private copy */
+ static void at803x_context_save(struct phy_device *phydev,
+ 				struct at803x_context *context)
+@@ -209,8 +257,16 @@ static int at803x_probe(struct phy_devic
+ 	return 0;
+ }
+ 
++static void at803x_disable_smarteee(struct phy_device *phydev)
++{
++	phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3,
++		1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT);
++	phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
++}
++
+ static int at803x_config_init(struct phy_device *phydev)
+ {
++	struct at803x_platform_data *pdata;
+ 	int ret;
+ 
+ 	ret = genphy_config_init(phydev);
+@@ -228,6 +284,26 @@ static int at803x_config_init(struct phy
+ 			return ret;
+ 	}
+ 
++	pdata = dev_get_platdata(&phydev->dev);
++	if (pdata) {
++		if (pdata->disable_smarteee)
++			at803x_disable_smarteee(phydev);
++
++		if (pdata->enable_rgmii_rx_delay)
++			at803x_dbg_reg_set(phydev, AT803X_DBG0_REG,
++				AT803X_DEBUG_RGMII_RX_CLK_DLY);
++		else
++			at803x_dbg_reg_clr(phydev, AT803X_DBG0_REG,
++				AT803X_DEBUG_RGMII_RX_CLK_DLY);
++
++		if (pdata->enable_rgmii_tx_delay)
++			at803x_dbg_reg_set(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++		else
++			at803x_dbg_reg_clr(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++	}
++
+ 	return 0;
+ }
+ 
+@@ -259,6 +335,8 @@ static int at803x_config_intr(struct phy
+ static void at803x_link_change_notify(struct phy_device *phydev)
+ {
+ 	struct at803x_priv *priv = phydev->priv;
++	struct at803x_platform_data *pdata;
++	pdata = dev_get_platdata(&phydev->dev);
+ 
+ 	/*
+ 	 * Conduct a hardware reset for AT8030 every time a link loss is
+@@ -289,6 +367,26 @@ static void at803x_link_change_notify(st
+ 			priv->phy_reset = false;
+ 		}
+ 	}
++	if (pdata && pdata->fixup_rgmii_tx_delay &&
++	    phydev->speed != priv->prev_speed) {
++		switch (phydev->speed) {
++		case SPEED_10:
++		case SPEED_100:
++			at803x_dbg_reg_set(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		case SPEED_1000:
++			at803x_dbg_reg_clr(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		default:
++			break;
++		}
++
++		priv->prev_speed = phydev->speed;
++	}
+ }
+ 
+ static struct phy_driver at803x_driver[] = {
+--- /dev/null
++++ b/include/linux/platform_data/phy-at803x.h
+@@ -0,0 +1,11 @@
++#ifndef _PHY_AT803X_PDATA_H
++#define _PHY_AT803X_PDATA_H
++
++struct at803x_platform_data {
++	int disable_smarteee:1;
++	int enable_rgmii_tx_delay:1;
++	int enable_rgmii_rx_delay:1;
++	int fixup_rgmii_tx_delay:1;
++};
++
++#endif /* _PHY_AT803X_PDATA_H */
diff --git a/target/linux/generic/patches-4.4/734-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/generic/patches-4.4/734-net-phy-at803x-allow-to-configure-via-pdata.patch
new file mode 100644
index 0000000..53abcc3
--- /dev/null
+++ b/target/linux/generic/patches-4.4/734-net-phy-at803x-allow-to-configure-via-pdata.patch
@@ -0,0 +1,180 @@
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -12,12 +12,14 @@
+  */
+ 
+ #include <linux/phy.h>
++#include <linux/mdio.h>
+ #include <linux/module.h>
+ #include <linux/string.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/of_gpio.h>
+ #include <linux/gpio/consumer.h>
++#include <linux/platform_data/phy-at803x.h>
+ 
+ #define AT803X_INTR_ENABLE			0x12
+ #define AT803X_INTR_STATUS			0x13
+@@ -34,8 +36,16 @@
+ #define AT803X_INER				0x0012
+ #define AT803X_INER_INIT			0xec00
+ #define AT803X_INSR				0x0013
++
++#define AT803X_PCS_SMART_EEE_CTRL3			0x805D
++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK	0x3
++#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT	12
++#define AT803X_SMART_EEE_CTRL3_LPI_EN			BIT(8)
++
+ #define AT803X_DEBUG_ADDR			0x1D
+ #define AT803X_DEBUG_DATA			0x1E
++#define AT803X_DBG0_REG				0x00
++#define AT803X_DEBUG_RGMII_RX_CLK_DLY		BIT(8)
+ #define AT803X_DEBUG_SYSTEM_MODE_CTRL		0x05
+ #define AT803X_DEBUG_RGMII_TX_CLK_DLY		BIT(8)
+ 
+@@ -50,6 +60,7 @@ MODULE_LICENSE("GPL");
+ struct at803x_priv {
+ 	bool phy_reset:1;
+ 	struct gpio_desc *gpiod_reset;
++	int prev_speed;
+ };
+ 
+ struct at803x_context {
+@@ -61,6 +72,43 @@ struct at803x_context {
+ 	u16 led_control;
+ };
+ 
++static u16
++at803x_dbg_reg_rmw(struct phy_device *phydev, u16 reg, u16 clear, u16 set)
++{
++	struct mii_bus *bus = phydev->bus;
++	int val;
++
++	mutex_lock(&bus->mdio_lock);
++
++	bus->write(bus, phydev->addr, AT803X_DEBUG_ADDR, reg);
++	val = bus->read(bus, phydev->addr, AT803X_DEBUG_DATA);
++	if (val < 0) {
++		val = 0xffff;
++		goto out;
++	}
++
++	val &= ~clear;
++	val |= set;
++	bus->write(bus, phydev->addr, AT803X_DEBUG_DATA, val);
++
++out:
++	mutex_unlock(&bus->mdio_lock);
++	return val;
++}
++
++static inline void
++at803x_dbg_reg_set(struct phy_device *phydev, u16 reg, u16 set)
++{
++	at803x_dbg_reg_rmw(phydev, reg, 0, set);
++}
++
++static inline void
++at803x_dbg_reg_clr(struct phy_device *phydev, u16 reg, u16 clear)
++{
++	at803x_dbg_reg_rmw(phydev, reg, clear, 0);
++}
++
++
+ /* save relevant PHY registers to private copy */
+ static void at803x_context_save(struct phy_device *phydev,
+ 				struct at803x_context *context)
+@@ -209,8 +257,16 @@ static int at803x_probe(struct phy_devic
+ 	return 0;
+ }
+ 
++static void at803x_disable_smarteee(struct phy_device *phydev)
++{
++	phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3,
++		1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT);
++	phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
++}
++
+ static int at803x_config_init(struct phy_device *phydev)
+ {
++	struct at803x_platform_data *pdata;
+ 	int ret;
+ 
+ 	ret = genphy_config_init(phydev);
+@@ -228,6 +284,26 @@ static int at803x_config_init(struct phy
+ 			return ret;
+ 	}
+ 
++	pdata = dev_get_platdata(&phydev->dev);
++	if (pdata) {
++		if (pdata->disable_smarteee)
++			at803x_disable_smarteee(phydev);
++
++		if (pdata->enable_rgmii_rx_delay)
++			at803x_dbg_reg_set(phydev, AT803X_DBG0_REG,
++				AT803X_DEBUG_RGMII_RX_CLK_DLY);
++		else
++			at803x_dbg_reg_clr(phydev, AT803X_DBG0_REG,
++				AT803X_DEBUG_RGMII_RX_CLK_DLY);
++
++		if (pdata->enable_rgmii_tx_delay)
++			at803x_dbg_reg_set(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++		else
++			at803x_dbg_reg_clr(phydev, AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++	}
++
+ 	return 0;
+ }
+ 
+@@ -259,6 +335,8 @@ static int at803x_config_intr(struct phy
+ static void at803x_link_change_notify(struct phy_device *phydev)
+ {
+ 	struct at803x_priv *priv = phydev->priv;
++	struct at803x_platform_data *pdata;
++	pdata = dev_get_platdata(&phydev->dev);
+ 
+ 	/*
+ 	 * Conduct a hardware reset for AT8030 every time a link loss is
+@@ -289,6 +367,26 @@ static void at803x_link_change_notify(st
+ 			priv->phy_reset = false;
+ 		}
+ 	}
++	if (pdata && pdata->fixup_rgmii_tx_delay &&
++	    phydev->speed != priv->prev_speed) {
++		switch (phydev->speed) {
++		case SPEED_10:
++		case SPEED_100:
++			at803x_dbg_reg_set(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		case SPEED_1000:
++			at803x_dbg_reg_clr(phydev,
++				AT803X_DEBUG_SYSTEM_MODE_CTRL,
++				AT803X_DEBUG_RGMII_TX_CLK_DLY);
++			break;
++		default:
++			break;
++		}
++
++		priv->prev_speed = phydev->speed;
++	}
+ }
+ 
+ static struct phy_driver at803x_driver[] = {
+--- /dev/null
++++ b/include/linux/platform_data/phy-at803x.h
+@@ -0,0 +1,11 @@
++#ifndef _PHY_AT803X_PDATA_H
++#define _PHY_AT803X_PDATA_H
++
++struct at803x_platform_data {
++	int disable_smarteee:1;
++	int enable_rgmii_tx_delay:1;
++	int enable_rgmii_rx_delay:1;
++	int fixup_rgmii_tx_delay:1;
++};
++
++#endif /* _PHY_AT803X_PDATA_H */
-- 
2.5.0
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list