xref: /openbmc/u-boot/drivers/qe/uec_phy.c (revision f62fb999)
1 /*
2  * Copyright (C) 2005 Freescale Semiconductor, Inc.
3  *
4  * Author: Shlomi Gridish
5  *
6  * Description: UCC GETH Driver -- PHY handling
7  *		Driver for UEC on QE
8  *		Based on 8260_io/fcc_enet.c
9  *
10  * This program is free software; you can redistribute	it and/or modify it
11  * under  the terms of	the GNU General	 Public License as published by the
12  * Free Software Foundation;  either version 2 of the  License, or (at your
13  * option) any later version.
14  *
15  */
16 
17 #include "common.h"
18 #include "net.h"
19 #include "malloc.h"
20 #include "asm/errno.h"
21 #include "asm/immap_qe.h"
22 #include "asm/io.h"
23 #include "qe.h"
24 #include "uccf.h"
25 #include "uec.h"
26 #include "uec_phy.h"
27 #include "miiphy.h"
28 
29 #define ugphy_printk(format, arg...)  \
30 	printf(format "\n", ## arg)
31 
32 #define ugphy_dbg(format, arg...)	     \
33 	ugphy_printk(format , ## arg)
34 #define ugphy_err(format, arg...)	     \
35 	ugphy_printk(format , ## arg)
36 #define ugphy_info(format, arg...)	     \
37 	ugphy_printk(format , ## arg)
38 #define ugphy_warn(format, arg...)	     \
39 	ugphy_printk(format , ## arg)
40 
41 #ifdef UEC_VERBOSE_DEBUG
42 #define ugphy_vdbg ugphy_dbg
43 #else
44 #define ugphy_vdbg(ugeth, fmt, args...) do { } while (0)
45 #endif /* UEC_VERBOSE_DEBUG */
46 
47 /*--------------------------------------------------------------------+
48  * Fixed PHY (PHY-less) support for Ethernet Ports.
49  *
50  * Copied from cpu/ppc4xx/4xx_enet.c
51  *--------------------------------------------------------------------*/
52 
53 /*
54  * Some boards do not have a PHY for each ethernet port. These ports
55  * are known as Fixed PHY (or PHY-less) ports. For such ports, set
56  * the appropriate CONFIG_PHY_ADDR equal to CONFIG_FIXED_PHY and
57  * then define CONFIG_SYS_FIXED_PHY_PORTS to define what the speed and
58  * duplex should be for these ports in the board configuration
59  * file.
60  *
61  * For Example:
62  *     #define CONFIG_FIXED_PHY   0xFFFFFFFF
63  *
64  *     #define CONFIG_PHY_ADDR    CONFIG_FIXED_PHY
65  *     #define CONFIG_PHY1_ADDR   1
66  *     #define CONFIG_PHY2_ADDR   CONFIG_FIXED_PHY
67  *     #define CONFIG_PHY3_ADDR   3
68  *
69  *     #define CONFIG_SYS_FIXED_PHY_PORT(devnum,speed,duplex) \
70  *                     {devnum, speed, duplex},
71  *
72  *     #define CONFIG_SYS_FIXED_PHY_PORTS \
73  *                     CONFIG_SYS_FIXED_PHY_PORT(0,SPEED_100,DUPLEX_FULL) \
74  *                     CONFIG_SYS_FIXED_PHY_PORT(2,SPEED_100,DUPLEX_HALF)
75  */
76 
77 #ifndef CONFIG_FIXED_PHY
78 #define CONFIG_FIXED_PHY	0xFFFFFFFF /* Fixed PHY (PHY-less) */
79 #endif
80 
81 #ifndef CONFIG_SYS_FIXED_PHY_PORTS
82 #define CONFIG_SYS_FIXED_PHY_PORTS	/* default is an empty array */
83 #endif
84 
85 struct fixed_phy_port {
86 	unsigned int devnum;	/* ethernet port */
87 	unsigned int speed;	/* specified speed 10,100 or 1000 */
88 	unsigned int duplex;	/* specified duplex FULL or HALF */
89 };
90 
91 static const struct fixed_phy_port fixed_phy_port[] = {
92 	CONFIG_SYS_FIXED_PHY_PORTS /* defined in board configuration file */
93 };
94 
95 static void config_genmii_advert (struct uec_mii_info *mii_info);
96 static void genmii_setup_forced (struct uec_mii_info *mii_info);
97 static void genmii_restart_aneg (struct uec_mii_info *mii_info);
98 static int gbit_config_aneg (struct uec_mii_info *mii_info);
99 static int genmii_config_aneg (struct uec_mii_info *mii_info);
100 static int genmii_update_link (struct uec_mii_info *mii_info);
101 static int genmii_read_status (struct uec_mii_info *mii_info);
102 u16 phy_read (struct uec_mii_info *mii_info, u16 regnum);
103 void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
104 
105 /* Write value to the PHY for this device to the register at regnum, */
106 /* waiting until the write is done before it returns.  All PHY */
107 /* configuration has to be done through the TSEC1 MIIM regs */
108 void uec_write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int value)
109 {
110 	uec_private_t *ugeth = (uec_private_t *) dev->priv;
111 	uec_mii_t *ug_regs;
112 	enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
113 	u32 tmp_reg;
114 
115 	ug_regs = ugeth->uec_mii_regs;
116 
117 	/* Stop the MII management read cycle */
118 	out_be32 (&ug_regs->miimcom, 0);
119 	/* Setting up the MII Mangement Address Register */
120 	tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
121 	out_be32 (&ug_regs->miimadd, tmp_reg);
122 
123 	/* Setting up the MII Mangement Control Register with the value */
124 	out_be32 (&ug_regs->miimcon, (u32) value);
125 	sync();
126 
127 	/* Wait till MII management write is complete */
128 	while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY);
129 }
130 
131 /* Reads from register regnum in the PHY for device dev, */
132 /* returning the value.  Clears miimcom first.  All PHY */
133 /* configuration has to be done through the TSEC1 MIIM regs */
134 int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum)
135 {
136 	uec_private_t *ugeth = (uec_private_t *) dev->priv;
137 	uec_mii_t *ug_regs;
138 	enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
139 	u32 tmp_reg;
140 	u16 value;
141 
142 	ug_regs = ugeth->uec_mii_regs;
143 
144 	/* Setting up the MII Mangement Address Register */
145 	tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
146 	out_be32 (&ug_regs->miimadd, tmp_reg);
147 
148 	/* clear MII management command cycle */
149 	out_be32 (&ug_regs->miimcom, 0);
150 	sync();
151 
152 	/* Perform an MII management read cycle */
153 	out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE);
154 
155 	/* Wait till MII management write is complete */
156 	while ((in_be32 (&ug_regs->miimind)) &
157 	       (MIIMIND_NOT_VALID | MIIMIND_BUSY));
158 
159 	/* Read MII management status  */
160 	value = (u16) in_be32 (&ug_regs->miimstat);
161 	if (value == 0xffff)
162 		ugphy_vdbg
163 			("read wrong value : mii_id %d,mii_reg %d, base %08x",
164 			 mii_id, mii_reg, (u32) & (ug_regs->miimcfg));
165 
166 	return (value);
167 }
168 
169 void mii_clear_phy_interrupt (struct uec_mii_info *mii_info)
170 {
171 	if (mii_info->phyinfo->ack_interrupt)
172 		mii_info->phyinfo->ack_interrupt (mii_info);
173 }
174 
175 void mii_configure_phy_interrupt (struct uec_mii_info *mii_info,
176 				  u32 interrupts)
177 {
178 	mii_info->interrupts = interrupts;
179 	if (mii_info->phyinfo->config_intr)
180 		mii_info->phyinfo->config_intr (mii_info);
181 }
182 
183 /* Writes MII_ADVERTISE with the appropriate values, after
184  * sanitizing advertise to make sure only supported features
185  * are advertised
186  */
187 static void config_genmii_advert (struct uec_mii_info *mii_info)
188 {
189 	u32 advertise;
190 	u16 adv;
191 
192 	/* Only allow advertising what this PHY supports */
193 	mii_info->advertising &= mii_info->phyinfo->features;
194 	advertise = mii_info->advertising;
195 
196 	/* Setup standard advertisement */
197 	adv = phy_read (mii_info, PHY_ANAR);
198 	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
199 	if (advertise & ADVERTISED_10baseT_Half)
200 		adv |= ADVERTISE_10HALF;
201 	if (advertise & ADVERTISED_10baseT_Full)
202 		adv |= ADVERTISE_10FULL;
203 	if (advertise & ADVERTISED_100baseT_Half)
204 		adv |= ADVERTISE_100HALF;
205 	if (advertise & ADVERTISED_100baseT_Full)
206 		adv |= ADVERTISE_100FULL;
207 	phy_write (mii_info, PHY_ANAR, adv);
208 }
209 
210 static void genmii_setup_forced (struct uec_mii_info *mii_info)
211 {
212 	u16 ctrl;
213 	u32 features = mii_info->phyinfo->features;
214 
215 	ctrl = phy_read (mii_info, PHY_BMCR);
216 
217 	ctrl &= ~(PHY_BMCR_DPLX | PHY_BMCR_100_MBPS |
218 		  PHY_BMCR_1000_MBPS | PHY_BMCR_AUTON);
219 	ctrl |= PHY_BMCR_RESET;
220 
221 	switch (mii_info->speed) {
222 	case SPEED_1000:
223 		if (features & (SUPPORTED_1000baseT_Half
224 				| SUPPORTED_1000baseT_Full)) {
225 			ctrl |= PHY_BMCR_1000_MBPS;
226 			break;
227 		}
228 		mii_info->speed = SPEED_100;
229 	case SPEED_100:
230 		if (features & (SUPPORTED_100baseT_Half
231 				| SUPPORTED_100baseT_Full)) {
232 			ctrl |= PHY_BMCR_100_MBPS;
233 			break;
234 		}
235 		mii_info->speed = SPEED_10;
236 	case SPEED_10:
237 		if (features & (SUPPORTED_10baseT_Half
238 				| SUPPORTED_10baseT_Full))
239 			break;
240 	default:		/* Unsupported speed! */
241 		ugphy_err ("%s: Bad speed!", mii_info->dev->name);
242 		break;
243 	}
244 
245 	phy_write (mii_info, PHY_BMCR, ctrl);
246 }
247 
248 /* Enable and Restart Autonegotiation */
249 static void genmii_restart_aneg (struct uec_mii_info *mii_info)
250 {
251 	u16 ctl;
252 
253 	ctl = phy_read (mii_info, PHY_BMCR);
254 	ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
255 	phy_write (mii_info, PHY_BMCR, ctl);
256 }
257 
258 static int gbit_config_aneg (struct uec_mii_info *mii_info)
259 {
260 	u16 adv;
261 	u32 advertise;
262 
263 	if (mii_info->autoneg) {
264 		/* Configure the ADVERTISE register */
265 		config_genmii_advert (mii_info);
266 		advertise = mii_info->advertising;
267 
268 		adv = phy_read (mii_info, MII_1000BASETCONTROL);
269 		adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
270 			 MII_1000BASETCONTROL_HALFDUPLEXCAP);
271 		if (advertise & SUPPORTED_1000baseT_Half)
272 			adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
273 		if (advertise & SUPPORTED_1000baseT_Full)
274 			adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
275 		phy_write (mii_info, MII_1000BASETCONTROL, adv);
276 
277 		/* Start/Restart aneg */
278 		genmii_restart_aneg (mii_info);
279 	} else
280 		genmii_setup_forced (mii_info);
281 
282 	return 0;
283 }
284 
285 static int marvell_config_aneg (struct uec_mii_info *mii_info)
286 {
287 	/* The Marvell PHY has an errata which requires
288 	 * that certain registers get written in order
289 	 * to restart autonegotiation */
290 	phy_write (mii_info, PHY_BMCR, PHY_BMCR_RESET);
291 
292 	phy_write (mii_info, 0x1d, 0x1f);
293 	phy_write (mii_info, 0x1e, 0x200c);
294 	phy_write (mii_info, 0x1d, 0x5);
295 	phy_write (mii_info, 0x1e, 0);
296 	phy_write (mii_info, 0x1e, 0x100);
297 
298 	gbit_config_aneg (mii_info);
299 
300 	return 0;
301 }
302 
303 static int genmii_config_aneg (struct uec_mii_info *mii_info)
304 {
305 	if (mii_info->autoneg) {
306 		config_genmii_advert (mii_info);
307 		genmii_restart_aneg (mii_info);
308 	} else
309 		genmii_setup_forced (mii_info);
310 
311 	return 0;
312 }
313 
314 static int genmii_update_link (struct uec_mii_info *mii_info)
315 {
316 	u16 status;
317 
318 	/* Status is read once to clear old link state */
319 	phy_read (mii_info, PHY_BMSR);
320 
321 	/*
322 	 * Wait if the link is up, and autonegotiation is in progress
323 	 * (ie - we're capable and it's not done)
324 	 */
325 	status = phy_read(mii_info, PHY_BMSR);
326 	if ((status & PHY_BMSR_LS) && (status & PHY_BMSR_AUTN_ABLE)
327 	    && !(status & PHY_BMSR_AUTN_COMP)) {
328 		int i = 0;
329 
330 		while (!(status & PHY_BMSR_AUTN_COMP)) {
331 			/*
332 			 * Timeout reached ?
333 			 */
334 			if (i > UGETH_AN_TIMEOUT) {
335 				mii_info->link = 0;
336 				return 0;
337 			}
338 
339 			i++;
340 			udelay(1000);	/* 1 ms */
341 			status = phy_read(mii_info, PHY_BMSR);
342 		}
343 		mii_info->link = 1;
344 		udelay(500000);	/* another 500 ms (results in faster booting) */
345 	} else {
346 		if (status & PHY_BMSR_LS)
347 			mii_info->link = 1;
348 		else
349 			mii_info->link = 0;
350 	}
351 
352 	return 0;
353 }
354 
355 static int genmii_read_status (struct uec_mii_info *mii_info)
356 {
357 	u16 status;
358 	int err;
359 
360 	/* Update the link, but return if there
361 	 * was an error */
362 	err = genmii_update_link (mii_info);
363 	if (err)
364 		return err;
365 
366 	if (mii_info->autoneg) {
367 		status = phy_read(mii_info, MII_1000BASETSTATUS);
368 
369 		if (status & (LPA_1000FULL | LPA_1000HALF)) {
370 			mii_info->speed = SPEED_1000;
371 			if (status & LPA_1000FULL)
372 				mii_info->duplex = DUPLEX_FULL;
373 			else
374 				mii_info->duplex = DUPLEX_HALF;
375 		} else {
376 			status = phy_read(mii_info, PHY_ANLPAR);
377 
378 			if (status & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD))
379 				mii_info->duplex = DUPLEX_FULL;
380 			else
381 				mii_info->duplex = DUPLEX_HALF;
382 			if (status & (PHY_ANLPAR_TXFD | PHY_ANLPAR_TX))
383 				mii_info->speed = SPEED_100;
384 			else
385 				mii_info->speed = SPEED_10;
386 		}
387 		mii_info->pause = 0;
388 	}
389 	/* On non-aneg, we assume what we put in BMCR is the speed,
390 	 * though magic-aneg shouldn't prevent this case from occurring
391 	 */
392 
393 	return 0;
394 }
395 
396 static int bcm_init(struct uec_mii_info *mii_info)
397 {
398 	struct eth_device *edev = mii_info->dev;
399 	uec_private_t *uec = edev->priv;
400 
401 	gbit_config_aneg(mii_info);
402 
403 	if (uec->uec_info->enet_interface == ENET_1000_RGMII_RXID) {
404 		u16 val;
405 		int cnt = 50;
406 
407 		/* Wait for aneg to complete. */
408 		do
409 			val = phy_read(mii_info, PHY_BMSR);
410 		while (--cnt && !(val & PHY_BMSR_AUTN_COMP));
411 
412 		/* Set RDX clk delay. */
413 		phy_write(mii_info, 0x18, 0x7 | (7 << 12));
414 
415 		val = phy_read(mii_info, 0x18);
416 		/* Set RDX-RXC skew. */
417 		val |= (1 << 8);
418 		val |= (7 | (7 << 12));
419 		/* Write bits 14:0. */
420 		val |= (1 << 15);
421 		phy_write(mii_info, 0x18, val);
422 	}
423 
424 	 return 0;
425 }
426 
427 static int marvell_init(struct uec_mii_info *mii_info)
428 {
429 	struct eth_device *edev = mii_info->dev;
430 	uec_private_t *uec = edev->priv;
431 
432 	if (uec->uec_info->enet_interface == ENET_1000_RGMII_ID) {
433 		int temp;
434 
435 		temp = phy_read(mii_info, MII_M1111_PHY_EXT_CR);
436 		temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
437 		phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
438 
439 		temp = phy_read(mii_info, MII_M1111_PHY_EXT_SR);
440 		temp &= ~MII_M1111_HWCFG_MODE_MASK;
441 		temp |= MII_M1111_HWCFG_MODE_RGMII;
442 		phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
443 
444 		phy_write(mii_info, PHY_BMCR, PHY_BMCR_RESET);
445 	}
446 
447 	return 0;
448 }
449 
450 static int marvell_read_status (struct uec_mii_info *mii_info)
451 {
452 	u16 status;
453 	int err;
454 
455 	/* Update the link, but return if there
456 	 * was an error */
457 	err = genmii_update_link (mii_info);
458 	if (err)
459 		return err;
460 
461 	/* If the link is up, read the speed and duplex */
462 	/* If we aren't autonegotiating, assume speeds
463 	 * are as set */
464 	if (mii_info->autoneg && mii_info->link) {
465 		int speed;
466 
467 		status = phy_read (mii_info, MII_M1011_PHY_SPEC_STATUS);
468 
469 		/* Get the duplexity */
470 		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
471 			mii_info->duplex = DUPLEX_FULL;
472 		else
473 			mii_info->duplex = DUPLEX_HALF;
474 
475 		/* Get the speed */
476 		speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
477 		switch (speed) {
478 		case MII_M1011_PHY_SPEC_STATUS_1000:
479 			mii_info->speed = SPEED_1000;
480 			break;
481 		case MII_M1011_PHY_SPEC_STATUS_100:
482 			mii_info->speed = SPEED_100;
483 			break;
484 		default:
485 			mii_info->speed = SPEED_10;
486 			break;
487 		}
488 		mii_info->pause = 0;
489 	}
490 
491 	return 0;
492 }
493 
494 static int marvell_ack_interrupt (struct uec_mii_info *mii_info)
495 {
496 	/* Clear the interrupts by reading the reg */
497 	phy_read (mii_info, MII_M1011_IEVENT);
498 
499 	return 0;
500 }
501 
502 static int marvell_config_intr (struct uec_mii_info *mii_info)
503 {
504 	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
505 		phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
506 	else
507 		phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
508 
509 	return 0;
510 }
511 
512 static int dm9161_init (struct uec_mii_info *mii_info)
513 {
514 	/* Reset the PHY */
515 	phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) |
516 		   PHY_BMCR_RESET);
517 	/* PHY and MAC connect */
518 	phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) &
519 		   ~PHY_BMCR_ISO);
520 
521 	phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
522 
523 	config_genmii_advert (mii_info);
524 	/* Start/restart aneg */
525 	genmii_config_aneg (mii_info);
526 
527 	return 0;
528 }
529 
530 static int dm9161_config_aneg (struct uec_mii_info *mii_info)
531 {
532 	return 0;
533 }
534 
535 static int dm9161_read_status (struct uec_mii_info *mii_info)
536 {
537 	u16 status;
538 	int err;
539 
540 	/* Update the link, but return if there was an error */
541 	err = genmii_update_link (mii_info);
542 	if (err)
543 		return err;
544 	/* If the link is up, read the speed and duplex
545 	   If we aren't autonegotiating assume speeds are as set */
546 	if (mii_info->autoneg && mii_info->link) {
547 		status = phy_read (mii_info, MII_DM9161_SCSR);
548 		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
549 			mii_info->speed = SPEED_100;
550 		else
551 			mii_info->speed = SPEED_10;
552 
553 		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
554 			mii_info->duplex = DUPLEX_FULL;
555 		else
556 			mii_info->duplex = DUPLEX_HALF;
557 	}
558 
559 	return 0;
560 }
561 
562 static int dm9161_ack_interrupt (struct uec_mii_info *mii_info)
563 {
564 	/* Clear the interrupt by reading the reg */
565 	phy_read (mii_info, MII_DM9161_INTR);
566 
567 	return 0;
568 }
569 
570 static int dm9161_config_intr (struct uec_mii_info *mii_info)
571 {
572 	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
573 		phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
574 	else
575 		phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
576 
577 	return 0;
578 }
579 
580 static void dm9161_close (struct uec_mii_info *mii_info)
581 {
582 }
583 
584 static int fixed_phy_aneg (struct uec_mii_info *mii_info)
585 {
586 	mii_info->autoneg = 0; /* Turn off auto negotiation for fixed phy */
587 	return 0;
588 }
589 
590 static int fixed_phy_read_status (struct uec_mii_info *mii_info)
591 {
592 	int i = 0;
593 
594 	for (i = 0; i < ARRAY_SIZE(fixed_phy_port); i++) {
595 		if (mii_info->mii_id == fixed_phy_port[i].devnum) {
596 			mii_info->speed = fixed_phy_port[i].speed;
597 			mii_info->duplex = fixed_phy_port[i].duplex;
598 			mii_info->link = 1; /* Link is always UP */
599 			mii_info->pause = 0;
600 			break;
601 		}
602 	}
603 	return 0;
604 }
605 
606 static int smsc_config_aneg (struct uec_mii_info *mii_info)
607 {
608 	return 0;
609 }
610 
611 static int smsc_read_status (struct uec_mii_info *mii_info)
612 {
613 	u16 status;
614 	int err;
615 
616 	/* Update the link, but return if there
617 	 * was an error */
618 	err = genmii_update_link (mii_info);
619 	if (err)
620 		return err;
621 
622 	/* If the link is up, read the speed and duplex */
623 	/* If we aren't autonegotiating, assume speeds
624 	 * are as set */
625 	if (mii_info->autoneg && mii_info->link) {
626 		int	val;
627 
628 		status = phy_read (mii_info, 0x1f);
629 		val = (status & 0x1c) >> 2;
630 
631 		switch (val) {
632 			case 1:
633 				mii_info->duplex = DUPLEX_HALF;
634 				mii_info->speed = SPEED_10;
635 				break;
636 			case 5:
637 				mii_info->duplex = DUPLEX_FULL;
638 				mii_info->speed = SPEED_10;
639 				break;
640 			case 2:
641 				mii_info->duplex = DUPLEX_HALF;
642 				mii_info->speed = SPEED_100;
643 				break;
644 			case 6:
645 				mii_info->duplex = DUPLEX_FULL;
646 				mii_info->speed = SPEED_100;
647 				break;
648 		}
649 		mii_info->pause = 0;
650 	}
651 
652 	return 0;
653 }
654 
655 static struct phy_info phy_info_dm9161 = {
656 	.phy_id = 0x0181b880,
657 	.phy_id_mask = 0x0ffffff0,
658 	.name = "Davicom DM9161E",
659 	.init = dm9161_init,
660 	.config_aneg = dm9161_config_aneg,
661 	.read_status = dm9161_read_status,
662 	.close = dm9161_close,
663 };
664 
665 static struct phy_info phy_info_dm9161a = {
666 	.phy_id = 0x0181b8a0,
667 	.phy_id_mask = 0x0ffffff0,
668 	.name = "Davicom DM9161A",
669 	.features = MII_BASIC_FEATURES,
670 	.init = dm9161_init,
671 	.config_aneg = dm9161_config_aneg,
672 	.read_status = dm9161_read_status,
673 	.ack_interrupt = dm9161_ack_interrupt,
674 	.config_intr = dm9161_config_intr,
675 	.close = dm9161_close,
676 };
677 
678 static struct phy_info phy_info_marvell = {
679 	.phy_id = 0x01410c00,
680 	.phy_id_mask = 0xffffff00,
681 	.name = "Marvell 88E11x1",
682 	.features = MII_GBIT_FEATURES,
683 	.init = &marvell_init,
684 	.config_aneg = &marvell_config_aneg,
685 	.read_status = &marvell_read_status,
686 	.ack_interrupt = &marvell_ack_interrupt,
687 	.config_intr = &marvell_config_intr,
688 };
689 
690 static struct phy_info phy_info_bcm5481 = {
691 	.phy_id = 0x0143bca0,
692 	.phy_id_mask = 0xffffff0,
693 	.name = "Broadcom 5481",
694 	.features = MII_GBIT_FEATURES,
695 	.read_status = genmii_read_status,
696 	.init = bcm_init,
697 };
698 
699 static struct phy_info phy_info_fixedphy = {
700 	.phy_id = CONFIG_FIXED_PHY,
701 	.phy_id_mask = CONFIG_FIXED_PHY,
702 	.name = "Fixed PHY",
703 	.config_aneg = fixed_phy_aneg,
704 	.read_status = fixed_phy_read_status,
705 };
706 
707 static struct phy_info phy_info_smsclan8700 = {
708 	.phy_id = 0x0007c0c0,
709 	.phy_id_mask = 0xfffffff0,
710 	.name = "SMSC LAN8700",
711 	.features = MII_BASIC_FEATURES,
712 	.config_aneg = smsc_config_aneg,
713 	.read_status = smsc_read_status,
714 };
715 
716 static struct phy_info phy_info_genmii = {
717 	.phy_id = 0x00000000,
718 	.phy_id_mask = 0x00000000,
719 	.name = "Generic MII",
720 	.features = MII_BASIC_FEATURES,
721 	.config_aneg = genmii_config_aneg,
722 	.read_status = genmii_read_status,
723 };
724 
725 static struct phy_info *phy_info[] = {
726 	&phy_info_dm9161,
727 	&phy_info_dm9161a,
728 	&phy_info_marvell,
729 	&phy_info_bcm5481,
730 	&phy_info_smsclan8700,
731 	&phy_info_fixedphy,
732 	&phy_info_genmii,
733 	NULL
734 };
735 
736 u16 phy_read (struct uec_mii_info *mii_info, u16 regnum)
737 {
738 	return mii_info->mdio_read (mii_info->dev, mii_info->mii_id, regnum);
739 }
740 
741 void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val)
742 {
743 	mii_info->mdio_write (mii_info->dev, mii_info->mii_id, regnum, val);
744 }
745 
746 /* Use the PHY ID registers to determine what type of PHY is attached
747  * to device dev.  return a struct phy_info structure describing that PHY
748  */
749 struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
750 {
751 	u16 phy_reg;
752 	u32 phy_ID;
753 	int i;
754 	struct phy_info *theInfo = NULL;
755 
756 	/* Grab the bits from PHYIR1, and put them in the upper half */
757 	phy_reg = phy_read (mii_info, PHY_PHYIDR1);
758 	phy_ID = (phy_reg & 0xffff) << 16;
759 
760 	/* Grab the bits from PHYIR2, and put them in the lower half */
761 	phy_reg = phy_read (mii_info, PHY_PHYIDR2);
762 	phy_ID |= (phy_reg & 0xffff);
763 
764 	/* loop through all the known PHY types, and find one that */
765 	/* matches the ID we read from the PHY. */
766 	for (i = 0; phy_info[i]; i++)
767 		if (phy_info[i]->phy_id ==
768 		    (phy_ID & phy_info[i]->phy_id_mask)) {
769 			theInfo = phy_info[i];
770 			break;
771 		}
772 
773 	/* This shouldn't happen, as we have generic PHY support */
774 	if (theInfo == NULL) {
775 		ugphy_info ("UEC: PHY id %x is not supported!", phy_ID);
776 		return NULL;
777 	} else {
778 		ugphy_info ("UEC: PHY is %s (%x)", theInfo->name, phy_ID);
779 	}
780 
781 	return theInfo;
782 }
783 
784 void marvell_phy_interface_mode (struct eth_device *dev,
785 				 enet_interface_e mode)
786 {
787 	uec_private_t *uec = (uec_private_t *) dev->priv;
788 	struct uec_mii_info *mii_info;
789 	u16 status;
790 
791 	if (!uec->mii_info) {
792 		printf ("%s: the PHY not initialized\n", __FUNCTION__);
793 		return;
794 	}
795 	mii_info = uec->mii_info;
796 
797 	if (mode == ENET_100_RGMII) {
798 		phy_write (mii_info, 0x00, 0x9140);
799 		phy_write (mii_info, 0x1d, 0x001f);
800 		phy_write (mii_info, 0x1e, 0x200c);
801 		phy_write (mii_info, 0x1d, 0x0005);
802 		phy_write (mii_info, 0x1e, 0x0000);
803 		phy_write (mii_info, 0x1e, 0x0100);
804 		phy_write (mii_info, 0x09, 0x0e00);
805 		phy_write (mii_info, 0x04, 0x01e1);
806 		phy_write (mii_info, 0x00, 0x9140);
807 		phy_write (mii_info, 0x00, 0x1000);
808 		udelay (100000);
809 		phy_write (mii_info, 0x00, 0x2900);
810 		phy_write (mii_info, 0x14, 0x0cd2);
811 		phy_write (mii_info, 0x00, 0xa100);
812 		phy_write (mii_info, 0x09, 0x0000);
813 		phy_write (mii_info, 0x1b, 0x800b);
814 		phy_write (mii_info, 0x04, 0x05e1);
815 		phy_write (mii_info, 0x00, 0xa100);
816 		phy_write (mii_info, 0x00, 0x2100);
817 		udelay (1000000);
818 	} else if (mode == ENET_10_RGMII) {
819 		phy_write (mii_info, 0x14, 0x8e40);
820 		phy_write (mii_info, 0x1b, 0x800b);
821 		phy_write (mii_info, 0x14, 0x0c82);
822 		phy_write (mii_info, 0x00, 0x8100);
823 		udelay (1000000);
824 	}
825 
826 	/* handle 88e1111 rev.B2 erratum 5.6 */
827 	if (mii_info->autoneg) {
828 		status = phy_read (mii_info, PHY_BMCR);
829 		phy_write (mii_info, PHY_BMCR, status | PHY_BMCR_AUTON);
830 	}
831 	/* now the B2 will correctly report autoneg completion status */
832 }
833 
834 void change_phy_interface_mode (struct eth_device *dev, enet_interface_e mode)
835 {
836 #ifdef CONFIG_PHY_MODE_NEED_CHANGE
837 	marvell_phy_interface_mode (dev, mode);
838 #endif
839 }
840