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