| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ciphy.c,v 1.26.10.1 2019/05/13 12:40:13 martin Exp $ */ | | 1 | /* $NetBSD: ciphy.c,v 1.26.10.2 2019/09/01 10:19:04 martin Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2004 | | 4 | * Copyright (c) 2004 |
5 | * Bill Paul <wpaul@windriver.com>. All rights reserved. | | 5 | * Bill Paul <wpaul@windriver.com>. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -25,27 +25,27 @@ | | | @@ -25,27 +25,27 @@ |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD | | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD |
26 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 26 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
32 | * THE POSSIBILITY OF SUCH DAMAGE. | | 32 | * THE POSSIBILITY OF SUCH DAMAGE. |
33 | * | | 33 | * |
34 | * FreeBSD: src/sys/dev/mii/ciphy.c,v 1.2 2005/01/06 01:42:55 imp Exp | | 34 | * FreeBSD: src/sys/dev/mii/ciphy.c,v 1.2 2005/01/06 01:42:55 imp Exp |
35 | */ | | 35 | */ |
36 | | | 36 | |
37 | #include <sys/cdefs.h> | | 37 | #include <sys/cdefs.h> |
38 | __KERNEL_RCSID(0, "$NetBSD: ciphy.c,v 1.26.10.1 2019/05/13 12:40:13 martin Exp $"); | | 38 | __KERNEL_RCSID(0, "$NetBSD: ciphy.c,v 1.26.10.2 2019/09/01 10:19:04 martin Exp $"); |
39 | | | 39 | |
40 | /* | | 40 | /* |
41 | * Driver for the Cicada CS8201 10/100/1000 copper PHY. | | 41 | * Driver for the Cicada CS8201 10/100/1000 copper PHY. |
42 | */ | | 42 | */ |
43 | | | 43 | |
44 | #include <sys/param.h> | | 44 | #include <sys/param.h> |
45 | #include <sys/systm.h> | | 45 | #include <sys/systm.h> |
46 | #include <sys/device.h> | | 46 | #include <sys/device.h> |
47 | #include <sys/kernel.h> | | 47 | #include <sys/kernel.h> |
48 | #include <sys/socket.h> | | 48 | #include <sys/socket.h> |
49 | #include <sys/bus.h> | | 49 | #include <sys/bus.h> |
50 | | | 50 | |
51 | #include <net/if.h> | | 51 | #include <net/if.h> |
| @@ -73,49 +73,61 @@ static const struct mii_phy_funcs ciphy_ | | | @@ -73,49 +73,61 @@ static const struct mii_phy_funcs ciphy_ |
73 | ciphy_service, ciphy_status, mii_phy_reset, | | 73 | ciphy_service, ciphy_status, mii_phy_reset, |
74 | }; | | 74 | }; |
75 | | | 75 | |
76 | static const struct mii_phydesc ciphys[] = { | | 76 | static const struct mii_phydesc ciphys[] = { |
77 | { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201, | | 77 | { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201, |
78 | MII_STR_CICADA_CS8201 }, | | 78 | MII_STR_CICADA_CS8201 }, |
79 | | | 79 | |
80 | { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201A, | | 80 | { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201A, |
81 | MII_STR_CICADA_CS8201A }, | | 81 | MII_STR_CICADA_CS8201A }, |
82 | | | 82 | |
83 | { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201B, | | 83 | { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201B, |
84 | MII_STR_CICADA_CS8201B }, | | 84 | MII_STR_CICADA_CS8201B }, |
85 | | | 85 | |
| | | 86 | { MII_OUI_CICADA, MII_MODEL_CICADA_CS8204, |
| | | 87 | MII_STR_CICADA_CS8204 }, |
| | | 88 | |
| | | 89 | { MII_OUI_CICADA, MII_MODEL_CICADA_VSC8211, |
| | | 90 | MII_STR_CICADA_VSC8211 }, |
| | | 91 | |
| | | 92 | { MII_OUI_CICADA, MII_MODEL_CICADA_CS8244, |
| | | 93 | MII_STR_CICADA_CS8244 }, |
| | | 94 | |
86 | { MII_OUI_xxCICADA, MII_MODEL_CICADA_CS8201, | | 95 | { MII_OUI_xxCICADA, MII_MODEL_CICADA_CS8201, |
87 | MII_STR_CICADA_CS8201 }, | | 96 | MII_STR_CICADA_CS8201 }, |
88 | | | 97 | |
89 | { MII_OUI_xxCICADA, MII_MODEL_CICADA_CS8201A, | | 98 | { MII_OUI_xxCICADA, MII_MODEL_CICADA_CS8201A, |
90 | MII_STR_CICADA_CS8201A }, | | 99 | MII_STR_CICADA_CS8201A }, |
91 | | | 100 | |
92 | { MII_OUI_xxCICADA, MII_MODEL_xxCICADA_CS8201B, | | 101 | { MII_OUI_xxCICADA, MII_MODEL_xxCICADA_CS8201B, |
93 | MII_STR_xxCICADA_CS8201B }, | | 102 | MII_STR_xxCICADA_CS8201B }, |
94 | | | 103 | |
| | | 104 | { MII_OUI_VITESSE, MII_MODEL_VITESSE_VSC8601, |
| | | 105 | MII_STR_VITESSE_VSC8601 }, |
| | | 106 | |
95 | { 0, 0, | | 107 | { 0, 0, |
96 | NULL }, | | 108 | NULL }, |
97 | }; | | 109 | }; |
98 | | | 110 | |
99 | static int | | 111 | static int |
100 | ciphymatch(device_t parent, cfdata_t match, | | 112 | ciphymatch(device_t parent, cfdata_t match, |
101 | void *aux) | | 113 | void *aux) |
102 | { | | 114 | { |
103 | struct mii_attach_args *ma = aux; | | 115 | struct mii_attach_args *ma = aux; |
104 | | | 116 | |
105 | if (mii_phy_match(ma, ciphys) != NULL) | | 117 | if (mii_phy_match(ma, ciphys) != NULL) |
106 | return (10); | | 118 | return 10; |
107 | | | 119 | |
108 | return (0); | | 120 | return 0; |
109 | } | | 121 | } |
110 | | | 122 | |
111 | static void | | 123 | static void |
112 | ciphyattach(device_t parent, device_t self, void *aux) | | 124 | ciphyattach(device_t parent, device_t self, void *aux) |
113 | { | | 125 | { |
114 | struct mii_softc *sc = device_private(self); | | 126 | struct mii_softc *sc = device_private(self); |
115 | struct mii_attach_args *ma = aux; | | 127 | struct mii_attach_args *ma = aux; |
116 | struct mii_data *mii = ma->mii_data; | | 128 | struct mii_data *mii = ma->mii_data; |
117 | const struct mii_phydesc *mpd; | | 129 | const struct mii_phydesc *mpd; |
118 | | | 130 | |
119 | mpd = mii_phy_match(ma, ciphys); | | 131 | mpd = mii_phy_match(ma, ciphys); |
120 | aprint_naive(": Media interface\n"); | | 132 | aprint_naive(": Media interface\n"); |
121 | aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); | | 133 | aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); |
| @@ -141,131 +153,117 @@ ciphyattach(device_t parent, device_t se | | | @@ -141,131 +153,117 @@ ciphyattach(device_t parent, device_t se |
141 | else | | 153 | else |
142 | mii_phy_add_media(sc); | | 154 | mii_phy_add_media(sc); |
143 | aprint_normal("\n"); | | 155 | aprint_normal("\n"); |
144 | } | | 156 | } |
145 | | | 157 | |
146 | static int | | 158 | static int |
147 | ciphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) | | 159 | ciphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) |
148 | { | | 160 | { |
149 | struct ifmedia_entry *ife = mii->mii_media.ifm_cur; | | 161 | struct ifmedia_entry *ife = mii->mii_media.ifm_cur; |
150 | int reg, speed, gig; | | 162 | int reg, speed, gig; |
151 | | | 163 | |
152 | switch (cmd) { | | 164 | switch (cmd) { |
153 | case MII_POLLSTAT: | | 165 | case MII_POLLSTAT: |
154 | /* | | 166 | /* If we're not polling our PHY instance, just return. */ |
155 | * If we're not polling our PHY instance, just return. | | | |
156 | */ | | | |
157 | if (IFM_INST(ife->ifm_media) != sc->mii_inst) | | 167 | if (IFM_INST(ife->ifm_media) != sc->mii_inst) |
158 | return (0); | | 168 | return 0; |
159 | break; | | 169 | break; |
160 | | | 170 | |
161 | case MII_MEDIACHG: | | 171 | case MII_MEDIACHG: |
162 | /* | | 172 | /* |
163 | * If the media indicates a different PHY instance, | | 173 | * If the media indicates a different PHY instance, |
164 | * isolate ourselves. | | 174 | * isolate ourselves. |
165 | */ | | 175 | */ |
166 | if (IFM_INST(ife->ifm_media) != sc->mii_inst) { | | 176 | if (IFM_INST(ife->ifm_media) != sc->mii_inst) { |
167 | reg = PHY_READ(sc, MII_BMCR); | | 177 | reg = PHY_READ(sc, MII_BMCR); |
168 | PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); | | 178 | PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); |
169 | return (0); | | 179 | return 0; |
170 | } | | 180 | } |
171 | | | 181 | |
172 | /* | | 182 | /* If the interface is not up, don't do anything. */ |
173 | * If the interface is not up, don't do anything. | | | |
174 | */ | | | |
175 | if ((mii->mii_ifp->if_flags & IFF_UP) == 0) | | 183 | if ((mii->mii_ifp->if_flags & IFF_UP) == 0) |
176 | break; | | 184 | break; |
177 | | | 185 | |
178 | ciphy_fixup(sc); /* XXX hardware bug work-around */ | | 186 | ciphy_fixup(sc); /* XXX hardware bug work-around */ |
179 | | | 187 | |
180 | switch (IFM_SUBTYPE(ife->ifm_media)) { | | 188 | switch (IFM_SUBTYPE(ife->ifm_media)) { |
181 | case IFM_AUTO: | | 189 | case IFM_AUTO: |
182 | #ifdef foo | | 190 | #ifdef foo |
183 | /* | | 191 | /* If we're already in auto mode, just return. */ |
184 | * If we're already in auto mode, just return. | | 192 | if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) |
185 | */ | | 193 | return 0; |
186 | if (PHY_READ(sc, CIPHY_MII_BMCR) & CIPHY_BMCR_AUTOEN) | | | |
187 | return (0); | | | |
188 | #endif | | 194 | #endif |
189 | (void) mii_phy_auto(sc, 0); | | 195 | (void) mii_phy_auto(sc, 0); |
190 | break; | | 196 | break; |
191 | case IFM_1000_T: | | 197 | case IFM_1000_T: |
192 | speed = CIPHY_S1000; | | 198 | speed = BMCR_S1000; |
193 | goto setit; | | 199 | goto setit; |
194 | case IFM_100_TX: | | 200 | case IFM_100_TX: |
195 | speed = CIPHY_S100; | | 201 | speed = BMCR_S100; |
196 | goto setit; | | 202 | goto setit; |
197 | case IFM_10_T: | | 203 | case IFM_10_T: |
198 | speed = CIPHY_S10; | | 204 | speed = BMCR_S10; |
199 | setit: | | 205 | setit: |
200 | if ((ife->ifm_media & IFM_FDX) != 0) { | | 206 | if ((ife->ifm_media & IFM_FDX) != 0) { |
201 | speed |= CIPHY_BMCR_FDX; | | 207 | speed |= BMCR_FDX; |
202 | gig = CIPHY_1000CTL_AFD; | | 208 | gig = GTCR_ADV_1000TFDX; |
203 | } else { | | 209 | } else |
204 | gig = CIPHY_1000CTL_AHD; | | 210 | gig = GTCR_ADV_1000THDX; |
205 | } | | 211 | |
206 | | | 212 | PHY_WRITE(sc, MII_100T2CR, 0); |
207 | PHY_WRITE(sc, CIPHY_MII_1000CTL, 0); | | 213 | PHY_WRITE(sc, MII_BMCR, speed); |
208 | PHY_WRITE(sc, CIPHY_MII_BMCR, speed); | | 214 | PHY_WRITE(sc, MII_ANAR, ANAR_CSMA); |
209 | PHY_WRITE(sc, CIPHY_MII_ANAR, CIPHY_SEL_TYPE); | | | |
210 | | | 215 | |
211 | if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) | | 216 | if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) |
212 | break; | | 217 | break; |
213 | | | 218 | |
214 | PHY_WRITE(sc, CIPHY_MII_1000CTL, gig); | | 219 | PHY_WRITE(sc, MII_100T2CR, gig); |
215 | PHY_WRITE(sc, CIPHY_MII_BMCR, | | 220 | PHY_WRITE(sc, MII_BMCR, |
216 | speed|CIPHY_BMCR_AUTOEN|CIPHY_BMCR_STARTNEG); | | 221 | speed | BMCR_AUTOEN | BMCR_STARTNEG); |
217 | | | 222 | |
218 | /* | | 223 | /* |
219 | * When setting the link manually, one side must | | 224 | * When setting the link manually, one side must |
220 | * be the master and the other the slave. However | | 225 | * be the master and the other the slave. However |
221 | * ifmedia doesn't give us a good way to specify | | 226 | * ifmedia doesn't give us a good way to specify |
222 | * this, so we fake it by using one of the LINK | | 227 | * this, so we fake it by using one of the LINK |
223 | * flags. If LINK0 is set, we program the PHY to | | 228 | * flags. If LINK0 is set, we program the PHY to |
224 | * be a master, otherwise it's a slave. | | 229 | * be a master, otherwise it's a slave. |
225 | */ | | 230 | */ |
226 | if ((mii->mii_ifp->if_flags & IFF_LINK0)) { | | 231 | if ((mii->mii_ifp->if_flags & IFF_LINK0)) { |
227 | PHY_WRITE(sc, CIPHY_MII_1000CTL, | | 232 | PHY_WRITE(sc, MII_100T2CR, |
228 | gig|CIPHY_1000CTL_MSE|CIPHY_1000CTL_MSC); | | 233 | gig | GTCR_MAN_MS | GTCR_ADV_MS); |
229 | } else { | | 234 | } else { |
230 | PHY_WRITE(sc, CIPHY_MII_1000CTL, | | 235 | PHY_WRITE(sc, MII_100T2CR, gig | GTCR_MAN_MS); |
231 | gig|CIPHY_1000CTL_MSE); | | | |
232 | } | | 236 | } |
233 | break; | | 237 | break; |
234 | case IFM_NONE: | | 238 | case IFM_NONE: |
235 | PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN); | | 239 | PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN); |
236 | break; | | 240 | break; |
237 | case IFM_100_T4: | | 241 | case IFM_100_T4: |
238 | default: | | 242 | default: |
239 | return (EINVAL); | | 243 | return EINVAL; |
240 | } | | 244 | } |
241 | break; | | 245 | break; |
242 | | | 246 | |
243 | case MII_TICK: | | 247 | case MII_TICK: |
244 | /* | | 248 | /* If we're not currently selected, just return. */ |
245 | * If we're not currently selected, just return. | | | |
246 | */ | | | |
247 | if (IFM_INST(ife->ifm_media) != sc->mii_inst) | | 249 | if (IFM_INST(ife->ifm_media) != sc->mii_inst) |
248 | return (0); | | 250 | return 0; |
249 | | | 251 | |
250 | /* | | 252 | /* Is the interface even up? */ |
251 | * Is the interface even up? | | | |
252 | */ | | | |
253 | if ((mii->mii_ifp->if_flags & IFF_UP) == 0) | | 253 | if ((mii->mii_ifp->if_flags & IFF_UP) == 0) |
254 | return (0); | | 254 | return 0; |
255 | | | 255 | |
256 | /* | | 256 | /* Only used for autonegotiation. */ |
257 | * Only used for autonegotiation. | | | |
258 | */ | | | |
259 | if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) && | | 257 | if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) && |
260 | (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) { | | 258 | (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) { |
261 | /* | | 259 | /* |
262 | * Reset autonegotiation timer to 0 just to make sure | | 260 | * Reset autonegotiation timer to 0 just to make sure |
263 | * the future autonegotiation start with 0. | | 261 | * the future autonegotiation start with 0. |
264 | */ | | 262 | */ |
265 | sc->mii_ticks = 0; | | 263 | sc->mii_ticks = 0; |
266 | break; | | 264 | break; |
267 | } | | 265 | } |
268 | | | 266 | |
269 | /* | | 267 | /* |
270 | * Check to see if we have link. If we do, we don't | | 268 | * Check to see if we have link. If we do, we don't |
271 | * need to restart the autonegotiation process. Read | | 269 | * need to restart the autonegotiation process. Read |
| @@ -280,73 +278,71 @@ setit: | | | @@ -280,73 +278,71 @@ setit: |
280 | sc->mii_ticks = 0; | | 278 | sc->mii_ticks = 0; |
281 | /* See above. */ | | 279 | /* See above. */ |
282 | break; | | 280 | break; |
283 | } | | 281 | } |
284 | | | 282 | |
285 | /* | | 283 | /* |
286 | * mii_ticks == 0 means it's the first tick after changing the | | 284 | * mii_ticks == 0 means it's the first tick after changing the |
287 | * media or the link became down since the last tick | | 285 | * media or the link became down since the last tick |
288 | * (see above), so return with 0 to update the status. | | 286 | * (see above), so return with 0 to update the status. |
289 | */ | | 287 | */ |
290 | if (sc->mii_ticks++ == 0) | | 288 | if (sc->mii_ticks++ == 0) |
291 | break; | | 289 | break; |
292 | | | 290 | |
293 | /* | | 291 | /* Only retry autonegotiation every N seconds. */ |
294 | * Only retry autonegotiation every N seconds. | | | |
295 | */ | | | |
296 | if (sc->mii_ticks <= MII_ANEGTICKS_GIGE) | | 292 | if (sc->mii_ticks <= MII_ANEGTICKS_GIGE) |
297 | break; | | 293 | break; |
298 | | | 294 | |
299 | mii_phy_auto(sc, 0); | | 295 | mii_phy_auto(sc, 0); |
300 | return (0); | | 296 | return 0; |
301 | } | | 297 | } |
302 | | | 298 | |
303 | /* Update the media status. */ | | 299 | /* Update the media status. */ |
304 | ciphy_status(sc); | | 300 | ciphy_status(sc); |
305 | | | 301 | |
306 | /* | | 302 | /* |
307 | * Callback if something changed. Note that we need to poke | | 303 | * Callback if something changed. Note that we need to poke |
308 | * apply fixups for certain PHY revs. | | 304 | * apply fixups for certain PHY revs. |
309 | */ | | 305 | */ |
310 | if (sc->mii_media_active != mii->mii_media_active || | | 306 | if (sc->mii_media_active != mii->mii_media_active || |
311 | sc->mii_media_status != mii->mii_media_status || | | 307 | sc->mii_media_status != mii->mii_media_status || |
312 | cmd == MII_MEDIACHG) { | | 308 | cmd == MII_MEDIACHG) { |
313 | ciphy_fixup(sc); | | 309 | ciphy_fixup(sc); |
314 | } | | 310 | } |
315 | mii_phy_update(sc, cmd); | | 311 | mii_phy_update(sc, cmd); |
316 | return (0); | | 312 | return 0; |
317 | } | | 313 | } |
318 | | | 314 | |
319 | static void | | 315 | static void |
320 | ciphy_status(struct mii_softc *sc) | | 316 | ciphy_status(struct mii_softc *sc) |
321 | { | | 317 | { |
322 | struct mii_data *mii = sc->mii_pdata; | | 318 | struct mii_data *mii = sc->mii_pdata; |
323 | int bmsr, bmcr; | | 319 | int bmsr, bmcr; |
324 | | | 320 | |
325 | mii->mii_media_status = IFM_AVALID; | | 321 | mii->mii_media_status = IFM_AVALID; |
326 | mii->mii_media_active = IFM_ETHER; | | 322 | mii->mii_media_active = IFM_ETHER; |
327 | | | 323 | |
328 | bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); | | 324 | bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); |
329 | | | 325 | |
330 | if (bmsr & BMSR_LINK) | | 326 | if (bmsr & BMSR_LINK) |
331 | mii->mii_media_status |= IFM_ACTIVE; | | 327 | mii->mii_media_status |= IFM_ACTIVE; |
332 | | | 328 | |
333 | bmcr = PHY_READ(sc, CIPHY_MII_BMCR); | | 329 | bmcr = PHY_READ(sc, MII_BMCR); |
334 | | | 330 | |
335 | if (bmcr & CIPHY_BMCR_LOOP) | | 331 | if (bmcr & BMCR_LOOP) |
336 | mii->mii_media_active |= IFM_LOOP; | | 332 | mii->mii_media_active |= IFM_LOOP; |
337 | | | 333 | |
338 | if (bmcr & CIPHY_BMCR_AUTOEN) { | | 334 | if (bmcr & BMCR_AUTOEN) { |
339 | if ((bmsr & CIPHY_BMSR_ACOMP) == 0) { | | 335 | if ((bmsr & BMSR_ACOMP) == 0) { |
340 | /* Erg, still trying, I guess... */ | | 336 | /* Erg, still trying, I guess... */ |
341 | mii->mii_media_active |= IFM_NONE; | | 337 | mii->mii_media_active |= IFM_NONE; |
342 | return; | | 338 | return; |
343 | } | | 339 | } |
344 | } | | 340 | } |
345 | | | 341 | |
346 | bmsr = PHY_READ(sc, CIPHY_MII_AUXCSR); | | 342 | bmsr = PHY_READ(sc, CIPHY_MII_AUXCSR); |
347 | switch (bmsr & CIPHY_AUXCSR_SPEED) { | | 343 | switch (bmsr & CIPHY_AUXCSR_SPEED) { |
348 | case CIPHY_SPEED10: | | 344 | case CIPHY_SPEED10: |
349 | mii->mii_media_active |= IFM_10_T; | | 345 | mii->mii_media_active |= IFM_10_T; |
350 | break; | | 346 | break; |
351 | case CIPHY_SPEED100: | | 347 | case CIPHY_SPEED100: |
352 | mii->mii_media_active |= IFM_100_TX; | | 348 | mii->mii_media_active |= IFM_100_TX; |
| @@ -378,38 +374,39 @@ ciphy_reset(struct mii_softc *sc) | | | @@ -378,38 +374,39 @@ ciphy_reset(struct mii_softc *sc) |
378 | } | | 374 | } |
379 | | | 375 | |
380 | #define PHY_SETBIT(x, y, z) \ | | 376 | #define PHY_SETBIT(x, y, z) \ |
381 | PHY_WRITE(x, y, (PHY_READ(x, y) | (z))) | | 377 | PHY_WRITE(x, y, (PHY_READ(x, y) | (z))) |
382 | #define PHY_CLRBIT(x, y, z) \ | | 378 | #define PHY_CLRBIT(x, y, z) \ |
383 | PHY_WRITE(x, y, (PHY_READ(x, y) & ~(z))) | | 379 | PHY_WRITE(x, y, (PHY_READ(x, y) & ~(z))) |
384 | | | 380 | |
385 | static void | | 381 | static void |
386 | ciphy_fixup(struct mii_softc *sc) | | 382 | ciphy_fixup(struct mii_softc *sc) |
387 | { | | 383 | { |
388 | uint16_t model; | | 384 | uint16_t model; |
389 | uint16_t status, speed; | | 385 | uint16_t status, speed; |
390 | | | 386 | |
391 | model = MII_MODEL(PHY_READ(sc, CIPHY_MII_PHYIDR2)); | | 387 | model = MII_MODEL(PHY_READ(sc, MII_PHYIDR2)); |
392 | status = PHY_READ(sc, CIPHY_MII_AUXCSR); | | 388 | status = PHY_READ(sc, CIPHY_MII_AUXCSR); |
393 | speed = status & CIPHY_AUXCSR_SPEED; | | 389 | speed = status & CIPHY_AUXCSR_SPEED; |
394 | | | 390 | |
395 | if (device_is_a(device_parent(sc->mii_dev), "nfe")) { | | 391 | if (device_is_a(device_parent(sc->mii_dev), "nfe")) { |
396 | /* need to set for 2.5V RGMII for NVIDIA adapters */ | | 392 | /* Need to set for 2.5V RGMII for NVIDIA adapters */ |
397 | PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_INTSEL_RGMII); | | 393 | PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_INTSEL_RGMII); |
398 | PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_IOVOL_2500MV); | | 394 | PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_IOVOL_2500MV); |
399 | } | | 395 | } |
400 | | | 396 | |
401 | switch (model) { | | 397 | switch (model) { |
402 | case MII_MODEL_CICADA_CS8201: | | 398 | case MII_MODEL_CICADA_CS8201: |
| | | 399 | case MII_MODEL_CICADA_CS8204: |
403 | | | 400 | |
404 | /* Turn off "aux mode" (whatever that means) */ | | 401 | /* Turn off "aux mode" (whatever that means) */ |
405 | PHY_SETBIT(sc, CIPHY_MII_AUXCSR, CIPHY_AUXCSR_MDPPS); | | 402 | PHY_SETBIT(sc, CIPHY_MII_AUXCSR, CIPHY_AUXCSR_MDPPS); |
406 | | | 403 | |
407 | /* | | 404 | /* |
408 | * Work around speed polling bug in VT3119/VT3216 | | 405 | * Work around speed polling bug in VT3119/VT3216 |
409 | * when using MII in full duplex mode. | | 406 | * when using MII in full duplex mode. |
410 | */ | | 407 | */ |
411 | if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) && | | 408 | if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) && |
412 | (status & CIPHY_AUXCSR_FDX)) { | | 409 | (status & CIPHY_AUXCSR_FDX)) { |
413 | PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); | | 410 | PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); |
414 | } else { | | 411 | } else { |
415 | PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); | | 412 | PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); |
| @@ -420,26 +417,29 @@ ciphy_fixup(struct mii_softc *sc) | | | @@ -420,26 +417,29 @@ ciphy_fixup(struct mii_softc *sc) |
420 | | | 417 | |
421 | break; | | 418 | break; |
422 | | | 419 | |
423 | case MII_MODEL_CICADA_CS8201A: | | 420 | case MII_MODEL_CICADA_CS8201A: |
424 | case MII_MODEL_CICADA_CS8201B: | | 421 | case MII_MODEL_CICADA_CS8201B: |
425 | | | 422 | |
426 | /* | | 423 | /* |
427 | * Work around speed polling bug in VT3119/VT3216 | | 424 | * Work around speed polling bug in VT3119/VT3216 |
428 | * when using MII in full duplex mode. | | 425 | * when using MII in full duplex mode. |
429 | */ | | 426 | */ |
430 | if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) && | | 427 | if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) && |
431 | (status & CIPHY_AUXCSR_FDX)) { | | 428 | (status & CIPHY_AUXCSR_FDX)) { |
432 | PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); | | 429 | PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); |
433 | } else { | | 430 | } else |
434 | PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); | | 431 | PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); |
435 | } | | | |
436 | | | 432 | |
437 | break; | | 433 | break; |
| | | 434 | case MII_MODEL_CICADA_VSC8211: |
| | | 435 | case MII_MODEL_CICADA_CS8244: |
| | | 436 | case MII_MODEL_VITESSE_VSC8601: |
| | | 437 | break; |
438 | default: | | 438 | default: |
439 | aprint_error_dev(sc->mii_dev, "unknown CICADA PHY model %x\n", | | 439 | aprint_error_dev(sc->mii_dev, "unknown CICADA PHY model %x\n", |
440 | model); | | 440 | model); |
441 | break; | | 441 | break; |
442 | } | | 442 | } |
443 | | | 443 | |
444 | return; | | 444 | return; |
445 | } | | 445 | } |