Deleted Added
full compact
atphy.c (213893) atphy.c (215298)
1/*-
2 * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 12 unchanged lines hidden (view full) ---

21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 12 unchanged lines hidden (view full) ---

21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/dev/mii/atphy.c 213893 2010-10-15 14:52:11Z marius $");
29__FBSDID("$FreeBSD: head/sys/dev/mii/atphy.c 215298 2010-11-14 13:31:01Z marius $");
30
31/*
32 * Driver for the Attansic/Atheros F1 10/100/1000 PHY.
33 */
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>

--- 39 unchanged lines hidden (view full) ---

77};
78
79DRIVER_MODULE(atphy, miibus, atphy_driver, atphy_devclass, 0, 0);
80
81static int atphy_service(struct mii_softc *, struct mii_data *, int);
82static void atphy_status(struct mii_softc *);
83static void atphy_reset(struct mii_softc *);
84static uint16_t atphy_anar(struct ifmedia_entry *);
30
31/*
32 * Driver for the Attansic/Atheros F1 10/100/1000 PHY.
33 */
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>

--- 39 unchanged lines hidden (view full) ---

77};
78
79DRIVER_MODULE(atphy, miibus, atphy_driver, atphy_devclass, 0, 0);
80
81static int atphy_service(struct mii_softc *, struct mii_data *, int);
82static void atphy_status(struct mii_softc *);
83static void atphy_reset(struct mii_softc *);
84static uint16_t atphy_anar(struct ifmedia_entry *);
85static int atphy_auto(struct mii_softc *);
85static int atphy_setmedia(struct mii_softc *, int);
86
87static const struct mii_phydesc atphys[] = {
88 MII_PHY_DESC(ATHEROS, F1),
89 MII_PHY_DESC(ATHEROS, F1_7),
90 MII_PHY_DESC(ATHEROS, F2),
91 MII_PHY_END
92};
93

--- 59 unchanged lines hidden (view full) ---

153 /*
154 * If the interface is not up, don't do anything.
155 */
156 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
157 break;
158
159 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO ||
160 IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
86
87static const struct mii_phydesc atphys[] = {
88 MII_PHY_DESC(ATHEROS, F1),
89 MII_PHY_DESC(ATHEROS, F1_7),
90 MII_PHY_DESC(ATHEROS, F2),
91 MII_PHY_END
92};
93

--- 59 unchanged lines hidden (view full) ---

153 /*
154 * If the interface is not up, don't do anything.
155 */
156 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
157 break;
158
159 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO ||
160 IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
161 atphy_auto(sc);
161 atphy_setmedia(sc, ife->ifm_media);
162 break;
163 }
164
165 bmcr = 0;
166 switch (IFM_SUBTYPE(ife->ifm_media)) {
167 case IFM_100_TX:
168 bmcr = BMCR_S100;
169 break;
170 case IFM_10_T:
171 bmcr = BMCR_S10;
172 break;
173 case IFM_NONE:
174 bmcr = PHY_READ(sc, MII_BMCR);
175 /*
176 * XXX
177 * Due to an unknown reason powering down PHY resulted
162 break;
163 }
164
165 bmcr = 0;
166 switch (IFM_SUBTYPE(ife->ifm_media)) {
167 case IFM_100_TX:
168 bmcr = BMCR_S100;
169 break;
170 case IFM_10_T:
171 bmcr = BMCR_S10;
172 break;
173 case IFM_NONE:
174 bmcr = PHY_READ(sc, MII_BMCR);
175 /*
176 * XXX
177 * Due to an unknown reason powering down PHY resulted
178 * in unexpected results such as inaccessbility of
178 * in unexpected results such as inaccessibility of
179 * hardware of freshly rebooted system. Disable
180 * powering down PHY until I got more information for
181 * Attansic/Atheros PHY hardwares.
182 */
183 PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO);
184 goto done;
185 default:
186 return (EINVAL);
187 }
188
189 anar = atphy_anar(ife);
190 if (((ife->ifm_media & IFM_GMASK) & IFM_FDX) != 0) {
191 bmcr |= BMCR_FDX;
179 * hardware of freshly rebooted system. Disable
180 * powering down PHY until I got more information for
181 * Attansic/Atheros PHY hardwares.
182 */
183 PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO);
184 goto done;
185 default:
186 return (EINVAL);
187 }
188
189 anar = atphy_anar(ife);
190 if (((ife->ifm_media & IFM_GMASK) & IFM_FDX) != 0) {
191 bmcr |= BMCR_FDX;
192 /* Enable pause. */
193 anar |= (3 << 10);
192 if (((ife->ifm_media & IFM_GMASK) & IFM_FLOW) != 0 ||
193 (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
194 anar |= ANAR_PAUSE_TOWARDS;
194 }
195
196 if ((sc->mii_extcapabilities & (EXTSR_1000TFDX |
197 EXTSR_1000THDX)) != 0)
198 PHY_WRITE(sc, MII_100T2CR, 0);
199 PHY_WRITE(sc, MII_ANAR, anar | ANAR_CSMA);
200
201 /*

--- 15 unchanged lines hidden (view full) ---

217 * Only used for autonegotiation.
218 */
219 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
220 sc->mii_ticks = 0;
221 break;
222 }
223
224 /*
195 }
196
197 if ((sc->mii_extcapabilities & (EXTSR_1000TFDX |
198 EXTSR_1000THDX)) != 0)
199 PHY_WRITE(sc, MII_100T2CR, 0);
200 PHY_WRITE(sc, MII_ANAR, anar | ANAR_CSMA);
201
202 /*

--- 15 unchanged lines hidden (view full) ---

218 * Only used for autonegotiation.
219 */
220 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
221 sc->mii_ticks = 0;
222 break;
223 }
224
225 /*
225 * check for link.
226 * Check for link.
226 * Read the status register twice; BMSR_LINK is latch-low.
227 */
228 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
229 if (bmsr & BMSR_LINK) {
230 sc->mii_ticks = 0;
231 break;
232 }
233
234 /* Announce link loss right after it happens. */
235 if (sc->mii_ticks++ == 0)
236 break;
237 if (sc->mii_ticks <= sc->mii_anegticks)
238 return (0);
239
240 sc->mii_ticks = 0;
227 * Read the status register twice; BMSR_LINK is latch-low.
228 */
229 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
230 if (bmsr & BMSR_LINK) {
231 sc->mii_ticks = 0;
232 break;
233 }
234
235 /* Announce link loss right after it happens. */
236 if (sc->mii_ticks++ == 0)
237 break;
238 if (sc->mii_ticks <= sc->mii_anegticks)
239 return (0);
240
241 sc->mii_ticks = 0;
241 atphy_auto(sc);
242 atphy_setmedia(sc, ife->ifm_media);
242 break;
243 }
244
245 /* Update the media status. */
246 atphy_status(sc);
247
248 /* Callback if something changed. */
249 mii_phy_update(sc, cmd);

--- 29 unchanged lines hidden (view full) ---

279 mii->mii_media_active |= IFM_NONE;
280 return;
281 }
282
283 switch (ssr & ATPHY_SSR_SPEED_MASK) {
284 case ATPHY_SSR_1000MBS:
285 mii->mii_media_active |= IFM_1000_T;
286 /*
243 break;
244 }
245
246 /* Update the media status. */
247 atphy_status(sc);
248
249 /* Callback if something changed. */
250 mii_phy_update(sc, cmd);

--- 29 unchanged lines hidden (view full) ---

280 mii->mii_media_active |= IFM_NONE;
281 return;
282 }
283
284 switch (ssr & ATPHY_SSR_SPEED_MASK) {
285 case ATPHY_SSR_1000MBS:
286 mii->mii_media_active |= IFM_1000_T;
287 /*
287 * atphy(4) got a valid link so reset mii_ticks.
288 * atphy(4) has a valid link so reset mii_ticks.
288 * Resetting mii_ticks is needed in order to
289 * detect link loss after auto-negotiation.
290 */
291 sc->mii_ticks = 0;
292 break;
293 case ATPHY_SSR_100MBS:
294 mii->mii_media_active |= IFM_100_TX;
295 sc->mii_ticks = 0;
296 break;
297 case ATPHY_SSR_10MBS:
298 mii->mii_media_active |= IFM_10_T;
299 sc->mii_ticks = 0;
300 break;
301 default:
302 mii->mii_media_active |= IFM_NONE;
303 return;
304 }
305
306 if ((ssr & ATPHY_SSR_DUPLEX) != 0)
289 * Resetting mii_ticks is needed in order to
290 * detect link loss after auto-negotiation.
291 */
292 sc->mii_ticks = 0;
293 break;
294 case ATPHY_SSR_100MBS:
295 mii->mii_media_active |= IFM_100_TX;
296 sc->mii_ticks = 0;
297 break;
298 case ATPHY_SSR_10MBS:
299 mii->mii_media_active |= IFM_10_T;
300 sc->mii_ticks = 0;
301 break;
302 default:
303 mii->mii_media_active |= IFM_NONE;
304 return;
305 }
306
307 if ((ssr & ATPHY_SSR_DUPLEX) != 0)
307 mii->mii_media_active |= IFM_FDX;
308 mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc);
308 else
309 mii->mii_media_active |= IFM_HDX;
310
309 else
310 mii->mii_media_active |= IFM_HDX;
311
311 /* XXX Master/Slave, Flow-control */
312 if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
313 (PHY_READ(sc, MII_100T2SR) & GTSR_MS_RES) != 0)
314 mii->mii_media_active |= IFM_ETH_MASTER;
312}
313
314static void
315atphy_reset(struct mii_softc *sc)
316{
317 struct atphy_softc *asc;
318 uint32_t reg;
319 int i;

--- 11 unchanged lines hidden (view full) ---

331 reg &= ~ATPHY_SCR_MAC_PDOWN;
332 /* Enable CRS on Tx. */
333 reg |= ATPHY_SCR_ASSERT_CRS_ON_TX;
334 /* Auto correction for reversed cable polarity. */
335 reg |= ATPHY_SCR_POLARITY_REVERSAL;
336 PHY_WRITE(sc, ATPHY_SCR, reg);
337
338 /* Workaround F1 bug to reset phy. */
315}
316
317static void
318atphy_reset(struct mii_softc *sc)
319{
320 struct atphy_softc *asc;
321 uint32_t reg;
322 int i;

--- 11 unchanged lines hidden (view full) ---

334 reg &= ~ATPHY_SCR_MAC_PDOWN;
335 /* Enable CRS on Tx. */
336 reg |= ATPHY_SCR_ASSERT_CRS_ON_TX;
337 /* Auto correction for reversed cable polarity. */
338 reg |= ATPHY_SCR_POLARITY_REVERSAL;
339 PHY_WRITE(sc, ATPHY_SCR, reg);
340
341 /* Workaround F1 bug to reset phy. */
339 atphy_auto(sc);
342 atphy_setmedia(sc, sc->mii_pdata->mii_media.ifm_cur->ifm_media);
340
341 for (i = 0; i < 1000; i++) {
342 DELAY(1);
343 if ((PHY_READ(sc, MII_BMCR) & BMCR_RESET) == 0)
344 break;
345 }
346}
347

--- 25 unchanged lines hidden (view full) ---

373 else
374 anar |= ANAR_10_FD;
375 }
376
377 return (anar);
378}
379
380static int
343
344 for (i = 0; i < 1000; i++) {
345 DELAY(1);
346 if ((PHY_READ(sc, MII_BMCR) & BMCR_RESET) == 0)
347 break;
348 }
349}
350

--- 25 unchanged lines hidden (view full) ---

376 else
377 anar |= ANAR_10_FD;
378 }
379
380 return (anar);
381}
382
383static int
381atphy_auto(struct mii_softc *sc)
384atphy_setmedia(struct mii_softc *sc, int media)
382{
383 uint16_t anar;
384
385{
386 uint16_t anar;
387
385 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities);
386 PHY_WRITE(sc, MII_ANAR, anar | (3 << 10) | ANAR_CSMA);
388 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
389 if (((IFM_SUBTYPE(media) == IFM_AUTO ||
390 ((media & IFM_GMASK) & IFM_FDX) != 0) &&
391 ((media & IFM_GMASK) & IFM_FLOW) != 0) ||
392 (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
393 anar |= ANAR_PAUSE_TOWARDS;
394 PHY_WRITE(sc, MII_ANAR, anar);
387 if ((sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0)
388 PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX |
389 GTCR_ADV_1000THDX);
390 PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);
391
392 return (EJUSTRETURN);
393}
395 if ((sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0)
396 PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX |
397 GTCR_ADV_1000THDX);
398 PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);
399
400 return (EJUSTRETURN);
401}