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