| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * drivers/net/phy/marvell.c | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Driver for Marvell PHYs | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Author: Andy Fleming | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2004 Freescale Semiconductor, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute  it and/or modify it | 
					
						
							|  |  |  |  * under  the terms of  the GNU General  Public License as published by the | 
					
						
							|  |  |  |  * Free Software Foundation;  either version 2 of the  License, or (at your | 
					
						
							|  |  |  |  * option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/string.h>
 | 
					
						
							|  |  |  | #include <linux/errno.h>
 | 
					
						
							|  |  |  | #include <linux/unistd.h>
 | 
					
						
							|  |  |  | #include <linux/interrupt.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/delay.h>
 | 
					
						
							|  |  |  | #include <linux/netdevice.h>
 | 
					
						
							|  |  |  | #include <linux/etherdevice.h>
 | 
					
						
							|  |  |  | #include <linux/skbuff.h>
 | 
					
						
							|  |  |  | #include <linux/spinlock.h>
 | 
					
						
							|  |  |  | #include <linux/mm.h>
 | 
					
						
							|  |  |  | #include <linux/module.h>
 | 
					
						
							|  |  |  | #include <linux/mii.h>
 | 
					
						
							|  |  |  | #include <linux/ethtool.h>
 | 
					
						
							|  |  |  | #include <linux/phy.h>
 | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | #include <linux/marvell_phy.h>
 | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <asm/io.h>
 | 
					
						
							|  |  |  | #include <asm/irq.h>
 | 
					
						
							|  |  |  | #include <asm/uaccess.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MII_M1011_IEVENT		0x13
 | 
					
						
							|  |  |  | #define MII_M1011_IEVENT_CLEAR		0x0000
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MII_M1011_IMASK			0x12
 | 
					
						
							|  |  |  | #define MII_M1011_IMASK_INIT		0x6400
 | 
					
						
							|  |  |  | #define MII_M1011_IMASK_CLEAR		0x0000
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | #define MII_M1011_PHY_SCR		0x10
 | 
					
						
							|  |  |  | #define MII_M1011_PHY_SCR_AUTO_CROSS	0x0060
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MII_M1145_PHY_EXT_CR		0x14
 | 
					
						
							|  |  |  | #define MII_M1145_RGMII_RX_DELAY	0x0080
 | 
					
						
							|  |  |  | #define MII_M1145_RGMII_TX_DELAY	0x0002
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MII_M1111_PHY_LED_CONTROL	0x18
 | 
					
						
							|  |  |  | #define MII_M1111_PHY_LED_DIRECT	0x4100
 | 
					
						
							|  |  |  | #define MII_M1111_PHY_LED_COMBINE	0x411c
 | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | #define MII_M1111_PHY_EXT_CR		0x14
 | 
					
						
							|  |  |  | #define MII_M1111_RX_DELAY		0x80
 | 
					
						
							|  |  |  | #define MII_M1111_TX_DELAY		0x2
 | 
					
						
							|  |  |  | #define MII_M1111_PHY_EXT_SR		0x1b
 | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define MII_M1111_HWCFG_MODE_MASK		0xf
 | 
					
						
							|  |  |  | #define MII_M1111_HWCFG_MODE_COPPER_RGMII	0xb
 | 
					
						
							|  |  |  | #define MII_M1111_HWCFG_MODE_FIBER_RGMII	0x3
 | 
					
						
							| 
									
										
										
										
											2007-05-11 18:25:18 -05:00
										 |  |  | #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK	0x4
 | 
					
						
							| 
									
										
										
										
											2010-01-13 22:13:19 +00:00
										 |  |  | #define MII_M1111_HWCFG_MODE_COPPER_RTBI	0x9
 | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  | #define MII_M1111_HWCFG_FIBER_COPPER_AUTO	0x8000
 | 
					
						
							|  |  |  | #define MII_M1111_HWCFG_FIBER_COPPER_RES	0x2000
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MII_M1111_COPPER		0
 | 
					
						
							|  |  |  | #define MII_M1111_FIBER			1
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-02 09:44:53 +00:00
										 |  |  | #define MII_88E1121_PHY_MSCR_PAGE	2
 | 
					
						
							|  |  |  | #define MII_88E1121_PHY_MSCR_REG	21
 | 
					
						
							|  |  |  | #define MII_88E1121_PHY_MSCR_RX_DELAY	BIT(5)
 | 
					
						
							|  |  |  | #define MII_88E1121_PHY_MSCR_TX_DELAY	BIT(4)
 | 
					
						
							|  |  |  | #define MII_88E1121_PHY_MSCR_DELAY_MASK	(~(0x3 << 4))
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-03 19:36:06 -07:00
										 |  |  | #define MII_88EC048_PHY_MSCR1_REG	16
 | 
					
						
							|  |  |  | #define MII_88EC048_PHY_MSCR1_PAD_ODD	BIT(6)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:41 +00:00
										 |  |  | #define MII_88E1121_PHY_LED_CTRL	16
 | 
					
						
							|  |  |  | #define MII_88E1121_PHY_LED_PAGE	3
 | 
					
						
							|  |  |  | #define MII_88E1121_PHY_LED_DEF		0x0030
 | 
					
						
							|  |  |  | #define MII_88E1121_PHY_PAGE		22
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  | #define MII_M1011_PHY_STATUS		0x11
 | 
					
						
							|  |  |  | #define MII_M1011_PHY_STATUS_1000	0x8000
 | 
					
						
							|  |  |  | #define MII_M1011_PHY_STATUS_100	0x4000
 | 
					
						
							|  |  |  | #define MII_M1011_PHY_STATUS_SPD_MASK	0xc000
 | 
					
						
							|  |  |  | #define MII_M1011_PHY_STATUS_FULLDUPLEX	0x2000
 | 
					
						
							|  |  |  | #define MII_M1011_PHY_STATUS_RESOLVED	0x0800
 | 
					
						
							|  |  |  | #define MII_M1011_PHY_STATUS_LINK	0x0400
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | MODULE_DESCRIPTION("Marvell PHY driver"); | 
					
						
							|  |  |  | MODULE_AUTHOR("Andy Fleming"); | 
					
						
							|  |  |  | MODULE_LICENSE("GPL"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int marvell_ack_interrupt(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Clear the interrupts by reading the reg */ | 
					
						
							|  |  |  | 	err = phy_read(phydev, MII_M1011_IEVENT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int marvell_config_intr(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | 		err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int marvell_config_aneg(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* The Marvell PHY has an errata which requires
 | 
					
						
							|  |  |  | 	 * that certain registers get written in order | 
					
						
							|  |  |  | 	 * to restart autonegotiation */ | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_BMCR, BMCR_RESET); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x1d, 0x1f); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x1e, 0x200c); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x1d, 0x5); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x1e, 0); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x1e, 0x100); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | 	err = phy_write(phydev, MII_M1011_PHY_SCR, | 
					
						
							|  |  |  | 			MII_M1011_PHY_SCR_AUTO_CROSS); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, | 
					
						
							|  |  |  | 			MII_M1111_PHY_LED_DIRECT); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err = genphy_config_aneg(phydev); | 
					
						
							| 
									
										
										
										
											2009-09-09 16:01:30 +00:00
										 |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-09 16:01:30 +00:00
										 |  |  | 	if (phydev->autoneg != AUTONEG_ENABLE) { | 
					
						
							|  |  |  | 		int bmcr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * A write to speed/duplex bits (that is performed by | 
					
						
							|  |  |  | 		 * genphy_config_aneg() call above) must be followed by | 
					
						
							|  |  |  | 		 * a software reset. Otherwise, the write has no effect. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		bmcr = phy_read(phydev, MII_BMCR); | 
					
						
							|  |  |  | 		if (bmcr < 0) | 
					
						
							|  |  |  | 			return bmcr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = phy_write(phydev, MII_BMCR, bmcr | BMCR_RESET); | 
					
						
							|  |  |  | 		if (err < 0) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:41 +00:00
										 |  |  | static int m88e1121_config_aneg(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-02 09:44:53 +00:00
										 |  |  | 	int err, oldpage, mscr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_88E1121_PHY_PAGE, | 
					
						
							|  |  |  | 			MII_88E1121_PHY_MSCR_PAGE); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 	mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) & | 
					
						
							|  |  |  | 		MII_88E1121_PHY_MSCR_DELAY_MASK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) | 
					
						
							|  |  |  | 		mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY | | 
					
						
							|  |  |  | 			 MII_88E1121_PHY_MSCR_TX_DELAY); | 
					
						
							|  |  |  | 	else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) | 
					
						
							|  |  |  | 		mscr |= MII_88E1121_PHY_MSCR_RX_DELAY; | 
					
						
							|  |  |  | 	else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) | 
					
						
							|  |  |  | 		mscr |= MII_88E1121_PHY_MSCR_TX_DELAY; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_BMCR, BMCR_RESET); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_M1011_PHY_SCR, | 
					
						
							|  |  |  | 			MII_M1011_PHY_SCR_AUTO_CROSS); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-02 09:44:53 +00:00
										 |  |  | 	oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); | 
					
						
							|  |  |  | 	phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF); | 
					
						
							| 
									
										
										
										
											2010-08-02 09:44:53 +00:00
										 |  |  | 	phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	err = genphy_config_aneg(phydev); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-03 19:36:06 -07:00
										 |  |  | static int m88ec048_config_aneg(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int err, oldpage, mscr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_88E1121_PHY_PAGE, | 
					
						
							|  |  |  | 			MII_88E1121_PHY_MSCR_PAGE); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mscr = phy_read(phydev, MII_88EC048_PHY_MSCR1_REG); | 
					
						
							|  |  |  | 	mscr |= MII_88EC048_PHY_MSCR1_PAD_ODD; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return m88e1121_config_aneg(phydev); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | static int m88e1111_config_init(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int err; | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  | 	int temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Enable Fiber/Copper auto selection */ | 
					
						
							|  |  |  | 	temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); | 
					
						
							| 
									
										
										
										
											2008-07-16 21:46:17 +08:00
										 |  |  | 	temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO; | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  | 	phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	temp = phy_read(phydev, MII_BMCR); | 
					
						
							|  |  |  | 	temp |= BMCR_RESET; | 
					
						
							|  |  |  | 	phy_write(phydev, MII_BMCR, temp); | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || | 
					
						
							| 
									
										
										
										
											2007-11-26 16:17:52 -06:00
										 |  |  | 	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || | 
					
						
							|  |  |  | 	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || | 
					
						
							|  |  |  | 	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:17:52 -06:00
										 |  |  | 		temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); | 
					
						
							|  |  |  | 		if (temp < 0) | 
					
						
							|  |  |  | 			return temp; | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:17:52 -06:00
										 |  |  | 		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | 			temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:17:52 -06:00
										 |  |  | 		} else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { | 
					
						
							|  |  |  | 			temp &= ~MII_M1111_TX_DELAY; | 
					
						
							|  |  |  | 			temp |= MII_M1111_RX_DELAY; | 
					
						
							|  |  |  | 		} else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { | 
					
						
							|  |  |  | 			temp &= ~MII_M1111_RX_DELAY; | 
					
						
							|  |  |  | 			temp |= MII_M1111_TX_DELAY; | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:17:52 -06:00
										 |  |  | 		err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); | 
					
						
							|  |  |  | 		if (err < 0) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | 		temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); | 
					
						
							|  |  |  | 		if (temp < 0) | 
					
						
							|  |  |  | 			return temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		temp &= ~(MII_M1111_HWCFG_MODE_MASK); | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-16 21:46:20 +08:00
										 |  |  | 		if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES) | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  | 			temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII; | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); | 
					
						
							|  |  |  | 		if (err < 0) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-05-11 18:25:18 -05:00
										 |  |  | 	if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { | 
					
						
							|  |  |  | 		temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); | 
					
						
							|  |  |  | 		if (temp < 0) | 
					
						
							|  |  |  | 			return temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		temp &= ~(MII_M1111_HWCFG_MODE_MASK); | 
					
						
							|  |  |  | 		temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; | 
					
						
							| 
									
										
										
										
											2009-06-02 04:04:13 +00:00
										 |  |  | 		temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO; | 
					
						
							| 
									
										
										
										
											2007-05-11 18:25:18 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); | 
					
						
							|  |  |  | 		if (err < 0) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-13 22:13:19 +00:00
										 |  |  | 	if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { | 
					
						
							|  |  |  | 		temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); | 
					
						
							|  |  |  | 		if (temp < 0) | 
					
						
							|  |  |  | 			return temp; | 
					
						
							|  |  |  | 		temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); | 
					
						
							|  |  |  | 		err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); | 
					
						
							|  |  |  | 		if (err < 0) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); | 
					
						
							|  |  |  | 		if (temp < 0) | 
					
						
							|  |  |  | 			return temp; | 
					
						
							|  |  |  | 		temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); | 
					
						
							|  |  |  | 		temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO; | 
					
						
							|  |  |  | 		err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); | 
					
						
							|  |  |  | 		if (err < 0) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* soft reset */ | 
					
						
							|  |  |  | 		err = phy_write(phydev, MII_BMCR, BMCR_RESET); | 
					
						
							|  |  |  | 		if (err < 0) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 		do | 
					
						
							|  |  |  | 			temp = phy_read(phydev, MII_BMCR); | 
					
						
							|  |  |  | 		while (temp & BMCR_RESET); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); | 
					
						
							|  |  |  | 		if (temp < 0) | 
					
						
							|  |  |  | 			return temp; | 
					
						
							|  |  |  | 		temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); | 
					
						
							|  |  |  | 		temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO; | 
					
						
							|  |  |  | 		err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); | 
					
						
							|  |  |  | 		if (err < 0) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | 	err = phy_write(phydev, MII_BMCR, BMCR_RESET); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-06 09:05:26 +00:00
										 |  |  | static int m88e1118_config_aneg(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_BMCR, BMCR_RESET); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_M1011_PHY_SCR, | 
					
						
							|  |  |  | 			MII_M1011_PHY_SCR_AUTO_CROSS); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = genphy_config_aneg(phydev); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int m88e1118_config_init(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Change address */ | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x16, 0x0002); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Enable 1000 Mbit */ | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x15, 0x1070); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Change address */ | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x16, 0x0003); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Adjust LED Control */ | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | 	if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS) | 
					
						
							|  |  |  | 		err = phy_write(phydev, 0x10, 0x1100); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		err = phy_write(phydev, 0x10, 0x021e); | 
					
						
							| 
									
										
										
										
											2008-11-06 09:05:26 +00:00
										 |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Reset address */ | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x16, 0x0); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, MII_BMCR, BMCR_RESET); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | static int m88e1145_config_init(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Take care of errata E0 & E1 */ | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x1d, 0x001b); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x1e, 0x418f); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x1d, 0x0016); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = phy_write(phydev, 0x1e, 0xa2da); | 
					
						
							|  |  |  | 	if (err < 0) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-05 18:46:47 +08:00
										 |  |  | 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | 		int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); | 
					
						
							|  |  |  | 		if (temp < 0) | 
					
						
							|  |  |  | 			return temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); | 
					
						
							|  |  |  | 		if (err < 0) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | 		if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) { | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | 			err = phy_write(phydev, 0x1d, 0x0012); | 
					
						
							|  |  |  | 			if (err < 0) | 
					
						
							|  |  |  | 				return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			temp = phy_read(phydev, 0x1e); | 
					
						
							|  |  |  | 			if (temp < 0) | 
					
						
							|  |  |  | 				return temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			temp &= 0xf03f; | 
					
						
							|  |  |  | 			temp |= 2 << 9;	/* 36 ohm */ | 
					
						
							|  |  |  | 			temp |= 2 << 6;	/* 39 ohm */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			err = phy_write(phydev, 0x1e, temp); | 
					
						
							|  |  |  | 			if (err < 0) | 
					
						
							|  |  |  | 				return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			err = phy_write(phydev, 0x1d, 0x3); | 
					
						
							|  |  |  | 			if (err < 0) | 
					
						
							|  |  |  | 				return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			err = phy_write(phydev, 0x1e, 0x8000); | 
					
						
							|  |  |  | 			if (err < 0) | 
					
						
							|  |  |  | 				return err; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  | /* marvell_read_status
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Generic status code does not detect Fiber correctly! | 
					
						
							| 
									
										
										
										
											2008-03-25 23:53:24 -04:00
										 |  |  |  * Description: | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  |  *   Check the link, then figure out the current state | 
					
						
							|  |  |  |  *   by comparing what we advertise with what the link partner | 
					
						
							|  |  |  |  *   advertises.  Start by checking the gigabit possibilities, | 
					
						
							|  |  |  |  *   then move on to 10/100. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int marvell_read_status(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int adv; | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 	int lpa; | 
					
						
							|  |  |  | 	int status = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Update the link, but return if there
 | 
					
						
							|  |  |  | 	 * was an error */ | 
					
						
							|  |  |  | 	err = genphy_update_link(phydev); | 
					
						
							|  |  |  | 	if (err) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (AUTONEG_ENABLE == phydev->autoneg) { | 
					
						
							|  |  |  | 		status = phy_read(phydev, MII_M1011_PHY_STATUS); | 
					
						
							|  |  |  | 		if (status < 0) | 
					
						
							|  |  |  | 			return status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		lpa = phy_read(phydev, MII_LPA); | 
					
						
							|  |  |  | 		if (lpa < 0) | 
					
						
							|  |  |  | 			return lpa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		adv = phy_read(phydev, MII_ADVERTISE); | 
					
						
							|  |  |  | 		if (adv < 0) | 
					
						
							|  |  |  | 			return adv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		lpa &= adv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) | 
					
						
							|  |  |  | 			phydev->duplex = DUPLEX_FULL; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			phydev->duplex = DUPLEX_HALF; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		status = status & MII_M1011_PHY_STATUS_SPD_MASK; | 
					
						
							|  |  |  | 		phydev->pause = phydev->asym_pause = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch (status) { | 
					
						
							|  |  |  | 		case MII_M1011_PHY_STATUS_1000: | 
					
						
							|  |  |  | 			phydev->speed = SPEED_1000; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case MII_M1011_PHY_STATUS_100: | 
					
						
							|  |  |  | 			phydev->speed = SPEED_100; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			phydev->speed = SPEED_10; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (phydev->duplex == DUPLEX_FULL) { | 
					
						
							|  |  |  | 			phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; | 
					
						
							|  |  |  | 			phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		int bmcr = phy_read(phydev, MII_BMCR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (bmcr < 0) | 
					
						
							|  |  |  | 			return bmcr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (bmcr & BMCR_FULLDPLX) | 
					
						
							|  |  |  | 			phydev->duplex = DUPLEX_FULL; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			phydev->duplex = DUPLEX_HALF; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (bmcr & BMCR_SPEED1000) | 
					
						
							|  |  |  | 			phydev->speed = SPEED_1000; | 
					
						
							|  |  |  | 		else if (bmcr & BMCR_SPEED100) | 
					
						
							|  |  |  | 			phydev->speed = SPEED_100; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			phydev->speed = SPEED_10; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		phydev->pause = phydev->asym_pause = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:43 +00:00
										 |  |  | static int m88e1121_did_interrupt(struct phy_device *phydev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int imask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	imask = phy_read(phydev, MII_M1011_IEVENT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (imask & MII_M1011_IMASK_INIT) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | static struct phy_driver marvell_drivers[] = { | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | 		.phy_id = MARVELL_PHY_ID_88E1101, | 
					
						
							|  |  |  | 		.phy_id_mask = MARVELL_PHY_ID_MASK, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 		.name = "Marvell 88E1101", | 
					
						
							|  |  |  | 		.features = PHY_GBIT_FEATURES, | 
					
						
							|  |  |  | 		.flags = PHY_HAS_INTERRUPT, | 
					
						
							|  |  |  | 		.config_aneg = &marvell_config_aneg, | 
					
						
							|  |  |  | 		.read_status = &genphy_read_status, | 
					
						
							|  |  |  | 		.ack_interrupt = &marvell_ack_interrupt, | 
					
						
							|  |  |  | 		.config_intr = &marvell_config_intr, | 
					
						
							| 
									
										
										
										
											2007-11-04 16:08:51 -06:00
										 |  |  | 		.driver = { .owner = THIS_MODULE }, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:24:32 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | 		.phy_id = MARVELL_PHY_ID_88E1112, | 
					
						
							|  |  |  | 		.phy_id_mask = MARVELL_PHY_ID_MASK, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:24:32 -05:00
										 |  |  | 		.name = "Marvell 88E1112", | 
					
						
							|  |  |  | 		.features = PHY_GBIT_FEATURES, | 
					
						
							|  |  |  | 		.flags = PHY_HAS_INTERRUPT, | 
					
						
							|  |  |  | 		.config_init = &m88e1111_config_init, | 
					
						
							|  |  |  | 		.config_aneg = &marvell_config_aneg, | 
					
						
							|  |  |  | 		.read_status = &genphy_read_status, | 
					
						
							|  |  |  | 		.ack_interrupt = &marvell_ack_interrupt, | 
					
						
							|  |  |  | 		.config_intr = &marvell_config_intr, | 
					
						
							| 
									
										
										
										
											2007-11-04 16:08:51 -06:00
										 |  |  | 		.driver = { .owner = THIS_MODULE }, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:24:32 -05:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | 		.phy_id = MARVELL_PHY_ID_88E1111, | 
					
						
							|  |  |  | 		.phy_id_mask = MARVELL_PHY_ID_MASK, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 		.name = "Marvell 88E1111", | 
					
						
							|  |  |  | 		.features = PHY_GBIT_FEATURES, | 
					
						
							|  |  |  | 		.flags = PHY_HAS_INTERRUPT, | 
					
						
							|  |  |  | 		.config_init = &m88e1111_config_init, | 
					
						
							|  |  |  | 		.config_aneg = &marvell_config_aneg, | 
					
						
							| 
									
										
										
										
											2008-03-19 00:37:24 +03:00
										 |  |  | 		.read_status = &marvell_read_status, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 		.ack_interrupt = &marvell_ack_interrupt, | 
					
						
							|  |  |  | 		.config_intr = &marvell_config_intr, | 
					
						
							| 
									
										
										
										
											2007-11-04 16:08:51 -06:00
										 |  |  | 		.driver = { .owner = THIS_MODULE }, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2008-11-06 09:05:26 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | 		.phy_id = MARVELL_PHY_ID_88E1118, | 
					
						
							|  |  |  | 		.phy_id_mask = MARVELL_PHY_ID_MASK, | 
					
						
							| 
									
										
										
										
											2008-11-06 09:05:26 +00:00
										 |  |  | 		.name = "Marvell 88E1118", | 
					
						
							|  |  |  | 		.features = PHY_GBIT_FEATURES, | 
					
						
							|  |  |  | 		.flags = PHY_HAS_INTERRUPT, | 
					
						
							|  |  |  | 		.config_init = &m88e1118_config_init, | 
					
						
							|  |  |  | 		.config_aneg = &m88e1118_config_aneg, | 
					
						
							|  |  |  | 		.read_status = &genphy_read_status, | 
					
						
							|  |  |  | 		.ack_interrupt = &marvell_ack_interrupt, | 
					
						
							|  |  |  | 		.config_intr = &marvell_config_intr, | 
					
						
							|  |  |  | 		.driver = {.owner = THIS_MODULE,}, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:41 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | 		.phy_id = MARVELL_PHY_ID_88E1121R, | 
					
						
							|  |  |  | 		.phy_id_mask = MARVELL_PHY_ID_MASK, | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:41 +00:00
										 |  |  | 		.name = "Marvell 88E1121R", | 
					
						
							|  |  |  | 		.features = PHY_GBIT_FEATURES, | 
					
						
							|  |  |  | 		.flags = PHY_HAS_INTERRUPT, | 
					
						
							|  |  |  | 		.config_aneg = &m88e1121_config_aneg, | 
					
						
							|  |  |  | 		.read_status = &marvell_read_status, | 
					
						
							|  |  |  | 		.ack_interrupt = &marvell_ack_interrupt, | 
					
						
							|  |  |  | 		.config_intr = &marvell_config_intr, | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:43 +00:00
										 |  |  | 		.did_interrupt = &m88e1121_did_interrupt, | 
					
						
							| 
									
										
										
										
											2009-04-07 02:01:41 +00:00
										 |  |  | 		.driver = { .owner = THIS_MODULE }, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2010-08-03 19:36:06 -07:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-08-04 11:47:58 -07:00
										 |  |  | 		.phy_id = MARVELL_PHY_ID_88EC048, | 
					
						
							|  |  |  | 		.phy_id_mask = MARVELL_PHY_ID_MASK, | 
					
						
							| 
									
										
										
										
											2010-08-03 19:36:06 -07:00
										 |  |  | 		.name = "Marvell 88EC048", | 
					
						
							|  |  |  | 		.features = PHY_GBIT_FEATURES, | 
					
						
							|  |  |  | 		.flags = PHY_HAS_INTERRUPT, | 
					
						
							|  |  |  | 		.config_aneg = &m88ec048_config_aneg, | 
					
						
							|  |  |  | 		.read_status = &marvell_read_status, | 
					
						
							|  |  |  | 		.ack_interrupt = &marvell_ack_interrupt, | 
					
						
							|  |  |  | 		.config_intr = &marvell_config_intr, | 
					
						
							|  |  |  | 		.did_interrupt = &m88e1121_did_interrupt, | 
					
						
							|  |  |  | 		.driver = { .owner = THIS_MODULE }, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | 		.phy_id = MARVELL_PHY_ID_88E1145, | 
					
						
							|  |  |  | 		.phy_id_mask = MARVELL_PHY_ID_MASK, | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 		.name = "Marvell 88E1145", | 
					
						
							|  |  |  | 		.features = PHY_GBIT_FEATURES, | 
					
						
							|  |  |  | 		.flags = PHY_HAS_INTERRUPT, | 
					
						
							|  |  |  | 		.config_init = &m88e1145_config_init, | 
					
						
							|  |  |  | 		.config_aneg = &marvell_config_aneg, | 
					
						
							|  |  |  | 		.read_status = &genphy_read_status, | 
					
						
							|  |  |  | 		.ack_interrupt = &marvell_ack_interrupt, | 
					
						
							|  |  |  | 		.config_intr = &marvell_config_intr, | 
					
						
							| 
									
										
										
										
											2007-11-04 16:08:51 -06:00
										 |  |  | 		.driver = { .owner = THIS_MODULE }, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-21 13:20:46 +10:00
										 |  |  | 		.phy_id = MARVELL_PHY_ID_88E1240, | 
					
						
							|  |  |  | 		.phy_id_mask = MARVELL_PHY_ID_MASK, | 
					
						
							| 
									
										
										
										
											2007-11-04 16:08:51 -06:00
										 |  |  | 		.name = "Marvell 88E1240", | 
					
						
							|  |  |  | 		.features = PHY_GBIT_FEATURES, | 
					
						
							|  |  |  | 		.flags = PHY_HAS_INTERRUPT, | 
					
						
							|  |  |  | 		.config_init = &m88e1111_config_init, | 
					
						
							|  |  |  | 		.config_aneg = &marvell_config_aneg, | 
					
						
							|  |  |  | 		.read_status = &genphy_read_status, | 
					
						
							|  |  |  | 		.ack_interrupt = &marvell_ack_interrupt, | 
					
						
							|  |  |  | 		.config_intr = &marvell_config_intr, | 
					
						
							|  |  |  | 		.driver = { .owner = THIS_MODULE }, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int __init marvell_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | 	int ret; | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 	for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) { | 
					
						
							|  |  |  | 		ret = phy_driver_register(&marvell_drivers[i]); | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 		if (ret) { | 
					
						
							|  |  |  | 			while (i-- > 0) | 
					
						
							|  |  |  | 				phy_driver_unregister(&marvell_drivers[i]); | 
					
						
							|  |  |  | 			return ret; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-02-09 18:13:58 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void __exit marvell_exit(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-07-03 16:23:46 -05:00
										 |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) | 
					
						
							|  |  |  | 		phy_driver_unregister(&marvell_drivers[i]); | 
					
						
							| 
									
										
										
										
											2005-07-30 19:31:23 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module_init(marvell_init); | 
					
						
							|  |  |  | module_exit(marvell_exit); | 
					
						
							| 
									
										
										
										
											2010-04-02 01:05:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct mdio_device_id marvell_tbl[] = { | 
					
						
							|  |  |  | 	{ 0x01410c60, 0xfffffff0 }, | 
					
						
							|  |  |  | 	{ 0x01410c90, 0xfffffff0 }, | 
					
						
							|  |  |  | 	{ 0x01410cc0, 0xfffffff0 }, | 
					
						
							|  |  |  | 	{ 0x01410e10, 0xfffffff0 }, | 
					
						
							|  |  |  | 	{ 0x01410cb0, 0xfffffff0 }, | 
					
						
							|  |  |  | 	{ 0x01410cd0, 0xfffffff0 }, | 
					
						
							|  |  |  | 	{ 0x01410e30, 0xfffffff0 }, | 
					
						
							| 
									
										
										
										
											2010-08-03 19:36:06 -07:00
										 |  |  | 	{ 0x01410e90, 0xfffffff0 }, | 
					
						
							| 
									
										
										
										
											2010-04-02 01:05:56 +00:00
										 |  |  | 	{ } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MODULE_DEVICE_TABLE(mdio, marvell_tbl); |