d48d4fe73f07f3db1f05ec65c1bf809432992f05
[oweals/u-boot.git] / drivers / net / phy / vitesse.c
1 /*
2  * Vitesse PHY drivers
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17  * MA 02111-1307 USA
18  *
19  * Copyright 2010-2011 Freescale Semiconductor, Inc.
20  * author Andy Fleming
21  *
22  */
23 #include <miiphy.h>
24
25 /* Cicada Auxiliary Control/Status Register */
26 #define MIIM_CIS82xx_AUX_CONSTAT        0x1c
27 #define MIIM_CIS82xx_AUXCONSTAT_INIT    0x0004
28 #define MIIM_CIS82xx_AUXCONSTAT_DUPLEX  0x0020
29 #define MIIM_CIS82xx_AUXCONSTAT_SPEED   0x0018
30 #define MIIM_CIS82xx_AUXCONSTAT_GBIT    0x0010
31 #define MIIM_CIS82xx_AUXCONSTAT_100     0x0008
32
33 /* Cicada Extended Control Register 1 */
34 #define MIIM_CIS82xx_EXT_CON1           0x17
35 #define MIIM_CIS8201_EXTCON1_INIT       0x0000
36
37 /* Cicada 8204 Extended PHY Control Register 1 */
38 #define MIIM_CIS8204_EPHY_CON           0x17
39 #define MIIM_CIS8204_EPHYCON_INIT       0x0006
40 #define MIIM_CIS8204_EPHYCON_RGMII      0x1100
41
42 /* Cicada 8204 Serial LED Control Register */
43 #define MIIM_CIS8204_SLED_CON           0x1b
44 #define MIIM_CIS8204_SLEDCON_INIT       0x1115
45
46 /* Vitesse VSC8601 Extended PHY Control Register 1 */
47 #define MIIM_VSC8601_EPHY_CON           0x17
48 #define MIIM_VSC8601_EPHY_CON_INIT_SKEW 0x1120
49 #define MIIM_VSC8601_SKEW_CTRL          0x1c
50
51 #define PHY_EXT_PAGE_ACCESS    0x1f
52
53 /* CIS8201 */
54 static int vitesse_config(struct phy_device *phydev)
55 {
56         /* Override PHY config settings */
57         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
58                         MIIM_CIS82xx_AUXCONSTAT_INIT);
59         /* Set up the interface mode */
60         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1,
61                         MIIM_CIS8201_EXTCON1_INIT);
62
63         genphy_config_aneg(phydev);
64
65         return 0;
66 }
67
68 static int vitesse_parse_status(struct phy_device *phydev)
69 {
70         int speed;
71         int mii_reg;
72
73         mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT);
74
75         if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX)
76                 phydev->duplex = DUPLEX_FULL;
77         else
78                 phydev->duplex = DUPLEX_HALF;
79
80         speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED;
81         switch (speed) {
82         case MIIM_CIS82xx_AUXCONSTAT_GBIT:
83                 phydev->speed = SPEED_1000;
84                 break;
85         case MIIM_CIS82xx_AUXCONSTAT_100:
86                 phydev->speed = SPEED_100;
87                 break;
88         default:
89                 phydev->speed = SPEED_10;
90                 break;
91         }
92
93         return 0;
94 }
95
96 static int vitesse_startup(struct phy_device *phydev)
97 {
98         genphy_update_link(phydev);
99         vitesse_parse_status(phydev);
100
101         return 0;
102 }
103
104 static int cis8204_config(struct phy_device *phydev)
105 {
106         /* Override PHY config settings */
107         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
108                         MIIM_CIS82xx_AUXCONSTAT_INIT);
109
110         genphy_config_aneg(phydev);
111
112         if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
113                         (phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
114                         (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
115                         (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
116                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
117                                 MIIM_CIS8204_EPHYCON_INIT |
118                                 MIIM_CIS8204_EPHYCON_RGMII);
119         else
120                 phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
121                                 MIIM_CIS8204_EPHYCON_INIT);
122
123         return 0;
124 }
125
126 /* Vitesse VSC8601 */
127 int vsc8601_config(struct phy_device *phydev)
128 {
129         /* Configure some basic stuff */
130 #ifdef CONFIG_SYS_VSC8601_SKEWFIX
131         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON,
132                         MIIM_VSC8601_EPHY_CON_INIT_SKEW);
133 #if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
134         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1);
135 #define VSC8101_SKEW \
136         ((CONFIG_SYS_VSC8601_SKEW_TX << 14) \
137         | (CONFIG_SYS_VSC8601_SKEW_RX << 12))
138         phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL,
139                         VSC8101_SKEW);
140         phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
141 #endif
142 #endif
143
144         genphy_config_aneg(phydev);
145
146         return 0;
147 }
148
149 static struct phy_driver VSC8211_driver = {
150         .name   = "Vitesse VSC8211",
151         .uid    = 0xfc4b0,
152         .mask   = 0xffff0,
153         .features = PHY_GBIT_FEATURES,
154         .config = &vitesse_config,
155         .startup = &vitesse_startup,
156         .shutdown = &genphy_shutdown,
157 };
158
159 static struct phy_driver VSC8221_driver = {
160         .name = "Vitesse VSC8221",
161         .uid = 0xfc550,
162         .mask = 0xffff0,
163         .features = PHY_GBIT_FEATURES,
164         .config = &genphy_config_aneg,
165         .startup = &vitesse_startup,
166         .shutdown = &genphy_shutdown,
167 };
168
169 static struct phy_driver VSC8244_driver = {
170         .name = "Vitesse VSC8244",
171         .uid = 0xfc6c0,
172         .mask = 0xffff0,
173         .features = PHY_GBIT_FEATURES,
174         .config = &genphy_config_aneg,
175         .startup = &vitesse_startup,
176         .shutdown = &genphy_shutdown,
177 };
178
179 static struct phy_driver VSC8234_driver = {
180         .name = "Vitesse VSC8234",
181         .uid = 0xfc620,
182         .mask = 0xffff0,
183         .features = PHY_GBIT_FEATURES,
184         .config = &genphy_config_aneg,
185         .startup = &vitesse_startup,
186         .shutdown = &genphy_shutdown,
187 };
188
189 static struct phy_driver VSC8601_driver = {
190         .name = "Vitesse VSC8601",
191         .uid = 0x70420,
192         .mask = 0xffff0,
193         .features = PHY_GBIT_FEATURES,
194         .config = &vsc8601_config,
195         .startup = &vitesse_startup,
196         .shutdown = &genphy_shutdown,
197 };
198
199 static struct phy_driver VSC8641_driver = {
200         .name = "Vitesse VSC8641",
201         .uid = 0x70430,
202         .mask = 0xffff0,
203         .features = PHY_GBIT_FEATURES,
204         .config = &genphy_config_aneg,
205         .startup = &vitesse_startup,
206         .shutdown = &genphy_shutdown,
207 };
208
209 /* Vitesse bought Cicada, so we'll put these here */
210 static struct phy_driver cis8201_driver = {
211         .name = "CIS8201",
212         .uid = 0xfc410,
213         .mask = 0xffff0,
214         .features = PHY_GBIT_FEATURES,
215         .config = &vitesse_config,
216         .startup = &vitesse_startup,
217         .shutdown = &genphy_shutdown,
218 };
219
220 static struct phy_driver cis8204_driver = {
221         .name = "Cicada Cis8204",
222         .uid = 0xfc440,
223         .mask = 0xffff0,
224         .features = PHY_GBIT_FEATURES,
225         .config = &cis8204_config,
226         .startup = &vitesse_startup,
227         .shutdown = &genphy_shutdown,
228 };
229
230 int phy_vitesse_init(void)
231 {
232         phy_register(&VSC8641_driver);
233         phy_register(&VSC8601_driver);
234         phy_register(&VSC8234_driver);
235         phy_register(&VSC8244_driver);
236         phy_register(&VSC8211_driver);
237         phy_register(&VSC8221_driver);
238         phy_register(&cis8201_driver);
239         phy_register(&cis8204_driver);
240
241         return 0;
242 }