xref: /openbmc/u-boot/drivers/net/phy/vitesse.c (revision e2a53458)
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 }
243