]>
Commit | Line | Data |
---|---|---|
9082eeac AF |
1 | /* |
2 | * Vitesse PHY drivers | |
3 | * | |
f91ba0ec PJ |
4 | * Copyright 2010-2012 Freescale Semiconductor, Inc. |
5 | * Author: Andy Fleming | |
6 | * Add vsc8662 phy support - Priyanka Jain | |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
9082eeac AF |
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 | |
7794b1a7 SX |
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 | |
9082eeac AF |
51 | |
52 | /* CIS8201 */ | |
53 | static int vitesse_config(struct phy_device *phydev) | |
54 | { | |
55 | /* Override PHY config settings */ | |
56 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, | |
57 | MIIM_CIS82xx_AUXCONSTAT_INIT); | |
58 | /* Set up the interface mode */ | |
59 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1, | |
60 | MIIM_CIS8201_EXTCON1_INIT); | |
61 | ||
62 | genphy_config_aneg(phydev); | |
63 | ||
64 | return 0; | |
65 | } | |
66 | ||
67 | static int vitesse_parse_status(struct phy_device *phydev) | |
68 | { | |
69 | int speed; | |
70 | int mii_reg; | |
71 | ||
72 | mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT); | |
73 | ||
74 | if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX) | |
75 | phydev->duplex = DUPLEX_FULL; | |
76 | else | |
77 | phydev->duplex = DUPLEX_HALF; | |
78 | ||
79 | speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED; | |
80 | switch (speed) { | |
81 | case MIIM_CIS82xx_AUXCONSTAT_GBIT: | |
82 | phydev->speed = SPEED_1000; | |
83 | break; | |
84 | case MIIM_CIS82xx_AUXCONSTAT_100: | |
85 | phydev->speed = SPEED_100; | |
86 | break; | |
87 | default: | |
88 | phydev->speed = SPEED_10; | |
89 | break; | |
90 | } | |
91 | ||
92 | return 0; | |
93 | } | |
94 | ||
95 | static int vitesse_startup(struct phy_device *phydev) | |
96 | { | |
97 | genphy_update_link(phydev); | |
98 | vitesse_parse_status(phydev); | |
99 | ||
100 | return 0; | |
101 | } | |
102 | ||
103 | static int cis8204_config(struct phy_device *phydev) | |
104 | { | |
105 | /* Override PHY config settings */ | |
106 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, | |
107 | MIIM_CIS82xx_AUXCONSTAT_INIT); | |
108 | ||
109 | genphy_config_aneg(phydev); | |
110 | ||
111 | if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || | |
112 | (phydev->interface == PHY_INTERFACE_MODE_RGMII) || | |
113 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) || | |
114 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) | |
115 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, | |
116 | MIIM_CIS8204_EPHYCON_INIT | | |
117 | MIIM_CIS8204_EPHYCON_RGMII); | |
118 | else | |
119 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, | |
120 | MIIM_CIS8204_EPHYCON_INIT); | |
121 | ||
122 | return 0; | |
123 | } | |
124 | ||
125 | /* Vitesse VSC8601 */ | |
960d70c6 | 126 | static int vsc8601_config(struct phy_device *phydev) |
9082eeac AF |
127 | { |
128 | /* Configure some basic stuff */ | |
129 | #ifdef CONFIG_SYS_VSC8601_SKEWFIX | |
130 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON, | |
131 | MIIM_VSC8601_EPHY_CON_INIT_SKEW); | |
132 | #if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX) | |
133 | phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1); | |
134 | #define VSC8101_SKEW \ | |
135 | ((CONFIG_SYS_VSC8601_SKEW_TX << 14) \ | |
136 | | (CONFIG_SYS_VSC8601_SKEW_RX << 12)) | |
137 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL, | |
138 | VSC8101_SKEW); | |
139 | phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); | |
140 | #endif | |
141 | #endif | |
142 | ||
143 | genphy_config_aneg(phydev); | |
144 | ||
145 | return 0; | |
146 | } | |
147 | ||
7794b1a7 SX |
148 | static int vsc8574_config(struct phy_device *phydev) |
149 | { | |
150 | u32 val; | |
151 | /* configure regiser 19G for MAC */ | |
152 | phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, | |
153 | PHY_EXT_PAGE_ACCESS_GENERAL); | |
154 | ||
155 | val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19); | |
156 | if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) { | |
157 | /* set bit 15:14 to '01' for QSGMII mode */ | |
158 | val = (val & 0x3fff) | (1 << 14); | |
159 | phy_write(phydev, MDIO_DEVAD_NONE, | |
160 | MIIM_VSC8574_GENERAL19, val); | |
161 | /* Enable 4 ports MAC QSGMII */ | |
162 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18, | |
163 | MIIM_VSC8574_18G_QSGMII); | |
164 | } else { | |
165 | /* set bit 15:14 to '00' for SGMII mode */ | |
166 | val = val & 0x3fff; | |
167 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19, val); | |
168 | /* Enable 4 ports MAC SGMII */ | |
169 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18, | |
170 | MIIM_VSC8574_18G_SGMII); | |
171 | } | |
172 | val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18); | |
173 | /* When bit 15 is cleared the command has completed */ | |
174 | while (val & MIIM_VSC8574_18G_CMDSTAT) | |
175 | val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18); | |
176 | ||
177 | /* Enable Serdes Auto-negotiation */ | |
178 | phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, | |
179 | PHY_EXT_PAGE_ACCESS_EXTENDED3); | |
180 | val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON); | |
181 | val = val | MIIM_VSC8574_MAC_SERDES_ANEG; | |
182 | phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON, val); | |
183 | ||
184 | phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); | |
185 | ||
186 | genphy_config_aneg(phydev); | |
187 | ||
188 | return 0; | |
189 | } | |
190 | ||
9082eeac AF |
191 | static struct phy_driver VSC8211_driver = { |
192 | .name = "Vitesse VSC8211", | |
193 | .uid = 0xfc4b0, | |
194 | .mask = 0xffff0, | |
195 | .features = PHY_GBIT_FEATURES, | |
196 | .config = &vitesse_config, | |
197 | .startup = &vitesse_startup, | |
198 | .shutdown = &genphy_shutdown, | |
199 | }; | |
200 | ||
201 | static struct phy_driver VSC8221_driver = { | |
202 | .name = "Vitesse VSC8221", | |
203 | .uid = 0xfc550, | |
204 | .mask = 0xffff0, | |
205 | .features = PHY_GBIT_FEATURES, | |
206 | .config = &genphy_config_aneg, | |
207 | .startup = &vitesse_startup, | |
208 | .shutdown = &genphy_shutdown, | |
209 | }; | |
210 | ||
211 | static struct phy_driver VSC8244_driver = { | |
212 | .name = "Vitesse VSC8244", | |
213 | .uid = 0xfc6c0, | |
214 | .mask = 0xffff0, | |
215 | .features = PHY_GBIT_FEATURES, | |
216 | .config = &genphy_config_aneg, | |
217 | .startup = &vitesse_startup, | |
218 | .shutdown = &genphy_shutdown, | |
219 | }; | |
220 | ||
221 | static struct phy_driver VSC8234_driver = { | |
222 | .name = "Vitesse VSC8234", | |
223 | .uid = 0xfc620, | |
224 | .mask = 0xffff0, | |
225 | .features = PHY_GBIT_FEATURES, | |
226 | .config = &genphy_config_aneg, | |
227 | .startup = &vitesse_startup, | |
228 | .shutdown = &genphy_shutdown, | |
229 | }; | |
230 | ||
7794b1a7 SX |
231 | static struct phy_driver VSC8574_driver = { |
232 | .name = "Vitesse VSC8574", | |
233 | .uid = 0x704a0, | |
234 | .mask = 0xffff0, | |
235 | .features = PHY_GBIT_FEATURES, | |
236 | .config = &vsc8574_config, | |
237 | .startup = &vitesse_startup, | |
238 | .shutdown = &genphy_shutdown, | |
239 | }; | |
240 | ||
9082eeac AF |
241 | static struct phy_driver VSC8601_driver = { |
242 | .name = "Vitesse VSC8601", | |
243 | .uid = 0x70420, | |
244 | .mask = 0xffff0, | |
245 | .features = PHY_GBIT_FEATURES, | |
246 | .config = &vsc8601_config, | |
247 | .startup = &vitesse_startup, | |
248 | .shutdown = &genphy_shutdown, | |
249 | }; | |
250 | ||
251 | static struct phy_driver VSC8641_driver = { | |
252 | .name = "Vitesse VSC8641", | |
253 | .uid = 0x70430, | |
254 | .mask = 0xffff0, | |
255 | .features = PHY_GBIT_FEATURES, | |
256 | .config = &genphy_config_aneg, | |
257 | .startup = &vitesse_startup, | |
258 | .shutdown = &genphy_shutdown, | |
259 | }; | |
260 | ||
f91ba0ec PJ |
261 | static struct phy_driver VSC8662_driver = { |
262 | .name = "Vitesse VSC8662", | |
263 | .uid = 0x70660, | |
264 | .mask = 0xffff0, | |
265 | .features = PHY_GBIT_FEATURES, | |
266 | .config = &genphy_config_aneg, | |
267 | .startup = &vitesse_startup, | |
268 | .shutdown = &genphy_shutdown, | |
269 | }; | |
270 | ||
9082eeac AF |
271 | /* Vitesse bought Cicada, so we'll put these here */ |
272 | static struct phy_driver cis8201_driver = { | |
273 | .name = "CIS8201", | |
274 | .uid = 0xfc410, | |
275 | .mask = 0xffff0, | |
276 | .features = PHY_GBIT_FEATURES, | |
277 | .config = &vitesse_config, | |
278 | .startup = &vitesse_startup, | |
279 | .shutdown = &genphy_shutdown, | |
280 | }; | |
281 | ||
282 | static struct phy_driver cis8204_driver = { | |
283 | .name = "Cicada Cis8204", | |
284 | .uid = 0xfc440, | |
285 | .mask = 0xffff0, | |
286 | .features = PHY_GBIT_FEATURES, | |
287 | .config = &cis8204_config, | |
288 | .startup = &vitesse_startup, | |
289 | .shutdown = &genphy_shutdown, | |
290 | }; | |
291 | ||
292 | int phy_vitesse_init(void) | |
293 | { | |
294 | phy_register(&VSC8641_driver); | |
295 | phy_register(&VSC8601_driver); | |
296 | phy_register(&VSC8234_driver); | |
297 | phy_register(&VSC8244_driver); | |
298 | phy_register(&VSC8211_driver); | |
299 | phy_register(&VSC8221_driver); | |
7794b1a7 | 300 | phy_register(&VSC8574_driver); |
f91ba0ec | 301 | phy_register(&VSC8662_driver); |
9082eeac AF |
302 | phy_register(&cis8201_driver); |
303 | phy_register(&cis8204_driver); | |
304 | ||
305 | return 0; | |
306 | } |