summaryrefslogtreecommitdiff
path: root/target/linux/ar71xx/patches-3.10/425-net-phy-at803x-allow-to-configure-via-pdata.patch
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2014-04-13 20:41:50 +0000
committerGabor Juhos <juhosg@openwrt.org>2014-04-13 20:41:50 +0000
commit02ea5b9e560255ae07686fe1a55721691b106e9e (patch)
tree8d4b2f2329e8f472fdeb5b537acad2983a934a46 /target/linux/ar71xx/patches-3.10/425-net-phy-at803x-allow-to-configure-via-pdata.patch
parent27dec099071e6871bd276410af0cd99131ef05bf (diff)
downloadmtk-20170518-02ea5b9e560255ae07686fe1a55721691b106e9e.zip
mtk-20170518-02ea5b9e560255ae07686fe1a55721691b106e9e.tar.gz
mtk-20170518-02ea5b9e560255ae07686fe1a55721691b106e9e.tar.bz2
ar71xx: allow to configure AR803x PHYs via platform data
Add a patch for the at803x phy driver, in order to be able to configure some register settings via platform data. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> SVN-Revision: 40507
Diffstat (limited to 'target/linux/ar71xx/patches-3.10/425-net-phy-at803x-allow-to-configure-via-pdata.patch')
-rw-r--r--target/linux/ar71xx/patches-3.10/425-net-phy-at803x-allow-to-configure-via-pdata.patch134
1 files changed, 134 insertions, 0 deletions
diff --git a/target/linux/ar71xx/patches-3.10/425-net-phy-at803x-allow-to-configure-via-pdata.patch b/target/linux/ar71xx/patches-3.10/425-net-phy-at803x-allow-to-configure-via-pdata.patch
new file mode 100644
index 0000000..788653f
--- /dev/null
+++ b/target/linux/ar71xx/patches-3.10/425-net-phy-at803x-allow-to-configure-via-pdata.patch
@@ -0,0 +1,134 @@
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -12,10 +12,12 @@
+ */
+
+ #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/platform_data/phy-at803x.h>
+
+ #define AT803X_INTR_ENABLE 0x12
+ #define AT803X_INTR_STATUS 0x13
+@@ -28,10 +30,61 @@
+ #define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E
+ #define AT803X_FUNC_DATA 0x4003
+
++#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_PORT_ACCESS_OFFSET 0x1D
++#define AT803X_DEBUG_PORT_ACCESS_DATA 0x1E
++
++#define AT803X_DBG0_REG 0x00
++#define AT803X_DBG0_RGMII_RX_CLK_DELAY_EN BIT(8)
++
++#define AT803X_DBG5_REG 0x05
++#define AT803X_DBG5_RGMII_TX_CLK_DELAY_EN BIT(8)
++
+ MODULE_DESCRIPTION("Atheros 803x PHY driver");
+ MODULE_AUTHOR("Matus Ujhelyi");
+ MODULE_LICENSE("GPL");
+
++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_PORT_ACCESS_OFFSET, reg);
++ val = bus->read(bus, phydev->addr, AT803X_DEBUG_PORT_ACCESS_DATA);
++ if (val < 0) {
++ val = 0xffff;
++ goto out;
++ }
++
++ val &= ~clear;
++ val |= set;
++ bus->write(bus, phydev->addr, AT803X_DEBUG_PORT_ACCESS_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);
++}
++
+ static void at803x_set_wol_mac_addr(struct phy_device *phydev)
+ {
+ struct net_device *ndev = phydev->attached_dev;
+@@ -62,8 +115,16 @@ static void at803x_set_wol_mac_addr(stru
+ }
+ }
+
++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 val;
+ u32 features;
+ int status;
+@@ -105,6 +166,26 @@ static int at803x_config_init(struct phy
+ status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE);
+ status = phy_read(phydev, AT803X_INTR_STATUS);
+
++ 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_DBG0_RGMII_RX_CLK_DELAY_EN);
++ else
++ at803x_dbg_reg_clr(phydev, AT803X_DBG0_REG,
++ AT803X_DBG0_RGMII_RX_CLK_DELAY_EN);
++
++ if (pdata->enable_rgmii_tx_delay)
++ at803x_dbg_reg_set(phydev, AT803X_DBG5_REG,
++ AT803X_DBG5_RGMII_TX_CLK_DELAY_EN);
++ else
++ at803x_dbg_reg_clr(phydev, AT803X_DBG5_REG,
++ AT803X_DBG5_RGMII_TX_CLK_DELAY_EN);
++ }
++
+ return 0;
+ }
+
+--- /dev/null
++++ b/include/linux/platform_data/phy-at803x.h
+@@ -0,0 +1,10 @@
++#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;
++};
++
++#endif /* _PHY_AT803X_PDATA_H */