1 /*	$NetBSD: ikphy.c,v 1.11 2016/07/07 06:55:41 msaitoh Exp $	*/
2 
3 /*******************************************************************************
4 Copyright (c) 2001-2005, Intel Corporation
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10  1. Redistributions of source code must retain the above copyright notice,
11     this list of conditions and the following disclaimer.
12 
13  2. Redistributions in binary form must reproduce the above copyright
14     notice, this list of conditions and the following disclaimer in the
15     documentation and/or other materials provided with the distribution.
16 
17  3. Neither the name of the Intel Corporation nor the names of its
18     contributors may be used to endorse or promote products derived from
19     this software without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 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  * Copyright (c) 2006 Manuel Bouyer.  All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
46  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
49  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
51  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
52  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
53  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
54  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55  */
56 
57 /*
58  * driver for Intel's i82563 ethernet 10/100/1000 PHY
59  */
60 
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: ikphy.c,v 1.11 2016/07/07 06:55:41 msaitoh Exp $");
63 
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/kernel.h>
67 #include <sys/device.h>
68 #include <sys/socket.h>
69 #include <sys/errno.h>
70 
71 #include <net/if.h>
72 #include <net/if_media.h>
73 
74 #include <dev/mii/mii.h>
75 #include <dev/mii/miivar.h>
76 #include <dev/mii/miidevs.h>
77 
78 #include <dev/mii/ikphyreg.h>
79 
80 static int	ikphymatch(device_t, cfdata_t, void *);
81 static void	ikphyattach(device_t, device_t, void *);
82 
83 CFATTACH_DECL_NEW(ikphy, sizeof(struct mii_softc),
84     ikphymatch, ikphyattach, mii_phy_detach, mii_phy_activate);
85 
86 static int	ikphy_service(struct mii_softc *, struct mii_data *, int);
87 static void	ikphy_status(struct mii_softc *);
88 static void	ikphy_setmedia(struct mii_softc *);
89 
90 static const struct mii_phy_funcs ikphy_funcs = {
91 	ikphy_service, ikphy_status, mii_phy_reset,
92 };
93 
94 static const struct mii_phydesc ikphys[] = {
95 	{ MII_OUI_xxMARVELL,		MII_MODEL_xxMARVELL_I82563,
96 	  MII_STR_xxMARVELL_I82563 },
97 
98 	{ 0,				0,
99 	  NULL },
100 };
101 
102 static int
ikphymatch(device_t parent,cfdata_t match,void * aux)103 ikphymatch(device_t parent, cfdata_t match, void *aux)
104 {
105 	struct mii_attach_args *ma = aux;
106 
107 	if (mii_phy_match(ma, ikphys) != NULL)
108 		return (10);
109 
110 	return (0);
111 }
112 
113 static void
ikphyattach(device_t parent,device_t self,void * aux)114 ikphyattach(device_t parent, device_t self, void *aux)
115 {
116 	struct mii_softc *sc = device_private(self);
117 	struct mii_attach_args *ma = aux;
118 	struct mii_data *mii = ma->mii_data;
119 	const struct mii_phydesc *mpd;
120 
121 	mpd = mii_phy_match(ma, ikphys);
122 	aprint_naive(": Media interface\n");
123 	aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
124 
125 	sc->mii_dev = self;
126 	sc->mii_inst = mii->mii_instance;
127 	sc->mii_phy = ma->mii_phyno;
128 	sc->mii_funcs = &ikphy_funcs;
129 	sc->mii_pdata = mii;
130 	sc->mii_flags = ma->mii_flags;
131 	sc->mii_anegticks = MII_ANEGTICKS;
132 
133 	PHY_RESET(sc);
134 
135 	sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
136 	if (sc->mii_capabilities & BMSR_EXTSTAT)
137 	    sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
138 	aprint_normal_dev(self, "");
139 	if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
140 	    (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
141 		aprint_error("no media present");
142 	else
143 		mii_phy_add_media(sc);
144 	aprint_normal("\n");
145 }
146 
147 static int
ikphy_service(struct mii_softc * sc,struct mii_data * mii,int cmd)148 ikphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
149 {
150 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
151 	int reg;
152 
153 	switch (cmd) {
154 	case MII_POLLSTAT:
155 		/*
156 		 * If we're not polling our PHY instance, just return.
157 		 */
158 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
159 			return (0);
160 		break;
161 
162 	case MII_MEDIACHG:
163 		/*
164 		 * If the media indicates a different PHY instance,
165 		 * isolate ourselves.
166 		 */
167 		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
168 			reg = PHY_READ(sc, MII_BMCR);
169 			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
170 			return (0);
171 		}
172 
173 		/*
174 		 * If the interface is not up, don't do anything.
175 		 */
176 		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
177 			break;
178 
179 		ikphy_setmedia(sc);
180 		break;
181 
182 	case MII_TICK:
183 		/*
184 		 * If we're not currently selected, just return.
185 		 */
186 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
187 			return (0);
188 
189 		if (mii_phy_tick(sc) == EJUSTRETURN)
190 			return (0);
191 		break;
192 
193 	case MII_DOWN:
194 		mii_phy_down(sc);
195 		return (0);
196 	}
197 
198 	/* Update the media status. */
199 	mii_phy_status(sc);
200 
201 	/* Callback if something changed. */
202 	mii_phy_update(sc, cmd);
203 	return (0);
204 }
205 
206 static void
ikphy_setmedia(struct mii_softc * sc)207 ikphy_setmedia(struct mii_softc *sc)
208 {
209 	uint16_t phy_data;
210 	struct mii_data *mii = sc->mii_pdata;
211 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
212 
213 	/* Enable CRS on TX for half-duplex operation. */
214 	phy_data = PHY_READ(sc, GG82563_PHY_MAC_SPEC_CTRL);
215 	phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
216 	/* Use 25MHz for both link down and 1000BASE-T for Tx clock */
217 	phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ;
218 	PHY_WRITE(sc, GG82563_PHY_MAC_SPEC_CTRL, phy_data);
219 
220 	/* set mdi/mid-x options */
221 	phy_data = PHY_READ(sc, GG82563_PHY_SPEC_CTRL);
222 	phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
223 	if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO)
224 		phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
225 	else
226 		phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
227 	/* set polarity correction */
228 	phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
229 	PHY_WRITE(sc, GG82563_PHY_SPEC_CTRL, phy_data);
230 
231 	/* SW Reset the PHY so all changes take effect */
232 	PHY_RESET(sc);
233 
234 	/* for the i80003 */
235 	phy_data = PHY_READ(sc, GG82563_PHY_SPEC_CTRL_2);
236 	phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
237 	PHY_WRITE(sc, GG82563_PHY_SPEC_CTRL_2, phy_data);
238 
239 	/* Enable Electrical Idle on the PHY */
240 	phy_data = PHY_READ(sc, GG82563_PHY_PWR_MGMT_CTRL);
241 	phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
242 	PHY_WRITE(sc, GG82563_PHY_PWR_MGMT_CTRL, phy_data);
243 
244 	phy_data = PHY_READ(sc, GG82563_PHY_KMRN_MODE_CTRL);
245 	phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
246 	PHY_WRITE(sc, GG82563_PHY_KMRN_MODE_CTRL, phy_data);
247 
248 	/*
249 	 * Workaround: Disable padding in Kumeran interface in the MAC
250 	 * and in the PHY to avoid CRC errors.
251 	 */
252 	phy_data = PHY_READ(sc, GG82563_PHY_INBAND_CTRL);
253 	phy_data |= GG82563_ICR_DIS_PADDING;
254 	PHY_WRITE(sc, GG82563_PHY_INBAND_CTRL, phy_data);
255 
256 	mii_phy_setmedia(sc);
257 	if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
258 		/*
259 		 * when not in auto mode, we need to restart nego
260 		 * anyway, or a switch from a fixed mode to another
261 		 * fixed mode may not be seen by the switch.
262 		 */
263 		PHY_WRITE(sc, MII_BMCR,
264 		    PHY_READ(sc, MII_BMCR) | BMCR_STARTNEG);
265 	}
266 	phy_data = PHY_READ(sc, GG82563_PHY_MAC_SPEC_CTRL);
267 	phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
268 	switch(IFM_SUBTYPE(ife->ifm_media)) {
269 	case IFM_10_T:
270 		phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ;
271 		break;
272 	case IFM_100_TX:
273 		phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25MHZ;
274 		break;
275 	case IFM_1000_T:
276 		phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ;
277 		break;
278 	}
279 	phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
280 	PHY_WRITE(sc, GG82563_PHY_MAC_SPEC_CTRL, phy_data);
281 }
282 
283 static void
ikphy_status(struct mii_softc * sc)284 ikphy_status(struct mii_softc *sc)
285 {
286 	struct mii_data *mii = sc->mii_pdata;
287 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
288 	int pssr, bmcr, gtsr, kmrn;
289 
290 	mii->mii_media_status = IFM_AVALID;
291 	mii->mii_media_active = IFM_ETHER;
292 
293 	pssr = PHY_READ(sc, GG82563_PHY_SPEC_STATUS);
294 
295 	if (pssr & GG82563_PSSR_LINK)
296 		mii->mii_media_status |= IFM_ACTIVE;
297 
298 	bmcr = PHY_READ(sc, MII_BMCR);
299 	if (bmcr & BMCR_ISO) {
300 		mii->mii_media_active |= IFM_NONE;
301 		mii->mii_media_status = 0;
302 		return;
303 	}
304 
305 	if (bmcr & BMCR_LOOP)
306 		mii->mii_media_active |= IFM_LOOP;
307 
308 	if (bmcr & BMCR_AUTOEN) {
309 		/*
310 		 * The media status bits are only valid of autonegotiation
311 		 * has completed (or it's disabled).
312 		 */
313 		if ((pssr & GG82563_PSSR_SPEED_DUPLEX_RESOLVED) == 0) {
314 			/* Erg, still trying, I guess... */
315 			mii->mii_media_active |= IFM_NONE;
316 			return;
317 		}
318 
319 		switch (pssr & GG82563_PSSR_SPEED_MASK) {
320 		case GG82563_PSSR_SPEED_1000MBPS:
321 			mii->mii_media_active |= IFM_1000_T;
322 			gtsr = PHY_READ(sc, MII_100T2SR);
323 			if (gtsr & GTSR_MS_RES)
324 				mii->mii_media_active |= IFM_ETH_MASTER;
325 			break;
326 
327 		case GG82563_PSSR_SPEED_100MBPS:
328 			mii->mii_media_active |= IFM_100_TX;
329 			break;
330 
331 		case GG82563_PSSR_SPEED_10MBPS:
332 			mii->mii_media_active |= IFM_10_T;
333 			break;
334 
335 		default:
336 			mii->mii_media_active |= IFM_NONE;
337 			mii->mii_media_status = 0;
338 			return;
339 		}
340 
341 		if (pssr & GG82563_PSSR_DUPLEX)
342 			mii->mii_media_active |=
343 			    IFM_FDX | mii_phy_flowstatus(sc);
344 		else
345 			mii->mii_media_active |= IFM_HDX;
346 	} else
347 		mii->mii_media_active = ife->ifm_media;
348 	kmrn = PHY_READ(sc, GG82563_PHY_KMRN_MODE_CTRL);
349 	if (mii->mii_media_active & IFM_FDX)
350 		kmrn &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
351 	else
352 		kmrn |= GG82563_KMCR_PASS_FALSE_CARRIER;
353 	PHY_WRITE(sc, GG82563_PHY_KMRN_MODE_CTRL, kmrn);
354 }
355