makphy.c revision 1.44 1 /* $NetBSD: makphy.c,v 1.44 2018/06/16 17:44:53 jdolecek Exp $ */
2 /* $OpenBSD: eephy.c,v 1.56 2015/03/14 03:38:48 jsg Exp $ */
3
4 /*-
5 * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10 * NASA Ames Research Center.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 */
57
58 /*
59 * Principal Author: Parag Patel
60 * Copyright (c) 2001
61 * All rights reserved.
62 *
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
65 * are met:
66 * 1. Redistributions of source code must retain the above copyright
67 * notice unmodified, this list of conditions, and the following
68 * disclaimer.
69 * 2. Redistributions in binary form must reproduce the above copyright
70 * notice, this list of conditions and the following disclaimer in the
71 * documentation and/or other materials provided with the distribution.
72 *
73 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
74 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
76 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
77 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
78 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
79 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
80 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
81 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
82 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
83 * SUCH DAMAGE.
84 *
85 * Additonal Copyright (c) 2001 by Traakan Software under same licence.
86 * Secondary Author: Matthew Jacob
87 */
88 /*
89 * Driver for the Marvell 88E1000 ``Alaska'' 10/100/1000 PHY.
90 */
91
92 /*
93 * Support added for the Marvell 88E1011 (Alaska) 1000/100/10baseTX and
94 * 1000baseSX PHY.
95 * Nathan Binkert <nate (at) openbsd.org>
96 */
97
98 #include <sys/cdefs.h>
99 __KERNEL_RCSID(0, "$NetBSD: makphy.c,v 1.44 2018/06/16 17:44:53 jdolecek Exp $");
100
101 #include <sys/param.h>
102 #include <sys/systm.h>
103 #include <sys/kernel.h>
104 #include <sys/device.h>
105 #include <sys/socket.h>
106 #include <sys/errno.h>
107
108 #include <net/if.h>
109 #include <net/if_media.h>
110
111 #include <dev/mii/mii.h>
112 #include <dev/mii/miivar.h>
113 #include <dev/mii/miidevs.h>
114
115 #include <dev/mii/e1000phyreg.h>
116
117 static int makphymatch(device_t, cfdata_t, void *);
118 static void makphyattach(device_t, device_t, void *);
119
120 CFATTACH_DECL_NEW(makphy, sizeof(struct mii_softc),
121 makphymatch, makphyattach, mii_phy_detach, mii_phy_activate);
122
123 static int makphy_service(struct mii_softc *, struct mii_data *, int);
124 static void makphy_status(struct mii_softc *);
125 static void makphy_reset(struct mii_softc *);
126
127 static const struct mii_phy_funcs eephy_funcs = {
128 makphy_service, makphy_status, makphy_reset,
129 };
130
131 static const struct mii_phydesc eephys[] = {
132 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_0,
133 MII_STR_MARVELL_E1000_0 },
134
135 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_3,
136 MII_STR_MARVELL_E1000_3 },
137
138 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_5,
139 MII_STR_MARVELL_E1000_5 },
140
141 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_6,
142 MII_STR_MARVELL_E1000_6 },
143
144 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1000_3,
145 MII_STR_xxMARVELL_E1000_3 },
146
147 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1000_5,
148 MII_STR_xxMARVELL_E1000_5 },
149
150 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1000S,
151 MII_STR_xxMARVELL_E1000S },
152
153 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1011,
154 MII_STR_xxMARVELL_E1011 },
155
156 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1111,
157 MII_STR_xxMARVELL_E1111 },
158
159 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1112,
160 MII_STR_xxMARVELL_E1112 },
161
162 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1116,
163 MII_STR_xxMARVELL_E1116 },
164
165 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1116R,
166 MII_STR_xxMARVELL_E1116R },
167
168 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1116R_29,
169 MII_STR_xxMARVELL_E1116R_29 },
170
171 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1118,
172 MII_STR_xxMARVELL_E1118 },
173
174 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1145,
175 MII_STR_xxMARVELL_E1145 },
176
177 /* XXX: reported not to work on eg. HP XW9400 */
178 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1149,
179 MII_STR_xxMARVELL_E1149 },
180
181 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1149R,
182 MII_STR_xxMARVELL_E1149R },
183
184 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1543,
185 MII_STR_xxMARVELL_E1543 },
186
187 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E3016,
188 MII_STR_xxMARVELL_E3016 },
189
190 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E3082,
191 MII_STR_xxMARVELL_E3082 },
192
193 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_PHYG65G,
194 MII_STR_xxMARVELL_PHYG65G },
195 { 0, 0,
196 NULL },
197 };
198
199 static int
200 makphymatch(device_t parent, cfdata_t match, void *aux)
201 {
202 struct mii_attach_args *ma = aux;
203
204 if (mii_phy_match(ma, eephys) != NULL)
205 return (10);
206
207 return (0);
208 }
209
210 static void
211 makphyattach(device_t parent, device_t self, void *aux)
212 {
213 struct mii_softc *sc = device_private(self);
214 struct mii_attach_args *ma = aux;
215 struct mii_data *mii = ma->mii_data;
216 const struct mii_phydesc *mpd;
217
218 mpd = mii_phy_match(ma, eephys);
219 aprint_naive(": Media interface\n");
220 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
221
222 sc->mii_dev = self;
223 sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2);
224 sc->mii_mpd_model = MII_MODEL(ma->mii_id2);
225 sc->mii_mpd_rev = MII_REV(ma->mii_id2);
226 sc->mii_inst = mii->mii_instance;
227 sc->mii_phy = ma->mii_phyno;
228 sc->mii_funcs = &eephy_funcs;
229 sc->mii_pdata = mii;
230 sc->mii_flags = ma->mii_flags;
231 sc->mii_anegticks = MII_ANEGTICKS;
232
233 /* XXX No loopback support yet, although the hardware can do it. */
234 sc->mii_flags |= MIIF_NOLOOP;
235
236 /* Make sure page 0 is selected. */
237 PHY_WRITE(sc, E1000_EADR, 0);
238
239 /* Switch to copper-only mode if necessary. */
240 if (sc->mii_mpd_model == MII_MODEL_MARVELL_E1111 &&
241 (sc->mii_flags & MIIF_HAVEFIBER) == 0) {
242 /*
243 * The onboard 88E1111 PHYs on the Sun X4100 M2 come
244 * up with fiber/copper auto-selection enabled, even
245 * though the machine only has copper ports. This
246 * makes the chip autoselect to 1000baseX, and makes
247 * it impossible to select any other media. So
248 * disable fiber/copper autoselection.
249 */
250 int reg = PHY_READ(sc, E1000_ESSR);
251 if ((reg & E1000_ESSR_HWCFG_MODE) == E1000_ESSR_RGMII_COPPER) {
252 reg |= E1000_ESSR_DIS_FC;
253 PHY_WRITE(sc, E1000_ESSR, reg);
254 }
255 }
256
257 /* Switch to fiber-only mode if necessary. */
258 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1112 &&
259 sc->mii_flags & MIIF_HAVEFIBER) {
260 int page = PHY_READ(sc, E1000_EADR);
261 PHY_WRITE(sc, E1000_EADR, 2);
262 int reg = PHY_READ(sc, E1000_SCR);
263 reg &= ~E1000_SCR_MODE_MASK;
264 reg |= E1000_SCR_MODE_1000BX;
265 PHY_WRITE(sc, E1000_SCR, reg);
266 PHY_WRITE(sc, E1000_EADR, page);
267 }
268
269 PHY_RESET(sc);
270
271 sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
272 if (sc->mii_capabilities & BMSR_EXTSTAT)
273 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
274
275 aprint_normal_dev(self, "");
276 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
277 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
278 aprint_error("no media present");
279 else
280 mii_phy_add_media(sc);
281 aprint_normal("\n");
282 }
283
284 static void
285 makphy_reset(struct mii_softc *sc)
286 {
287 int reg, i;
288
289 reg = PHY_READ(sc, E1000_CR);
290 reg |= E1000_CR_RESET;
291 PHY_WRITE(sc, E1000_CR, reg);
292
293 for (i = 0; i < 500; i++) {
294 DELAY(1);
295 reg = PHY_READ(sc, E1000_CR);
296 if (!(reg & E1000_CR_RESET))
297 break;
298 }
299
300 /*
301 * Initialize PHY Specific Control Register.
302 */
303 reg = PHY_READ(sc, E1000_SCR);
304
305 /* Assert CRS on transmit. */
306 reg |= E1000_SCR_ASSERT_CRS_ON_TX;
307
308 /* Enable auto crossover. */
309 switch (sc->mii_mpd_model) {
310 case MII_MODEL_xxMARVELL_E3016:
311 case MII_MODEL_xxMARVELL_E3082:
312 /* Bits are in a different position. */
313 reg |= (E1000_SCR_AUTO_X_MODE >> 1);
314 break;
315 default:
316 /* Automatic crossover causes problems for 1000baseX. */
317 if (sc->mii_flags & MIIF_IS_1000X)
318 reg &= ~E1000_SCR_AUTO_X_MODE;
319 else
320 reg |= E1000_SCR_AUTO_X_MODE;
321 }
322
323 /* Disable energy detect; only available on some models. */
324 switch(sc->mii_mpd_model) {
325 case MII_MODEL_xxMARVELL_E3016:
326 reg &= ~E3000_SCR_EN_DETECT_MASK;
327 break;
328 case MII_MODEL_MARVELL_E1011:
329 case MII_MODEL_MARVELL_E1111:
330 case MII_MODEL_xxMARVELL_E1112:
331 case MII_MODEL_xxMARVELL_PHYG65G:
332 reg &= ~E1000_SCR_EN_DETECT_MASK;
333 break;
334 }
335
336 /* Enable scrambler if necessary. */
337 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E3016)
338 reg &= ~E3000_SCR_SCRAMBLER_DISABLE;
339
340 /*
341 * Store next page in the Link Partner Next Page register for
342 * compatibility with 802.3ab.
343 */
344 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E3016)
345 reg |= E3000_SCR_REG8_NEXT_PAGE;
346
347 PHY_WRITE(sc, E1000_SCR, reg);
348
349 /* 25 MHz TX_CLK should always work. */
350 reg = PHY_READ(sc, E1000_ESCR);
351 reg |= E1000_ESCR_TX_CLK_25;
352 PHY_WRITE(sc, E1000_ESCR, reg);
353
354 /* Configure LEDs if they were left unconfigured. */
355 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E3016 &&
356 PHY_READ(sc, 0x16) == 0) {
357 reg = (0x0b << 8) | (0x05 << 4) | 0x04; /* XXX */
358 PHY_WRITE(sc, 0x16, reg);
359 }
360
361 /*
362 * Do a software reset for these settings to take effect.
363 * Disable autonegotiation, such that all capabilities get
364 * advertised when it is switched back on.
365 */
366 reg = PHY_READ(sc, E1000_CR);
367 reg &= ~E1000_CR_AUTO_NEG_ENABLE;
368 PHY_WRITE(sc, E1000_CR, reg | E1000_CR_RESET);
369 }
370
371 static int
372 makphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
373 {
374 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
375 int bmcr;
376
377 if (!device_is_active(sc->mii_dev))
378 return (ENXIO);
379
380 switch (cmd) {
381 case MII_POLLSTAT:
382 /*
383 * If we're not polling our PHY instance, just return.
384 */
385 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
386 return (0);
387 break;
388
389 case MII_MEDIACHG:
390 /*
391 * If the media indicates a different PHY instance,
392 * isolate ourselves.
393 */
394 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
395 bmcr = PHY_READ(sc, E1000_CR);
396 PHY_WRITE(sc, E1000_CR, bmcr | E1000_CR_ISOLATE);
397 return (0);
398 }
399
400 /*
401 * If the interface is not up, don't do anything.
402 */
403 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
404 break;
405
406 mii_phy_setmedia(sc);
407
408 /*
409 * If autonegitation is not enabled, we need a
410 * software reset for the settings to take effect.
411 */
412 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
413 bmcr = PHY_READ(sc, E1000_CR);
414 PHY_WRITE(sc, E1000_CR, bmcr | E1000_CR_RESET);
415 }
416 break;
417
418 case MII_TICK:
419 /*
420 * If we're not currently selected, just return.
421 */
422 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
423 return (0);
424
425 if (mii_phy_tick(sc) == EJUSTRETURN)
426 return (0);
427 break;
428
429 case MII_DOWN:
430 mii_phy_down(sc);
431 return (0);
432 }
433
434 /* Update the media status. */
435 mii_phy_status(sc);
436
437 /* Callback if something changed. */
438 mii_phy_update(sc, cmd);
439 return (0);
440 }
441
442 static void
443 makphy_status(struct mii_softc *sc)
444 {
445 struct mii_data *mii = sc->mii_pdata;
446 int bmcr, gsr, ssr;
447
448 mii->mii_media_status = IFM_AVALID;
449 mii->mii_media_active = IFM_ETHER;
450
451 bmcr = PHY_READ(sc, E1000_CR);
452 ssr = PHY_READ(sc, E1000_SSR);
453
454 if (ssr & E1000_SSR_LINK)
455 mii->mii_media_status |= IFM_ACTIVE;
456
457 if (bmcr & E1000_CR_LOOPBACK)
458 mii->mii_media_active |= IFM_LOOP;
459
460 if (!(ssr & E1000_SSR_SPD_DPLX_RESOLVED)) {
461 /* Erg, still trying, I guess... */
462 mii->mii_media_active |= IFM_NONE;
463 return;
464 }
465
466 if (sc->mii_flags & MIIF_IS_1000X) {
467 mii->mii_media_active |= IFM_1000_SX;
468 } else {
469 if (ssr & E1000_SSR_1000MBS)
470 mii->mii_media_active |= IFM_1000_T;
471 else if (ssr & E1000_SSR_100MBS)
472 mii->mii_media_active |= IFM_100_TX;
473 else
474 mii->mii_media_active |= IFM_10_T;
475 }
476
477 if (ssr & E1000_SSR_DUPLEX)
478 mii->mii_media_active |= mii_phy_flowstatus(sc) | IFM_FDX;
479 else
480 mii->mii_media_active |= IFM_HDX;
481
482 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
483 gsr = PHY_READ(sc, E1000_1GSR) | PHY_READ(sc, E1000_1GSR);
484 if (gsr & E1000_1GSR_MS_CONFIG_RES)
485 mii->mii_media_active |= IFM_ETH_MASTER;
486 }
487 }
488