SPDX: Convert all of our single license tags to Linux Kernel style
[oweals/u-boot.git] / drivers / net / phy / vitesse.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Vitesse PHY drivers
4  *
5  * Copyright 2010-2014 Freescale Semiconductor, Inc.
6  * Original Author: Andy Fleming
7  * Add vsc8662 phy support - Priyanka Jain
8  */
9 #include <miiphy.h>
10
11 /* Cicada Auxiliary Control/Status Register */
12 #define MIIM_CIS82xx_AUX_CONSTAT        0x1c
13 #define MIIM_CIS82xx_AUXCONSTAT_INIT    0x0004
14 #define MIIM_CIS82xx_AUXCONSTAT_DUPLEX  0x0020
15 #define MIIM_CIS82xx_AUXCONSTAT_SPEED   0x0018
16 #define MIIM_CIS82xx_AUXCONSTAT_GBIT    0x0010
17 #define MIIM_CIS82xx_AUXCONSTAT_100     0x0008
18
19 /* Cicada Extended Control Register 1 */
20 #define MIIM_CIS82xx_EXT_CON1           0x17
21 #define MIIM_CIS8201_EXTCON1_INIT       0x0000
22
23 /* Cicada 8204 Extended PHY Control Register 1 */
24 #define MIIM_CIS8204_EPHY_CON           0x17
25 #define MIIM_CIS8204_EPHYCON_INIT       0x0006
26 #define MIIM_CIS8204_EPHYCON_RGMII      0x1100
27
28 /* Cicada 8204 Serial LED Control Register */
29 #define MIIM_CIS8204_SLED_CON           0x1b
30 #define MIIM_CIS8204_SLEDCON_INIT       0x1115
31
32 /* Vitesse VSC8601 Extended PHY Control Register 1 */
33 #define MII_VSC8601_EPHY_CTL            0x17
34 #define MII_VSC8601_EPHY_CTL_RGMII_SKEW (1 << 8)
35
36 #define PHY_EXT_PAGE_ACCESS    0x1f
37 #define PHY_EXT_PAGE_ACCESS_GENERAL     0x10
38 #define PHY_EXT_PAGE_ACCESS_EXTENDED3   0x3
39
40 /* Vitesse VSC8574 control register */
41 #define MIIM_VSC8574_MAC_SERDES_CON     0x10
42 #define MIIM_VSC8574_MAC_SERDES_ANEG    0x80
43 #define MIIM_VSC8574_GENERAL18          0x12
44 #define MIIM_VSC8574_GENERAL19          0x13
45
46 /* Vitesse VSC8574 gerenal purpose register 18 */
47 #define MIIM_VSC8574_18G_SGMII          0x80f0
48 #define MIIM_VSC8574_18G_QSGMII         0x80e0
49 #define MIIM_VSC8574_18G_CMDSTAT        0x8000
50
51 /* Vitesse VSC8514 control register */
52 #define MIIM_VSC8514_MAC_SERDES_CON     0x10
53 #define MIIM_VSC8514_GENERAL18          0x12
54 #define MIIM_VSC8514_GENERAL19          0x13
55 #define MIIM_VSC8514_GENERAL23          0x17
56
57 /* Vitesse VSC8514 gerenal purpose register 18 */
58 #define MIIM_VSC8514_18G_QSGMII         0x80e0
59 #define MIIM_VSC8514_18G_CMDSTAT        0x8000
60
61 /* Vitesse VSC8664 Control/Status Register */
62 #define MIIM_VSC8664_SERDES_AND_SIGDET  0x13
63 #define MIIM_VSC8664_ADDITIONAL_DEV     0x16
64 #define MIIM_VSC8664_EPHY_CON           0x17
65 #define MIIM_VSC8664_LED_CON            0x1E
66
67 #define PHY_EXT_PAGE_ACCESS_EXTENDED    0x0001
68
69 /* CIS8201 */
70 static int vitesse_config(struct phy_device *phydev)
71 {
72         /* Override PHY config settings */
73         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
74                         MIIM_CIS82xx_AUXCONSTAT_INIT);
75         /* Set up the interface mode */
76         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1,
77                         MIIM_CIS8201_EXTCON1_INIT);
78
79         genphy_config_aneg(phydev);
80
81         return 0;
82 }
83
84 static int vitesse_parse_status(struct phy_device *phydev)
85 {
86         int speed;
87         int mii_reg;
88
89         mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT);
90
91         if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX)
92                 phydev->duplex = DUPLEX_FULL;
93         else
94                 phydev->duplex = DUPLEX_HALF;
95
96         speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED;
97         switch (speed) {
98         case MIIM_CIS82xx_AUXCONSTAT_GBIT:
99                 phydev->speed = SPEED_1000;
100                 break;
101         case MIIM_CIS82xx_AUXCONSTAT_100:
102                 phydev->speed = SPEED_100;
103                 break;
104         default:
105                 phydev->speed = SPEED_10;
106                 break;
107         }
108
109         return 0;
110 }
111
112 static int vitesse_startup(struct phy_device *phydev)
113 {
114         int ret;
115
116         ret = genphy_update_link(phydev);
117         if (ret)
118                 return ret;
119         return vitesse_parse_status(phydev);
120 }
121
122 static int cis8204_config(struct phy_device *phydev)
123 {
124         /* Override PHY config settings */
125         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
126                         MIIM_CIS82xx_AUXCONSTAT_INIT);
127
128         genphy_config_aneg(phydev);
129
130         if (phy_interface_is_rgmii(phydev))
131                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
132                                 MIIM_CIS8204_EPHYCON_INIT |
133                                 MIIM_CIS8204_EPHYCON_RGMII);
134         else
135                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
136                                 MIIM_CIS8204_EPHYCON_INIT);
137
138         return 0;
139 }
140
141 /* Vitesse VSC8601 */
142 /* This adds a skew for both TX and RX clocks, so the skew should only be
143  * applied to "rgmii-id" interfaces. It may not work as expected
144  * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */
145 static int vsc8601_add_skew(struct phy_device *phydev)
146 {
147         int ret;
148
149         ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_VSC8601_EPHY_CTL);
150         if (ret < 0)
151                 return ret;
152
153         ret |= MII_VSC8601_EPHY_CTL_RGMII_SKEW;
154         return phy_write(phydev, MDIO_DEVAD_NONE, MII_VSC8601_EPHY_CTL, ret);
155 }
156
157 static int vsc8601_config(struct phy_device *phydev)
158 {
159         int ret = 0;
160
161         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
162                 ret = vsc8601_add_skew(phydev);
163
164         if (ret < 0)
165                 return ret;
166
167         return genphy_config_aneg(phydev);
168 }
169
170 static int vsc8574_config(struct phy_device *phydev)
171 {
172         u32 val;
173         /* configure register 19G for MAC */
174         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
175                   PHY_EXT_PAGE_ACCESS_GENERAL);
176
177         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19);
178         if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
179                 /* set bit 15:14 to '01' for QSGMII mode */
180                 val = (val & 0x3fff) | (1 << 14);
181                 phy_write(phydev, MDIO_DEVAD_NONE,
182                           MIIM_VSC8574_GENERAL19, val);
183                 /* Enable 4 ports MAC QSGMII */
184                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18,
185                           MIIM_VSC8574_18G_QSGMII);
186         } else {
187                 /* set bit 15:14 to '00' for SGMII mode */
188                 val = val & 0x3fff;
189                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19, val);
190                 /* Enable 4 ports MAC SGMII */
191                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18,
192                           MIIM_VSC8574_18G_SGMII);
193         }
194         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18);
195         /* When bit 15 is cleared the command has completed */
196         while (val & MIIM_VSC8574_18G_CMDSTAT)
197                 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18);
198
199         /* Enable Serdes Auto-negotiation */
200         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
201                   PHY_EXT_PAGE_ACCESS_EXTENDED3);
202         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON);
203         val = val | MIIM_VSC8574_MAC_SERDES_ANEG;
204         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON, val);
205
206         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
207
208         genphy_config_aneg(phydev);
209
210         return 0;
211 }
212
213 static int vsc8514_config(struct phy_device *phydev)
214 {
215         u32 val;
216         int timeout = 1000000;
217
218         /* configure register to access 19G */
219         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
220                   PHY_EXT_PAGE_ACCESS_GENERAL);
221
222         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL19);
223         if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
224                 /* set bit 15:14 to '01' for QSGMII mode */
225                 val = (val & 0x3fff) | (1 << 14);
226                 phy_write(phydev, MDIO_DEVAD_NONE,
227                           MIIM_VSC8514_GENERAL19, val);
228                 /* Enable 4 ports MAC QSGMII */
229                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18,
230                           MIIM_VSC8514_18G_QSGMII);
231         } else {
232                 /*TODO Add SGMII functionality once spec sheet
233                  * for VSC8514 defines complete functionality
234                  */
235         }
236
237         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18);
238         /* When bit 15 is cleared the command has completed */
239         while ((val & MIIM_VSC8514_18G_CMDSTAT) && timeout--)
240                 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18);
241
242         if (0 == timeout) {
243                 printf("PHY 8514 config failed\n");
244                 return -1;
245         }
246
247         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
248
249         /* configure register to access 23 */
250         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23);
251         /* set bits 10:8 to '000' */
252         val = (val & 0xf8ff);
253         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23, val);
254
255         /* Enable Serdes Auto-negotiation */
256         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
257                   PHY_EXT_PAGE_ACCESS_EXTENDED3);
258         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON);
259         val = val | MIIM_VSC8574_MAC_SERDES_ANEG;
260         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON, val);
261         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
262
263         genphy_config_aneg(phydev);
264
265         return 0;
266 }
267
268 static int vsc8664_config(struct phy_device *phydev)
269 {
270         u32 val;
271
272         /* Enable MAC interface auto-negotiation */
273         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
274         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_EPHY_CON);
275         val |= (1 << 13);
276         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_EPHY_CON, val);
277
278         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
279                   PHY_EXT_PAGE_ACCESS_EXTENDED);
280         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_SERDES_AND_SIGDET);
281         val |= (1 << 11);
282         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_SERDES_AND_SIGDET, val);
283         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
284
285         /* Enable LED blink */
286         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_LED_CON);
287         val &= ~(1 << 2);
288         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_LED_CON, val);
289
290         genphy_config_aneg(phydev);
291
292         return 0;
293 }
294
295 static struct phy_driver VSC8211_driver = {
296         .name   = "Vitesse VSC8211",
297         .uid    = 0xfc4b0,
298         .mask   = 0xffff0,
299         .features = PHY_GBIT_FEATURES,
300         .config = &vitesse_config,
301         .startup = &vitesse_startup,
302         .shutdown = &genphy_shutdown,
303 };
304
305 static struct phy_driver VSC8221_driver = {
306         .name = "Vitesse VSC8221",
307         .uid = 0xfc550,
308         .mask = 0xffff0,
309         .features = PHY_GBIT_FEATURES,
310         .config = &genphy_config_aneg,
311         .startup = &vitesse_startup,
312         .shutdown = &genphy_shutdown,
313 };
314
315 static struct phy_driver VSC8244_driver = {
316         .name = "Vitesse VSC8244",
317         .uid = 0xfc6c0,
318         .mask = 0xffff0,
319         .features = PHY_GBIT_FEATURES,
320         .config = &genphy_config_aneg,
321         .startup = &vitesse_startup,
322         .shutdown = &genphy_shutdown,
323 };
324
325 static struct phy_driver VSC8234_driver = {
326         .name = "Vitesse VSC8234",
327         .uid = 0xfc620,
328         .mask = 0xffff0,
329         .features = PHY_GBIT_FEATURES,
330         .config = &genphy_config_aneg,
331         .startup = &vitesse_startup,
332         .shutdown = &genphy_shutdown,
333 };
334
335 static struct phy_driver VSC8574_driver = {
336         .name = "Vitesse VSC8574",
337         .uid = 0x704a0,
338         .mask = 0xffff0,
339         .features = PHY_GBIT_FEATURES,
340         .config = &vsc8574_config,
341         .startup = &vitesse_startup,
342         .shutdown = &genphy_shutdown,
343 };
344
345 static struct phy_driver VSC8514_driver = {
346         .name = "Vitesse VSC8514",
347         .uid = 0x70670,
348         .mask = 0xffff0,
349         .features = PHY_GBIT_FEATURES,
350         .config = &vsc8514_config,
351         .startup = &vitesse_startup,
352         .shutdown = &genphy_shutdown,
353 };
354
355 static struct phy_driver VSC8584_driver = {
356         .name = "Vitesse VSC8584",
357         .uid = 0x707c0,
358         .mask = 0xffff0,
359         .features = PHY_GBIT_FEATURES,
360         .config = &vsc8574_config,
361         .startup = &vitesse_startup,
362         .shutdown = &genphy_shutdown,
363 };
364
365 static struct phy_driver VSC8601_driver = {
366         .name = "Vitesse VSC8601",
367         .uid = 0x70420,
368         .mask = 0xffff0,
369         .features = PHY_GBIT_FEATURES,
370         .config = &vsc8601_config,
371         .startup = &vitesse_startup,
372         .shutdown = &genphy_shutdown,
373 };
374
375 static struct phy_driver VSC8641_driver = {
376         .name = "Vitesse VSC8641",
377         .uid = 0x70430,
378         .mask = 0xffff0,
379         .features = PHY_GBIT_FEATURES,
380         .config = &genphy_config_aneg,
381         .startup = &vitesse_startup,
382         .shutdown = &genphy_shutdown,
383 };
384
385 static struct phy_driver VSC8662_driver = {
386         .name = "Vitesse VSC8662",
387         .uid = 0x70660,
388         .mask = 0xffff0,
389         .features = PHY_GBIT_FEATURES,
390         .config = &genphy_config_aneg,
391         .startup = &vitesse_startup,
392         .shutdown = &genphy_shutdown,
393 };
394
395 static struct phy_driver VSC8664_driver = {
396         .name = "Vitesse VSC8664",
397         .uid = 0x70660,
398         .mask = 0xffff0,
399         .features = PHY_GBIT_FEATURES,
400         .config = &vsc8664_config,
401         .startup = &vitesse_startup,
402         .shutdown = &genphy_shutdown,
403 };
404
405 /* Vitesse bought Cicada, so we'll put these here */
406 static struct phy_driver cis8201_driver = {
407         .name = "CIS8201",
408         .uid = 0xfc410,
409         .mask = 0xffff0,
410         .features = PHY_GBIT_FEATURES,
411         .config = &vitesse_config,
412         .startup = &vitesse_startup,
413         .shutdown = &genphy_shutdown,
414 };
415
416 static struct phy_driver cis8204_driver = {
417         .name = "Cicada Cis8204",
418         .uid = 0xfc440,
419         .mask = 0xffff0,
420         .features = PHY_GBIT_FEATURES,
421         .config = &cis8204_config,
422         .startup = &vitesse_startup,
423         .shutdown = &genphy_shutdown,
424 };
425
426 int phy_vitesse_init(void)
427 {
428         phy_register(&VSC8641_driver);
429         phy_register(&VSC8601_driver);
430         phy_register(&VSC8234_driver);
431         phy_register(&VSC8244_driver);
432         phy_register(&VSC8211_driver);
433         phy_register(&VSC8221_driver);
434         phy_register(&VSC8574_driver);
435         phy_register(&VSC8584_driver);
436         phy_register(&VSC8514_driver);
437         phy_register(&VSC8662_driver);
438         phy_register(&VSC8664_driver);
439         phy_register(&cis8201_driver);
440         phy_register(&cis8204_driver);
441
442         return 0;
443 }