Browse Source

kernel: move at803x phy patch to generic

Signed-off-by: Roman Yeryomin <[email protected]>

SVN-Revision: 48108
Felix Fietkau 10 years ago
parent
commit
54b4265873

+ 0 - 0
target/linux/ar71xx/patches-4.1/425-net-phy-at803x-allow-to-configure-via-pdata.patch → target/linux/generic/patches-3.18/734-net-phy-at803x-allow-to-configure-via-pdata.patch


+ 180 - 0
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 */

+ 180 - 0
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 */

+ 180 - 0
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 */