blob: d48d4fe73f07f3db1f05ec65c1bf809432992f05 [file] [log] [blame]
Andy Fleming60ca78b2011-04-07 21:56:05 -05001/*
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 */
54static 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
68static 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
96static int vitesse_startup(struct phy_device *phydev)
97{
98 genphy_update_link(phydev);
99 vitesse_parse_status(phydev);
100
101 return 0;
102}
103
104static 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 */
127int 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
149static 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
159static 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
169static 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
179static 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
189static 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
199static 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 */
210static 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
220static 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
230int 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}