diff options
Diffstat (limited to 'drivers/net/phy')
| -rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
| -rw-r--r-- | drivers/net/phy/atheros.c | 45 | ||||
| -rw-r--r-- | drivers/net/phy/icplus.c | 94 | ||||
| -rw-r--r-- | drivers/net/phy/marvell.c | 48 | ||||
| -rw-r--r-- | drivers/net/phy/micrel.c | 113 | ||||
| -rw-r--r-- | drivers/net/phy/natsemi.c | 37 | ||||
| -rw-r--r-- | drivers/net/phy/phy.c | 26 | 
7 files changed, 335 insertions, 29 deletions
| diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index af5f4b848..695873eaa 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -35,6 +35,7 @@ COBJS-$(CONFIG_PHY_ATHEROS) += atheros.o  COBJS-$(CONFIG_PHY_BROADCOM) += broadcom.o  COBJS-$(CONFIG_PHY_DAVICOM) += davicom.o  COBJS-$(CONFIG_PHY_ET1011C) += et1011c.o +COBJS-$(CONFIG_PHY_ICPLUS) += icplus.o  COBJS-$(CONFIG_PHY_LXT) += lxt.o  COBJS-$(CONFIG_PHY_MARVELL) += marvell.o  COBJS-$(CONFIG_PHY_MICREL) += micrel.o diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index 9b3808bfa..09d487971 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -16,7 +16,7 @@   * Foundation, Inc., 59 Temple Place, Suite 330, Boston,   * MA 02111-1307 USA   * - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011, 2013 Freescale Semiconductor, Inc.   * author Andy Fleming   *   */ @@ -30,6 +30,27 @@ static int ar8021_config(struct phy_device *phydev)  	return 0;  } +static int ar8035_config(struct phy_device *phydev) +{ +	int regval; + +	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007); +	phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016); +	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007); +	regval = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); +	phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (regval|0x0018)); + +	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); +	regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); +	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100)); + +	genphy_config_aneg(phydev); + +	phy_reset(phydev); + +	return 0; +} +  static struct phy_driver AR8021_driver =  {  	.name = "AR8021",  	.uid = 0x4dd040, @@ -40,9 +61,31 @@ static struct phy_driver AR8021_driver =  {  	.shutdown = genphy_shutdown,  }; +static struct phy_driver AR8031_driver =  { +	.name = "AR8031", +	.uid = 0x4dd074, +	.mask = 0xfffff0, +	.features = PHY_GBIT_FEATURES, +	.config = genphy_config, +	.startup = genphy_startup, +	.shutdown = genphy_shutdown, +}; + +static struct phy_driver AR8035_driver =  { +	.name = "AR8035", +	.uid = 0x4dd072, +	.mask = 0x4fffff, +	.features = PHY_GBIT_FEATURES, +	.config = ar8035_config, +	.startup = genphy_startup, +	.shutdown = genphy_shutdown, +}; +  int phy_atheros_init(void)  {  	phy_register(&AR8021_driver); +	phy_register(&AR8031_driver); +	phy_register(&AR8035_driver);  	return 0;  } diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c new file mode 100644 index 000000000..dd5c59259 --- /dev/null +++ b/drivers/net/phy/icplus.c @@ -0,0 +1,94 @@ +/* + * ICPlus PHY drivers + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Copyright (c) 2007 Freescale Semiconductor, Inc. + * + */ +#include <phy.h> + +/* IP101A/G - IP1001 */ +#define IP10XX_SPEC_CTRL_STATUS         16      /* Spec. Control Register */ +#define IP1001_SPEC_CTRL_STATUS_2       20      /* IP1001 Spec. Control Reg 2 */ +#define IP1001_PHASE_SEL_MASK           3       /* IP1001 RX/TXPHASE_SEL */ +#define IP1001_APS_ON                   11      /* IP1001 APS Mode  bit */ +#define IP101A_G_APS_ON                 2       /* IP101A/G APS Mode bit */ +#define IP101A_G_IRQ_CONF_STATUS        0x11    /* Conf Info IRQ & Status Reg */ +#define IP101A_G_IRQ_PIN_USED           (1<<15) /* INTR pin used */ +#define IP101A_G_IRQ_DEFAULT            IP101A_G_IRQ_PIN_USED + +static int ip1001_config(struct phy_device *phydev) +{ +	int c; + +	/* Enable Auto Power Saving mode */ +	c = phy_read(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2); +	if (c < 0) +		return c; +	c |= IP1001_APS_ON; +	c = phy_write(phydev, MDIO_DEVAD_NONE, IP1001_SPEC_CTRL_STATUS_2, c); +	if (c < 0) +		return c; + +	/* INTR pin used: speed/link/duplex will cause an interrupt */ +	c = phy_write(phydev, MDIO_DEVAD_NONE, IP101A_G_IRQ_CONF_STATUS, +		      IP101A_G_IRQ_DEFAULT); +	if (c < 0) +		return c; + +	if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { +		/* +		 * Additional delay (2ns) used to adjust RX clock phase +		 * at RGMII interface +		 */ +		c = phy_read(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS); +		if (c < 0) +			return c; + +		c |= IP1001_PHASE_SEL_MASK; +		c = phy_write(phydev, MDIO_DEVAD_NONE, IP10XX_SPEC_CTRL_STATUS, +			      c); +		if (c < 0) +			return c; +	} + +	return 0; +} + +static int ip1001_startup(struct phy_device *phydev) +{ +	genphy_update_link(phydev); +	genphy_parse_link(phydev); + +	return 0; +} +static struct phy_driver IP1001_driver = { +	.name = "ICPlus IP1001", +	.uid = 0x02430d90, +	.mask = 0x0ffffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &ip1001_config, +	.startup = &ip1001_startup, +	.shutdown = &genphy_shutdown, +}; + +int phy_icplus_init(void) +{ +	phy_register(&IP1001_driver); + +	return 0; +} diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 46801c791..8397e32e1 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -89,6 +89,12 @@  #define MIIM_88E1149_PHY_PAGE	29 +/* 88E1310 PHY defines */ +#define MIIM_88E1310_PHY_LED_CTRL	16 +#define MIIM_88E1310_PHY_IRQ_EN		18 +#define MIIM_88E1310_PHY_RGMII_CTRL	21 +#define MIIM_88E1310_PHY_PAGE		22 +  /* Marvell 88E1011S */  static int m88e1011s_config(struct phy_device *phydev)  { @@ -394,6 +400,37 @@ static int m88e1149_config(struct phy_device *phydev)  	return 0;  } +/* Marvell 88E1310 */ +static int m88e1310_config(struct phy_device *phydev) +{ +	u16 reg; + +	/* LED link and activity */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); +	reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL); +	reg = (reg & ~0xf) | 0x1; +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL, reg); + +	/* Set LED2/INT to INT mode, low active */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); +	reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN); +	reg = (reg & 0x77ff) | 0x0880; +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN, reg); + +	/* Set RGMII delay */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0002); +	reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL); +	reg |= 0x0030; +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL, reg); + +	/* Ensure to return to page 0 */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000); + +	genphy_config_aneg(phydev); +	phy_reset(phydev); + +	return 0; +}  static struct phy_driver M88E1011S_driver = {  	.name = "Marvell 88E1011S", @@ -475,8 +512,19 @@ static struct phy_driver M88E1518_driver = {  	.shutdown = &genphy_shutdown,  }; +static struct phy_driver M88E1310_driver = { +	.name = "Marvell 88E1310", +	.uid = 0x01410e90, +	.mask = 0xffffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &m88e1310_config, +	.startup = &m88e1011s_startup, +	.shutdown = &genphy_shutdown, +}; +  int phy_marvell_init(void)  { +	phy_register(&M88E1310_driver);  	phy_register(&M88E1149S_driver);  	phy_register(&M88E1145_driver);  	phy_register(&M88E1121R_driver); diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 30f326489..aa9cbcfff 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -18,6 +18,7 @@   *   * Copyright 2010-2011 Freescale Semiconductor, Inc.   * author Andy Fleming + * (C) 2012 NetModule AG, David Andrey, added KSZ9031   *   */  #include <config.h> @@ -52,16 +53,46 @@ static struct phy_driver KS8721_driver = {  };  #endif + +/** + * KSZ9021 - KSZ9031 common + */ + +#define MII_KSZ90xx_PHY_CTL		0x1f +#define MIIM_KSZ90xx_PHYCTL_1000	(1 << 6) +#define MIIM_KSZ90xx_PHYCTL_100		(1 << 5) +#define MIIM_KSZ90xx_PHYCTL_10		(1 << 4) +#define MIIM_KSZ90xx_PHYCTL_DUPLEX	(1 << 3) + +static int ksz90xx_startup(struct phy_device *phydev) +{ +	unsigned phy_ctl; +	genphy_update_link(phydev); +	phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL); + +	if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX) +		phydev->duplex = DUPLEX_FULL; +	else +		phydev->duplex = DUPLEX_HALF; + +	if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000) +		phydev->speed = SPEED_1000; +	else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100) +		phydev->speed = SPEED_100; +	else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10) +		phydev->speed = SPEED_10; +	return 0; +}  #ifdef CONFIG_PHY_MICREL_KSZ9021 -/* ksz9021 PHY Registers */ + +/* + * KSZ9021 + */ + +/* PHY Registers */  #define MII_KSZ9021_EXTENDED_CTRL	0x0b  #define MII_KSZ9021_EXTENDED_DATAW	0x0c  #define MII_KSZ9021_EXTENDED_DATAR	0x0d -#define MII_KSZ9021_PHY_CTL		0x1f -#define MIIM_KSZ9021_PHYCTL_1000	(1 << 6) -#define MIIM_KSZ9021_PHYCTL_100		(1 << 5) -#define MIIM_KSZ9021_PHYCTL_10		(1 << 4) -#define MIIM_KSZ9021_PHYCTL_DUPLEX	(1 << 3)  #define CTRL1000_PREFER_MASTER		(1 << 10)  #define CTRL1000_CONFIG_MASTER		(1 << 11) @@ -106,37 +137,64 @@ static int ksz9021_config(struct phy_device *phydev)  	return 0;  } -static int ksz9021_startup(struct phy_device *phydev) -{ -	unsigned phy_ctl; -	genphy_update_link(phydev); -	phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_PHY_CTL); - -	if (phy_ctl & MIIM_KSZ9021_PHYCTL_DUPLEX) -		phydev->duplex = DUPLEX_FULL; -	else -		phydev->duplex = DUPLEX_HALF; - -	if (phy_ctl & MIIM_KSZ9021_PHYCTL_1000) -		phydev->speed = SPEED_1000; -	else if (phy_ctl & MIIM_KSZ9021_PHYCTL_100) -		phydev->speed = SPEED_100; -	else if (phy_ctl & MIIM_KSZ9021_PHYCTL_10) -		phydev->speed = SPEED_10; -	return 0; -} -  static struct phy_driver ksz9021_driver = {  	.name = "Micrel ksz9021",  	.uid  = 0x221610,  	.mask = 0xfffff0,  	.features = PHY_GBIT_FEATURES,  	.config = &ksz9021_config, -	.startup = &ksz9021_startup, +	.startup = &ksz90xx_startup,  	.shutdown = &genphy_shutdown,  };  #endif +/** + * KSZ9031 + */ +/* PHY Registers */ +#define MII_KSZ9031_MMD_ACCES_CTRL	0x0d +#define MII_KSZ9031_MMD_REG_DATA	0x0e + +/* Accessors to extended registers*/ +int ksz9031_phy_extended_write(struct phy_device *phydev, +			       int devaddr, int regnum, u16 mode, u16 val) +{ +	/*select register addr for mmd*/ +	phy_write(phydev, MDIO_DEVAD_NONE, +		  MII_KSZ9031_MMD_ACCES_CTRL, devaddr); +	/*select register for mmd*/ +	phy_write(phydev, MDIO_DEVAD_NONE, +		  MII_KSZ9031_MMD_REG_DATA, regnum); +	/*setup mode*/ +	phy_write(phydev, MDIO_DEVAD_NONE, +		  MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr)); +	/*write the value*/ +	return	phy_write(phydev, MDIO_DEVAD_NONE, +		MII_KSZ9031_MMD_REG_DATA, val); +} + +int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr, +			      int regnum, u16 mode) +{ +	phy_write(phydev, MDIO_DEVAD_NONE, +		  MII_KSZ9031_MMD_ACCES_CTRL, devaddr); +	phy_write(phydev, MDIO_DEVAD_NONE, +		  MII_KSZ9031_MMD_REG_DATA, regnum); +	phy_write(phydev, MDIO_DEVAD_NONE, +		  MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode)); +	return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA); +} + +static struct phy_driver ksz9031_driver = { +	.name = "Micrel ksz9031", +	.uid  = 0x221620, +	.mask = 0xfffffe, +	.features = PHY_GBIT_FEATURES, +	.config   = &genphy_config, +	.startup  = &ksz90xx_startup, +	.shutdown = &genphy_shutdown, +}; +  int phy_micrel_init(void)  {  	phy_register(&KSZ804_driver); @@ -145,5 +203,6 @@ int phy_micrel_init(void)  #else  	phy_register(&KS8721_driver);  #endif +	phy_register(&ksz9031_driver);  	return 0;  } diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c index ea60ac1b0..6dc7ed505 100644 --- a/drivers/net/phy/natsemi.c +++ b/drivers/net/phy/natsemi.c @@ -22,6 +22,42 @@   */  #include <phy.h> +/* NatSemi DP83630 */ + +#define DP83630_PHY_PAGESEL_REG		0x13 +#define DP83630_PHY_PTP_COC_REG		0x14 +#define DP83630_PHY_PTP_CLKOUT_EN	(1<<15) +#define DP83630_PHY_RBR_REG		0x17 + +static int dp83630_config(struct phy_device *phydev) +{ +	int ptp_coc_reg; + +	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); +	phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PAGESEL_REG, 0x6); +	ptp_coc_reg = phy_read(phydev, MDIO_DEVAD_NONE, +			       DP83630_PHY_PTP_COC_REG); +	ptp_coc_reg &= ~DP83630_PHY_PTP_CLKOUT_EN; +	phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PTP_COC_REG, +		  ptp_coc_reg); +	phy_write(phydev, MDIO_DEVAD_NONE, DP83630_PHY_PAGESEL_REG, 0); + +	genphy_config_aneg(phydev); + +	return 0; +} + +static struct phy_driver DP83630_driver = { +	.name = "NatSemi DP83630", +	.uid = 0x20005ce1, +	.mask = 0xfffffff0, +	.features = PHY_BASIC_FEATURES, +	.config = &dp83630_config, +	.startup = &genphy_startup, +	.shutdown = &genphy_shutdown, +}; + +  /* DP83865 Link and Auto-Neg Status Register */  #define MIIM_DP83865_LANR      0x11  #define MIIM_DP83865_SPD_MASK  0x0018 @@ -90,6 +126,7 @@ static struct phy_driver DP83865_driver = {  int phy_natsemi_init(void)  { +	phy_register(&DP83630_driver);  	phy_register(&DP83865_driver);  	return 0; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index f8c548147..7c0eaec51 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -75,6 +75,10 @@ static int genphy_config_advert(struct phy_device *phydev)  		adv |= ADVERTISE_PAUSE_CAP;  	if (advertise & ADVERTISED_Asym_Pause)  		adv |= ADVERTISE_PAUSE_ASYM; +	if (advertise & ADVERTISED_1000baseX_Half) +		adv |= ADVERTISE_1000XHALF; +	if (advertise & ADVERTISED_1000baseX_Full) +		adv |= ADVERTISE_1000XFULL;  	if (adv != oldadv) {  		err = phy_write(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE, adv); @@ -280,7 +284,7 @@ int genphy_update_link(struct phy_device *phydev)   *   * Stolen from Linux's mii.c and phy_device.c   */ -static int genphy_parse_link(struct phy_device *phydev) +int genphy_parse_link(struct phy_device *phydev)  {  	int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); @@ -288,6 +292,7 @@ static int genphy_parse_link(struct phy_device *phydev)  	if (mii_reg & BMSR_ANEGCAPABLE) {  		u32 lpa = 0;  		u32 gblpa = 0; +		u32 estatus = 0;  		/* Check for gigabit capability */  		if (mii_reg & BMSR_ERCAP) { @@ -327,6 +332,18 @@ static int genphy_parse_link(struct phy_device *phydev)  		} else if (lpa & LPA_10FULL)  			phydev->duplex = DUPLEX_FULL; + +		if (mii_reg & BMSR_ESTATEN) +			estatus = phy_read(phydev, MDIO_DEVAD_NONE, +					   MII_ESTATUS); + +		if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_XHALF | +				ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) { +			phydev->speed = SPEED_1000; +			if (estatus & (ESTATUS_1000_XFULL | ESTATUS_1000_TFULL)) +				phydev->duplex = DUPLEX_FULL; +		} +  	} else {  		u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); @@ -384,6 +401,10 @@ int genphy_config(struct phy_device *phydev)  			features |= SUPPORTED_1000baseT_Full;  		if (val & ESTATUS_1000_THALF)  			features |= SUPPORTED_1000baseT_Half; +		if (val & ESTATUS_1000_XFULL) +			features |= SUPPORTED_1000baseX_Full; +		if (val & ESTATUS_1000_XHALF) +			features |= SUPPORTED_1000baseX_Full;  	}  	phydev->supported = features; @@ -433,6 +454,9 @@ int phy_init(void)  #ifdef CONFIG_PHY_ET1011C  	phy_et1011c_init();  #endif +#ifdef CONFIG_PHY_ICPLUS +	phy_icplus_init(); +#endif  #ifdef CONFIG_PHY_LXT  	phy_lxt_init();  #endif |