diff options
Diffstat (limited to 'drivers/net/phy/vitesse.c')
| -rw-r--r-- | drivers/net/phy/vitesse.c | 242 | 
1 files changed, 242 insertions, 0 deletions
| diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c new file mode 100644 index 000000000..d48d4fe73 --- /dev/null +++ b/drivers/net/phy/vitesse.c @@ -0,0 +1,242 @@ +/* + * Vitesse 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 2010-2011 Freescale Semiconductor, Inc. + * author Andy Fleming + * + */ +#include <miiphy.h> + +/* Cicada Auxiliary Control/Status Register */ +#define MIIM_CIS82xx_AUX_CONSTAT	0x1c +#define MIIM_CIS82xx_AUXCONSTAT_INIT	0x0004 +#define MIIM_CIS82xx_AUXCONSTAT_DUPLEX	0x0020 +#define MIIM_CIS82xx_AUXCONSTAT_SPEED	0x0018 +#define MIIM_CIS82xx_AUXCONSTAT_GBIT	0x0010 +#define MIIM_CIS82xx_AUXCONSTAT_100	0x0008 + +/* Cicada Extended Control Register 1 */ +#define MIIM_CIS82xx_EXT_CON1		0x17 +#define MIIM_CIS8201_EXTCON1_INIT	0x0000 + +/* Cicada 8204 Extended PHY Control Register 1 */ +#define MIIM_CIS8204_EPHY_CON		0x17 +#define MIIM_CIS8204_EPHYCON_INIT	0x0006 +#define MIIM_CIS8204_EPHYCON_RGMII	0x1100 + +/* Cicada 8204 Serial LED Control Register */ +#define MIIM_CIS8204_SLED_CON		0x1b +#define MIIM_CIS8204_SLEDCON_INIT	0x1115 + +/* Vitesse VSC8601 Extended PHY Control Register 1 */ +#define MIIM_VSC8601_EPHY_CON		0x17 +#define MIIM_VSC8601_EPHY_CON_INIT_SKEW	0x1120 +#define MIIM_VSC8601_SKEW_CTRL		0x1c + +#define PHY_EXT_PAGE_ACCESS    0x1f + +/* CIS8201 */ +static int vitesse_config(struct phy_device *phydev) +{ +	/* Override PHY config settings */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, +			MIIM_CIS82xx_AUXCONSTAT_INIT); +	/* Set up the interface mode */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1, +			MIIM_CIS8201_EXTCON1_INIT); + +	genphy_config_aneg(phydev); + +	return 0; +} + +static int vitesse_parse_status(struct phy_device *phydev) +{ +	int speed; +	int mii_reg; + +	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT); + +	if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX) +		phydev->duplex = DUPLEX_FULL; +	else +		phydev->duplex = DUPLEX_HALF; + +	speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED; +	switch (speed) { +	case MIIM_CIS82xx_AUXCONSTAT_GBIT: +		phydev->speed = SPEED_1000; +		break; +	case MIIM_CIS82xx_AUXCONSTAT_100: +		phydev->speed = SPEED_100; +		break; +	default: +		phydev->speed = SPEED_10; +		break; +	} + +	return 0; +} + +static int vitesse_startup(struct phy_device *phydev) +{ +	genphy_update_link(phydev); +	vitesse_parse_status(phydev); + +	return 0; +} + +static int cis8204_config(struct phy_device *phydev) +{ +	/* Override PHY config settings */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, +			MIIM_CIS82xx_AUXCONSTAT_INIT); + +	genphy_config_aneg(phydev); + +	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || +			(phydev->interface == PHY_INTERFACE_MODE_RGMII) || +			(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) || +			(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) +		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, +				MIIM_CIS8204_EPHYCON_INIT | +				MIIM_CIS8204_EPHYCON_RGMII); +	else +		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, +				MIIM_CIS8204_EPHYCON_INIT); + +	return 0; +} + +/* Vitesse VSC8601 */ +int vsc8601_config(struct phy_device *phydev) +{ +	/* Configure some basic stuff */ +#ifdef CONFIG_SYS_VSC8601_SKEWFIX +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON, +			MIIM_VSC8601_EPHY_CON_INIT_SKEW); +#if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX) +	phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1); +#define VSC8101_SKEW \ +	((CONFIG_SYS_VSC8601_SKEW_TX << 14) \ +	| (CONFIG_SYS_VSC8601_SKEW_RX << 12)) +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL, +			VSC8101_SKEW); +	phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); +#endif +#endif + +	genphy_config_aneg(phydev); + +	return 0; +} + +static struct phy_driver VSC8211_driver = { +	.name	= "Vitesse VSC8211", +	.uid	= 0xfc4b0, +	.mask	= 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &vitesse_config, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8221_driver = { +	.name = "Vitesse VSC8221", +	.uid = 0xfc550, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &genphy_config_aneg, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8244_driver = { +	.name = "Vitesse VSC8244", +	.uid = 0xfc6c0, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &genphy_config_aneg, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8234_driver = { +	.name = "Vitesse VSC8234", +	.uid = 0xfc620, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &genphy_config_aneg, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8601_driver = { +	.name = "Vitesse VSC8601", +	.uid = 0x70420, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &vsc8601_config, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8641_driver = { +	.name = "Vitesse VSC8641", +	.uid = 0x70430, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &genphy_config_aneg, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +/* Vitesse bought Cicada, so we'll put these here */ +static struct phy_driver cis8201_driver = { +	.name = "CIS8201", +	.uid = 0xfc410, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &vitesse_config, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver cis8204_driver = { +	.name = "Cicada Cis8204", +	.uid = 0xfc440, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &cis8204_config, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +int phy_vitesse_init(void) +{ +	phy_register(&VSC8641_driver); +	phy_register(&VSC8601_driver); +	phy_register(&VSC8234_driver); +	phy_register(&VSC8244_driver); +	phy_register(&VSC8211_driver); +	phy_register(&VSC8221_driver); +	phy_register(&cis8201_driver); +	phy_register(&cis8204_driver); + +	return 0; +} |