xref: /openbmc/u-boot/drivers/qe/uec_phy.c (revision e4430779)
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 struct phy_info phy_info_dm9161 = {
607 	.phy_id = 0x0181b880,
608 	.phy_id_mask = 0x0ffffff0,
609 	.name = "Davicom DM9161E",
610 	.init = dm9161_init,
611 	.config_aneg = dm9161_config_aneg,
612 	.read_status = dm9161_read_status,
613 	.close = dm9161_close,
614 };
615 
616 static struct phy_info phy_info_dm9161a = {
617 	.phy_id = 0x0181b8a0,
618 	.phy_id_mask = 0x0ffffff0,
619 	.name = "Davicom DM9161A",
620 	.features = MII_BASIC_FEATURES,
621 	.init = dm9161_init,
622 	.config_aneg = dm9161_config_aneg,
623 	.read_status = dm9161_read_status,
624 	.ack_interrupt = dm9161_ack_interrupt,
625 	.config_intr = dm9161_config_intr,
626 	.close = dm9161_close,
627 };
628 
629 static struct phy_info phy_info_marvell = {
630 	.phy_id = 0x01410c00,
631 	.phy_id_mask = 0xffffff00,
632 	.name = "Marvell 88E11x1",
633 	.features = MII_GBIT_FEATURES,
634 	.init = &marvell_init,
635 	.config_aneg = &marvell_config_aneg,
636 	.read_status = &marvell_read_status,
637 	.ack_interrupt = &marvell_ack_interrupt,
638 	.config_intr = &marvell_config_intr,
639 };
640 
641 static struct phy_info phy_info_bcm5481 = {
642 	.phy_id = 0x0143bca0,
643 	.phy_id_mask = 0xffffff0,
644 	.name = "Broadcom 5481",
645 	.features = MII_GBIT_FEATURES,
646 	.read_status = genmii_read_status,
647 	.init = bcm_init,
648 };
649 
650 static struct phy_info phy_info_fixedphy = {
651 	.phy_id = CONFIG_FIXED_PHY,
652 	.phy_id_mask = CONFIG_FIXED_PHY,
653 	.name = "Fixed PHY",
654 	.config_aneg = fixed_phy_aneg,
655 	.read_status = fixed_phy_read_status,
656 };
657 
658 static struct phy_info phy_info_genmii = {
659 	.phy_id = 0x00000000,
660 	.phy_id_mask = 0x00000000,
661 	.name = "Generic MII",
662 	.features = MII_BASIC_FEATURES,
663 	.config_aneg = genmii_config_aneg,
664 	.read_status = genmii_read_status,
665 };
666 
667 static struct phy_info *phy_info[] = {
668 	&phy_info_dm9161,
669 	&phy_info_dm9161a,
670 	&phy_info_marvell,
671 	&phy_info_bcm5481,
672 	&phy_info_fixedphy,
673 	&phy_info_genmii,
674 	NULL
675 };
676 
677 u16 phy_read (struct uec_mii_info *mii_info, u16 regnum)
678 {
679 	return mii_info->mdio_read (mii_info->dev, mii_info->mii_id, regnum);
680 }
681 
682 void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val)
683 {
684 	mii_info->mdio_write (mii_info->dev, mii_info->mii_id, regnum, val);
685 }
686 
687 /* Use the PHY ID registers to determine what type of PHY is attached
688  * to device dev.  return a struct phy_info structure describing that PHY
689  */
690 struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
691 {
692 	u16 phy_reg;
693 	u32 phy_ID;
694 	int i;
695 	struct phy_info *theInfo = NULL;
696 
697 	/* Grab the bits from PHYIR1, and put them in the upper half */
698 	phy_reg = phy_read (mii_info, PHY_PHYIDR1);
699 	phy_ID = (phy_reg & 0xffff) << 16;
700 
701 	/* Grab the bits from PHYIR2, and put them in the lower half */
702 	phy_reg = phy_read (mii_info, PHY_PHYIDR2);
703 	phy_ID |= (phy_reg & 0xffff);
704 
705 	/* loop through all the known PHY types, and find one that */
706 	/* matches the ID we read from the PHY. */
707 	for (i = 0; phy_info[i]; i++)
708 		if (phy_info[i]->phy_id ==
709 		    (phy_ID & phy_info[i]->phy_id_mask)) {
710 			theInfo = phy_info[i];
711 			break;
712 		}
713 
714 	/* This shouldn't happen, as we have generic PHY support */
715 	if (theInfo == NULL) {
716 		ugphy_info ("UEC: PHY id %x is not supported!", phy_ID);
717 		return NULL;
718 	} else {
719 		ugphy_info ("UEC: PHY is %s (%x)", theInfo->name, phy_ID);
720 	}
721 
722 	return theInfo;
723 }
724 
725 void marvell_phy_interface_mode (struct eth_device *dev,
726 				 enet_interface_e mode)
727 {
728 	uec_private_t *uec = (uec_private_t *) dev->priv;
729 	struct uec_mii_info *mii_info;
730 	u16 status;
731 
732 	if (!uec->mii_info) {
733 		printf ("%s: the PHY not initialized\n", __FUNCTION__);
734 		return;
735 	}
736 	mii_info = uec->mii_info;
737 
738 	if (mode == ENET_100_RGMII) {
739 		phy_write (mii_info, 0x00, 0x9140);
740 		phy_write (mii_info, 0x1d, 0x001f);
741 		phy_write (mii_info, 0x1e, 0x200c);
742 		phy_write (mii_info, 0x1d, 0x0005);
743 		phy_write (mii_info, 0x1e, 0x0000);
744 		phy_write (mii_info, 0x1e, 0x0100);
745 		phy_write (mii_info, 0x09, 0x0e00);
746 		phy_write (mii_info, 0x04, 0x01e1);
747 		phy_write (mii_info, 0x00, 0x9140);
748 		phy_write (mii_info, 0x00, 0x1000);
749 		udelay (100000);
750 		phy_write (mii_info, 0x00, 0x2900);
751 		phy_write (mii_info, 0x14, 0x0cd2);
752 		phy_write (mii_info, 0x00, 0xa100);
753 		phy_write (mii_info, 0x09, 0x0000);
754 		phy_write (mii_info, 0x1b, 0x800b);
755 		phy_write (mii_info, 0x04, 0x05e1);
756 		phy_write (mii_info, 0x00, 0xa100);
757 		phy_write (mii_info, 0x00, 0x2100);
758 		udelay (1000000);
759 	} else if (mode == ENET_10_RGMII) {
760 		phy_write (mii_info, 0x14, 0x8e40);
761 		phy_write (mii_info, 0x1b, 0x800b);
762 		phy_write (mii_info, 0x14, 0x0c82);
763 		phy_write (mii_info, 0x00, 0x8100);
764 		udelay (1000000);
765 	}
766 
767 	/* handle 88e1111 rev.B2 erratum 5.6 */
768 	if (mii_info->autoneg) {
769 		status = phy_read (mii_info, PHY_BMCR);
770 		phy_write (mii_info, PHY_BMCR, status | PHY_BMCR_AUTON);
771 	}
772 	/* now the B2 will correctly report autoneg completion status */
773 }
774 
775 void change_phy_interface_mode (struct eth_device *dev, enet_interface_e mode)
776 {
777 #ifdef CONFIG_PHY_MODE_NEED_CHANGE
778 	marvell_phy_interface_mode (dev, mode);
779 #endif
780 }
781