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-10-29 13:50:25 -07:00
# define MII_88E1318S_PHY_MSCR1_REG 16
# define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6)
2010-08-03 19:36:06 -07:00
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 ;
2010-10-21 03:59:57 -07:00
if ( ( phydev - > interface = = PHY_INTERFACE_MODE_RGMII ) | |
( phydev - > interface = = PHY_INTERFACE_MODE_RGMII_ID ) | |
( phydev - > interface = = PHY_INTERFACE_MODE_RGMII_RXID ) | |
( phydev - > interface = = PHY_INTERFACE_MODE_RGMII_TXID ) ) {
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 ;
}
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 = 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-10-29 13:50:25 -07:00
static int m88e1318_config_aneg ( struct phy_device * phydev )
2010-08-03 19:36:06 -07: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 ;
2010-10-29 13:50:25 -07:00
mscr = phy_read ( phydev , MII_88E1318S_PHY_MSCR1_REG ) ;
mscr | = MII_88E1318S_PHY_MSCR1_PAD_ODD ;
2010-08-03 19:36:06 -07:00
2010-10-29 13:50:25 -07:00
err = phy_write ( phydev , MII_88E1318S_PHY_MSCR1_REG , mscr ) ;
2010-08-03 19:36:06 -07:00
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-10-29 13:50:25 -07:00
. phy_id = MARVELL_PHY_ID_88E1318S ,
2010-08-04 11:47:58 -07:00
. phy_id_mask = MARVELL_PHY_ID_MASK ,
2010-10-29 13:50:25 -07:00
. name = " Marvell 88E1318S " ,
2010-08-03 19:36:06 -07:00
. features = PHY_GBIT_FEATURES ,
. flags = PHY_HAS_INTERRUPT ,
2010-10-29 13:50:25 -07:00
. config_aneg = & m88e1318_config_aneg ,
2010-08-03 19:36:06 -07:00
. 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
2010-10-03 23:43:32 +00:00
static struct mdio_device_id __maybe_unused marvell_tbl [ ] = {
2010-04-02 01:05:56 +00:00
{ 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 ) ;