Merge tag 'platform-drivers-x86-v5.19-3' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / net / phy / microchip_t1.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2018 Microchip Technology
3
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include <linux/delay.h>
7 #include <linux/mii.h>
8 #include <linux/phy.h>
9 #include <linux/ethtool.h>
10 #include <linux/ethtool_netlink.h>
11 #include <linux/bitfield.h>
12
13 #define PHY_ID_LAN87XX                          0x0007c150
14 #define PHY_ID_LAN937X                          0x0007c180
15
16 /* External Register Control Register */
17 #define LAN87XX_EXT_REG_CTL                     (0x14)
18 #define LAN87XX_EXT_REG_CTL_RD_CTL              (0x1000)
19 #define LAN87XX_EXT_REG_CTL_WR_CTL              (0x0800)
20 #define LAN87XX_REG_BANK_SEL_MASK               GENMASK(10, 8)
21 #define LAN87XX_REG_ADDR_MASK                   GENMASK(7, 0)
22
23 /* External Register Read Data Register */
24 #define LAN87XX_EXT_REG_RD_DATA                 (0x15)
25
26 /* External Register Write Data Register */
27 #define LAN87XX_EXT_REG_WR_DATA                 (0x16)
28
29 /* Interrupt Source Register */
30 #define LAN87XX_INTERRUPT_SOURCE                (0x18)
31
32 /* Interrupt Mask Register */
33 #define LAN87XX_INTERRUPT_MASK                  (0x19)
34 #define LAN87XX_MASK_LINK_UP                    (0x0004)
35 #define LAN87XX_MASK_LINK_DOWN                  (0x0002)
36
37 /* MISC Control 1 Register */
38 #define LAN87XX_CTRL_1                          (0x11)
39 #define LAN87XX_MASK_RGMII_TXC_DLY_EN           (0x4000)
40 #define LAN87XX_MASK_RGMII_RXC_DLY_EN           (0x2000)
41
42 /* phyaccess nested types */
43 #define PHYACC_ATTR_MODE_READ           0
44 #define PHYACC_ATTR_MODE_WRITE          1
45 #define PHYACC_ATTR_MODE_MODIFY         2
46 #define PHYACC_ATTR_MODE_POLL           3
47
48 #define PHYACC_ATTR_BANK_SMI            0
49 #define PHYACC_ATTR_BANK_MISC           1
50 #define PHYACC_ATTR_BANK_PCS            2
51 #define PHYACC_ATTR_BANK_AFE            3
52 #define PHYACC_ATTR_BANK_DSP            4
53 #define PHYACC_ATTR_BANK_MAX            7
54
55 /* measurement defines */
56 #define LAN87XX_CABLE_TEST_OK           0
57 #define LAN87XX_CABLE_TEST_OPEN 1
58 #define LAN87XX_CABLE_TEST_SAME_SHORT   2
59
60 /* T1 Registers */
61 #define T1_AFE_PORT_CFG1_REG            0x0B
62 #define T1_POWER_DOWN_CONTROL_REG       0x1A
63 #define T1_SLV_FD_MULT_CFG_REG          0x18
64 #define T1_CDR_CFG_PRE_LOCK_REG         0x05
65 #define T1_CDR_CFG_POST_LOCK_REG        0x06
66 #define T1_LCK_STG2_MUFACT_CFG_REG      0x1A
67 #define T1_LCK_STG3_MUFACT_CFG_REG      0x1B
68 #define T1_POST_LCK_MUFACT_CFG_REG      0x1C
69 #define T1_TX_RX_FIFO_CFG_REG           0x02
70 #define T1_TX_LPF_FIR_CFG_REG           0x55
71 #define T1_COEF_CLK_PWR_DN_CFG          0x04
72 #define T1_COEF_RW_CTL_CFG              0x0D
73 #define T1_SQI_CONFIG_REG               0x2E
74 #define T1_SQI_CONFIG2_REG              0x4A
75 #define T1_DCQ_SQI_REG                  0xC3
76 #define T1_DCQ_SQI_MSK                  GENMASK(3, 1)
77 #define T1_MDIO_CONTROL2_REG            0x10
78 #define T1_INTERRUPT_SOURCE_REG         0x18
79 #define T1_INTERRUPT2_SOURCE_REG        0x08
80 #define T1_EQ_FD_STG1_FRZ_CFG           0x69
81 #define T1_EQ_FD_STG2_FRZ_CFG           0x6A
82 #define T1_EQ_FD_STG3_FRZ_CFG           0x6B
83 #define T1_EQ_FD_STG4_FRZ_CFG           0x6C
84 #define T1_EQ_WT_FD_LCK_FRZ_CFG         0x6D
85 #define T1_PST_EQ_LCK_STG1_FRZ_CFG      0x6E
86
87 #define T1_MODE_STAT_REG                0x11
88 #define T1_LINK_UP_MSK                  BIT(0)
89
90 /* SQI defines */
91 #define LAN87XX_MAX_SQI                 0x07
92
93 #define DRIVER_AUTHOR   "Nisar Sayed <nisar.sayed@microchip.com>"
94 #define DRIVER_DESC     "Microchip LAN87XX/LAN937x T1 PHY driver"
95
96 struct access_ereg_val {
97         u8  mode;
98         u8  bank;
99         u8  offset;
100         u16 val;
101         u16 mask;
102 };
103
104 static int lan937x_dsp_workaround(struct phy_device *phydev, u16 ereg, u8 bank)
105 {
106         u8 prev_bank;
107         int rc = 0;
108         u16 val;
109
110         mutex_lock(&phydev->lock);
111         /* Read previous selected bank */
112         rc = phy_read(phydev, LAN87XX_EXT_REG_CTL);
113         if (rc < 0)
114                 goto out_unlock;
115
116         /* store the prev_bank */
117         prev_bank = FIELD_GET(LAN87XX_REG_BANK_SEL_MASK, rc);
118
119         if (bank != prev_bank && bank == PHYACC_ATTR_BANK_DSP) {
120                 val = ereg & ~LAN87XX_REG_ADDR_MASK;
121
122                 val &= ~LAN87XX_EXT_REG_CTL_WR_CTL;
123                 val |= LAN87XX_EXT_REG_CTL_RD_CTL;
124
125                 /* access twice for DSP bank change,dummy access */
126                 rc = phy_write(phydev, LAN87XX_EXT_REG_CTL, val);
127         }
128
129 out_unlock:
130         mutex_unlock(&phydev->lock);
131
132         return rc;
133 }
134
135 static int access_ereg(struct phy_device *phydev, u8 mode, u8 bank,
136                        u8 offset, u16 val)
137 {
138         u16 ereg = 0;
139         int rc = 0;
140
141         if (mode > PHYACC_ATTR_MODE_WRITE || bank > PHYACC_ATTR_BANK_MAX)
142                 return -EINVAL;
143
144         if (bank == PHYACC_ATTR_BANK_SMI) {
145                 if (mode == PHYACC_ATTR_MODE_WRITE)
146                         rc = phy_write(phydev, offset, val);
147                 else
148                         rc = phy_read(phydev, offset);
149                 return rc;
150         }
151
152         if (mode == PHYACC_ATTR_MODE_WRITE) {
153                 ereg = LAN87XX_EXT_REG_CTL_WR_CTL;
154                 rc = phy_write(phydev, LAN87XX_EXT_REG_WR_DATA, val);
155                 if (rc < 0)
156                         return rc;
157         } else {
158                 ereg = LAN87XX_EXT_REG_CTL_RD_CTL;
159         }
160
161         ereg |= (bank << 8) | offset;
162
163         /* DSP bank access workaround for lan937x */
164         if (phydev->phy_id == PHY_ID_LAN937X) {
165                 rc = lan937x_dsp_workaround(phydev, ereg, bank);
166                 if (rc < 0)
167                         return rc;
168         }
169
170         rc = phy_write(phydev, LAN87XX_EXT_REG_CTL, ereg);
171         if (rc < 0)
172                 return rc;
173
174         if (mode == PHYACC_ATTR_MODE_READ)
175                 rc = phy_read(phydev, LAN87XX_EXT_REG_RD_DATA);
176
177         return rc;
178 }
179
180 static int access_ereg_modify_changed(struct phy_device *phydev,
181                                       u8 bank, u8 offset, u16 val, u16 mask)
182 {
183         int new = 0, rc = 0;
184
185         if (bank > PHYACC_ATTR_BANK_MAX)
186                 return -EINVAL;
187
188         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, bank, offset, val);
189         if (rc < 0)
190                 return rc;
191
192         new = val | (rc & (mask ^ 0xFFFF));
193         rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, bank, offset, new);
194
195         return rc;
196 }
197
198 static int access_smi_poll_timeout(struct phy_device *phydev,
199                                    u8 offset, u16 mask, u16 clr)
200 {
201         int val;
202
203         return phy_read_poll_timeout(phydev, offset, val, (val & mask) == clr,
204                                      150, 30000, true);
205 }
206
207 static int lan87xx_config_rgmii_delay(struct phy_device *phydev)
208 {
209         int rc;
210
211         if (!phy_interface_is_rgmii(phydev))
212                 return 0;
213
214         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
215                          PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, 0);
216         if (rc < 0)
217                 return rc;
218
219         switch (phydev->interface) {
220         case PHY_INTERFACE_MODE_RGMII:
221                 rc &= ~LAN87XX_MASK_RGMII_TXC_DLY_EN;
222                 rc &= ~LAN87XX_MASK_RGMII_RXC_DLY_EN;
223                 break;
224         case PHY_INTERFACE_MODE_RGMII_ID:
225                 rc |= LAN87XX_MASK_RGMII_TXC_DLY_EN;
226                 rc |= LAN87XX_MASK_RGMII_RXC_DLY_EN;
227                 break;
228         case PHY_INTERFACE_MODE_RGMII_RXID:
229                 rc &= ~LAN87XX_MASK_RGMII_TXC_DLY_EN;
230                 rc |= LAN87XX_MASK_RGMII_RXC_DLY_EN;
231                 break;
232         case PHY_INTERFACE_MODE_RGMII_TXID:
233                 rc |= LAN87XX_MASK_RGMII_TXC_DLY_EN;
234                 rc &= ~LAN87XX_MASK_RGMII_RXC_DLY_EN;
235                 break;
236         default:
237                 return 0;
238         }
239
240         return access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
241                            PHYACC_ATTR_BANK_MISC, LAN87XX_CTRL_1, rc);
242 }
243
244 static int lan87xx_phy_init(struct phy_device *phydev)
245 {
246         static const struct access_ereg_val init[] = {
247                 /* TXPD/TXAMP6 Configs */
248                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_AFE,
249                   T1_AFE_PORT_CFG1_REG,       0x002D,  0 },
250                 /* HW_Init Hi and Force_ED */
251                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
252                   T1_POWER_DOWN_CONTROL_REG,  0x0308,  0 },
253                 /* Equalizer Full Duplex Freeze - T1 Slave */
254                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
255                   T1_EQ_FD_STG1_FRZ_CFG,     0x0002,  0 },
256                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
257                   T1_EQ_FD_STG2_FRZ_CFG,     0x0002,  0 },
258                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
259                   T1_EQ_FD_STG3_FRZ_CFG,     0x0002,  0 },
260                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
261                   T1_EQ_FD_STG4_FRZ_CFG,     0x0002,  0 },
262                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
263                   T1_EQ_WT_FD_LCK_FRZ_CFG,    0x0002,  0 },
264                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
265                   T1_PST_EQ_LCK_STG1_FRZ_CFG, 0x0002,  0 },
266                 /* Slave Full Duplex Multi Configs */
267                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
268                   T1_SLV_FD_MULT_CFG_REG,     0x0D53,  0 },
269                 /* CDR Pre and Post Lock Configs */
270                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
271                   T1_CDR_CFG_PRE_LOCK_REG,    0x0AB2,  0 },
272                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
273                   T1_CDR_CFG_POST_LOCK_REG,   0x0AB3,  0 },
274                 /* Lock Stage 2-3 Multi Factor Config */
275                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
276                   T1_LCK_STG2_MUFACT_CFG_REG, 0x0AEA,  0 },
277                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
278                   T1_LCK_STG3_MUFACT_CFG_REG, 0x0AEB,  0 },
279                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
280                   T1_POST_LCK_MUFACT_CFG_REG, 0x0AEB,  0 },
281                 /* Pointer delay */
282                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
283                   T1_TX_RX_FIFO_CFG_REG, 0x1C00, 0 },
284                 /* Tx iir edits */
285                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
286                   T1_TX_LPF_FIR_CFG_REG, 0x1000, 0 },
287                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
288                   T1_TX_LPF_FIR_CFG_REG, 0x1861, 0 },
289                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
290                   T1_TX_LPF_FIR_CFG_REG, 0x1061, 0 },
291                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
292                   T1_TX_LPF_FIR_CFG_REG, 0x1922, 0 },
293                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
294                   T1_TX_LPF_FIR_CFG_REG, 0x1122, 0 },
295                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
296                   T1_TX_LPF_FIR_CFG_REG, 0x1983, 0 },
297                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
298                   T1_TX_LPF_FIR_CFG_REG, 0x1183, 0 },
299                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
300                   T1_TX_LPF_FIR_CFG_REG, 0x1944, 0 },
301                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
302                   T1_TX_LPF_FIR_CFG_REG, 0x1144, 0 },
303                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
304                   T1_TX_LPF_FIR_CFG_REG, 0x18c5, 0 },
305                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
306                   T1_TX_LPF_FIR_CFG_REG, 0x10c5, 0 },
307                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
308                   T1_TX_LPF_FIR_CFG_REG, 0x1846, 0 },
309                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
310                   T1_TX_LPF_FIR_CFG_REG, 0x1046, 0 },
311                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
312                   T1_TX_LPF_FIR_CFG_REG, 0x1807, 0 },
313                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
314                   T1_TX_LPF_FIR_CFG_REG, 0x1007, 0 },
315                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
316                   T1_TX_LPF_FIR_CFG_REG, 0x1808, 0 },
317                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
318                   T1_TX_LPF_FIR_CFG_REG, 0x1008, 0 },
319                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
320                   T1_TX_LPF_FIR_CFG_REG, 0x1809, 0 },
321                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
322                   T1_TX_LPF_FIR_CFG_REG, 0x1009, 0 },
323                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
324                   T1_TX_LPF_FIR_CFG_REG, 0x180A, 0 },
325                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
326                   T1_TX_LPF_FIR_CFG_REG, 0x100A, 0 },
327                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
328                   T1_TX_LPF_FIR_CFG_REG, 0x180B, 0 },
329                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
330                   T1_TX_LPF_FIR_CFG_REG, 0x100B, 0 },
331                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
332                   T1_TX_LPF_FIR_CFG_REG, 0x180C, 0 },
333                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
334                   T1_TX_LPF_FIR_CFG_REG, 0x100C, 0 },
335                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
336                   T1_TX_LPF_FIR_CFG_REG, 0x180D, 0 },
337                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
338                   T1_TX_LPF_FIR_CFG_REG, 0x100D, 0 },
339                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
340                   T1_TX_LPF_FIR_CFG_REG, 0x180E, 0 },
341                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
342                   T1_TX_LPF_FIR_CFG_REG, 0x100E, 0 },
343                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
344                   T1_TX_LPF_FIR_CFG_REG, 0x180F, 0 },
345                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
346                   T1_TX_LPF_FIR_CFG_REG, 0x100F, 0 },
347                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
348                   T1_TX_LPF_FIR_CFG_REG, 0x1810, 0 },
349                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
350                   T1_TX_LPF_FIR_CFG_REG, 0x1010, 0 },
351                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
352                   T1_TX_LPF_FIR_CFG_REG, 0x1811, 0 },
353                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
354                   T1_TX_LPF_FIR_CFG_REG, 0x1011, 0 },
355                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
356                   T1_TX_LPF_FIR_CFG_REG, 0x1000, 0 },
357                 /* Setup SQI measurement */
358                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
359                   T1_COEF_CLK_PWR_DN_CFG,       0x16d6, 0 },
360                 /* SQI enable */
361                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
362                   T1_SQI_CONFIG_REG,            0x9572, 0 },
363                 /* SQI select mode 5 */
364                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
365                   T1_SQI_CONFIG2_REG,           0x0001, 0 },
366                 /* Throws the first SQI reading */
367                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
368                   T1_COEF_RW_CTL_CFG,           0x0301, 0 },
369                 { PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_DSP,
370                   T1_DCQ_SQI_REG,               0,      0 },
371                 /* Flag LPS and WUR as idle errors */
372                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
373                   T1_MDIO_CONTROL2_REG,         0x0014, 0 },
374                 /* HW_Init toggle, undo force ED, TXPD off */
375                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
376                   T1_POWER_DOWN_CONTROL_REG,    0x0200, 0 },
377                 /* Reset PCS to trigger hardware initialization */
378                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
379                   T1_MDIO_CONTROL2_REG,         0x0094, 0 },
380                 /* Poll till Hardware is initialized */
381                 { PHYACC_ATTR_MODE_POLL, PHYACC_ATTR_BANK_SMI,
382                   T1_MDIO_CONTROL2_REG,         0x0080, 0 },
383                 /* Tx AMP - 0x06  */
384                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_AFE,
385                   T1_AFE_PORT_CFG1_REG,         0x000C, 0 },
386                 /* Read INTERRUPT_SOURCE Register */
387                 { PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI,
388                   T1_INTERRUPT_SOURCE_REG,      0,      0 },
389                 /* Read INTERRUPT_SOURCE Register */
390                 { PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_MISC,
391                   T1_INTERRUPT2_SOURCE_REG,     0,      0 },
392                 /* HW_Init Hi */
393                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
394                   T1_POWER_DOWN_CONTROL_REG,    0x0300, 0 },
395         };
396         int rc, i;
397
398         /* phy Soft reset */
399         rc = genphy_soft_reset(phydev);
400         if (rc < 0)
401                 return rc;
402
403         /* PHY Initialization */
404         for (i = 0; i < ARRAY_SIZE(init); i++) {
405                 if (init[i].mode == PHYACC_ATTR_MODE_POLL &&
406                     init[i].bank == PHYACC_ATTR_BANK_SMI) {
407                         rc = access_smi_poll_timeout(phydev,
408                                                      init[i].offset,
409                                                      init[i].val,
410                                                      init[i].mask);
411                 } else {
412                         rc = access_ereg(phydev, init[i].mode, init[i].bank,
413                                          init[i].offset, init[i].val);
414                 }
415                 if (rc < 0)
416                         return rc;
417         }
418
419         return lan87xx_config_rgmii_delay(phydev);
420 }
421
422 static int lan87xx_phy_config_intr(struct phy_device *phydev)
423 {
424         int rc, val = 0;
425
426         if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
427                 /* unmask all source and clear them before enable */
428                 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, 0x7FFF);
429                 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
430                 val = LAN87XX_MASK_LINK_UP | LAN87XX_MASK_LINK_DOWN;
431                 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
432         } else {
433                 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
434                 if (rc)
435                         return rc;
436
437                 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
438         }
439
440         return rc < 0 ? rc : 0;
441 }
442
443 static irqreturn_t lan87xx_handle_interrupt(struct phy_device *phydev)
444 {
445         int irq_status;
446
447         irq_status = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
448         if (irq_status < 0) {
449                 phy_error(phydev);
450                 return IRQ_NONE;
451         }
452
453         if (irq_status == 0)
454                 return IRQ_NONE;
455
456         phy_trigger_machine(phydev);
457
458         return IRQ_HANDLED;
459 }
460
461 static int lan87xx_config_init(struct phy_device *phydev)
462 {
463         int rc = lan87xx_phy_init(phydev);
464
465         return rc < 0 ? rc : 0;
466 }
467
468 static int microchip_cable_test_start_common(struct phy_device *phydev)
469 {
470         int bmcr, bmsr, ret;
471
472         /* If auto-negotiation is enabled, but not complete, the cable
473          * test never completes. So disable auto-neg.
474          */
475         bmcr = phy_read(phydev, MII_BMCR);
476         if (bmcr < 0)
477                 return bmcr;
478
479         bmsr = phy_read(phydev, MII_BMSR);
480
481         if (bmsr < 0)
482                 return bmsr;
483
484         if (bmcr & BMCR_ANENABLE) {
485                 ret =  phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
486                 if (ret < 0)
487                         return ret;
488                 ret = genphy_soft_reset(phydev);
489                 if (ret < 0)
490                         return ret;
491         }
492
493         /* If the link is up, allow it some time to go down */
494         if (bmsr & BMSR_LSTATUS)
495                 msleep(1500);
496
497         return 0;
498 }
499
500 static int lan87xx_cable_test_start(struct phy_device *phydev)
501 {
502         static const struct access_ereg_val cable_test[] = {
503                 /* min wait */
504                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 93,
505                  0, 0},
506                 /* max wait */
507                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94,
508                  10, 0},
509                 /* pulse cycle */
510                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 95,
511                  90, 0},
512                 /* cable diag thresh */
513                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 92,
514                  60, 0},
515                 /* max gain */
516                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 79,
517                  31, 0},
518                 /* clock align for each iteration */
519                 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_DSP, 55,
520                  0, 0x0038},
521                 /* max cycle wait config */
522                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94,
523                  70, 0},
524                 /* start cable diag*/
525                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 90,
526                  1, 0},
527         };
528         int rc, i;
529
530         rc = microchip_cable_test_start_common(phydev);
531         if (rc < 0)
532                 return rc;
533
534         /* start cable diag */
535         /* check if part is alive - if not, return diagnostic error */
536         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI,
537                          0x00, 0);
538         if (rc < 0)
539                 return rc;
540
541         /* master/slave specific configs */
542         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI,
543                          0x0A, 0);
544         if (rc < 0)
545                 return rc;
546
547         if ((rc & 0x4000) != 0x4000) {
548                 /* DUT is Slave */
549                 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_AFE,
550                                                 0x0E, 0x5, 0x7);
551                 if (rc < 0)
552                         return rc;
553                 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
554                                                 0x1A, 0x8, 0x8);
555                 if (rc < 0)
556                         return rc;
557         } else {
558                 /* DUT is Master */
559                 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
560                                                 0x10, 0x8, 0x40);
561                 if (rc < 0)
562                         return rc;
563         }
564
565         for (i = 0; i < ARRAY_SIZE(cable_test); i++) {
566                 if (cable_test[i].mode == PHYACC_ATTR_MODE_MODIFY) {
567                         rc = access_ereg_modify_changed(phydev,
568                                                         cable_test[i].bank,
569                                                         cable_test[i].offset,
570                                                         cable_test[i].val,
571                                                         cable_test[i].mask);
572                         /* wait 50ms */
573                         msleep(50);
574                 } else {
575                         rc = access_ereg(phydev, cable_test[i].mode,
576                                          cable_test[i].bank,
577                                          cable_test[i].offset,
578                                          cable_test[i].val);
579                 }
580                 if (rc < 0)
581                         return rc;
582         }
583         /* cable diag started */
584
585         return 0;
586 }
587
588 static int lan87xx_cable_test_report_trans(u32 result)
589 {
590         switch (result) {
591         case LAN87XX_CABLE_TEST_OK:
592                 return ETHTOOL_A_CABLE_RESULT_CODE_OK;
593         case LAN87XX_CABLE_TEST_OPEN:
594                 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
595         case LAN87XX_CABLE_TEST_SAME_SHORT:
596                 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
597         default:
598                 /* DIAGNOSTIC_ERROR */
599                 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
600         }
601 }
602
603 static int lan87xx_cable_test_report(struct phy_device *phydev)
604 {
605         int pos_peak_cycle = 0, pos_peak_in_phases = 0, pos_peak_phase = 0;
606         int neg_peak_cycle = 0, neg_peak_in_phases = 0, neg_peak_phase = 0;
607         int noise_margin = 20, time_margin = 89, jitter_var = 30;
608         int min_time_diff = 96, max_time_diff = 96 + time_margin;
609         bool fault = false, check_a = false, check_b = false;
610         int gain_idx = 0, pos_peak = 0, neg_peak = 0;
611         int pos_peak_time = 0, neg_peak_time = 0;
612         int pos_peak_in_phases_hybrid = 0;
613         int detect = -1;
614
615         gain_idx = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
616                                PHYACC_ATTR_BANK_DSP, 151, 0);
617         /* read non-hybrid results */
618         pos_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
619                                PHYACC_ATTR_BANK_DSP, 153, 0);
620         neg_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
621                                PHYACC_ATTR_BANK_DSP, 154, 0);
622         pos_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
623                                     PHYACC_ATTR_BANK_DSP, 156, 0);
624         neg_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
625                                     PHYACC_ATTR_BANK_DSP, 157, 0);
626
627         pos_peak_cycle = (pos_peak_time >> 7) & 0x7F;
628         /* calculate non-hybrid values */
629         pos_peak_phase = pos_peak_time & 0x7F;
630         pos_peak_in_phases = (pos_peak_cycle * 96) + pos_peak_phase;
631         neg_peak_cycle = (neg_peak_time >> 7) & 0x7F;
632         neg_peak_phase = neg_peak_time & 0x7F;
633         neg_peak_in_phases = (neg_peak_cycle * 96) + neg_peak_phase;
634
635         /* process values */
636         check_a =
637                 ((pos_peak_in_phases - neg_peak_in_phases) >= min_time_diff) &&
638                 ((pos_peak_in_phases - neg_peak_in_phases) < max_time_diff) &&
639                 pos_peak_in_phases_hybrid < pos_peak_in_phases &&
640                 (pos_peak_in_phases_hybrid < (neg_peak_in_phases + jitter_var));
641         check_b =
642                 ((neg_peak_in_phases - pos_peak_in_phases) >= min_time_diff) &&
643                 ((neg_peak_in_phases - pos_peak_in_phases) < max_time_diff) &&
644                 pos_peak_in_phases_hybrid < neg_peak_in_phases &&
645                 (pos_peak_in_phases_hybrid < (pos_peak_in_phases + jitter_var));
646
647         if (pos_peak_in_phases > neg_peak_in_phases && check_a)
648                 detect = 2;
649         else if ((neg_peak_in_phases > pos_peak_in_phases) && check_b)
650                 detect = 1;
651
652         if (pos_peak > noise_margin && neg_peak > noise_margin &&
653             gain_idx >= 0) {
654                 if (detect == 1 || detect == 2)
655                         fault = true;
656         }
657
658         if (!fault)
659                 detect = 0;
660
661         ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
662                                 lan87xx_cable_test_report_trans(detect));
663
664         return 0;
665 }
666
667 static int lan87xx_cable_test_get_status(struct phy_device *phydev,
668                                          bool *finished)
669 {
670         int rc = 0;
671
672         *finished = false;
673
674         /* check if cable diag was finished */
675         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_DSP,
676                          90, 0);
677         if (rc < 0)
678                 return rc;
679
680         if ((rc & 2) == 2) {
681                 /* stop cable diag*/
682                 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
683                                  PHYACC_ATTR_BANK_DSP,
684                                  90, 0);
685                 if (rc < 0)
686                         return rc;
687
688                 *finished = true;
689
690                 return lan87xx_cable_test_report(phydev);
691         }
692
693         return 0;
694 }
695
696 static int lan87xx_read_status(struct phy_device *phydev)
697 {
698         int rc = 0;
699
700         rc = phy_read(phydev, T1_MODE_STAT_REG);
701         if (rc < 0)
702                 return rc;
703
704         if (rc & T1_LINK_UP_MSK)
705                 phydev->link = 1;
706         else
707                 phydev->link = 0;
708
709         phydev->speed = SPEED_UNKNOWN;
710         phydev->duplex = DUPLEX_UNKNOWN;
711         phydev->pause = 0;
712         phydev->asym_pause = 0;
713
714         rc = genphy_read_master_slave(phydev);
715         if (rc < 0)
716                 return rc;
717
718         rc = genphy_read_status_fixed(phydev);
719         if (rc < 0)
720                 return rc;
721
722         return rc;
723 }
724
725 static int lan87xx_config_aneg(struct phy_device *phydev)
726 {
727         u16 ctl = 0;
728
729         switch (phydev->master_slave_set) {
730         case MASTER_SLAVE_CFG_MASTER_FORCE:
731                 ctl |= CTL1000_AS_MASTER;
732                 break;
733         case MASTER_SLAVE_CFG_SLAVE_FORCE:
734                 break;
735         case MASTER_SLAVE_CFG_UNKNOWN:
736         case MASTER_SLAVE_CFG_UNSUPPORTED:
737                 return 0;
738         default:
739                 phydev_warn(phydev, "Unsupported Master/Slave mode\n");
740                 return -EOPNOTSUPP;
741         }
742
743         return phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl);
744 }
745
746 static int lan87xx_get_sqi(struct phy_device *phydev)
747 {
748         u8 sqi_value = 0;
749         int rc;
750
751         rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
752                          PHYACC_ATTR_BANK_DSP, T1_COEF_RW_CTL_CFG, 0x0301);
753         if (rc < 0)
754                 return rc;
755
756         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
757                          PHYACC_ATTR_BANK_DSP, T1_DCQ_SQI_REG, 0x0);
758         if (rc < 0)
759                 return rc;
760
761         sqi_value = FIELD_GET(T1_DCQ_SQI_MSK, rc);
762
763         return sqi_value;
764 }
765
766 static int lan87xx_get_sqi_max(struct phy_device *phydev)
767 {
768         return LAN87XX_MAX_SQI;
769 }
770
771 static struct phy_driver microchip_t1_phy_driver[] = {
772         {
773                 PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX),
774                 .name           = "Microchip LAN87xx T1",
775                 .flags          = PHY_POLL_CABLE_TEST,
776                 .features       = PHY_BASIC_T1_FEATURES,
777                 .config_init    = lan87xx_config_init,
778                 .config_intr    = lan87xx_phy_config_intr,
779                 .handle_interrupt = lan87xx_handle_interrupt,
780                 .suspend        = genphy_suspend,
781                 .resume         = genphy_resume,
782                 .config_aneg    = lan87xx_config_aneg,
783                 .read_status    = lan87xx_read_status,
784                 .get_sqi        = lan87xx_get_sqi,
785                 .get_sqi_max    = lan87xx_get_sqi_max,
786                 .cable_test_start = lan87xx_cable_test_start,
787                 .cable_test_get_status = lan87xx_cable_test_get_status,
788         },
789         {
790                 PHY_ID_MATCH_MODEL(PHY_ID_LAN937X),
791                 .name           = "Microchip LAN937x T1",
792                 .flags          = PHY_POLL_CABLE_TEST,
793                 .features       = PHY_BASIC_T1_FEATURES,
794                 .config_init    = lan87xx_config_init,
795                 .config_intr    = lan87xx_phy_config_intr,
796                 .handle_interrupt = lan87xx_handle_interrupt,
797                 .suspend        = genphy_suspend,
798                 .resume         = genphy_resume,
799                 .config_aneg    = lan87xx_config_aneg,
800                 .read_status    = lan87xx_read_status,
801                 .get_sqi        = lan87xx_get_sqi,
802                 .get_sqi_max    = lan87xx_get_sqi_max,
803                 .cable_test_start = lan87xx_cable_test_start,
804                 .cable_test_get_status = lan87xx_cable_test_get_status,
805         }
806 };
807
808 module_phy_driver(microchip_t1_phy_driver);
809
810 static struct mdio_device_id __maybe_unused microchip_t1_tbl[] = {
811         { PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX) },
812         { PHY_ID_MATCH_MODEL(PHY_ID_LAN937X) },
813         { }
814 };
815
816 MODULE_DEVICE_TABLE(mdio, microchip_t1_tbl);
817
818 MODULE_AUTHOR(DRIVER_AUTHOR);
819 MODULE_DESCRIPTION(DRIVER_DESC);
820 MODULE_LICENSE("GPL");