GNU Linux-libre 6.8.9-gnu
[releases.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_cmd(struct phy_device *phydev,
249                                 const struct access_ereg_val *cmd_seq, int cnt)
250 {
251         int ret, i;
252
253         for (i = 0; i < cnt; i++) {
254                 if (cmd_seq[i].mode == PHYACC_ATTR_MODE_POLL &&
255                     cmd_seq[i].bank == PHYACC_ATTR_BANK_SMI) {
256                         ret = access_smi_poll_timeout(phydev,
257                                                       cmd_seq[i].offset,
258                                                       cmd_seq[i].val,
259                                                       cmd_seq[i].mask);
260                 } else {
261                         ret = access_ereg(phydev, cmd_seq[i].mode,
262                                           cmd_seq[i].bank, cmd_seq[i].offset,
263                                           cmd_seq[i].val);
264                 }
265                 if (ret < 0)
266                         return ret;
267         }
268
269         return ret;
270 }
271
272 static int lan87xx_phy_init(struct phy_device *phydev)
273 {
274         static const struct access_ereg_val hw_init[] = {
275                 /* TXPD/TXAMP6 Configs */
276                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_AFE,
277                   T1_AFE_PORT_CFG1_REG,       0x002D,  0 },
278                 /* HW_Init Hi and Force_ED */
279                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
280                   T1_POWER_DOWN_CONTROL_REG,  0x0308,  0 },
281         };
282
283         static const struct access_ereg_val slave_init[] = {
284                 /* Equalizer Full Duplex Freeze - T1 Slave */
285                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
286                   T1_EQ_FD_STG1_FRZ_CFG,     0x0002,  0 },
287                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
288                   T1_EQ_FD_STG2_FRZ_CFG,     0x0002,  0 },
289                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
290                   T1_EQ_FD_STG3_FRZ_CFG,     0x0002,  0 },
291                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
292                   T1_EQ_FD_STG4_FRZ_CFG,     0x0002,  0 },
293                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
294                   T1_EQ_WT_FD_LCK_FRZ_CFG,    0x0002,  0 },
295                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
296                   T1_PST_EQ_LCK_STG1_FRZ_CFG, 0x0002,  0 },
297         };
298
299         static const struct access_ereg_val phy_init[] = {
300                 /* Slave Full Duplex Multi Configs */
301                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
302                   T1_SLV_FD_MULT_CFG_REG,     0x0D53,  0 },
303                 /* CDR Pre and Post Lock Configs */
304                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
305                   T1_CDR_CFG_PRE_LOCK_REG,    0x0AB2,  0 },
306                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
307                   T1_CDR_CFG_POST_LOCK_REG,   0x0AB3,  0 },
308                 /* Lock Stage 2-3 Multi Factor Config */
309                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
310                   T1_LCK_STG2_MUFACT_CFG_REG, 0x0AEA,  0 },
311                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
312                   T1_LCK_STG3_MUFACT_CFG_REG, 0x0AEB,  0 },
313                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
314                   T1_POST_LCK_MUFACT_CFG_REG, 0x0AEB,  0 },
315                 /* Pointer delay */
316                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
317                   T1_TX_RX_FIFO_CFG_REG, 0x1C00, 0 },
318                 /* Tx iir edits */
319                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
320                   T1_TX_LPF_FIR_CFG_REG, 0x1000, 0 },
321                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
322                   T1_TX_LPF_FIR_CFG_REG, 0x1861, 0 },
323                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
324                   T1_TX_LPF_FIR_CFG_REG, 0x1061, 0 },
325                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
326                   T1_TX_LPF_FIR_CFG_REG, 0x1922, 0 },
327                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
328                   T1_TX_LPF_FIR_CFG_REG, 0x1122, 0 },
329                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
330                   T1_TX_LPF_FIR_CFG_REG, 0x1983, 0 },
331                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
332                   T1_TX_LPF_FIR_CFG_REG, 0x1183, 0 },
333                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
334                   T1_TX_LPF_FIR_CFG_REG, 0x1944, 0 },
335                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
336                   T1_TX_LPF_FIR_CFG_REG, 0x1144, 0 },
337                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
338                   T1_TX_LPF_FIR_CFG_REG, 0x18c5, 0 },
339                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
340                   T1_TX_LPF_FIR_CFG_REG, 0x10c5, 0 },
341                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
342                   T1_TX_LPF_FIR_CFG_REG, 0x1846, 0 },
343                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
344                   T1_TX_LPF_FIR_CFG_REG, 0x1046, 0 },
345                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
346                   T1_TX_LPF_FIR_CFG_REG, 0x1807, 0 },
347                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
348                   T1_TX_LPF_FIR_CFG_REG, 0x1007, 0 },
349                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
350                   T1_TX_LPF_FIR_CFG_REG, 0x1808, 0 },
351                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
352                   T1_TX_LPF_FIR_CFG_REG, 0x1008, 0 },
353                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
354                   T1_TX_LPF_FIR_CFG_REG, 0x1809, 0 },
355                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
356                   T1_TX_LPF_FIR_CFG_REG, 0x1009, 0 },
357                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
358                   T1_TX_LPF_FIR_CFG_REG, 0x180A, 0 },
359                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
360                   T1_TX_LPF_FIR_CFG_REG, 0x100A, 0 },
361                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
362                   T1_TX_LPF_FIR_CFG_REG, 0x180B, 0 },
363                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
364                   T1_TX_LPF_FIR_CFG_REG, 0x100B, 0 },
365                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
366                   T1_TX_LPF_FIR_CFG_REG, 0x180C, 0 },
367                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
368                   T1_TX_LPF_FIR_CFG_REG, 0x100C, 0 },
369                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
370                   T1_TX_LPF_FIR_CFG_REG, 0x180D, 0 },
371                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
372                   T1_TX_LPF_FIR_CFG_REG, 0x100D, 0 },
373                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
374                   T1_TX_LPF_FIR_CFG_REG, 0x180E, 0 },
375                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
376                   T1_TX_LPF_FIR_CFG_REG, 0x100E, 0 },
377                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
378                   T1_TX_LPF_FIR_CFG_REG, 0x180F, 0 },
379                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
380                   T1_TX_LPF_FIR_CFG_REG, 0x100F, 0 },
381                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
382                   T1_TX_LPF_FIR_CFG_REG, 0x1810, 0 },
383                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
384                   T1_TX_LPF_FIR_CFG_REG, 0x1010, 0 },
385                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
386                   T1_TX_LPF_FIR_CFG_REG, 0x1811, 0 },
387                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
388                   T1_TX_LPF_FIR_CFG_REG, 0x1011, 0 },
389                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
390                   T1_TX_LPF_FIR_CFG_REG, 0x1000, 0 },
391                 /* Setup SQI measurement */
392                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
393                   T1_COEF_CLK_PWR_DN_CFG,       0x16d6, 0 },
394                 /* SQI enable */
395                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
396                   T1_SQI_CONFIG_REG,            0x9572, 0 },
397                 /* SQI select mode 5 */
398                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
399                   T1_SQI_CONFIG2_REG,           0x0001, 0 },
400                 /* Throws the first SQI reading */
401                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP,
402                   T1_COEF_RW_CTL_CFG,           0x0301, 0 },
403                 { PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_DSP,
404                   T1_DCQ_SQI_REG,               0,      0 },
405                 /* Flag LPS and WUR as idle errors */
406                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
407                   T1_MDIO_CONTROL2_REG,         0x0014, 0 },
408                 /* HW_Init toggle, undo force ED, TXPD off */
409                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
410                   T1_POWER_DOWN_CONTROL_REG,    0x0200, 0 },
411                 /* Reset PCS to trigger hardware initialization */
412                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
413                   T1_MDIO_CONTROL2_REG,         0x0094, 0 },
414                 /* Poll till Hardware is initialized */
415                 { PHYACC_ATTR_MODE_POLL, PHYACC_ATTR_BANK_SMI,
416                   T1_MDIO_CONTROL2_REG,         0x0080, 0 },
417                 /* Tx AMP - 0x06  */
418                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_AFE,
419                   T1_AFE_PORT_CFG1_REG,         0x000C, 0 },
420                 /* Read INTERRUPT_SOURCE Register */
421                 { PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI,
422                   T1_INTERRUPT_SOURCE_REG,      0,      0 },
423                 /* Read INTERRUPT_SOURCE Register */
424                 { PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_MISC,
425                   T1_INTERRUPT2_SOURCE_REG,     0,      0 },
426                 /* HW_Init Hi */
427                 { PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_SMI,
428                   T1_POWER_DOWN_CONTROL_REG,    0x0300, 0 },
429         };
430         int rc;
431
432         /* phy Soft reset */
433         rc = genphy_soft_reset(phydev);
434         if (rc < 0)
435                 return rc;
436
437         /* PHY Initialization */
438         rc = lan87xx_phy_init_cmd(phydev, hw_init, ARRAY_SIZE(hw_init));
439         if (rc < 0)
440                 return rc;
441
442         rc = genphy_read_master_slave(phydev);
443         if (rc)
444                 return rc;
445
446         /* The following squence needs to run only if phydev is in
447          * slave mode.
448          */
449         if (phydev->master_slave_state == MASTER_SLAVE_STATE_SLAVE) {
450                 rc = lan87xx_phy_init_cmd(phydev, slave_init,
451                                           ARRAY_SIZE(slave_init));
452                 if (rc < 0)
453                         return rc;
454         }
455
456         rc = lan87xx_phy_init_cmd(phydev, phy_init, ARRAY_SIZE(phy_init));
457         if (rc < 0)
458                 return rc;
459
460         return lan87xx_config_rgmii_delay(phydev);
461 }
462
463 static int lan87xx_phy_config_intr(struct phy_device *phydev)
464 {
465         int rc, val = 0;
466
467         if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
468                 /* clear all interrupt */
469                 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
470                 if (rc < 0)
471                         return rc;
472
473                 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
474                 if (rc < 0)
475                         return rc;
476
477                 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
478                                  PHYACC_ATTR_BANK_MISC,
479                                  LAN87XX_INTERRUPT_MASK_2, val);
480                 if (rc < 0)
481                         return rc;
482
483                 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
484                                  PHYACC_ATTR_BANK_MISC,
485                                  LAN87XX_INTERRUPT_SOURCE_2, 0);
486                 if (rc < 0)
487                         return rc;
488
489                 /* enable link down and comm ready interrupt */
490                 val = LAN87XX_MASK_LINK_DOWN;
491                 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
492                 if (rc < 0)
493                         return rc;
494
495                 val = LAN87XX_MASK_COMM_RDY;
496                 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
497                                  PHYACC_ATTR_BANK_MISC,
498                                  LAN87XX_INTERRUPT_MASK_2, val);
499         } else {
500                 rc = phy_write(phydev, LAN87XX_INTERRUPT_MASK, val);
501                 if (rc < 0)
502                         return rc;
503
504                 rc = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
505                 if (rc < 0)
506                         return rc;
507
508                 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
509                                  PHYACC_ATTR_BANK_MISC,
510                                  LAN87XX_INTERRUPT_MASK_2, val);
511                 if (rc < 0)
512                         return rc;
513
514                 rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
515                                  PHYACC_ATTR_BANK_MISC,
516                                  LAN87XX_INTERRUPT_SOURCE_2, 0);
517         }
518
519         return rc < 0 ? rc : 0;
520 }
521
522 static irqreturn_t lan87xx_handle_interrupt(struct phy_device *phydev)
523 {
524         int irq_status;
525
526         irq_status  = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
527                                   PHYACC_ATTR_BANK_MISC,
528                                   LAN87XX_INTERRUPT_SOURCE_2, 0);
529         if (irq_status < 0) {
530                 phy_error(phydev);
531                 return IRQ_NONE;
532         }
533
534         irq_status = phy_read(phydev, LAN87XX_INTERRUPT_SOURCE);
535         if (irq_status < 0) {
536                 phy_error(phydev);
537                 return IRQ_NONE;
538         }
539
540         if (irq_status == 0)
541                 return IRQ_NONE;
542
543         phy_trigger_machine(phydev);
544
545         return IRQ_HANDLED;
546 }
547
548 static int lan87xx_config_init(struct phy_device *phydev)
549 {
550         int rc = lan87xx_phy_init(phydev);
551
552         return rc < 0 ? rc : 0;
553 }
554
555 static int microchip_cable_test_start_common(struct phy_device *phydev)
556 {
557         int bmcr, bmsr, ret;
558
559         /* If auto-negotiation is enabled, but not complete, the cable
560          * test never completes. So disable auto-neg.
561          */
562         bmcr = phy_read(phydev, MII_BMCR);
563         if (bmcr < 0)
564                 return bmcr;
565
566         bmsr = phy_read(phydev, MII_BMSR);
567
568         if (bmsr < 0)
569                 return bmsr;
570
571         if (bmcr & BMCR_ANENABLE) {
572                 ret =  phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
573                 if (ret < 0)
574                         return ret;
575                 ret = genphy_soft_reset(phydev);
576                 if (ret < 0)
577                         return ret;
578         }
579
580         /* If the link is up, allow it some time to go down */
581         if (bmsr & BMSR_LSTATUS)
582                 msleep(1500);
583
584         return 0;
585 }
586
587 static int lan87xx_cable_test_start(struct phy_device *phydev)
588 {
589         static const struct access_ereg_val cable_test[] = {
590                 /* min wait */
591                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 93,
592                  0, 0},
593                 /* max wait */
594                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94,
595                  10, 0},
596                 /* pulse cycle */
597                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 95,
598                  90, 0},
599                 /* cable diag thresh */
600                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 92,
601                  60, 0},
602                 /* max gain */
603                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 79,
604                  31, 0},
605                 /* clock align for each iteration */
606                 {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_DSP, 55,
607                  0, 0x0038},
608                 /* max cycle wait config */
609                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 94,
610                  70, 0},
611                 /* start cable diag*/
612                 {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_DSP, 90,
613                  1, 0},
614         };
615         int rc, i;
616
617         rc = microchip_cable_test_start_common(phydev);
618         if (rc < 0)
619                 return rc;
620
621         /* start cable diag */
622         /* check if part is alive - if not, return diagnostic error */
623         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI,
624                          0x00, 0);
625         if (rc < 0)
626                 return rc;
627
628         /* master/slave specific configs */
629         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI,
630                          0x0A, 0);
631         if (rc < 0)
632                 return rc;
633
634         if ((rc & 0x4000) != 0x4000) {
635                 /* DUT is Slave */
636                 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_AFE,
637                                                 0x0E, 0x5, 0x7);
638                 if (rc < 0)
639                         return rc;
640                 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
641                                                 0x1A, 0x8, 0x8);
642                 if (rc < 0)
643                         return rc;
644         } else {
645                 /* DUT is Master */
646                 rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
647                                                 0x10, 0x8, 0x40);
648                 if (rc < 0)
649                         return rc;
650         }
651
652         for (i = 0; i < ARRAY_SIZE(cable_test); i++) {
653                 if (cable_test[i].mode == PHYACC_ATTR_MODE_MODIFY) {
654                         rc = access_ereg_modify_changed(phydev,
655                                                         cable_test[i].bank,
656                                                         cable_test[i].offset,
657                                                         cable_test[i].val,
658                                                         cable_test[i].mask);
659                         /* wait 50ms */
660                         msleep(50);
661                 } else {
662                         rc = access_ereg(phydev, cable_test[i].mode,
663                                          cable_test[i].bank,
664                                          cable_test[i].offset,
665                                          cable_test[i].val);
666                 }
667                 if (rc < 0)
668                         return rc;
669         }
670         /* cable diag started */
671
672         return 0;
673 }
674
675 static int lan87xx_cable_test_report_trans(u32 result)
676 {
677         switch (result) {
678         case LAN87XX_CABLE_TEST_OK:
679                 return ETHTOOL_A_CABLE_RESULT_CODE_OK;
680         case LAN87XX_CABLE_TEST_OPEN:
681                 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
682         case LAN87XX_CABLE_TEST_SAME_SHORT:
683                 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
684         default:
685                 /* DIAGNOSTIC_ERROR */
686                 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
687         }
688 }
689
690 static int lan87xx_cable_test_report(struct phy_device *phydev)
691 {
692         int pos_peak_cycle = 0, pos_peak_in_phases = 0, pos_peak_phase = 0;
693         int neg_peak_cycle = 0, neg_peak_in_phases = 0, neg_peak_phase = 0;
694         int noise_margin = 20, time_margin = 89, jitter_var = 30;
695         int min_time_diff = 96, max_time_diff = 96 + time_margin;
696         bool fault = false, check_a = false, check_b = false;
697         int gain_idx = 0, pos_peak = 0, neg_peak = 0;
698         int pos_peak_time = 0, neg_peak_time = 0;
699         int pos_peak_in_phases_hybrid = 0;
700         int detect = -1;
701
702         gain_idx = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
703                                PHYACC_ATTR_BANK_DSP, 151, 0);
704         /* read non-hybrid results */
705         pos_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
706                                PHYACC_ATTR_BANK_DSP, 153, 0);
707         neg_peak = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
708                                PHYACC_ATTR_BANK_DSP, 154, 0);
709         pos_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
710                                     PHYACC_ATTR_BANK_DSP, 156, 0);
711         neg_peak_time = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
712                                     PHYACC_ATTR_BANK_DSP, 157, 0);
713
714         pos_peak_cycle = (pos_peak_time >> 7) & 0x7F;
715         /* calculate non-hybrid values */
716         pos_peak_phase = pos_peak_time & 0x7F;
717         pos_peak_in_phases = (pos_peak_cycle * 96) + pos_peak_phase;
718         neg_peak_cycle = (neg_peak_time >> 7) & 0x7F;
719         neg_peak_phase = neg_peak_time & 0x7F;
720         neg_peak_in_phases = (neg_peak_cycle * 96) + neg_peak_phase;
721
722         /* process values */
723         check_a =
724                 ((pos_peak_in_phases - neg_peak_in_phases) >= min_time_diff) &&
725                 ((pos_peak_in_phases - neg_peak_in_phases) < max_time_diff) &&
726                 pos_peak_in_phases_hybrid < pos_peak_in_phases &&
727                 (pos_peak_in_phases_hybrid < (neg_peak_in_phases + jitter_var));
728         check_b =
729                 ((neg_peak_in_phases - pos_peak_in_phases) >= min_time_diff) &&
730                 ((neg_peak_in_phases - pos_peak_in_phases) < max_time_diff) &&
731                 pos_peak_in_phases_hybrid < neg_peak_in_phases &&
732                 (pos_peak_in_phases_hybrid < (pos_peak_in_phases + jitter_var));
733
734         if (pos_peak_in_phases > neg_peak_in_phases && check_a)
735                 detect = 2;
736         else if ((neg_peak_in_phases > pos_peak_in_phases) && check_b)
737                 detect = 1;
738
739         if (pos_peak > noise_margin && neg_peak > noise_margin &&
740             gain_idx >= 0) {
741                 if (detect == 1 || detect == 2)
742                         fault = true;
743         }
744
745         if (!fault)
746                 detect = 0;
747
748         ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
749                                 lan87xx_cable_test_report_trans(detect));
750
751         return 0;
752 }
753
754 static int lan87xx_cable_test_get_status(struct phy_device *phydev,
755                                          bool *finished)
756 {
757         int rc = 0;
758
759         *finished = false;
760
761         /* check if cable diag was finished */
762         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_DSP,
763                          90, 0);
764         if (rc < 0)
765                 return rc;
766
767         if ((rc & 2) == 2) {
768                 /* stop cable diag*/
769                 rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
770                                  PHYACC_ATTR_BANK_DSP,
771                                  90, 0);
772                 if (rc < 0)
773                         return rc;
774
775                 *finished = true;
776
777                 return lan87xx_cable_test_report(phydev);
778         }
779
780         return 0;
781 }
782
783 static int lan87xx_read_status(struct phy_device *phydev)
784 {
785         int rc = 0;
786
787         rc = phy_read(phydev, T1_MODE_STAT_REG);
788         if (rc < 0)
789                 return rc;
790
791         if (rc & T1_LINK_UP_MSK)
792                 phydev->link = 1;
793         else
794                 phydev->link = 0;
795
796         phydev->speed = SPEED_UNKNOWN;
797         phydev->duplex = DUPLEX_UNKNOWN;
798         phydev->pause = 0;
799         phydev->asym_pause = 0;
800
801         rc = genphy_read_master_slave(phydev);
802         if (rc < 0)
803                 return rc;
804
805         rc = genphy_read_status_fixed(phydev);
806         if (rc < 0)
807                 return rc;
808
809         return rc;
810 }
811
812 static int lan87xx_config_aneg(struct phy_device *phydev)
813 {
814         u16 ctl = 0;
815         int ret;
816
817         switch (phydev->master_slave_set) {
818         case MASTER_SLAVE_CFG_MASTER_FORCE:
819                 ctl |= CTL1000_AS_MASTER;
820                 break;
821         case MASTER_SLAVE_CFG_SLAVE_FORCE:
822                 break;
823         case MASTER_SLAVE_CFG_UNKNOWN:
824         case MASTER_SLAVE_CFG_UNSUPPORTED:
825                 return 0;
826         default:
827                 phydev_warn(phydev, "Unsupported Master/Slave mode\n");
828                 return -EOPNOTSUPP;
829         }
830
831         ret = phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl);
832         if (ret == 1)
833                 return phy_init_hw(phydev);
834
835         return ret;
836 }
837
838 static int lan87xx_get_sqi(struct phy_device *phydev)
839 {
840         u8 sqi_value = 0;
841         int rc;
842
843         rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE,
844                          PHYACC_ATTR_BANK_DSP, T1_COEF_RW_CTL_CFG, 0x0301);
845         if (rc < 0)
846                 return rc;
847
848         rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
849                          PHYACC_ATTR_BANK_DSP, T1_DCQ_SQI_REG, 0x0);
850         if (rc < 0)
851                 return rc;
852
853         sqi_value = FIELD_GET(T1_DCQ_SQI_MSK, rc);
854
855         return sqi_value;
856 }
857
858 static int lan87xx_get_sqi_max(struct phy_device *phydev)
859 {
860         return LAN87XX_MAX_SQI;
861 }
862
863 static struct phy_driver microchip_t1_phy_driver[] = {
864         {
865                 PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX),
866                 .name           = "Microchip LAN87xx T1",
867                 .flags          = PHY_POLL_CABLE_TEST,
868                 .features       = PHY_BASIC_T1_FEATURES,
869                 .config_init    = lan87xx_config_init,
870                 .config_intr    = lan87xx_phy_config_intr,
871                 .handle_interrupt = lan87xx_handle_interrupt,
872                 .suspend        = genphy_suspend,
873                 .resume         = genphy_resume,
874                 .config_aneg    = lan87xx_config_aneg,
875                 .read_status    = lan87xx_read_status,
876                 .get_sqi        = lan87xx_get_sqi,
877                 .get_sqi_max    = lan87xx_get_sqi_max,
878                 .cable_test_start = lan87xx_cable_test_start,
879                 .cable_test_get_status = lan87xx_cable_test_get_status,
880         },
881         {
882                 PHY_ID_MATCH_MODEL(PHY_ID_LAN937X),
883                 .name           = "Microchip LAN937x T1",
884                 .flags          = PHY_POLL_CABLE_TEST,
885                 .features       = PHY_BASIC_T1_FEATURES,
886                 .config_init    = lan87xx_config_init,
887                 .config_intr    = lan87xx_phy_config_intr,
888                 .handle_interrupt = lan87xx_handle_interrupt,
889                 .suspend        = genphy_suspend,
890                 .resume         = genphy_resume,
891                 .config_aneg    = lan87xx_config_aneg,
892                 .read_status    = lan87xx_read_status,
893                 .get_sqi        = lan87xx_get_sqi,
894                 .get_sqi_max    = lan87xx_get_sqi_max,
895                 .cable_test_start = lan87xx_cable_test_start,
896                 .cable_test_get_status = lan87xx_cable_test_get_status,
897         }
898 };
899
900 module_phy_driver(microchip_t1_phy_driver);
901
902 static struct mdio_device_id __maybe_unused microchip_t1_tbl[] = {
903         { PHY_ID_MATCH_MODEL(PHY_ID_LAN87XX) },
904         { PHY_ID_MATCH_MODEL(PHY_ID_LAN937X) },
905         { }
906 };
907
908 MODULE_DEVICE_TABLE(mdio, microchip_t1_tbl);
909
910 MODULE_AUTHOR(DRIVER_AUTHOR);
911 MODULE_DESCRIPTION(DRIVER_DESC);
912 MODULE_LICENSE("GPL");