ar71xx: add linux 3.14 support
[openwrt/svn-archive/archive.git] / target / linux / ar71xx / patches-3.14 / 425-net-phy-at803x-allow-to-configure-via-pdata.patch
1 --- a/drivers/net/phy/at803x.c
2 +++ b/drivers/net/phy/at803x.c
3 @@ -12,10 +12,12 @@
4 */
5
6 #include <linux/phy.h>
7 +#include <linux/mdio.h>
8 #include <linux/module.h>
9 #include <linux/string.h>
10 #include <linux/netdevice.h>
11 #include <linux/etherdevice.h>
12 +#include <linux/platform_data/phy-at803x.h>
13
14 #define AT803X_INTR_ENABLE 0x12
15 #define AT803X_INTR_STATUS 0x13
16 @@ -32,10 +34,61 @@
17 #define AT803X_DEBUG_SYSTEM_MODE_CTRL 0x05
18 #define AT803X_DEBUG_RGMII_TX_CLK_DLY BIT(8)
19
20 +#define AT803X_PCS_SMART_EEE_CTRL3 0x805D
21 +
22 +#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK 0x3
23 +#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT 12
24 +#define AT803X_SMART_EEE_CTRL3_LPI_EN BIT(8)
25 +
26 +#define AT803X_DEBUG_PORT_ACCESS_OFFSET 0x1D
27 +#define AT803X_DEBUG_PORT_ACCESS_DATA 0x1E
28 +
29 +#define AT803X_DBG0_REG 0x00
30 +#define AT803X_DBG0_RGMII_RX_CLK_DELAY_EN BIT(8)
31 +
32 +#define AT803X_DBG5_REG 0x05
33 +#define AT803X_DBG5_RGMII_TX_CLK_DELAY_EN BIT(8)
34 +
35 MODULE_DESCRIPTION("Atheros 803x PHY driver");
36 MODULE_AUTHOR("Matus Ujhelyi");
37 MODULE_LICENSE("GPL");
38
39 +static u16
40 +at803x_dbg_reg_rmw(struct phy_device *phydev, u16 reg, u16 clear, u16 set)
41 +{
42 + struct mii_bus *bus = phydev->bus;
43 + int val;
44 +
45 + mutex_lock(&bus->mdio_lock);
46 +
47 + bus->write(bus, phydev->addr, AT803X_DEBUG_PORT_ACCESS_OFFSET, reg);
48 + val = bus->read(bus, phydev->addr, AT803X_DEBUG_PORT_ACCESS_DATA);
49 + if (val < 0) {
50 + val = 0xffff;
51 + goto out;
52 + }
53 +
54 + val &= ~clear;
55 + val |= set;
56 + bus->write(bus, phydev->addr, AT803X_DEBUG_PORT_ACCESS_DATA, val);
57 +
58 +out:
59 + mutex_unlock(&bus->mdio_lock);
60 + return val;
61 +}
62 +
63 +static inline void
64 +at803x_dbg_reg_set(struct phy_device *phydev, u16 reg, u16 set)
65 +{
66 + at803x_dbg_reg_rmw(phydev, reg, 0, set);
67 +}
68 +
69 +static inline void
70 +at803x_dbg_reg_clr(struct phy_device *phydev, u16 reg, u16 clear)
71 +{
72 + at803x_dbg_reg_rmw(phydev, reg, clear, 0);
73 +}
74 +
75 static int at803x_set_wol(struct phy_device *phydev,
76 struct ethtool_wolinfo *wol)
77 {
78 @@ -139,8 +192,16 @@ static int at803x_resume(struct phy_devi
79 return 0;
80 }
81
82 +static void at803x_disable_smarteee(struct phy_device *phydev)
83 +{
84 + phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3,
85 + 1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT);
86 + phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
87 +}
88 +
89 static int at803x_config_init(struct phy_device *phydev)
90 {
91 + struct at803x_platform_data *pdata;
92 int val;
93 int ret;
94 u32 features;
95 @@ -188,6 +249,26 @@ static int at803x_config_init(struct phy
96 return ret;
97 }
98
99 + pdata = dev_get_platdata(&phydev->dev);
100 + if (pdata) {
101 + if (pdata->disable_smarteee)
102 + at803x_disable_smarteee(phydev);
103 +
104 + if (pdata->enable_rgmii_rx_delay)
105 + at803x_dbg_reg_set(phydev, AT803X_DBG0_REG,
106 + AT803X_DBG0_RGMII_RX_CLK_DELAY_EN);
107 + else
108 + at803x_dbg_reg_clr(phydev, AT803X_DBG0_REG,
109 + AT803X_DBG0_RGMII_RX_CLK_DELAY_EN);
110 +
111 + if (pdata->enable_rgmii_tx_delay)
112 + at803x_dbg_reg_set(phydev, AT803X_DBG5_REG,
113 + AT803X_DBG5_RGMII_TX_CLK_DELAY_EN);
114 + else
115 + at803x_dbg_reg_clr(phydev, AT803X_DBG5_REG,
116 + AT803X_DBG5_RGMII_TX_CLK_DELAY_EN);
117 + }
118 +
119 return 0;
120 }
121
122 --- /dev/null
123 +++ b/include/linux/platform_data/phy-at803x.h
124 @@ -0,0 +1,10 @@
125 +#ifndef _PHY_AT803X_PDATA_H
126 +#define _PHY_AT803X_PDATA_H
127 +
128 +struct at803x_platform_data {
129 + int disable_smarteee:1;
130 + int enable_rgmii_tx_delay:1;
131 + int enable_rgmii_rx_delay:1;
132 +};
133 +
134 +#endif /* _PHY_AT803X_PDATA_H */