Fri Oct 11 09:29:04 2019 UTC ()
- Indicat master mode if the negotiated result say so.
- KNF


(msaitoh)
diff -r1.34 -r1.35 src/sys/dev/mii/ciphy.c
diff -r1.56 -r1.57 src/sys/dev/mii/rgephy.c

cvs diff -r1.34 -r1.35 src/sys/dev/mii/ciphy.c (switch to unified diff)

--- src/sys/dev/mii/ciphy.c 2019/04/11 09:14:07 1.34
+++ src/sys/dev/mii/ciphy.c 2019/10/11 09:29:04 1.35
@@ -1,442 +1,443 @@ @@ -1,442 +1,443 @@
1/* $NetBSD: ciphy.c,v 1.34 2019/04/11 09:14:07 msaitoh Exp $ */ 1/* $NetBSD: ciphy.c,v 1.35 2019/10/11 09:29:04 msaitoh 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.
15 * 3. All advertising materials mentioning features or use of this software 15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 16 * must display the following acknowledgement:
17 * This product includes software developed by Bill Paul. 17 * This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors 18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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.34 2019/04/11 09:14:07 msaitoh Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: ciphy.c,v 1.35 2019/10/11 09:29:04 msaitoh 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>
52#include <net/if_arp.h> 52#include <net/if_arp.h>
53#include <net/if_media.h> 53#include <net/if_media.h>
54 54
55#include <dev/mii/mii.h> 55#include <dev/mii/mii.h>
56#include <dev/mii/miivar.h> 56#include <dev/mii/miivar.h>
57#include <dev/mii/miidevs.h> 57#include <dev/mii/miidevs.h>
58 58
59#include <dev/mii/ciphyreg.h> 59#include <dev/mii/ciphyreg.h>
60 60
61static int ciphymatch(device_t, cfdata_t, void *); 61static int ciphymatch(device_t, cfdata_t, void *);
62static void ciphyattach(device_t, device_t, void *); 62static void ciphyattach(device_t, device_t, void *);
63 63
64CFATTACH_DECL_NEW(ciphy, sizeof(struct mii_softc), 64CFATTACH_DECL_NEW(ciphy, sizeof(struct mii_softc),
65 ciphymatch, ciphyattach, mii_phy_detach, mii_phy_activate); 65 ciphymatch, ciphyattach, mii_phy_detach, mii_phy_activate);
66 66
67static int ciphy_service(struct mii_softc *, struct mii_data *, int); 67static int ciphy_service(struct mii_softc *, struct mii_data *, int);
68static void ciphy_status(struct mii_softc *); 68static void ciphy_status(struct mii_softc *);
69static void ciphy_reset(struct mii_softc *); 69static void ciphy_reset(struct mii_softc *);
70static void ciphy_fixup(struct mii_softc *); 70static void ciphy_fixup(struct mii_softc *);
71 71
72static const struct mii_phy_funcs ciphy_funcs = { 72static const struct mii_phy_funcs ciphy_funcs = {
73 ciphy_service, ciphy_status, mii_phy_reset, 73 ciphy_service, ciphy_status, mii_phy_reset,
74}; 74};
75 75
76static const struct mii_phydesc ciphys[] = { 76static const struct mii_phydesc ciphys[] = {
77 MII_PHY_DESC(CICADA, CS8201), 77 MII_PHY_DESC(CICADA, CS8201),
78 MII_PHY_DESC(CICADA, CS8201A), 78 MII_PHY_DESC(CICADA, CS8201A),
79 MII_PHY_DESC(CICADA, CS8201B), 79 MII_PHY_DESC(CICADA, CS8201B),
80 MII_PHY_DESC(CICADA, CS8204), 80 MII_PHY_DESC(CICADA, CS8204),
81 MII_PHY_DESC(CICADA, VSC8211), 81 MII_PHY_DESC(CICADA, VSC8211),
82 MII_PHY_DESC(CICADA, CS8244), 82 MII_PHY_DESC(CICADA, CS8244),
83 MII_PHY_DESC(CICADA, CS8201), 83 MII_PHY_DESC(CICADA, CS8201),
84 MII_PHY_DESC(CICADA, CS8201A), 84 MII_PHY_DESC(CICADA, CS8201A),
85 MII_PHY_DESC(xxCICADA, CS8201B), 85 MII_PHY_DESC(xxCICADA, CS8201B),
86 MII_PHY_DESC(VITESSE, VSC8601), 86 MII_PHY_DESC(VITESSE, VSC8601),
87 MII_PHY_END, 87 MII_PHY_END,
88}; 88};
89 89
90static int 90static int
91ciphymatch(device_t parent, cfdata_t match, 91ciphymatch(device_t parent, cfdata_t match,
92 void *aux) 92 void *aux)
93{ 93{
94 struct mii_attach_args *ma = aux; 94 struct mii_attach_args *ma = aux;
95 95
96 if (mii_phy_match(ma, ciphys) != NULL) 96 if (mii_phy_match(ma, ciphys) != NULL)
97 return 10; 97 return 10;
98 98
99 return 0; 99 return 0;
100} 100}
101 101
102static void 102static void
103ciphyattach(device_t parent, device_t self, void *aux) 103ciphyattach(device_t parent, device_t self, void *aux)
104{ 104{
105 struct mii_softc *sc = device_private(self); 105 struct mii_softc *sc = device_private(self);
106 struct mii_attach_args *ma = aux; 106 struct mii_attach_args *ma = aux;
107 struct mii_data *mii = ma->mii_data; 107 struct mii_data *mii = ma->mii_data;
108 const struct mii_phydesc *mpd; 108 const struct mii_phydesc *mpd;
109 109
110 mpd = mii_phy_match(ma, ciphys); 110 mpd = mii_phy_match(ma, ciphys);
111 aprint_naive(": Media interface\n"); 111 aprint_naive(": Media interface\n");
112 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); 112 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
113 113
114 sc->mii_dev = self; 114 sc->mii_dev = self;
115 sc->mii_inst = mii->mii_instance; 115 sc->mii_inst = mii->mii_instance;
116 sc->mii_phy = ma->mii_phyno; 116 sc->mii_phy = ma->mii_phyno;
117 sc->mii_funcs = &ciphy_funcs; 117 sc->mii_funcs = &ciphy_funcs;
118 sc->mii_pdata = mii; 118 sc->mii_pdata = mii;
119 sc->mii_flags = ma->mii_flags; 119 sc->mii_flags = ma->mii_flags;
120 sc->mii_anegticks = MII_ANEGTICKS; 120 sc->mii_anegticks = MII_ANEGTICKS;
121 121
122 sc->mii_flags |= MIIF_NOISOLATE; 122 sc->mii_flags |= MIIF_NOISOLATE;
123 123
124 ciphy_reset(sc); 124 ciphy_reset(sc);
125 125
126 PHY_READ(sc, MII_BMSR, &sc->mii_capabilities); 126 PHY_READ(sc, MII_BMSR, &sc->mii_capabilities);
127 sc->mii_capabilities &= ma->mii_capmask; 127 sc->mii_capabilities &= ma->mii_capmask;
128 if (sc->mii_capabilities & BMSR_EXTSTAT) 128 if (sc->mii_capabilities & BMSR_EXTSTAT)
129 PHY_READ(sc, MII_EXTSR, &sc->mii_extcapabilities); 129 PHY_READ(sc, MII_EXTSR, &sc->mii_extcapabilities);
130 aprint_normal_dev(self, ""); 130 aprint_normal_dev(self, "");
131 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) 131 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
132 aprint_error("no media present"); 132 aprint_error("no media present");
133 else 133 else
134 mii_phy_add_media(sc); 134 mii_phy_add_media(sc);
135 aprint_normal("\n"); 135 aprint_normal("\n");
136} 136}
137 137
138static int 138static int
139ciphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 139ciphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
140{ 140{
141 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 141 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
142 uint16_t reg, speed, gig; 142 uint16_t reg, speed, gig;
143 143
144 switch (cmd) { 144 switch (cmd) {
145 case MII_POLLSTAT: 145 case MII_POLLSTAT:
146 /* If we're not polling our PHY instance, just return. */ 146 /* If we're not polling our PHY instance, just return. */
147 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 147 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
148 return 0; 148 return 0;
149 break; 149 break;
150 150
151 case MII_MEDIACHG: 151 case MII_MEDIACHG:
152 /* 152 /*
153 * If the media indicates a different PHY instance, 153 * If the media indicates a different PHY instance,
154 * isolate ourselves. 154 * isolate ourselves.
155 */ 155 */
156 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 156 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
157 PHY_READ(sc, MII_BMCR, &reg); 157 PHY_READ(sc, MII_BMCR, &reg);
158 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 158 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
159 return 0; 159 return 0;
160 } 160 }
161 161
162 /* If the interface is not up, don't do anything. */ 162 /* If the interface is not up, don't do anything. */
163 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 163 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
164 break; 164 break;
165 165
166 ciphy_fixup(sc); /* XXX hardware bug work-around */ 166 ciphy_fixup(sc); /* XXX hardware bug work-around */
167 167
168 switch (IFM_SUBTYPE(ife->ifm_media)) { 168 switch (IFM_SUBTYPE(ife->ifm_media)) {
169 case IFM_AUTO: 169 case IFM_AUTO:
170#ifdef foo 170#ifdef foo
171 /* If we're already in auto mode, just return. */ 171 /* If we're already in auto mode, just return. */
172 PHY_READ(sc, MII_BMCR, &reg); 172 PHY_READ(sc, MII_BMCR, &reg);
173 if (reg & BMCR_AUTOEN) 173 if (reg & BMCR_AUTOEN)
174 return 0; 174 return 0;
175#endif 175#endif
176 (void) mii_phy_auto(sc, 0); 176 (void) mii_phy_auto(sc, 0);
177 break; 177 break;
178 case IFM_1000_T: 178 case IFM_1000_T:
179 speed = BMCR_S1000; 179 speed = BMCR_S1000;
180 goto setit; 180 goto setit;
181 case IFM_100_TX: 181 case IFM_100_TX:
182 speed = BMCR_S100; 182 speed = BMCR_S100;
183 goto setit; 183 goto setit;
184 case IFM_10_T: 184 case IFM_10_T:
185 speed = BMCR_S10; 185 speed = BMCR_S10;
186setit: 186setit:
187 if ((ife->ifm_media & IFM_FDX) != 0) { 187 if ((ife->ifm_media & IFM_FDX) != 0) {
188 speed |= BMCR_FDX; 188 speed |= BMCR_FDX;
189 gig = GTCR_ADV_1000TFDX; 189 gig = GTCR_ADV_1000TFDX;
190 } else 190 } else
191 gig = GTCR_ADV_1000THDX; 191 gig = GTCR_ADV_1000THDX;
192 192
193 PHY_WRITE(sc, MII_GTCR, 0); 193 PHY_WRITE(sc, MII_GTCR, 0);
194 PHY_WRITE(sc, MII_BMCR, speed); 194 PHY_WRITE(sc, MII_BMCR, speed);
195 PHY_WRITE(sc, MII_ANAR, ANAR_CSMA); 195 PHY_WRITE(sc, MII_ANAR, ANAR_CSMA);
196 196
197 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) 197 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
198 break; 198 break;
199 199
200 PHY_WRITE(sc, MII_GTCR, gig); 200 PHY_WRITE(sc, MII_GTCR, gig);
201 PHY_WRITE(sc, MII_BMCR, 201 PHY_WRITE(sc, MII_BMCR,
202 speed | BMCR_AUTOEN | BMCR_STARTNEG); 202 speed | BMCR_AUTOEN | BMCR_STARTNEG);
203 203
204 /* 204 /*
205 * When setting the link manually, one side must 205 * When setting the link manually, one side must
206 * be the master and the other the slave. However 206 * be the master and the other the slave. However
207 * ifmedia doesn't give us a good way to specify 207 * ifmedia doesn't give us a good way to specify
208 * this, so we fake it by using one of the LINK 208 * this, so we fake it by using one of the LINK
209 * flags. If LINK0 is set, we program the PHY to 209 * flags. If LINK0 is set, we program the PHY to
210 * be a master, otherwise it's a slave. 210 * be a master, otherwise it's a slave.
211 */ 211 */
212 if ((mii->mii_ifp->if_flags & IFF_LINK0)) { 212 if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
213 PHY_WRITE(sc, MII_GTCR, 213 PHY_WRITE(sc, MII_GTCR,
214 gig | GTCR_MAN_MS | GTCR_ADV_MS); 214 gig | GTCR_MAN_MS | GTCR_ADV_MS);
215 } else 215 } else
216 PHY_WRITE(sc, MII_GTCR, gig | GTCR_MAN_MS); 216 PHY_WRITE(sc, MII_GTCR, gig | GTCR_MAN_MS);
217 break; 217 break;
218 case IFM_NONE: 218 case IFM_NONE:
219 PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN); 219 PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN);
220 break; 220 break;
221 case IFM_100_T4: 221 case IFM_100_T4:
222 default: 222 default:
223 return EINVAL; 223 return EINVAL;
224 } 224 }
225 break; 225 break;
226 226
227 case MII_TICK: 227 case MII_TICK:
228 /* If we're not currently selected, just return. */ 228 /* If we're not currently selected, just return. */
229 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 229 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
230 return 0; 230 return 0;
231 231
232 /* Is the interface even up? */ 232 /* Is the interface even up? */
233 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 233 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
234 return 0; 234 return 0;
235 235
236 /* Only used for autonegotiation. */ 236 /* Only used for autonegotiation. */
237 if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) && 237 if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) &&
238 (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) { 238 (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) {
239 /* 239 /*
240 * Reset autonegotiation timer to 0 just to make sure 240 * Reset autonegotiation timer to 0 just to make sure
241 * the future autonegotiation start with 0. 241 * the future autonegotiation start with 0.
242 */ 242 */
243 sc->mii_ticks = 0; 243 sc->mii_ticks = 0;
244 break; 244 break;
245 } 245 }
246 246
247 /* 247 /*
248 * Check to see if we have link. If we do, we don't 248 * Check to see if we have link. If we do, we don't
249 * need to restart the autonegotiation process. Read 249 * need to restart the autonegotiation process. Read
250 * the BMSR twice in case it's latched. 250 * the BMSR twice in case it's latched.
251 */ 251 */
252 PHY_READ(sc, MII_BMSR, &reg); 252 PHY_READ(sc, MII_BMSR, &reg);
253 PHY_READ(sc, MII_BMSR, &reg); 253 PHY_READ(sc, MII_BMSR, &reg);
254 if (reg & BMSR_LINK) { 254 if (reg & BMSR_LINK) {
255 /* 255 /*
256 * Reset autonegotiation timer to 0 in case the link 256 * Reset autonegotiation timer to 0 in case the link
257 * goes down in the next tick. 257 * goes down in the next tick.
258 */ 258 */
259 sc->mii_ticks = 0; 259 sc->mii_ticks = 0;
260 /* See above. */ 260 /* See above. */
261 break; 261 break;
262 } 262 }
263 263
264 /* 264 /*
265 * mii_ticks == 0 means it's the first tick after changing the 265 * mii_ticks == 0 means it's the first tick after changing the
266 * media or the link became down since the last tick 266 * media or the link became down since the last tick
267 * (see above), so return with 0 to update the status. 267 * (see above), so return with 0 to update the status.
268 */ 268 */
269 if (sc->mii_ticks++ == 0) 269 if (sc->mii_ticks++ == 0)
270 break; 270 break;
271 271
272 /* Only retry autonegotiation every N seconds. */ 272 /* Only retry autonegotiation every N seconds. */
273 if (sc->mii_ticks <= MII_ANEGTICKS_GIGE) 273 if (sc->mii_ticks <= MII_ANEGTICKS_GIGE)
274 break; 274 break;
275 275
276 mii_phy_auto(sc, 0); 276 mii_phy_auto(sc, 0);
277 return 0; 277 return 0;
278 } 278 }
279 279
280 /* Update the media status. */ 280 /* Update the media status. */
281 ciphy_status(sc); 281 ciphy_status(sc);
282 282
283 /* 283 /*
284 * Callback if something changed. Note that we need to poke 284 * Callback if something changed. Note that we need to poke
285 * apply fixups for certain PHY revs. 285 * apply fixups for certain PHY revs.
286 */ 286 */
287 if (sc->mii_media_active != mii->mii_media_active || 287 if (sc->mii_media_active != mii->mii_media_active ||
288 sc->mii_media_status != mii->mii_media_status || 288 sc->mii_media_status != mii->mii_media_status ||
289 cmd == MII_MEDIACHG) { 289 cmd == MII_MEDIACHG) {
290 ciphy_fixup(sc); 290 ciphy_fixup(sc);
291 } 291 }
292 mii_phy_update(sc, cmd); 292 mii_phy_update(sc, cmd);
293 return 0; 293 return 0;
294} 294}
295 295
296static void 296static void
297ciphy_status(struct mii_softc *sc) 297ciphy_status(struct mii_softc *sc)
298{ 298{
299 struct mii_data *mii = sc->mii_pdata; 299 struct mii_data *mii = sc->mii_pdata;
300 uint16_t bmsr, bmcr; 300 uint16_t bmsr, bmcr, gtsr;
301 301
302 mii->mii_media_status = IFM_AVALID; 302 mii->mii_media_status = IFM_AVALID;
303 mii->mii_media_active = IFM_ETHER; 303 mii->mii_media_active = IFM_ETHER;
304 304
305 PHY_READ(sc, MII_BMSR, &bmsr); 305 PHY_READ(sc, MII_BMSR, &bmsr);
306 PHY_READ(sc, MII_BMSR, &bmsr); 306 PHY_READ(sc, MII_BMSR, &bmsr);
307 307
308 if (bmsr & BMSR_LINK) 308 if (bmsr & BMSR_LINK)
309 mii->mii_media_status |= IFM_ACTIVE; 309 mii->mii_media_status |= IFM_ACTIVE;
310 310
311 PHY_READ(sc, MII_BMCR, &bmcr); 311 PHY_READ(sc, MII_BMCR, &bmcr);
312 312
313 if (bmcr & BMCR_LOOP) 313 if (bmcr & BMCR_LOOP)
314 mii->mii_media_active |= IFM_LOOP; 314 mii->mii_media_active |= IFM_LOOP;
315 315
316 if (bmcr & BMCR_AUTOEN) { 316 if (bmcr & BMCR_AUTOEN) {
317 if ((bmsr & BMSR_ACOMP) == 0) { 317 if ((bmsr & BMSR_ACOMP) == 0) {
318 /* Erg, still trying, I guess... */ 318 /* Erg, still trying, I guess... */
319 mii->mii_media_active |= IFM_NONE; 319 mii->mii_media_active |= IFM_NONE;
320 return; 320 return;
321 } 321 }
322 } 322 }
323 323
324 PHY_READ(sc, CIPHY_MII_AUXCSR, &bmsr); 324 PHY_READ(sc, CIPHY_MII_AUXCSR, &bmsr);
325 switch (bmsr & CIPHY_AUXCSR_SPEED) { 325 switch (bmsr & CIPHY_AUXCSR_SPEED) {
326 case CIPHY_SPEED10: 326 case CIPHY_SPEED10:
327 mii->mii_media_active |= IFM_10_T; 327 mii->mii_media_active |= IFM_10_T;
328 break; 328 break;
329 case CIPHY_SPEED100: 329 case CIPHY_SPEED100:
330 mii->mii_media_active |= IFM_100_TX; 330 mii->mii_media_active |= IFM_100_TX;
331 break; 331 break;
332 case CIPHY_SPEED1000: 332 case CIPHY_SPEED1000:
333 mii->mii_media_active |= IFM_1000_T; 333 mii->mii_media_active |= IFM_1000_T;
334 break; 334 break;
335 default: 335 default:
336 aprint_error_dev(sc->mii_dev, "unknown PHY speed %x\n", 336 aprint_error_dev(sc->mii_dev, "unknown PHY speed %x\n",
337 bmsr & CIPHY_AUXCSR_SPEED); 337 bmsr & CIPHY_AUXCSR_SPEED);
338 break; 338 break;
339 } 339 }
340 340
341 if (bmsr & CIPHY_AUXCSR_FDX) 341 if (bmsr & CIPHY_AUXCSR_FDX)
342 mii->mii_media_active |= IFM_FDX; 342 mii->mii_media_active |= IFM_FDX;
343 else 343 else
344 mii->mii_media_active |= IFM_HDX; 344 mii->mii_media_active |= IFM_HDX;
345 345
346 return; 346 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
 347 PHY_READ(sc, MII_GTSR, &gtsr);
 348 if ((gtsr & GTSR_MS_RES) != 0)
 349 mii->mii_media_active |= IFM_ETH_MASTER;
 350 }
347} 351}
348 352
349static void 353static void
350ciphy_reset(struct mii_softc *sc) 354ciphy_reset(struct mii_softc *sc)
351{ 355{
 356
352 mii_phy_reset(sc); 357 mii_phy_reset(sc);
353 DELAY(1000); 358 DELAY(1000);
354 
355 return; 
356} 359}
357 360
358static inline int 361static inline int
359PHY_SETBIT(struct mii_softc *sc, int y, uint16_t z) 362PHY_SETBIT(struct mii_softc *sc, int y, uint16_t z)
360{ 363{
361 uint16_t _tmp; 364 uint16_t _tmp;
362 int rv; 365 int rv;
363 366
364 if ((rv = PHY_READ(sc, y, &_tmp)) != 0) 367 if ((rv = PHY_READ(sc, y, &_tmp)) != 0)
365 return rv; 368 return rv;
366 return PHY_WRITE(sc, y, _tmp | z); 369 return PHY_WRITE(sc, y, _tmp | z);
367} 370}
368 371
369static inline int 372static inline int
370PHY_CLRBIT(struct mii_softc *sc, int y, uint16_t z) 373PHY_CLRBIT(struct mii_softc *sc, int y, uint16_t z)
371{ 374{
372 uint16_t _tmp; 375 uint16_t _tmp;
373 int rv; 376 int rv;
374 377
375 if ((rv = PHY_READ(sc, y, &_tmp)) != 0) 378 if ((rv = PHY_READ(sc, y, &_tmp)) != 0)
376 return rv; 379 return rv;
377 return PHY_WRITE(sc, y, _tmp & ~z); 380 return PHY_WRITE(sc, y, _tmp & ~z);
378} 381}
379 382
380static void 383static void
381ciphy_fixup(struct mii_softc *sc) 384ciphy_fixup(struct mii_softc *sc)
382{ 385{
383 uint16_t model, status, speed; 386 uint16_t model, status, speed;
384 uint16_t reg; 387 uint16_t reg;
385 388
386 PHY_READ(sc, MII_PHYIDR2, &reg); 389 PHY_READ(sc, MII_PHYIDR2, &reg);
387 model = MII_MODEL(reg); 390 model = MII_MODEL(reg);
388 PHY_READ(sc, CIPHY_MII_AUXCSR, &status); 391 PHY_READ(sc, CIPHY_MII_AUXCSR, &status);
389 speed = status & CIPHY_AUXCSR_SPEED; 392 speed = status & CIPHY_AUXCSR_SPEED;
390 393
391 if (device_is_a(device_parent(sc->mii_dev), "nfe")) { 394 if (device_is_a(device_parent(sc->mii_dev), "nfe")) {
392 /* Need to set for 2.5V RGMII for NVIDIA adapters */ 395 /* Need to set for 2.5V RGMII for NVIDIA adapters */
393 PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_INTSEL_RGMII); 396 PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_INTSEL_RGMII);
394 PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_IOVOL_2500MV); 397 PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_IOVOL_2500MV);
395 } 398 }
396 399
397 switch (model) { 400 switch (model) {
398 case MII_MODEL_CICADA_CS8201: 401 case MII_MODEL_CICADA_CS8201:
399 case MII_MODEL_CICADA_CS8204: 402 case MII_MODEL_CICADA_CS8204:
400 /* Turn off "aux mode" (whatever that means) */ 403 /* Turn off "aux mode" (whatever that means) */
401 PHY_SETBIT(sc, CIPHY_MII_AUXCSR, CIPHY_AUXCSR_MDPPS); 404 PHY_SETBIT(sc, CIPHY_MII_AUXCSR, CIPHY_AUXCSR_MDPPS);
402 405
403 /* 406 /*
404 * Work around speed polling bug in VT3119/VT3216 407 * Work around speed polling bug in VT3119/VT3216
405 * when using MII in full duplex mode. 408 * when using MII in full duplex mode.
406 */ 409 */
407 if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) && 410 if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) &&
408 (status & CIPHY_AUXCSR_FDX)) 411 (status & CIPHY_AUXCSR_FDX))
409 PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); 412 PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
410 else 413 else
411 PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); 414 PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
412 415
413 /* Enable link/activity LED blink. */ 416 /* Enable link/activity LED blink. */
414 PHY_SETBIT(sc, CIPHY_MII_LED, CIPHY_LED_LINKACTBLINK); 417 PHY_SETBIT(sc, CIPHY_MII_LED, CIPHY_LED_LINKACTBLINK);
415 418
416 break; 419 break;
417 420
418 case MII_MODEL_CICADA_CS8201A: 421 case MII_MODEL_CICADA_CS8201A:
419 case MII_MODEL_CICADA_CS8201B: 422 case MII_MODEL_CICADA_CS8201B:
420 /* 423 /*
421 * Work around speed polling bug in VT3119/VT3216 424 * Work around speed polling bug in VT3119/VT3216
422 * when using MII in full duplex mode. 425 * when using MII in full duplex mode.
423 */ 426 */
424 if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) && 427 if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) &&
425 (status & CIPHY_AUXCSR_FDX)) 428 (status & CIPHY_AUXCSR_FDX))
426 PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); 429 PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
427 else 430 else
428 PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); 431 PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
429 432
430 break; 433 break;
431 case MII_MODEL_CICADA_VSC8211: 434 case MII_MODEL_CICADA_VSC8211:
432 case MII_MODEL_CICADA_CS8244: 435 case MII_MODEL_CICADA_CS8244:
433 case MII_MODEL_VITESSE_VSC8601: 436 case MII_MODEL_VITESSE_VSC8601:
434 break; 437 break;
435 default: 438 default:
436 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",
437 model); 440 model);
438 break; 441 break;
439 } 442 }
440 
441 return; 
442} 443}

cvs diff -r1.56 -r1.57 src/sys/dev/mii/rgephy.c (switch to unified diff)

--- src/sys/dev/mii/rgephy.c 2019/10/11 03:40:01 1.56
+++ src/sys/dev/mii/rgephy.c 2019/10/11 09:29:04 1.57
@@ -1,683 +1,689 @@ @@ -1,683 +1,689 @@
1/* $NetBSD: rgephy.c,v 1.56 2019/10/11 03:40:01 msaitoh Exp $ */ 1/* $NetBSD: rgephy.c,v 1.57 2019/10/11 09:29:04 msaitoh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 4 * Copyright (c) 2003
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.
15 * 3. All advertising materials mentioning features or use of this software 15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 16 * must display the following acknowledgement:
17 * This product includes software developed by Bill Paul. 17 * This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors 18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
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 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36__KERNEL_RCSID(0, "$NetBSD: rgephy.c,v 1.56 2019/10/11 03:40:01 msaitoh Exp $"); 36__KERNEL_RCSID(0, "$NetBSD: rgephy.c,v 1.57 2019/10/11 09:29:04 msaitoh Exp $");
37 37
38 38
39/* 39/*
40 * Driver for the RealTek 8169S/8110S internal 10/100/1000 PHY. 40 * Driver for the RealTek 8169S/8110S internal 10/100/1000 PHY.
41 */ 41 */
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/systm.h> 44#include <sys/systm.h>
45#include <sys/kernel.h> 45#include <sys/kernel.h>
46#include <sys/device.h> 46#include <sys/device.h>
47#include <sys/socket.h> 47#include <sys/socket.h>
48 48
49 49
50#include <net/if.h> 50#include <net/if.h>
51#include <net/if_media.h> 51#include <net/if_media.h>
52 52
53#include <dev/mii/mii.h> 53#include <dev/mii/mii.h>
54#include <dev/mii/mdio.h> 54#include <dev/mii/mdio.h>
55#include <dev/mii/miivar.h> 55#include <dev/mii/miivar.h>
56#include <dev/mii/miidevs.h> 56#include <dev/mii/miidevs.h>
57 57
58#include <dev/mii/rgephyreg.h> 58#include <dev/mii/rgephyreg.h>
59 59
60#include <dev/ic/rtl81x9reg.h> 60#include <dev/ic/rtl81x9reg.h>
61 61
62static int rgephy_match(device_t, cfdata_t, void *); 62static int rgephy_match(device_t, cfdata_t, void *);
63static void rgephy_attach(device_t, device_t, void *); 63static void rgephy_attach(device_t, device_t, void *);
64 64
65struct rgephy_softc { 65struct rgephy_softc {
66 struct mii_softc mii_sc; 66 struct mii_softc mii_sc;
67 bool mii_no_rx_delay; 67 bool mii_no_rx_delay;
68}; 68};
69 69
70CFATTACH_DECL_NEW(rgephy, sizeof(struct rgephy_softc), 70CFATTACH_DECL_NEW(rgephy, sizeof(struct rgephy_softc),
71 rgephy_match, rgephy_attach, mii_phy_detach, mii_phy_activate); 71 rgephy_match, rgephy_attach, mii_phy_detach, mii_phy_activate);
72 72
73 73
74static int rgephy_service(struct mii_softc *, struct mii_data *, int); 74static int rgephy_service(struct mii_softc *, struct mii_data *, int);
75static void rgephy_status(struct mii_softc *); 75static void rgephy_status(struct mii_softc *);
76static int rgephy_mii_phy_auto(struct mii_softc *); 76static int rgephy_mii_phy_auto(struct mii_softc *);
77static void rgephy_reset(struct mii_softc *); 77static void rgephy_reset(struct mii_softc *);
78static bool rgephy_linkup(struct mii_softc *); 78static bool rgephy_linkup(struct mii_softc *);
79static void rgephy_loop(struct mii_softc *); 79static void rgephy_loop(struct mii_softc *);
80static void rgephy_load_dspcode(struct mii_softc *); 80static void rgephy_load_dspcode(struct mii_softc *);
81 81
82static const struct mii_phy_funcs rgephy_funcs = { 82static const struct mii_phy_funcs rgephy_funcs = {
83 rgephy_service, rgephy_status, rgephy_reset, 83 rgephy_service, rgephy_status, rgephy_reset,
84}; 84};
85 85
86static const struct mii_phydesc rgephys[] = { 86static const struct mii_phydesc rgephys[] = {
87 MII_PHY_DESC(xxREALTEK, RTL8169S), 87 MII_PHY_DESC(xxREALTEK, RTL8169S),
88 MII_PHY_DESC(REALTEK, RTL8169S), 88 MII_PHY_DESC(REALTEK, RTL8169S),
89 MII_PHY_DESC(REALTEK, RTL8251), 89 MII_PHY_DESC(REALTEK, RTL8251),
90 MII_PHY_END, 90 MII_PHY_END,
91}; 91};
92 92
93static int 93static int
94rgephy_match(device_t parent, cfdata_t match, void *aux) 94rgephy_match(device_t parent, cfdata_t match, void *aux)
95{ 95{
96 struct mii_attach_args *ma = aux; 96 struct mii_attach_args *ma = aux;
97 97
98 if (mii_phy_match(ma, rgephys) != NULL) 98 if (mii_phy_match(ma, rgephys) != NULL)
99 return 10; 99 return 10;
100 100
101 return 0; 101 return 0;
102} 102}
103 103
104static void 104static void
105rgephy_attach(device_t parent, device_t self, void *aux) 105rgephy_attach(device_t parent, device_t self, void *aux)
106{ 106{
107 struct rgephy_softc *rsc = device_private(self); 107 struct rgephy_softc *rsc = device_private(self);
108 prop_dictionary_t prop = device_properties(self); 108 prop_dictionary_t prop = device_properties(self);
109 struct mii_softc *sc = &rsc->mii_sc; 109 struct mii_softc *sc = &rsc->mii_sc;
110 struct mii_attach_args *ma = aux; 110 struct mii_attach_args *ma = aux;
111 struct mii_data *mii = ma->mii_data; 111 struct mii_data *mii = ma->mii_data;
112 const struct mii_phydesc *mpd; 112 const struct mii_phydesc *mpd;
113 int rev; 113 int rev;
114 const char *sep = ""; 114 const char *sep = "";
115 115
116 rev = MII_REV(ma->mii_id2); 116 rev = MII_REV(ma->mii_id2);
117 mpd = mii_phy_match(ma, rgephys); 117 mpd = mii_phy_match(ma, rgephys);
118 aprint_naive(": Media interface\n"); 118 aprint_naive(": Media interface\n");
119 119
120 sc->mii_dev = self; 120 sc->mii_dev = self;
121 sc->mii_inst = mii->mii_instance; 121 sc->mii_inst = mii->mii_instance;
122 sc->mii_phy = ma->mii_phyno; 122 sc->mii_phy = ma->mii_phyno;
123 sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2); 123 sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2);
124 sc->mii_mpd_model = MII_MODEL(ma->mii_id2); 124 sc->mii_mpd_model = MII_MODEL(ma->mii_id2);
125 sc->mii_mpd_rev = MII_REV(ma->mii_id2); 125 sc->mii_mpd_rev = MII_REV(ma->mii_id2);
126 126
127 if (sc->mii_mpd_model == MII_MODEL_REALTEK_RTL8169S) { 127 if (sc->mii_mpd_model == MII_MODEL_REALTEK_RTL8169S) {
128 aprint_normal(": RTL8211"); 128 aprint_normal(": RTL8211");
129 if (sc->mii_mpd_rev != 0) 129 if (sc->mii_mpd_rev != 0)
130 aprint_normal("%c",'@' + sc->mii_mpd_rev); 130 aprint_normal("%c",'@' + sc->mii_mpd_rev);
131 aprint_normal(" 1000BASE-T media interface\n"); 131 aprint_normal(" 1000BASE-T media interface\n");
132 } else 132 } else
133 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, rev); 133 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, rev);
134 134
135 sc->mii_pdata = mii; 135 sc->mii_pdata = mii;
136 sc->mii_flags = ma->mii_flags; 136 sc->mii_flags = ma->mii_flags;
137 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 137 sc->mii_anegticks = MII_ANEGTICKS_GIGE;
138 138
139 sc->mii_funcs = &rgephy_funcs; 139 sc->mii_funcs = &rgephy_funcs;
140 140
141 prop_dictionary_get_bool(prop, "no-rx-delay", &rsc->mii_no_rx_delay); 141 prop_dictionary_get_bool(prop, "no-rx-delay", &rsc->mii_no_rx_delay);
142 142
143#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 143#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
144#define PRINT(n) aprint_normal("%s%s", sep, (n)); sep = ", " 144#define PRINT(n) aprint_normal("%s%s", sep, (n)); sep = ", "
145 145
146#ifdef __FreeBSD__ 146#ifdef __FreeBSD__
147 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), 147 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
148 BMCR_LOOP | BMCR_S100); 148 BMCR_LOOP | BMCR_S100);
149#endif 149#endif
150 150
151 PHY_READ(sc, MII_BMSR, &sc->mii_capabilities); 151 PHY_READ(sc, MII_BMSR, &sc->mii_capabilities);
152 sc->mii_capabilities &= ma->mii_capmask; 152 sc->mii_capabilities &= ma->mii_capmask;
153 sc->mii_capabilities &= ~BMSR_ANEG; 153 sc->mii_capabilities &= ~BMSR_ANEG;
154 154
155 /* 155 /*
156 * FreeBSD does not check EXSTAT, but instead adds gigabit 156 * FreeBSD does not check EXSTAT, but instead adds gigabit
157 * media explicitly. Why? 157 * media explicitly. Why?
158 */ 158 */
159 aprint_normal_dev(self, ""); 159 aprint_normal_dev(self, "");
160 if (sc->mii_capabilities & BMSR_EXTSTAT) 160 if (sc->mii_capabilities & BMSR_EXTSTAT)
161 PHY_READ(sc, MII_EXTSR, &sc->mii_extcapabilities); 161 PHY_READ(sc, MII_EXTSR, &sc->mii_extcapabilities);
162 162
163 mii_phy_add_media(sc); 163 mii_phy_add_media(sc);
164 164
165 /* rtl8169S does not report auto-sense; add manually. */ 165 /* rtl8169S does not report auto-sense; add manually. */
166 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), MII_NMEDIA); 166 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), MII_NMEDIA);
167 sep =", "; 167 sep =", ";
168 PRINT("auto"); 168 PRINT("auto");
169 169
170#undef ADD 170#undef ADD
171#undef PRINT 171#undef PRINT
172 172
173 rgephy_reset(sc); 173 rgephy_reset(sc);
174 aprint_normal("\n"); 174 aprint_normal("\n");
175} 175}
176 176
177static int 177static int
178rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 178rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
179{ 179{
180 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 180 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
181 uint16_t reg, speed, gig, anar; 181 uint16_t reg, speed, gig, anar;
182 182
183 switch (cmd) { 183 switch (cmd) {
184 case MII_POLLSTAT: 184 case MII_POLLSTAT:
185 /* If we're not polling our PHY instance, just return. */ 185 /* If we're not polling our PHY instance, just return. */
186 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 186 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
187 return 0; 187 return 0;
188 break; 188 break;
189 189
190 case MII_MEDIACHG: 190 case MII_MEDIACHG:
191 /* 191 /*
192 * If the media indicates a different PHY instance, 192 * If the media indicates a different PHY instance,
193 * isolate ourselves. 193 * isolate ourselves.
194 */ 194 */
195 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 195 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
196 PHY_READ(sc, MII_BMCR, &reg); 196 PHY_READ(sc, MII_BMCR, &reg);
197 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 197 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
198 return 0; 198 return 0;
199 } 199 }
200 200
201 /* If the interface is not up, don't do anything. */ 201 /* If the interface is not up, don't do anything. */
202 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 202 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
203 break; 203 break;
204 204
205 rgephy_reset(sc); /* XXX hardware bug work-around */ 205 rgephy_reset(sc); /* XXX hardware bug work-around */
206 206
207 PHY_READ(sc, MII_ANAR, &anar); 207 PHY_READ(sc, MII_ANAR, &anar);
208 anar &= ~(ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10); 208 anar &= ~(ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10);
209 209
210 switch (IFM_SUBTYPE(ife->ifm_media)) { 210 switch (IFM_SUBTYPE(ife->ifm_media)) {
211 case IFM_AUTO: 211 case IFM_AUTO:
212#ifdef foo 212#ifdef foo
213 /* If we're already in auto mode, just return. */ 213 /* If we're already in auto mode, just return. */
214 PHY_READ(sc, MII_BMCR, &reg); 214 PHY_READ(sc, MII_BMCR, &reg);
215 if (reg & BMCR_AUTOEN) 215 if (reg & BMCR_AUTOEN)
216 return 0; 216 return 0;
217#endif 217#endif
218 (void)rgephy_mii_phy_auto(sc); 218 (void)rgephy_mii_phy_auto(sc);
219 break; 219 break;
220 case IFM_1000_T: 220 case IFM_1000_T:
221 speed = BMCR_S1000; 221 speed = BMCR_S1000;
222 goto setit; 222 goto setit;
223 case IFM_100_TX: 223 case IFM_100_TX:
224 speed = BMCR_S100; 224 speed = BMCR_S100;
225 anar |= ANAR_TX_FD | ANAR_TX; 225 anar |= ANAR_TX_FD | ANAR_TX;
226 goto setit; 226 goto setit;
227 case IFM_10_T: 227 case IFM_10_T:
228 speed = BMCR_S10; 228 speed = BMCR_S10;
229 anar |= ANAR_10_FD | ANAR_10; 229 anar |= ANAR_10_FD | ANAR_10;
230 setit: 230 setit:
231 rgephy_loop(sc); 231 rgephy_loop(sc);
232 if ((ife->ifm_media & IFM_FDX) != 0) { 232 if ((ife->ifm_media & IFM_FDX) != 0) {
233 speed |= BMCR_FDX; 233 speed |= BMCR_FDX;
234 gig = GTCR_ADV_1000TFDX; 234 gig = GTCR_ADV_1000TFDX;
235 anar &= ~(ANAR_TX | ANAR_10); 235 anar &= ~(ANAR_TX | ANAR_10);
236 } else { 236 } else {
237 gig = GTCR_ADV_1000THDX; 237 gig = GTCR_ADV_1000THDX;
238 anar &= ~(ANAR_TX_FD | ANAR_10_FD); 238 anar &= ~(ANAR_TX_FD | ANAR_10_FD);
239 } 239 }
240 240
241 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) { 241 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) {
242 PHY_WRITE(sc, MII_100T2CR, 0); 242 PHY_WRITE(sc, MII_100T2CR, 0);
243 PHY_WRITE(sc, MII_ANAR, anar); 243 PHY_WRITE(sc, MII_ANAR, anar);
244 PHY_WRITE(sc, MII_BMCR, 244 PHY_WRITE(sc, MII_BMCR,
245 speed | BMCR_AUTOEN | BMCR_STARTNEG); 245 speed | BMCR_AUTOEN | BMCR_STARTNEG);
246 break; 246 break;
247 } 247 }
248 248
249 /* 249 /*
250 * When setting the link manually, one side must be the 250 * When setting the link manually, one side must be the
251 * master and the other the slave. However ifmedia 251 * master and the other the slave. However ifmedia
252 * doesn't give us a good way to specify this, so we 252 * doesn't give us a good way to specify this, so we
253 * fake it by using one of the LINK flags. If LINK0 is 253 * fake it by using one of the LINK flags. If LINK0 is
254 * set, we program the PHY to be a master, otherwise 254 * set, we program the PHY to be a master, otherwise
255 * it's a slave. 255 * it's a slave.
256 */ 256 */
257 if ((mii->mii_ifp->if_flags & IFF_LINK0)) { 257 if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
258 PHY_WRITE(sc, MII_100T2CR, 258 PHY_WRITE(sc, MII_100T2CR,
259 gig | GTCR_MAN_MS | GTCR_ADV_MS); 259 gig | GTCR_MAN_MS | GTCR_ADV_MS);
260 } else 260 } else
261 PHY_WRITE(sc, MII_100T2CR, gig | GTCR_MAN_MS); 261 PHY_WRITE(sc, MII_100T2CR, gig | GTCR_MAN_MS);
262 PHY_WRITE(sc, MII_BMCR, 262 PHY_WRITE(sc, MII_BMCR,
263 speed | BMCR_AUTOEN | BMCR_STARTNEG); 263 speed | BMCR_AUTOEN | BMCR_STARTNEG);
264 break; 264 break;
265 case IFM_NONE: 265 case IFM_NONE:
266 PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN); 266 PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN);
267 break; 267 break;
268 case IFM_100_T4: 268 case IFM_100_T4:
269 default: 269 default:
270 return EINVAL; 270 return EINVAL;
271 } 271 }
272 break; 272 break;
273 273
274 case MII_TICK: 274 case MII_TICK:
275 /* If we're not currently selected, just return. */ 275 /* If we're not currently selected, just return. */
276 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 276 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
277 return 0; 277 return 0;
278 278
279 /* Is the interface even up? */ 279 /* Is the interface even up? */
280 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 280 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
281 return 0; 281 return 0;
282 282
283 /* Only used for autonegotiation. */ 283 /* Only used for autonegotiation. */
284 if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) && 284 if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) &&
285 (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) { 285 (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) {
286 /* 286 /*
287 * Reset autonegotiation timer to 0 to make sure 287 * Reset autonegotiation timer to 0 to make sure
288 * the future autonegotiation start with 0. 288 * the future autonegotiation start with 0.
289 */ 289 */
290 sc->mii_ticks = 0; 290 sc->mii_ticks = 0;
291 break; 291 break;
292 } 292 }
293 293
294 /* 294 /*
295 * Check to see if we have link. If we do, we don't 295 * Check to see if we have link. If we do, we don't
296 * need to restart the autonegotiation process. Read 296 * need to restart the autonegotiation process. Read
297 * the BMSR twice in case it's latched. 297 * the BMSR twice in case it's latched.
298 */ 298 */
299 if (rgephy_linkup(sc)) { 299 if (rgephy_linkup(sc)) {
300 sc->mii_ticks = 0; 300 sc->mii_ticks = 0;
301 break; 301 break;
302 } 302 }
303 303
304 /* Announce link loss right after it happens. */ 304 /* Announce link loss right after it happens. */
305 if (sc->mii_ticks++ == 0) 305 if (sc->mii_ticks++ == 0)
306 break; 306 break;
307 307
308 /* Only retry autonegotiation every mii_anegticks seconds. */ 308 /* Only retry autonegotiation every mii_anegticks seconds. */
309 if (sc->mii_ticks <= sc->mii_anegticks) 309 if (sc->mii_ticks <= sc->mii_anegticks)
310 return 0; 310 return 0;
311 311
312 rgephy_mii_phy_auto(sc); 312 rgephy_mii_phy_auto(sc);
313 break; 313 break;
314 } 314 }
315 315
316 /* Update the media status. */ 316 /* Update the media status. */
317 rgephy_status(sc); 317 rgephy_status(sc);
318 318
319 /* 319 /*
320 * Callback if something changed. Note that we need to poke 320 * Callback if something changed. Note that we need to poke
321 * the DSP on the RealTek PHYs if the media changes. 321 * the DSP on the RealTek PHYs if the media changes.
322 */ 322 */
323 if (sc->mii_media_active != mii->mii_media_active || 323 if (sc->mii_media_active != mii->mii_media_active ||
324 sc->mii_media_status != mii->mii_media_status || 324 sc->mii_media_status != mii->mii_media_status ||
325 cmd == MII_MEDIACHG) { 325 cmd == MII_MEDIACHG) {
326 rgephy_load_dspcode(sc); 326 rgephy_load_dspcode(sc);
327 } 327 }
328 mii_phy_update(sc, cmd); 328 mii_phy_update(sc, cmd);
329 return 0; 329 return 0;
330} 330}
331 331
332static bool 332static bool
333rgephy_linkup(struct mii_softc *sc) 333rgephy_linkup(struct mii_softc *sc)
334{ 334{
335 bool linkup = false; 335 bool linkup = false;
336 uint16_t reg; 336 uint16_t reg;
337 337
338 if (sc->mii_mpd_rev >= RGEPHY_8211F) { 338 if (sc->mii_mpd_rev >= RGEPHY_8211F) {
339 PHY_READ(sc, RGEPHY_MII_PHYSR, &reg); 339 PHY_READ(sc, RGEPHY_MII_PHYSR, &reg);
340 if (reg & RGEPHY_PHYSR_LINK) 340 if (reg & RGEPHY_PHYSR_LINK)
341 linkup = true; 341 linkup = true;
342 } else if (sc->mii_mpd_rev >= RGEPHY_8211B) { 342 } else if (sc->mii_mpd_rev >= RGEPHY_8211B) {
343 PHY_READ(sc, RGEPHY_MII_SSR, &reg); 343 PHY_READ(sc, RGEPHY_MII_SSR, &reg);
344 if (reg & RGEPHY_SSR_LINK) 344 if (reg & RGEPHY_SSR_LINK)
345 linkup = true; 345 linkup = true;
346 } else { 346 } else {
347 PHY_READ(sc, RTK_GMEDIASTAT, &reg); 347 PHY_READ(sc, RTK_GMEDIASTAT, &reg);
348 if ((reg & RTK_GMEDIASTAT_LINK) != 0) 348 if ((reg & RTK_GMEDIASTAT_LINK) != 0)
349 linkup = true; 349 linkup = true;
350 } 350 }
351 351
352 return linkup; 352 return linkup;
353} 353}
354 354
355static void 355static void
356rgephy_status(struct mii_softc *sc) 356rgephy_status(struct mii_softc *sc)
357{ 357{
358 struct mii_data *mii = sc->mii_pdata; 358 struct mii_data *mii = sc->mii_pdata;
359 uint16_t gstat, bmsr, bmcr, physr, ssr; 359 uint16_t gstat, bmsr, bmcr, gtsr, physr, ssr;
360 360
361 mii->mii_media_status = IFM_AVALID; 361 mii->mii_media_status = IFM_AVALID;
362 mii->mii_media_active = IFM_ETHER; 362 mii->mii_media_active = IFM_ETHER;
363 363
364 if (rgephy_linkup(sc)) 364 if (rgephy_linkup(sc))
365 mii->mii_media_status |= IFM_ACTIVE; 365 mii->mii_media_status |= IFM_ACTIVE;
366 366
367 PHY_READ(sc, MII_BMSR, &bmsr); 367 PHY_READ(sc, MII_BMSR, &bmsr);
368 PHY_READ(sc, MII_BMCR, &bmcr); 368 PHY_READ(sc, MII_BMCR, &bmcr);
369 369
370 if ((bmcr & BMCR_ISO) != 0) { 370 if ((bmcr & BMCR_ISO) != 0) {
371 mii->mii_media_active |= IFM_NONE; 371 mii->mii_media_active |= IFM_NONE;
372 mii->mii_media_status = 0; 372 mii->mii_media_status = 0;
373 return; 373 return;
374 } 374 }
375 375
376 if ((bmcr & BMCR_LOOP) != 0) 376 if ((bmcr & BMCR_LOOP) != 0)
377 mii->mii_media_active |= IFM_LOOP; 377 mii->mii_media_active |= IFM_LOOP;
378 378
379 if ((bmcr & BMCR_AUTOEN) != 0) { 379 if ((bmcr & BMCR_AUTOEN) != 0) {
380 if ((bmsr & BMSR_ACOMP) == 0) { 380 if ((bmsr & BMSR_ACOMP) == 0) {
381 /* Erg, still trying, I guess... */ 381 /* Erg, still trying, I guess... */
382 mii->mii_media_active |= IFM_NONE; 382 mii->mii_media_active |= IFM_NONE;
383 return; 383 return;
384 } 384 }
385 } 385 }
386 386
387 if (sc->mii_mpd_rev >= RGEPHY_8211F) { 387 if (sc->mii_mpd_rev >= RGEPHY_8211F) {
388 PHY_READ(sc, RGEPHY_MII_PHYSR, &physr); 388 PHY_READ(sc, RGEPHY_MII_PHYSR, &physr);
389 switch (__SHIFTOUT(physr, RGEPHY_PHYSR_SPEED)) { 389 switch (__SHIFTOUT(physr, RGEPHY_PHYSR_SPEED)) {
390 case RGEPHY_PHYSR_SPEED_1000: 390 case RGEPHY_PHYSR_SPEED_1000:
391 mii->mii_media_active |= IFM_1000_T; 391 mii->mii_media_active |= IFM_1000_T;
392 break; 392 break;
393 case RGEPHY_PHYSR_SPEED_100: 393 case RGEPHY_PHYSR_SPEED_100:
394 mii->mii_media_active |= IFM_100_TX; 394 mii->mii_media_active |= IFM_100_TX;
395 break; 395 break;
396 case RGEPHY_PHYSR_SPEED_10: 396 case RGEPHY_PHYSR_SPEED_10:
397 mii->mii_media_active |= IFM_10_T; 397 mii->mii_media_active |= IFM_10_T;
398 break; 398 break;
399 default: 399 default:
400 mii->mii_media_active |= IFM_NONE; 400 mii->mii_media_active |= IFM_NONE;
401 break; 401 break;
402 } 402 }
403 if (physr & RGEPHY_PHYSR_DUPLEX) 403 if (physr & RGEPHY_PHYSR_DUPLEX)
404 mii->mii_media_active |= mii_phy_flowstatus(sc) | 404 mii->mii_media_active |= mii_phy_flowstatus(sc) |
405 IFM_FDX; 405 IFM_FDX;
406 else 406 else
407 mii->mii_media_active |= IFM_HDX; 407 mii->mii_media_active |= IFM_HDX;
408 } else if (sc->mii_mpd_rev >= RGEPHY_8211B) { 408 } else if (sc->mii_mpd_rev >= RGEPHY_8211B) {
409 PHY_READ(sc, RGEPHY_MII_SSR, &ssr); 409 PHY_READ(sc, RGEPHY_MII_SSR, &ssr);
410 switch (ssr & RGEPHY_SSR_SPD_MASK) { 410 switch (ssr & RGEPHY_SSR_SPD_MASK) {
411 case RGEPHY_SSR_S1000: 411 case RGEPHY_SSR_S1000:
412 mii->mii_media_active |= IFM_1000_T; 412 mii->mii_media_active |= IFM_1000_T;
413 break; 413 break;
414 case RGEPHY_SSR_S100: 414 case RGEPHY_SSR_S100:
415 mii->mii_media_active |= IFM_100_TX; 415 mii->mii_media_active |= IFM_100_TX;
416 break; 416 break;
417 case RGEPHY_SSR_S10: 417 case RGEPHY_SSR_S10:
418 mii->mii_media_active |= IFM_10_T; 418 mii->mii_media_active |= IFM_10_T;
419 break; 419 break;
420 default: 420 default:
421 mii->mii_media_active |= IFM_NONE; 421 mii->mii_media_active |= IFM_NONE;
422 break; 422 break;
423 } 423 }
424 if (ssr & RGEPHY_SSR_FDX) 424 if (ssr & RGEPHY_SSR_FDX)
425 mii->mii_media_active |= mii_phy_flowstatus(sc) | 425 mii->mii_media_active |= mii_phy_flowstatus(sc) |
426 IFM_FDX; 426 IFM_FDX;
427 else 427 else
428 mii->mii_media_active |= IFM_HDX; 428 mii->mii_media_active |= IFM_HDX;
429 } else { 429 } else {
430 PHY_READ(sc, RTK_GMEDIASTAT, &gstat); 430 PHY_READ(sc, RTK_GMEDIASTAT, &gstat);
431 if ((gstat & RTK_GMEDIASTAT_1000MBPS) != 0) 431 if ((gstat & RTK_GMEDIASTAT_1000MBPS) != 0)
432 mii->mii_media_active |= IFM_1000_T; 432 mii->mii_media_active |= IFM_1000_T;
433 else if ((gstat & RTK_GMEDIASTAT_100MBPS) != 0) 433 else if ((gstat & RTK_GMEDIASTAT_100MBPS) != 0)
434 mii->mii_media_active |= IFM_100_TX; 434 mii->mii_media_active |= IFM_100_TX;
435 else if ((gstat & RTK_GMEDIASTAT_10MBPS) != 0) 435 else if ((gstat & RTK_GMEDIASTAT_10MBPS) != 0)
436 mii->mii_media_active |= IFM_10_T; 436 mii->mii_media_active |= IFM_10_T;
437 else 437 else
438 mii->mii_media_active |= IFM_NONE; 438 mii->mii_media_active |= IFM_NONE;
439 if ((gstat & RTK_GMEDIASTAT_FDX) != 0) 439 if ((gstat & RTK_GMEDIASTAT_FDX) != 0)
440 mii->mii_media_active |= mii_phy_flowstatus(sc) | 440 mii->mii_media_active |= mii_phy_flowstatus(sc) |
441 IFM_FDX; 441 IFM_FDX;
442 else 442 else
443 mii->mii_media_active |= IFM_HDX; 443 mii->mii_media_active |= IFM_HDX;
444 } 444 }
 445
 446 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
 447 PHY_READ(sc, MII_GTSR, &gtsr);
 448 if ((gtsr & GTSR_MS_RES) != 0)
 449 mii->mii_media_active |= IFM_ETH_MASTER;
 450 }
445} 451}
446 452
447static int 453static int
448rgephy_mii_phy_auto(struct mii_softc *mii) 454rgephy_mii_phy_auto(struct mii_softc *mii)
449{ 455{
450 int anar; 456 int anar;
451 457
452 mii->mii_ticks = 0; 458 mii->mii_ticks = 0;
453 rgephy_loop(mii); 459 rgephy_loop(mii);
454 rgephy_reset(mii); 460 rgephy_reset(mii);
455 461
456 anar = BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA; 462 anar = BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA;
457 if (mii->mii_flags & MIIF_DOPAUSE) 463 if (mii->mii_flags & MIIF_DOPAUSE)
458 anar |= ANAR_FC | ANAR_PAUSE_ASYM; 464 anar |= ANAR_FC | ANAR_PAUSE_ASYM;
459 465
460 PHY_WRITE(mii, MII_ANAR, anar); 466 PHY_WRITE(mii, MII_ANAR, anar);
461 DELAY(1000); 467 DELAY(1000);
462 PHY_WRITE(mii, MII_100T2CR, GTCR_ADV_1000THDX | GTCR_ADV_1000TFDX); 468 PHY_WRITE(mii, MII_100T2CR, GTCR_ADV_1000THDX | GTCR_ADV_1000TFDX);
463 DELAY(1000); 469 DELAY(1000);
464 PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); 470 PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
465 DELAY(100); 471 DELAY(100);
466 472
467 return EJUSTRETURN; 473 return EJUSTRETURN;
468} 474}
469 475
470static void 476static void
471rgephy_loop(struct mii_softc *sc) 477rgephy_loop(struct mii_softc *sc)
472{ 478{
473 uint16_t bmsr; 479 uint16_t bmsr;
474 int i; 480 int i;
475 481
476 if (sc->mii_mpd_model != MII_MODEL_REALTEK_RTL8251 && 482 if (sc->mii_mpd_model != MII_MODEL_REALTEK_RTL8251 &&
477 sc->mii_mpd_rev < RGEPHY_8211B) { 483 sc->mii_mpd_rev < RGEPHY_8211B) {
478 PHY_WRITE(sc, MII_BMCR, BMCR_PDOWN); 484 PHY_WRITE(sc, MII_BMCR, BMCR_PDOWN);
479 DELAY(1000); 485 DELAY(1000);
480 } 486 }
481 487
482 for (i = 0; i < 15000; i++) { 488 for (i = 0; i < 15000; i++) {
483 PHY_READ(sc, MII_BMSR, &bmsr); 489 PHY_READ(sc, MII_BMSR, &bmsr);
484 if ((bmsr & BMSR_LINK) == 0) { 490 if ((bmsr & BMSR_LINK) == 0) {
485#if 0 491#if 0
486 device_printf(sc->mii_dev, "looped %d\n", i); 492 device_printf(sc->mii_dev, "looped %d\n", i);
487#endif 493#endif
488 break; 494 break;
489 } 495 }
490 DELAY(10); 496 DELAY(10);
491 } 497 }
492} 498}
493 499
494static inline int 500static inline int
495PHY_SETBIT(struct mii_softc *sc, int y, uint16_t z) 501PHY_SETBIT(struct mii_softc *sc, int y, uint16_t z)
496{ 502{
497 uint16_t _tmp; 503 uint16_t _tmp;
498 int rv; 504 int rv;
499 505
500 if ((rv = PHY_READ(sc, y, &_tmp)) != 0) 506 if ((rv = PHY_READ(sc, y, &_tmp)) != 0)
501 return rv; 507 return rv;
502 return PHY_WRITE(sc, y, _tmp | z); 508 return PHY_WRITE(sc, y, _tmp | z);
503} 509}
504 510
505static inline int 511static inline int
506PHY_CLRBIT(struct mii_softc *sc, int y, uint16_t z) 512PHY_CLRBIT(struct mii_softc *sc, int y, uint16_t z)
507{ 513{
508 uint16_t _tmp; 514 uint16_t _tmp;
509 int rv; 515 int rv;
510 516
511 if ((rv = PHY_READ(sc, y, &_tmp)) != 0) 517 if ((rv = PHY_READ(sc, y, &_tmp)) != 0)
512 return rv; 518 return rv;
513 return PHY_WRITE(sc, y, _tmp & ~z); 519 return PHY_WRITE(sc, y, _tmp & ~z);
514} 520}
515 521
516/* 522/*
517 * Initialize RealTek PHY per the datasheet. The DSP in the PHYs of existing 523 * Initialize RealTek PHY per the datasheet. The DSP in the PHYs of existing
518 * revisions of the 8169S/8110S chips need to be tuned in order to reliably 524 * revisions of the 8169S/8110S chips need to be tuned in order to reliably
519 * negotiate a 1000Mbps link. This is only needed for rev 0 and rev 1 of the 525 * negotiate a 1000Mbps link. This is only needed for rev 0 and rev 1 of the
520 * PHY. Later versions work without any fixups. 526 * PHY. Later versions work without any fixups.
521 */ 527 */
522static void 528static void
523rgephy_load_dspcode(struct mii_softc *sc) 529rgephy_load_dspcode(struct mii_softc *sc)
524{ 530{
525 uint16_t val; 531 uint16_t val;
526 532
527 if (sc->mii_mpd_model == MII_MODEL_REALTEK_RTL8251 || 533 if (sc->mii_mpd_model == MII_MODEL_REALTEK_RTL8251 ||
528 sc->mii_mpd_rev >= RGEPHY_8211B) 534 sc->mii_mpd_rev >= RGEPHY_8211B)
529 return; 535 return;
530 536
531#if 1 537#if 1
532 PHY_WRITE(sc, 31, 0x0001); 538 PHY_WRITE(sc, 31, 0x0001);
533 PHY_WRITE(sc, 21, 0x1000); 539 PHY_WRITE(sc, 21, 0x1000);
534 PHY_WRITE(sc, 24, 0x65C7); 540 PHY_WRITE(sc, 24, 0x65C7);
535 PHY_CLRBIT(sc, 4, 0x0800); 541 PHY_CLRBIT(sc, 4, 0x0800);
536 PHY_READ(sc, 4, &val); 542 PHY_READ(sc, 4, &val);
537 val &= 0xFFF; 543 val &= 0xFFF;
538 PHY_WRITE(sc, 4, val); 544 PHY_WRITE(sc, 4, val);
539 PHY_WRITE(sc, 3, 0x00A1); 545 PHY_WRITE(sc, 3, 0x00A1);
540 PHY_WRITE(sc, 2, 0x0008); 546 PHY_WRITE(sc, 2, 0x0008);
541 PHY_WRITE(sc, 1, 0x1020); 547 PHY_WRITE(sc, 1, 0x1020);
542 PHY_WRITE(sc, 0, 0x1000); 548 PHY_WRITE(sc, 0, 0x1000);
543 PHY_SETBIT(sc, 4, 0x0800); 549 PHY_SETBIT(sc, 4, 0x0800);
544 PHY_CLRBIT(sc, 4, 0x0800); 550 PHY_CLRBIT(sc, 4, 0x0800);
545 PHY_READ(sc, 4, &val); 551 PHY_READ(sc, 4, &val);
546 val = (val & 0xFFF) | 0x7000; 552 val = (val & 0xFFF) | 0x7000;
547 PHY_WRITE(sc, 4, val); 553 PHY_WRITE(sc, 4, val);
548 PHY_WRITE(sc, 3, 0xFF41); 554 PHY_WRITE(sc, 3, 0xFF41);
549 PHY_WRITE(sc, 2, 0xDE60); 555 PHY_WRITE(sc, 2, 0xDE60);
550 PHY_WRITE(sc, 1, 0x0140); 556 PHY_WRITE(sc, 1, 0x0140);
551 PHY_WRITE(sc, 0, 0x0077); 557 PHY_WRITE(sc, 0, 0x0077);
552 PHY_READ(sc, 4, &val); 558 PHY_READ(sc, 4, &val);
553 val = (val & 0xFFF) | 0xA000; 559 val = (val & 0xFFF) | 0xA000;
554 PHY_WRITE(sc, 4, val); 560 PHY_WRITE(sc, 4, val);
555 PHY_WRITE(sc, 3, 0xDF01); 561 PHY_WRITE(sc, 3, 0xDF01);
556 PHY_WRITE(sc, 2, 0xDF20); 562 PHY_WRITE(sc, 2, 0xDF20);
557 PHY_WRITE(sc, 1, 0xFF95); 563 PHY_WRITE(sc, 1, 0xFF95);
558 PHY_WRITE(sc, 0, 0xFA00); 564 PHY_WRITE(sc, 0, 0xFA00);
559 PHY_READ(sc, 4, &val); 565 PHY_READ(sc, 4, &val);
560 val = (val & 0xFFF) | 0xB000; 566 val = (val & 0xFFF) | 0xB000;
561 PHY_WRITE(sc, 4, val); 567 PHY_WRITE(sc, 4, val);
562 PHY_WRITE(sc, 3, 0xFF41); 568 PHY_WRITE(sc, 3, 0xFF41);
563 PHY_WRITE(sc, 2, 0xDE20); 569 PHY_WRITE(sc, 2, 0xDE20);
564 PHY_WRITE(sc, 1, 0x0140); 570 PHY_WRITE(sc, 1, 0x0140);
565 PHY_WRITE(sc, 0, 0x00BB); 571 PHY_WRITE(sc, 0, 0x00BB);
566 PHY_READ(sc, 4, &val); 572 PHY_READ(sc, 4, &val);
567 val = (val & 0xFFF) | 0xF000; 573 val = (val & 0xFFF) | 0xF000;
568 PHY_WRITE(sc, 4, val); 574 PHY_WRITE(sc, 4, val);
569 PHY_WRITE(sc, 3, 0xDF01); 575 PHY_WRITE(sc, 3, 0xDF01);
570 PHY_WRITE(sc, 2, 0xDF20); 576 PHY_WRITE(sc, 2, 0xDF20);
571 PHY_WRITE(sc, 1, 0xFF95); 577 PHY_WRITE(sc, 1, 0xFF95);
572 PHY_WRITE(sc, 0, 0xBF00); 578 PHY_WRITE(sc, 0, 0xBF00);
573 PHY_SETBIT(sc, 4, 0x0800); 579 PHY_SETBIT(sc, 4, 0x0800);
574 PHY_CLRBIT(sc, 4, 0x0800); 580 PHY_CLRBIT(sc, 4, 0x0800);
575 PHY_WRITE(sc, 31, 0x0000); 581 PHY_WRITE(sc, 31, 0x0000);
576#else 582#else
577 (void)val; 583 (void)val;
578 PHY_WRITE(sc, 0x1f, 0x0001); 584 PHY_WRITE(sc, 0x1f, 0x0001);
579 PHY_WRITE(sc, 0x15, 0x1000); 585 PHY_WRITE(sc, 0x15, 0x1000);
580 PHY_WRITE(sc, 0x18, 0x65c7); 586 PHY_WRITE(sc, 0x18, 0x65c7);
581 PHY_WRITE(sc, 0x04, 0x0000); 587 PHY_WRITE(sc, 0x04, 0x0000);
582 PHY_WRITE(sc, 0x03, 0x00a1); 588 PHY_WRITE(sc, 0x03, 0x00a1);
583 PHY_WRITE(sc, 0x02, 0x0008); 589 PHY_WRITE(sc, 0x02, 0x0008);
584 PHY_WRITE(sc, 0x01, 0x1020); 590 PHY_WRITE(sc, 0x01, 0x1020);
585 PHY_WRITE(sc, 0x00, 0x1000); 591 PHY_WRITE(sc, 0x00, 0x1000);
586 PHY_WRITE(sc, 0x04, 0x0800); 592 PHY_WRITE(sc, 0x04, 0x0800);
587 PHY_WRITE(sc, 0x04, 0x0000); 593 PHY_WRITE(sc, 0x04, 0x0000);
588 PHY_WRITE(sc, 0x04, 0x7000); 594 PHY_WRITE(sc, 0x04, 0x7000);
589 PHY_WRITE(sc, 0x03, 0xff41); 595 PHY_WRITE(sc, 0x03, 0xff41);
590 PHY_WRITE(sc, 0x02, 0xde60); 596 PHY_WRITE(sc, 0x02, 0xde60);
591 PHY_WRITE(sc, 0x01, 0x0140); 597 PHY_WRITE(sc, 0x01, 0x0140);
592 PHY_WRITE(sc, 0x00, 0x0077); 598 PHY_WRITE(sc, 0x00, 0x0077);
593 PHY_WRITE(sc, 0x04, 0x7800); 599 PHY_WRITE(sc, 0x04, 0x7800);
594 PHY_WRITE(sc, 0x04, 0x7000); 600 PHY_WRITE(sc, 0x04, 0x7000);
595 PHY_WRITE(sc, 0x04, 0xa000); 601 PHY_WRITE(sc, 0x04, 0xa000);
596 PHY_WRITE(sc, 0x03, 0xdf01); 602 PHY_WRITE(sc, 0x03, 0xdf01);
597 PHY_WRITE(sc, 0x02, 0xdf20); 603 PHY_WRITE(sc, 0x02, 0xdf20);
598 PHY_WRITE(sc, 0x01, 0xff95); 604 PHY_WRITE(sc, 0x01, 0xff95);
599 PHY_WRITE(sc, 0x00, 0xfa00); 605 PHY_WRITE(sc, 0x00, 0xfa00);
600 PHY_WRITE(sc, 0x04, 0xa800); 606 PHY_WRITE(sc, 0x04, 0xa800);
601 PHY_WRITE(sc, 0x04, 0xa000); 607 PHY_WRITE(sc, 0x04, 0xa000);
602 PHY_WRITE(sc, 0x04, 0xb000); 608 PHY_WRITE(sc, 0x04, 0xb000);
603 PHY_WRITE(sc, 0x0e, 0xff41); 609 PHY_WRITE(sc, 0x0e, 0xff41);
604 PHY_WRITE(sc, 0x02, 0xde20); 610 PHY_WRITE(sc, 0x02, 0xde20);
605 PHY_WRITE(sc, 0x01, 0x0140); 611 PHY_WRITE(sc, 0x01, 0x0140);
606 PHY_WRITE(sc, 0x00, 0x00bb); 612 PHY_WRITE(sc, 0x00, 0x00bb);
607 PHY_WRITE(sc, 0x04, 0xb800); 613 PHY_WRITE(sc, 0x04, 0xb800);
608 PHY_WRITE(sc, 0x04, 0xb000); 614 PHY_WRITE(sc, 0x04, 0xb000);
609 PHY_WRITE(sc, 0x04, 0xf000); 615 PHY_WRITE(sc, 0x04, 0xf000);
610 PHY_WRITE(sc, 0x03, 0xdf01); 616 PHY_WRITE(sc, 0x03, 0xdf01);
611 PHY_WRITE(sc, 0x02, 0xdf20); 617 PHY_WRITE(sc, 0x02, 0xdf20);
612 PHY_WRITE(sc, 0x01, 0xff95); 618 PHY_WRITE(sc, 0x01, 0xff95);
613 PHY_WRITE(sc, 0x00, 0xbf00); 619 PHY_WRITE(sc, 0x00, 0xbf00);
614 PHY_WRITE(sc, 0x04, 0xf800); 620 PHY_WRITE(sc, 0x04, 0xf800);
615 PHY_WRITE(sc, 0x04, 0xf000); 621 PHY_WRITE(sc, 0x04, 0xf000);
616 PHY_WRITE(sc, 0x04, 0x0000); 622 PHY_WRITE(sc, 0x04, 0x0000);
617 PHY_WRITE(sc, 0x1f, 0x0000); 623 PHY_WRITE(sc, 0x1f, 0x0000);
618 PHY_WRITE(sc, 0x0b, 0x0000); 624 PHY_WRITE(sc, 0x0b, 0x0000);
619 625
620#endif 626#endif
621 627
622 DELAY(40); 628 DELAY(40);
623} 629}
624 630
625static void 631static void
626rgephy_reset(struct mii_softc *sc) 632rgephy_reset(struct mii_softc *sc)
627{ 633{
628 struct rgephy_softc *rsc = (struct rgephy_softc *)sc; 634 struct rgephy_softc *rsc = (struct rgephy_softc *)sc;
629 uint16_t ssr, phycr1; 635 uint16_t ssr, phycr1;
630 636
631 mii_phy_reset(sc); 637 mii_phy_reset(sc);
632 DELAY(1000); 638 DELAY(1000);
633 639
634 if (sc->mii_mpd_model != MII_MODEL_REALTEK_RTL8251 && 640 if (sc->mii_mpd_model != MII_MODEL_REALTEK_RTL8251 &&
635 sc->mii_mpd_rev < RGEPHY_8211B) { 641 sc->mii_mpd_rev < RGEPHY_8211B) {
636 rgephy_load_dspcode(sc); 642 rgephy_load_dspcode(sc);
637 } else if (sc->mii_mpd_rev == RGEPHY_8211C) { 643 } else if (sc->mii_mpd_rev == RGEPHY_8211C) {
638 /* RTL8211C(L) */ 644 /* RTL8211C(L) */
639 PHY_READ(sc, RGEPHY_MII_SSR, &ssr); 645 PHY_READ(sc, RGEPHY_MII_SSR, &ssr);
640 if ((ssr & RGEPHY_SSR_ALDPS) != 0) { 646 if ((ssr & RGEPHY_SSR_ALDPS) != 0) {
641 ssr &= ~RGEPHY_SSR_ALDPS; 647 ssr &= ~RGEPHY_SSR_ALDPS;
642 PHY_WRITE(sc, RGEPHY_MII_SSR, ssr); 648 PHY_WRITE(sc, RGEPHY_MII_SSR, ssr);
643 } 649 }
644 } else if (sc->mii_mpd_rev == RGEPHY_8211E) { 650 } else if (sc->mii_mpd_rev == RGEPHY_8211E) {
645 /* RTL8211E */ 651 /* RTL8211E */
646 if (rsc->mii_no_rx_delay) { 652 if (rsc->mii_no_rx_delay) {
647 /* Disable RX internal delay (undocumented) */ 653 /* Disable RX internal delay (undocumented) */
648 PHY_WRITE(sc, 0x1f, 0x0007); 654 PHY_WRITE(sc, 0x1f, 0x0007);
649 PHY_WRITE(sc, 0x1e, 0x00a4); 655 PHY_WRITE(sc, 0x1e, 0x00a4);
650 PHY_WRITE(sc, 0x1c, 0xb591); 656 PHY_WRITE(sc, 0x1c, 0xb591);
651 PHY_WRITE(sc, 0x1f, 0x0000); 657 PHY_WRITE(sc, 0x1f, 0x0000);
652 } 658 }
653 } else if (sc->mii_mpd_rev == RGEPHY_8211F) { 659 } else if (sc->mii_mpd_rev == RGEPHY_8211F) {
654 /* RTL8211F */ 660 /* RTL8211F */
655 PHY_READ(sc, RGEPHY_MII_PHYCR1, &phycr1); 661 PHY_READ(sc, RGEPHY_MII_PHYCR1, &phycr1);
656 phycr1 &= ~RGEPHY_PHYCR1_MDI_MMCE; 662 phycr1 &= ~RGEPHY_PHYCR1_MDI_MMCE;
657 phycr1 &= ~RGEPHY_PHYCR1_ALDPS_EN; 663 phycr1 &= ~RGEPHY_PHYCR1_ALDPS_EN;
658 PHY_WRITE(sc, RGEPHY_MII_PHYCR1, phycr1); 664 PHY_WRITE(sc, RGEPHY_MII_PHYCR1, phycr1);
659 } else { 665 } else {
660 PHY_WRITE(sc, 0x1F, 0x0000); 666 PHY_WRITE(sc, 0x1F, 0x0000);
661 PHY_WRITE(sc, 0x0e, 0x0000); 667 PHY_WRITE(sc, 0x0e, 0x0000);
662 } 668 }
663 669
664 /* Reset capabilities */ 670 /* Reset capabilities */
665 /* Step1: write our capability */ 671 /* Step1: write our capability */
666 /* 10/100 capability */ 672 /* 10/100 capability */
667 PHY_WRITE(sc, MII_ANAR, 673 PHY_WRITE(sc, MII_ANAR,
668 ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA); 674 ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA);
669 /* 1000 capability */ 675 /* 1000 capability */
670 PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX); 676 PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX);
671 677
672 /* Step2: Restart NWay */ 678 /* Step2: Restart NWay */
673 /* NWay enable and Restart NWay */ 679 /* NWay enable and Restart NWay */
674 PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG); 680 PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);
675 681
676 if (sc->mii_mpd_rev >= RGEPHY_8211D) { 682 if (sc->mii_mpd_rev >= RGEPHY_8211D) {
677 /* RTL8211F */ 683 /* RTL8211F */
678 delay(10000); 684 delay(10000);
679 /* disable EEE */ 685 /* disable EEE */
680 MMD_INDIRECT_WRITE(sc, MDIO_MMD_AN | MMDACR_FN_DATA, 686 MMD_INDIRECT_WRITE(sc, MDIO_MMD_AN | MMDACR_FN_DATA,
681 MDIO_AN_EEEADVERT, 0x0000); 687 MDIO_AN_EEEADVERT, 0x0000);
682 } 688 }
683} 689}