]> 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  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22 #include <miiphy.h>
23
24 /* Cicada Auxiliary Control/Status Register */
25 #define MIIM_CIS82xx_AUX_CONSTAT        0x1c
26 #define MIIM_CIS82xx_AUXCONSTAT_INIT    0x0004
27 #define MIIM_CIS82xx_AUXCONSTAT_DUPLEX  0x0020
28 #define MIIM_CIS82xx_AUXCONSTAT_SPEED   0x0018
29 #define MIIM_CIS82xx_AUXCONSTAT_GBIT    0x0010
30 #define MIIM_CIS82xx_AUXCONSTAT_100     0x0008
31
32 /* Cicada Extended Control Register 1 */
33 #define MIIM_CIS82xx_EXT_CON1           0x17
34 #define MIIM_CIS8201_EXTCON1_INIT       0x0000
35
36 /* Cicada 8204 Extended PHY Control Register 1 */
37 #define MIIM_CIS8204_EPHY_CON           0x17
38 #define MIIM_CIS8204_EPHYCON_INIT       0x0006
39 #define MIIM_CIS8204_EPHYCON_RGMII      0x1100
40
41 /* Cicada 8204 Serial LED Control Register */
42 #define MIIM_CIS8204_SLED_CON           0x1b
43 #define MIIM_CIS8204_SLEDCON_INIT       0x1115
44
45 /* Vitesse VSC8601 Extended PHY Control Register 1 */
46 #define MIIM_VSC8601_EPHY_CON           0x17
47 #define MIIM_VSC8601_EPHY_CON_INIT_SKEW 0x1120
48 #define MIIM_VSC8601_SKEW_CTRL          0x1c
49
50 #define PHY_EXT_PAGE_ACCESS    0x1f
51 #define PHY_EXT_PAGE_ACCESS_GENERAL     0x10
52 #define PHY_EXT_PAGE_ACCESS_EXTENDED3   0x3
53
54 /* Vitesse VSC8574 control register */
55 #define MIIM_VSC8574_MAC_SERDES_CON     0x10
56 #define MIIM_VSC8574_MAC_SERDES_ANEG    0x80
57 #define MIIM_VSC8574_GENERAL18          0x12
58 #define MIIM_VSC8574_GENERAL19          0x13
59
60 /* Vitesse VSC8574 gerenal purpose register 18 */
61 #define MIIM_VSC8574_18G_SGMII          0x80f0
62 #define MIIM_VSC8574_18G_QSGMII         0x80e0
63 #define MIIM_VSC8574_18G_CMDSTAT        0x8000
64
65 /* CIS8201 */
66 static int vitesse_config(struct phy_device *phydev)
67 {
68         /* Override PHY config settings */
69         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
70                         MIIM_CIS82xx_AUXCONSTAT_INIT);
71         /* Set up the interface mode */
72         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1,
73                         MIIM_CIS8201_EXTCON1_INIT);
74
75         genphy_config_aneg(phydev);
76
77         return 0;
78 }
79
80 static int vitesse_parse_status(struct phy_device *phydev)
81 {
82         int speed;
83         int mii_reg;
84
85         mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT);
86
87         if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX)
88                 phydev->duplex = DUPLEX_FULL;
89         else
90                 phydev->duplex = DUPLEX_HALF;
91
92         speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED;
93         switch (speed) {
94         case MIIM_CIS82xx_AUXCONSTAT_GBIT:
95                 phydev->speed = SPEED_1000;
96                 break;
97         case MIIM_CIS82xx_AUXCONSTAT_100:
98                 phydev->speed = SPEED_100;
99                 break;
100         default:
101                 phydev->speed = SPEED_10;
102                 break;
103         }
104
105         return 0;
106 }
107
108 static int vitesse_startup(struct phy_device *phydev)
109 {
110         genphy_update_link(phydev);
111         vitesse_parse_status(phydev);
112
113         return 0;
114 }
115
116 static int cis8204_config(struct phy_device *phydev)
117 {
118         /* Override PHY config settings */
119         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
120                         MIIM_CIS82xx_AUXCONSTAT_INIT);
121
122         genphy_config_aneg(phydev);
123
124         if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
125                         (phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
126                         (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
127                         (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
128                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
129                                 MIIM_CIS8204_EPHYCON_INIT |
130                                 MIIM_CIS8204_EPHYCON_RGMII);
131         else
132                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
133                                 MIIM_CIS8204_EPHYCON_INIT);
134
135         return 0;
136 }
137
138 /* Vitesse VSC8601 */
139 static int vsc8601_config(struct phy_device *phydev)
140 {
141         /* Configure some basic stuff */
142 #ifdef CONFIG_SYS_VSC8601_SKEWFIX
143         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON,
144                         MIIM_VSC8601_EPHY_CON_INIT_SKEW);
145 #if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
146         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1);
147 #define VSC8101_SKEW \
148         ((CONFIG_SYS_VSC8601_SKEW_TX << 14) \
149         | (CONFIG_SYS_VSC8601_SKEW_RX << 12))
150         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL,
151                         VSC8101_SKEW);
152         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
153 #endif
154 #endif
155
156         genphy_config_aneg(phydev);
157
158         return 0;
159 }
160
161 static int vsc8574_config(struct phy_device *phydev)
162 {
163         u32 val;
164         /* configure regiser 19G for MAC */
165         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
166                   PHY_EXT_PAGE_ACCESS_GENERAL);
167
168         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19);
169         if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
170                 /* set bit 15:14 to '01' for QSGMII mode */
171                 val = (val & 0x3fff) | (1 << 14);
172                 phy_write(phydev, MDIO_DEVAD_NONE,
173                           MIIM_VSC8574_GENERAL19, val);
174                 /* Enable 4 ports MAC QSGMII */
175                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18,
176                           MIIM_VSC8574_18G_QSGMII);
177         } else {
178                 /* set bit 15:14 to '00' for SGMII mode */
179                 val = val & 0x3fff;
180                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19, val);
181                 /* Enable 4 ports MAC SGMII */
182                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18,
183                           MIIM_VSC8574_18G_SGMII);
184         }
185         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18);
186         /* When bit 15 is cleared the command has completed */
187         while (val & MIIM_VSC8574_18G_CMDSTAT)
188                 val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18);
189
190         /* Enable Serdes Auto-negotiation */
191         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
192                   PHY_EXT_PAGE_ACCESS_EXTENDED3);
193         val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON);
194         val = val | MIIM_VSC8574_MAC_SERDES_ANEG;
195         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON, val);
196
197         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
198
199         genphy_config_aneg(phydev);
200
201         return 0;
202 }
203
204 static struct phy_driver VSC8211_driver = {
205         .name   = "Vitesse VSC8211",
206         .uid    = 0xfc4b0,
207         .mask   = 0xffff0,
208         .features = PHY_GBIT_FEATURES,
209         .config = &vitesse_config,
210         .startup = &vitesse_startup,
211         .shutdown = &genphy_shutdown,
212 };
213
214 static struct phy_driver VSC8221_driver = {
215         .name = "Vitesse VSC8221",
216         .uid = 0xfc550,
217         .mask = 0xffff0,
218         .features = PHY_GBIT_FEATURES,
219         .config = &genphy_config_aneg,
220         .startup = &vitesse_startup,
221         .shutdown = &genphy_shutdown,
222 };
223
224 static struct phy_driver VSC8244_driver = {
225         .name = "Vitesse VSC8244",
226         .uid = 0xfc6c0,
227         .mask = 0xffff0,
228         .features = PHY_GBIT_FEATURES,
229         .config = &genphy_config_aneg,
230         .startup = &vitesse_startup,
231         .shutdown = &genphy_shutdown,
232 };
233
234 static struct phy_driver VSC8234_driver = {
235         .name = "Vitesse VSC8234",
236         .uid = 0xfc620,
237         .mask = 0xffff0,
238         .features = PHY_GBIT_FEATURES,
239         .config = &genphy_config_aneg,
240         .startup = &vitesse_startup,
241         .shutdown = &genphy_shutdown,
242 };
243
244 static struct phy_driver VSC8574_driver = {
245         .name = "Vitesse VSC8574",
246         .uid = 0x704a0,
247         .mask = 0xffff0,
248         .features = PHY_GBIT_FEATURES,
249         .config = &vsc8574_config,
250         .startup = &vitesse_startup,
251         .shutdown = &genphy_shutdown,
252 };
253
254 static struct phy_driver VSC8601_driver = {
255         .name = "Vitesse VSC8601",
256         .uid = 0x70420,
257         .mask = 0xffff0,
258         .features = PHY_GBIT_FEATURES,
259         .config = &vsc8601_config,
260         .startup = &vitesse_startup,
261         .shutdown = &genphy_shutdown,
262 };
263
264 static struct phy_driver VSC8641_driver = {
265         .name = "Vitesse VSC8641",
266         .uid = 0x70430,
267         .mask = 0xffff0,
268         .features = PHY_GBIT_FEATURES,
269         .config = &genphy_config_aneg,
270         .startup = &vitesse_startup,
271         .shutdown = &genphy_shutdown,
272 };
273
274 static struct phy_driver VSC8662_driver = {
275         .name = "Vitesse VSC8662",
276         .uid = 0x70660,
277         .mask = 0xffff0,
278         .features = PHY_GBIT_FEATURES,
279         .config = &genphy_config_aneg,
280         .startup = &vitesse_startup,
281         .shutdown = &genphy_shutdown,
282 };
283
284 /* Vitesse bought Cicada, so we'll put these here */
285 static struct phy_driver cis8201_driver = {
286         .name = "CIS8201",
287         .uid = 0xfc410,
288         .mask = 0xffff0,
289         .features = PHY_GBIT_FEATURES,
290         .config = &vitesse_config,
291         .startup = &vitesse_startup,
292         .shutdown = &genphy_shutdown,
293 };
294
295 static struct phy_driver cis8204_driver = {
296         .name = "Cicada Cis8204",
297         .uid = 0xfc440,
298         .mask = 0xffff0,
299         .features = PHY_GBIT_FEATURES,
300         .config = &cis8204_config,
301         .startup = &vitesse_startup,
302         .shutdown = &genphy_shutdown,
303 };
304
305 int phy_vitesse_init(void)
306 {
307         phy_register(&VSC8641_driver);
308         phy_register(&VSC8601_driver);
309         phy_register(&VSC8234_driver);
310         phy_register(&VSC8244_driver);
311         phy_register(&VSC8211_driver);
312         phy_register(&VSC8221_driver);
313         phy_register(&VSC8574_driver);
314         phy_register(&VSC8662_driver);
315         phy_register(&cis8201_driver);
316         phy_register(&cis8204_driver);
317
318         return 0;
319 }