xref: /openbmc/u-boot/drivers/net/phy/vitesse.c (revision 9d86f0c3)
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 
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 */
126 static int vsc8601_config(struct phy_device *phydev)
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 
148 static struct phy_driver VSC8211_driver = {
149 	.name	= "Vitesse VSC8211",
150 	.uid	= 0xfc4b0,
151 	.mask	= 0xffff0,
152 	.features = PHY_GBIT_FEATURES,
153 	.config = &vitesse_config,
154 	.startup = &vitesse_startup,
155 	.shutdown = &genphy_shutdown,
156 };
157 
158 static struct phy_driver VSC8221_driver = {
159 	.name = "Vitesse VSC8221",
160 	.uid = 0xfc550,
161 	.mask = 0xffff0,
162 	.features = PHY_GBIT_FEATURES,
163 	.config = &genphy_config_aneg,
164 	.startup = &vitesse_startup,
165 	.shutdown = &genphy_shutdown,
166 };
167 
168 static struct phy_driver VSC8244_driver = {
169 	.name = "Vitesse VSC8244",
170 	.uid = 0xfc6c0,
171 	.mask = 0xffff0,
172 	.features = PHY_GBIT_FEATURES,
173 	.config = &genphy_config_aneg,
174 	.startup = &vitesse_startup,
175 	.shutdown = &genphy_shutdown,
176 };
177 
178 static struct phy_driver VSC8234_driver = {
179 	.name = "Vitesse VSC8234",
180 	.uid = 0xfc620,
181 	.mask = 0xffff0,
182 	.features = PHY_GBIT_FEATURES,
183 	.config = &genphy_config_aneg,
184 	.startup = &vitesse_startup,
185 	.shutdown = &genphy_shutdown,
186 };
187 
188 static struct phy_driver VSC8601_driver = {
189 	.name = "Vitesse VSC8601",
190 	.uid = 0x70420,
191 	.mask = 0xffff0,
192 	.features = PHY_GBIT_FEATURES,
193 	.config = &vsc8601_config,
194 	.startup = &vitesse_startup,
195 	.shutdown = &genphy_shutdown,
196 };
197 
198 static struct phy_driver VSC8641_driver = {
199 	.name = "Vitesse VSC8641",
200 	.uid = 0x70430,
201 	.mask = 0xffff0,
202 	.features = PHY_GBIT_FEATURES,
203 	.config = &genphy_config_aneg,
204 	.startup = &vitesse_startup,
205 	.shutdown = &genphy_shutdown,
206 };
207 
208 static struct phy_driver VSC8662_driver = {
209 	.name = "Vitesse VSC8662",
210 	.uid = 0x70660,
211 	.mask = 0xffff0,
212 	.features = PHY_GBIT_FEATURES,
213 	.config = &genphy_config_aneg,
214 	.startup = &vitesse_startup,
215 	.shutdown = &genphy_shutdown,
216 };
217 
218 /* Vitesse bought Cicada, so we'll put these here */
219 static struct phy_driver cis8201_driver = {
220 	.name = "CIS8201",
221 	.uid = 0xfc410,
222 	.mask = 0xffff0,
223 	.features = PHY_GBIT_FEATURES,
224 	.config = &vitesse_config,
225 	.startup = &vitesse_startup,
226 	.shutdown = &genphy_shutdown,
227 };
228 
229 static struct phy_driver cis8204_driver = {
230 	.name = "Cicada Cis8204",
231 	.uid = 0xfc440,
232 	.mask = 0xffff0,
233 	.features = PHY_GBIT_FEATURES,
234 	.config = &cis8204_config,
235 	.startup = &vitesse_startup,
236 	.shutdown = &genphy_shutdown,
237 };
238 
239 int phy_vitesse_init(void)
240 {
241 	phy_register(&VSC8641_driver);
242 	phy_register(&VSC8601_driver);
243 	phy_register(&VSC8234_driver);
244 	phy_register(&VSC8244_driver);
245 	phy_register(&VSC8211_driver);
246 	phy_register(&VSC8221_driver);
247 	phy_register(&VSC8662_driver);
248 	phy_register(&cis8201_driver);
249 	phy_register(&cis8204_driver);
250 
251 	return 0;
252 }
253