]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/phy/vitesse.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / drivers / net / phy / vitesse.c
1 /*
2  * Vitesse PHY drivers
3  *
4  * Copyright 2010-2012 Freescale Semiconductor, Inc.
5  * 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_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 /* CIS8201 */
62 static int vitesse_config(struct phy_device *phydev)
63 {
64         /* Override PHY config settings */
65         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
66                         MIIM_CIS82xx_AUXCONSTAT_INIT);
67         /* Set up the interface mode */
68         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1,
69                         MIIM_CIS8201_EXTCON1_INIT);
70
71         genphy_config_aneg(phydev);
72
73         return 0;
74 }
75
76 static int vitesse_parse_status(struct phy_device *phydev)
77 {
78         int speed;
79         int mii_reg;
80
81         mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT);
82
83         if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX)
84                 phydev->duplex = DUPLEX_FULL;
85         else
86                 phydev->duplex = DUPLEX_HALF;
87
88         speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED;
89         switch (speed) {
90         case MIIM_CIS82xx_AUXCONSTAT_GBIT:
91                 phydev->speed = SPEED_1000;
92                 break;
93         case MIIM_CIS82xx_AUXCONSTAT_100:
94                 phydev->speed = SPEED_100;
95                 break;
96         default:
97                 phydev->speed = SPEED_10;
98                 break;
99         }
100
101         return 0;
102 }
103
104 static int vitesse_startup(struct phy_device *phydev)
105 {
106         genphy_update_link(phydev);
107         vitesse_parse_status(phydev);
108
109         return 0;
110 }
111
112 static int cis8204_config(struct phy_device *phydev)
113 {
114         /* Override PHY config settings */
115         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
116                         MIIM_CIS82xx_AUXCONSTAT_INIT);
117
118         genphy_config_aneg(phydev);
119
120         if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
121                         (phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
122                         (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
123                         (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
124                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
125                                 MIIM_CIS8204_EPHYCON_INIT |
126                                 MIIM_CIS8204_EPHYCON_RGMII);
127         else
128                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
129                                 MIIM_CIS8204_EPHYCON_INIT);
130
131         return 0;
132 }
133
134 /* Vitesse VSC8601 */
135 static int vsc8601_config(struct phy_device *phydev)
136 {
137         /* Configure some basic stuff */
138 #ifdef CONFIG_SYS_VSC8601_SKEWFIX
139         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON,
140                         MIIM_VSC8601_EPHY_CON_INIT_SKEW);
141 #if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
142         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1);
143 #define VSC8101_SKEW \
144         ((CONFIG_SYS_VSC8601_SKEW_TX << 14) \
145         | (CONFIG_SYS_VSC8601_SKEW_RX << 12))
146         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL,
147                         VSC8101_SKEW);
148         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
149 #endif
150 #endif
151
152         genphy_config_aneg(phydev);
153
154         return 0;
155 }
156
157 static int vsc8574_config(struct phy_device *phydev)
158 {
159         u32 val;
160         /* configure register 19G for MAC */
161         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
162                   PHY_EXT_PAGE_ACCESS_GENERAL);
163
164         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19);
165         if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
166                 /* set bit 15:14 to '01' for QSGMII mode */
167                 val = (val & 0x3fff) | (1 << 14);
168                 phy_write(phydev, MDIO_DEVAD_NONE,
169                           MIIM_VSC8574_GENERAL19, val);
170                 /* Enable 4 ports MAC QSGMII */
171                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18,
172                           MIIM_VSC8574_18G_QSGMII);
173         } else {
174                 /* set bit 15:14 to '00' for SGMII mode */
175                 val = val & 0x3fff;
176                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19, val);
177                 /* Enable 4 ports MAC SGMII */
178                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18,
179                           MIIM_VSC8574_18G_SGMII);
180         }
181         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18);
182         /* When bit 15 is cleared the command has completed */
183         while (val & MIIM_VSC8574_18G_CMDSTAT)
184                 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18);
185
186         /* Enable Serdes Auto-negotiation */
187         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
188                   PHY_EXT_PAGE_ACCESS_EXTENDED3);
189         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON);
190         val = val | MIIM_VSC8574_MAC_SERDES_ANEG;
191         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON, val);
192
193         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
194
195         genphy_config_aneg(phydev);
196
197         return 0;
198 }
199
200 static int vsc8514_config(struct phy_device *phydev)
201 {
202         u32 val;
203         int timeout = 1000000;
204
205         /* configure register to access 19G */
206         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
207                   PHY_EXT_PAGE_ACCESS_GENERAL);
208
209         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL19);
210         if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
211                 /* set bit 15:14 to '01' for QSGMII mode */
212                 val = (val & 0x3fff) | (1 << 14);
213                 phy_write(phydev, MDIO_DEVAD_NONE,
214                           MIIM_VSC8514_GENERAL19, val);
215                 /* Enable 4 ports MAC QSGMII */
216                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18,
217                           MIIM_VSC8514_18G_QSGMII);
218         } else {
219                 /*TODO Add SGMII functionality once spec sheet
220                  * for VSC8514 defines complete functionality
221                  */
222         }
223
224         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18);
225         /* When bit 15 is cleared the command has completed */
226         while ((val & MIIM_VSC8514_18G_CMDSTAT) && timeout--)
227                 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18);
228
229         if (0 == timeout) {
230                 printf("PHY 8514 config failed\n");
231                 return -1;
232         }
233
234         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
235
236         /* configure register to access 23 */
237         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23);
238         /* set bits 10:8 to '000' */
239         val = (val & 0xf8ff);
240         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23, val);
241
242         genphy_config_aneg(phydev);
243
244         return 0;
245 }
246
247 static struct phy_driver VSC8211_driver = {
248         .name   = "Vitesse VSC8211",
249         .uid    = 0xfc4b0,
250         .mask   = 0xffff0,
251         .features = PHY_GBIT_FEATURES,
252         .config = &vitesse_config,
253         .startup = &vitesse_startup,
254         .shutdown = &genphy_shutdown,
255 };
256
257 static struct phy_driver VSC8221_driver = {
258         .name = "Vitesse VSC8221",
259         .uid = 0xfc550,
260         .mask = 0xffff0,
261         .features = PHY_GBIT_FEATURES,
262         .config = &genphy_config_aneg,
263         .startup = &vitesse_startup,
264         .shutdown = &genphy_shutdown,
265 };
266
267 static struct phy_driver VSC8244_driver = {
268         .name = "Vitesse VSC8244",
269         .uid = 0xfc6c0,
270         .mask = 0xffff0,
271         .features = PHY_GBIT_FEATURES,
272         .config = &genphy_config_aneg,
273         .startup = &vitesse_startup,
274         .shutdown = &genphy_shutdown,
275 };
276
277 static struct phy_driver VSC8234_driver = {
278         .name = "Vitesse VSC8234",
279         .uid = 0xfc620,
280         .mask = 0xffff0,
281         .features = PHY_GBIT_FEATURES,
282         .config = &genphy_config_aneg,
283         .startup = &vitesse_startup,
284         .shutdown = &genphy_shutdown,
285 };
286
287 static struct phy_driver VSC8574_driver = {
288         .name = "Vitesse VSC8574",
289         .uid = 0x704a0,
290         .mask = 0xffff0,
291         .features = PHY_GBIT_FEATURES,
292         .config = &vsc8574_config,
293         .startup = &vitesse_startup,
294         .shutdown = &genphy_shutdown,
295 };
296
297 static struct phy_driver VSC8514_driver = {
298         .name = "Vitesse VSC8514",
299         .uid = 0x70570,
300         .mask = 0xffff0,
301         .features = PHY_GBIT_FEATURES,
302         .config = &vsc8514_config,
303         .startup = &vitesse_startup,
304         .shutdown = &genphy_shutdown,
305 };
306
307 static struct phy_driver VSC8601_driver = {
308         .name = "Vitesse VSC8601",
309         .uid = 0x70420,
310         .mask = 0xffff0,
311         .features = PHY_GBIT_FEATURES,
312         .config = &vsc8601_config,
313         .startup = &vitesse_startup,
314         .shutdown = &genphy_shutdown,
315 };
316
317 static struct phy_driver VSC8641_driver = {
318         .name = "Vitesse VSC8641",
319         .uid = 0x70430,
320         .mask = 0xffff0,
321         .features = PHY_GBIT_FEATURES,
322         .config = &genphy_config_aneg,
323         .startup = &vitesse_startup,
324         .shutdown = &genphy_shutdown,
325 };
326
327 static struct phy_driver VSC8662_driver = {
328         .name = "Vitesse VSC8662",
329         .uid = 0x70660,
330         .mask = 0xffff0,
331         .features = PHY_GBIT_FEATURES,
332         .config = &genphy_config_aneg,
333         .startup = &vitesse_startup,
334         .shutdown = &genphy_shutdown,
335 };
336
337 /* Vitesse bought Cicada, so we'll put these here */
338 static struct phy_driver cis8201_driver = {
339         .name = "CIS8201",
340         .uid = 0xfc410,
341         .mask = 0xffff0,
342         .features = PHY_GBIT_FEATURES,
343         .config = &vitesse_config,
344         .startup = &vitesse_startup,
345         .shutdown = &genphy_shutdown,
346 };
347
348 static struct phy_driver cis8204_driver = {
349         .name = "Cicada Cis8204",
350         .uid = 0xfc440,
351         .mask = 0xffff0,
352         .features = PHY_GBIT_FEATURES,
353         .config = &cis8204_config,
354         .startup = &vitesse_startup,
355         .shutdown = &genphy_shutdown,
356 };
357
358 int phy_vitesse_init(void)
359 {
360         phy_register(&VSC8641_driver);
361         phy_register(&VSC8601_driver);
362         phy_register(&VSC8234_driver);
363         phy_register(&VSC8244_driver);
364         phy_register(&VSC8211_driver);
365         phy_register(&VSC8221_driver);
366         phy_register(&VSC8574_driver);
367         phy_register(&VSC8514_driver);
368         phy_register(&VSC8662_driver);
369         phy_register(&cis8201_driver);
370         phy_register(&cis8204_driver);
371
372         return 0;
373 }