f2e40fb0105a7cd1e554c331671433383362d40e
[oweals/openwrt.git] /
1 From 07667014469b0e1464d1cd77d0b42d523fd3ad46 Mon Sep 17 00:00:00 2001
2 From: Raghuram Chary J <raghuramchary.jallipalli@microchip.com>
3 Date: Wed, 11 Apr 2018 20:36:36 +0530
4 Subject: [PATCH 296/454] lan78xx: PHY DSP registers initialization to address
5  EEE link drop issues with long cables
6
7 commit 1c2734b31d72316e3faaad88c0c9c46fa92a4b20 upstream.
8
9 The patch is to configure DSP registers of PHY device
10 to handle Gbe-EEE failures with >40m cable length.
11
12 Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver")
13 Signed-off-by: Raghuram Chary J <raghuramchary.jallipalli@microchip.com>
14 Signed-off-by: David S. Miller <davem@davemloft.net>
15 ---
16  drivers/net/phy/microchip.c  | 178 ++++++++++++++++++++++++++++++++++-
17  include/linux/microchipphy.h |   8 ++
18  2 files changed, 185 insertions(+), 1 deletion(-)
19
20 --- a/drivers/net/phy/microchip.c
21 +++ b/drivers/net/phy/microchip.c
22 @@ -20,6 +20,7 @@
23  #include <linux/ethtool.h>
24  #include <linux/phy.h>
25  #include <linux/microchipphy.h>
26 +#include <linux/delay.h>
27  
28  #define DRIVER_AUTHOR  "WOOJUNG HUH <woojung.huh@microchip.com>"
29  #define DRIVER_DESC    "Microchip LAN88XX PHY driver"
30 @@ -30,6 +31,16 @@ struct lan88xx_priv {
31         __u32   wolopts;
32  };
33  
34 +static int lan88xx_read_page(struct phy_device *phydev)
35 +{
36 +       return __phy_read(phydev, LAN88XX_EXT_PAGE_ACCESS);
37 +}
38 +
39 +static int lan88xx_write_page(struct phy_device *phydev, int page)
40 +{
41 +       return __phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, page);
42 +}
43 +
44  static int lan88xx_phy_config_intr(struct phy_device *phydev)
45  {
46         int rc;
47 @@ -66,6 +77,150 @@ static int lan88xx_suspend(struct phy_de
48         return 0;
49  }
50  
51 +static int lan88xx_TR_reg_set(struct phy_device *phydev, u16 regaddr,
52 +                             u32 data)
53 +{
54 +       int val, save_page, ret = 0;
55 +       u16 buf;
56 +
57 +       /* Save current page */
58 +       save_page = phy_save_page(phydev);
59 +       if (save_page < 0) {
60 +               pr_warn("Failed to get current page\n");
61 +               goto err;
62 +       }
63 +
64 +       /* Switch to TR page */
65 +       lan88xx_write_page(phydev, LAN88XX_EXT_PAGE_ACCESS_TR);
66 +
67 +       ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_LOW_DATA,
68 +                         (data & 0xFFFF));
69 +       if (ret < 0) {
70 +               pr_warn("Failed to write TR low data\n");
71 +               goto err;
72 +       }
73 +
74 +       ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_HIGH_DATA,
75 +                         (data & 0x00FF0000) >> 16);
76 +       if (ret < 0) {
77 +               pr_warn("Failed to write TR high data\n");
78 +               goto err;
79 +       }
80 +
81 +       /* Config control bits [15:13] of register */
82 +       buf = (regaddr & ~(0x3 << 13));/* Clr [14:13] to write data in reg */
83 +       buf |= 0x8000; /* Set [15] to Packet transmit */
84 +
85 +       ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_CR, buf);
86 +       if (ret < 0) {
87 +               pr_warn("Failed to write data in reg\n");
88 +               goto err;
89 +       }
90 +
91 +       usleep_range(1000, 2000);/* Wait for Data to be written */
92 +       val = __phy_read(phydev, LAN88XX_EXT_PAGE_TR_CR);
93 +       if (!(val & 0x8000))
94 +               pr_warn("TR Register[0x%X] configuration failed\n", regaddr);
95 +err:
96 +       return phy_restore_page(phydev, save_page, ret);
97 +}
98 +
99 +static void lan88xx_config_TR_regs(struct phy_device *phydev)
100 +{
101 +       int err;
102 +
103 +       /* Get access to Channel 0x1, Node 0xF , Register 0x01.
104 +        * Write 24-bit value 0x12B00A to register. Setting MrvlTrFix1000Kf,
105 +        * MrvlTrFix1000Kp, MasterEnableTR bits.
106 +        */
107 +       err = lan88xx_TR_reg_set(phydev, 0x0F82, 0x12B00A);
108 +       if (err < 0)
109 +               pr_warn("Failed to Set Register[0x0F82]\n");
110 +
111 +       /* Get access to Channel b'10, Node b'1101, Register 0x06.
112 +        * Write 24-bit value 0xD2C46F to register. Setting SSTrKf1000Slv,
113 +        * SSTrKp1000Mas bits.
114 +        */
115 +       err = lan88xx_TR_reg_set(phydev, 0x168C, 0xD2C46F);
116 +       if (err < 0)
117 +               pr_warn("Failed to Set Register[0x168C]\n");
118 +
119 +       /* Get access to Channel b'10, Node b'1111, Register 0x11.
120 +        * Write 24-bit value 0x620 to register. Setting rem_upd_done_thresh
121 +        * bits
122 +        */
123 +       err = lan88xx_TR_reg_set(phydev, 0x17A2, 0x620);
124 +       if (err < 0)
125 +               pr_warn("Failed to Set Register[0x17A2]\n");
126 +
127 +       /* Get access to Channel b'10, Node b'1101, Register 0x10.
128 +        * Write 24-bit value 0xEEFFDD to register. Setting
129 +        * eee_TrKp1Long_1000, eee_TrKp2Long_1000, eee_TrKp3Long_1000,
130 +        * eee_TrKp1Short_1000,eee_TrKp2Short_1000, eee_TrKp3Short_1000 bits.
131 +        */
132 +       err = lan88xx_TR_reg_set(phydev, 0x16A0, 0xEEFFDD);
133 +       if (err < 0)
134 +               pr_warn("Failed to Set Register[0x16A0]\n");
135 +
136 +       /* Get access to Channel b'10, Node b'1101, Register 0x13.
137 +        * Write 24-bit value 0x071448 to register. Setting
138 +        * slv_lpi_tr_tmr_val1, slv_lpi_tr_tmr_val2 bits.
139 +        */
140 +       err = lan88xx_TR_reg_set(phydev, 0x16A6, 0x071448);
141 +       if (err < 0)
142 +               pr_warn("Failed to Set Register[0x16A6]\n");
143 +
144 +       /* Get access to Channel b'10, Node b'1101, Register 0x12.
145 +        * Write 24-bit value 0x13132F to register. Setting
146 +        * slv_sigdet_timer_val1, slv_sigdet_timer_val2 bits.
147 +        */
148 +       err = lan88xx_TR_reg_set(phydev, 0x16A4, 0x13132F);
149 +       if (err < 0)
150 +               pr_warn("Failed to Set Register[0x16A4]\n");
151 +
152 +       /* Get access to Channel b'10, Node b'1101, Register 0x14.
153 +        * Write 24-bit value 0x0 to register. Setting eee_3level_delay,
154 +        * eee_TrKf_freeze_delay bits.
155 +        */
156 +       err = lan88xx_TR_reg_set(phydev, 0x16A8, 0x0);
157 +       if (err < 0)
158 +               pr_warn("Failed to Set Register[0x16A8]\n");
159 +
160 +       /* Get access to Channel b'01, Node b'1111, Register 0x34.
161 +        * Write 24-bit value 0x91B06C to register. Setting
162 +        * FastMseSearchThreshLong1000, FastMseSearchThreshShort1000,
163 +        * FastMseSearchUpdGain1000 bits.
164 +        */
165 +       err = lan88xx_TR_reg_set(phydev, 0x0FE8, 0x91B06C);
166 +       if (err < 0)
167 +               pr_warn("Failed to Set Register[0x0FE8]\n");
168 +
169 +       /* Get access to Channel b'01, Node b'1111, Register 0x3E.
170 +        * Write 24-bit value 0xC0A028 to register. Setting
171 +        * FastMseKp2ThreshLong1000, FastMseKp2ThreshShort1000,
172 +        * FastMseKp2UpdGain1000, FastMseKp2ExitEn1000 bits.
173 +        */
174 +       err = lan88xx_TR_reg_set(phydev, 0x0FFC, 0xC0A028);
175 +       if (err < 0)
176 +               pr_warn("Failed to Set Register[0x0FFC]\n");
177 +
178 +       /* Get access to Channel b'01, Node b'1111, Register 0x35.
179 +        * Write 24-bit value 0x041600 to register. Setting
180 +        * FastMseSearchPhShNum1000, FastMseSearchClksPerPh1000,
181 +        * FastMsePhChangeDelay1000 bits.
182 +        */
183 +       err = lan88xx_TR_reg_set(phydev, 0x0FEA, 0x041600);
184 +       if (err < 0)
185 +               pr_warn("Failed to Set Register[0x0FEA]\n");
186 +
187 +       /* Get access to Channel b'10, Node b'1101, Register 0x03.
188 +        * Write 24-bit value 0x000004 to register. Setting TrFreeze bits.
189 +        */
190 +       err = lan88xx_TR_reg_set(phydev, 0x1686, 0x000004);
191 +       if (err < 0)
192 +               pr_warn("Failed to Set Register[0x1686]\n");
193 +}
194 +
195  static int lan88xx_probe(struct phy_device *phydev)
196  {
197         struct device *dev = &phydev->mdio.dev;
198 @@ -132,6 +287,25 @@ static void lan88xx_set_mdix(struct phy_
199         phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0);
200  }
201  
202 +static int lan88xx_config_init(struct phy_device *phydev)
203 +{
204 +       int val;
205 +
206 +       genphy_config_init(phydev);
207 +       /*Zerodetect delay enable */
208 +       val = phy_read_mmd(phydev, MDIO_MMD_PCS,
209 +                          PHY_ARDENNES_MMD_DEV_3_PHY_CFG);
210 +       val |= PHY_ARDENNES_MMD_DEV_3_PHY_CFG_ZD_DLY_EN_;
211 +
212 +       phy_write_mmd(phydev, MDIO_MMD_PCS, PHY_ARDENNES_MMD_DEV_3_PHY_CFG,
213 +                     val);
214 +
215 +       /* Config DSP registers */
216 +       lan88xx_config_TR_regs(phydev);
217 +
218 +       return 0;
219 +}
220 +
221  static int lan88xx_config_aneg(struct phy_device *phydev)
222  {
223         lan88xx_set_mdix(phydev);
224 @@ -151,7 +325,7 @@ static struct phy_driver microchip_phy_d
225         .probe          = lan88xx_probe,
226         .remove         = lan88xx_remove,
227  
228 -       .config_init    = genphy_config_init,
229 +       .config_init    = lan88xx_config_init,
230         .config_aneg    = lan88xx_config_aneg,
231         .read_status    = genphy_read_status,
232  
233 @@ -161,6 +335,8 @@ static struct phy_driver microchip_phy_d
234         .suspend        = lan88xx_suspend,
235         .resume         = genphy_resume,
236         .set_wol        = lan88xx_set_wol,
237 +       .read_page      = lan88xx_read_page,
238 +       .write_page     = lan88xx_write_page,
239  } };
240  
241  module_phy_driver(microchip_phy_driver);
242 --- a/include/linux/microchipphy.h
243 +++ b/include/linux/microchipphy.h
244 @@ -70,4 +70,12 @@
245  #define        LAN88XX_MMD3_CHIP_ID                    (32877)
246  #define        LAN88XX_MMD3_CHIP_REV                   (32878)
247  
248 +/* DSP registers */
249 +#define PHY_ARDENNES_MMD_DEV_3_PHY_CFG         (0x806A)
250 +#define PHY_ARDENNES_MMD_DEV_3_PHY_CFG_ZD_DLY_EN_      (0x2000)
251 +#define LAN88XX_EXT_PAGE_ACCESS_TR             (0x52B5)
252 +#define LAN88XX_EXT_PAGE_TR_CR                 16
253 +#define LAN88XX_EXT_PAGE_TR_LOW_DATA           17
254 +#define LAN88XX_EXT_PAGE_TR_HIGH_DATA          18
255 +
256  #endif /* _MICROCHIPPHY_H */