diff options
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/cpsw.c | 6 | ||||
| -rw-r--r-- | drivers/net/fm/b4860.c | 6 | ||||
| -rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
| -rw-r--r-- | drivers/net/phy/et1011c.c | 110 | ||||
| -rw-r--r-- | drivers/net/phy/marvell.c | 11 | ||||
| -rw-r--r-- | drivers/net/phy/phy.c | 3 | ||||
| -rw-r--r-- | drivers/net/phy/teranetics.c | 16 | ||||
| -rw-r--r-- | drivers/net/zynq_gem.c | 191 | 
8 files changed, 285 insertions, 59 deletions
| diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index 7a3685019..379b679d2 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -109,7 +109,13 @@ struct cpsw_slave_regs {  	u32	flow_thresh;  	u32	port_vlan;  	u32	tx_pri_map; +#ifdef CONFIG_AM33XX  	u32	gap_thresh; +#elif defined(CONFIG_TI814X) +	u32	ts_ctl; +	u32	ts_seq_ltype; +	u32	ts_vlan; +#endif  	u32	sa_lo;  	u32	sa_hi;  }; diff --git a/drivers/net/fm/b4860.c b/drivers/net/fm/b4860.c index 8cde7afc1..3b5defefa 100644 --- a/drivers/net/fm/b4860.c +++ b/drivers/net/fm/b4860.c @@ -55,8 +55,10 @@ phy_interface_t fman_port_enet_if(enum fm_port port)  	if (is_device_disabled(port))  		return PHY_INTERFACE_MODE_NONE; -	if ((port == FM1_10GEC1 || port == FM1_10GEC2) -			&& (is_serdes_configured(XAUI_FM1))) +	/*B4860 has two 10Gig Mac*/ +	if ((port == FM1_10GEC1 || port == FM1_10GEC2)	&& +	    ((is_serdes_configured(XAUI_FM1_MAC9))	|| +	    (is_serdes_configured(XAUI_FM1_MAC10))))  		return PHY_INTERFACE_MODE_XGMII;  	/* Fix me need to handle RGMII here first */ diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 5e90d7098..af5f4b848 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -34,6 +34,7 @@ COBJS-$(CONFIG_PHYLIB_10G) += generic_10g.o  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_LXT) += lxt.o  COBJS-$(CONFIG_PHY_MARVELL) += marvell.o  COBJS-$(CONFIG_PHY_MICREL) += micrel.o diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c new file mode 100644 index 000000000..5e22399af --- /dev/null +++ b/drivers/net/phy/et1011c.c @@ -0,0 +1,110 @@ +/* + * ET1011C PHY driver + * + * Derived from Linux kernel driver by Chaithrika U S + * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/ + * + * 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. + * + */ +#include <config.h> +#include <phy.h> + +#define ET1011C_CONFIG_REG		(0x16) +#define ET1011C_TX_FIFO_MASK		(0x3 << 12) +#define ET1011C_TX_FIFO_DEPTH_8		(0x0 << 12) +#define ET1011C_TX_FIFO_DEPTH_16	(0x1 << 12) +#define ET1011C_INTERFACE_MASK		(0x7 << 0) +#define ET1011C_GMII_INTERFACE		(0x2 << 0) +#define ET1011C_SYS_CLK_EN		(0x1 << 4) +#define ET1011C_TX_CLK_EN		(0x1 << 5) + +#define ET1011C_STATUS_REG		(0x1A) +#define ET1011C_DUPLEX_STATUS		(0x1 << 7) +#define ET1011C_SPEED_MASK		(0x3 << 8) +#define ET1011C_SPEED_1000		(0x2 << 8) +#define ET1011C_SPEED_100		(0x1 << 8) +#define ET1011C_SPEED_10		(0x0 << 8) + +static int et1011c_config(struct phy_device *phydev) +{ +	int ctl = 0; +	ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); +	if (ctl < 0) +		return ctl; +	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | +		 BMCR_ANENABLE); +	/* First clear the PHY */ +	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl | BMCR_RESET); + +	return genphy_config_aneg(phydev); +} + +static int et1011c_parse_status(struct phy_device *phydev) +{ +	int mii_reg; +	int speed; + +	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, ET1011C_STATUS_REG); + +	if (mii_reg & ET1011C_DUPLEX_STATUS) +		phydev->duplex = DUPLEX_FULL; +	else +		phydev->duplex = DUPLEX_HALF; + +	speed = mii_reg & ET1011C_SPEED_MASK; +	switch (speed) { +	case ET1011C_SPEED_1000: +		phydev->speed = SPEED_1000; +		mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, ET1011C_CONFIG_REG); +		mii_reg &= ~ET1011C_TX_FIFO_MASK; +		phy_write(phydev, MDIO_DEVAD_NONE, ET1011C_CONFIG_REG, +			  mii_reg | +			  ET1011C_GMII_INTERFACE | +			  ET1011C_SYS_CLK_EN | +#ifdef CONFIG_PHY_ET1011C_TX_CLK_FIX +			  ET1011C_TX_CLK_EN | +#endif +			  ET1011C_TX_FIFO_DEPTH_16); +		break; +	case ET1011C_SPEED_100: +		phydev->speed = SPEED_100; +		break; +	case ET1011C_SPEED_10: +		phydev->speed = SPEED_10; +		break; +	} + +	return 0; +} + +static int et1011c_startup(struct phy_device *phydev) +{ +	genphy_update_link(phydev); +	et1011c_parse_status(phydev); +	return 0; +} + +static struct phy_driver et1011c_driver = { +	.name		= "ET1011C", +	.uid		= 0x0282f014, +	.mask		= 0xfffffff0, +	.features	= PHY_GBIT_FEATURES, +	.config		= &et1011c_config, +	.startup	= &et1011c_startup, +}; + +int phy_et1011c_init(void) +{ +	phy_register(&et1011c_driver); + +	return 0; +} diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 4b271989a..46801c791 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -465,6 +465,16 @@ static struct phy_driver M88E1149S_driver = {  	.shutdown = &genphy_shutdown,  }; +static struct phy_driver M88E1518_driver = { +	.name = "Marvell 88E1518", +	.uid = 0x1410dd1, +	.mask = 0xffffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &m88e1111s_config, +	.startup = &m88e1011s_startup, +	.shutdown = &genphy_shutdown, +}; +  int phy_marvell_init(void)  {  	phy_register(&M88E1149S_driver); @@ -474,6 +484,7 @@ int phy_marvell_init(void)  	phy_register(&M88E1118R_driver);  	phy_register(&M88E1111S_driver);  	phy_register(&M88E1011S_driver); +	phy_register(&M88E1518_driver);  	return 0;  } diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index d0ed7666e..f8c548147 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -430,6 +430,9 @@ int phy_init(void)  #ifdef CONFIG_PHY_DAVICOM  	phy_davicom_init();  #endif +#ifdef CONFIG_PHY_ET1011C +	phy_et1011c_init(); +#endif  #ifdef CONFIG_PHY_LXT  	phy_lxt_init();  #endif diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index 78447b711..84ce7362f 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -34,9 +34,21 @@ int tn2020_config(struct phy_device *phydev)  		unsigned short restart_an = (MDIO_AN_CTRL1_RESTART |  						MDIO_AN_CTRL1_ENABLE |  						MDIO_AN_CTRL1_XNP); +		u8 phy_hwversion; -		phy_write(phydev, 30, 93, 2); -		phy_write(phydev, MDIO_MMD_AN, MDIO_CTRL1, restart_an); +		/* +		 * bit 15:12 of register 30.32 indicates PHY hardware +		 * version. It can be used to distinguish TN80xx from +		 * TN2020. TN2020 needs write 0x2 to 30.93, but TN80xx +		 * needs 0x1. +		 */ +		phy_hwversion = (phy_read(phydev, 30, 32) >> 12) & 0xf; +		if (phy_hwversion <= 3) { +			phy_write(phydev, 30, 93, 2); +			phy_write(phydev, MDIO_MMD_AN, MDIO_CTRL1, restart_an); +		} else { +			phy_write(phydev, 30, 93, 1); +		}  	}  	return 0; diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 359606569..eac9b6f45 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -33,6 +33,8 @@  #include <phy.h>  #include <miiphy.h>  #include <watchdog.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h>  #if !defined(CONFIG_PHYLIB)  # error XILINX_GEM_ETHERNET requires PHYLIB @@ -67,13 +69,14 @@  #define ZYNQ_GEM_NWCTRL_MDEN_MASK	0x00000010 /* Enable MDIO port */  #define ZYNQ_GEM_NWCTRL_STARTTX_MASK	0x00000200 /* Start tx (tx_go) */ -#define ZYNQ_GEM_NWCFG_SPEED		0x00000001 /* 100 Mbps operation */ -#define ZYNQ_GEM_NWCFG_FDEN		0x00000002 /* Full Duplex mode */ -#define ZYNQ_GEM_NWCFG_FSREM		0x00020000 /* FCS removal */ +#define ZYNQ_GEM_NWCFG_SPEED100		0x000000001 /* 100 Mbps operation */ +#define ZYNQ_GEM_NWCFG_SPEED1000	0x000000400 /* 1Gbps operation */ +#define ZYNQ_GEM_NWCFG_FDEN		0x000000002 /* Full Duplex mode */ +#define ZYNQ_GEM_NWCFG_FSREM		0x000020000 /* FCS removal */  #define ZYNQ_GEM_NWCFG_MDCCLKDIV	0x000080000 /* Div pclk by 32, 80MHz */ +#define ZYNQ_GEM_NWCFG_MDCCLKDIV2	0x0000c0000 /* Div pclk by 48, 120MHz */ -#define ZYNQ_GEM_NWCFG_INIT		(ZYNQ_GEM_NWCFG_SPEED | \ -					ZYNQ_GEM_NWCFG_FDEN | \ +#define ZYNQ_GEM_NWCFG_INIT		(ZYNQ_GEM_NWCFG_FDEN | \  					ZYNQ_GEM_NWCFG_FSREM | \  					ZYNQ_GEM_NWCFG_MDCCLKDIV) @@ -92,6 +95,17 @@  					ZYNQ_GEM_DMACR_TXSIZE | \  					ZYNQ_GEM_DMACR_RXBUF) +/* Use MII register 1 (MII status register) to detect PHY */ +#define PHY_DETECT_REG  1 + +/* Mask used to verify certain PHY features (or register contents) + * in the register above: + *  0x1000: 10Mbps full duplex support + *  0x0800: 10Mbps half duplex support + *  0x0008: Auto-negotiation support + */ +#define PHY_DETECT_MASK 0x1808 +  /* Device registers */  struct zynq_gem_regs {  	u32 nwctrl; /* Network Control reg */ @@ -134,6 +148,8 @@ struct zynq_gem_priv {  	u32 rxbd_current;  	u32 rx_first_buf;  	int phyaddr; +	u32 emio; +	int init;  	struct phy_device *phydev;  	struct mii_dev *bus;  }; @@ -196,6 +212,44 @@ static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data)  				ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data);  } +static void phy_detection(struct eth_device *dev) +{ +	int i; +	u16 phyreg; +	struct zynq_gem_priv *priv = dev->priv; + +	if (priv->phyaddr != -1) { +		phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg); +		if ((phyreg != 0xFFFF) && +		    ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { +			/* Found a valid PHY address */ +			debug("Default phy address %d is valid\n", +			      priv->phyaddr); +			return; +		} else { +			debug("PHY address is not setup correctly %d\n", +			      priv->phyaddr); +			priv->phyaddr = -1; +		} +	} + +	debug("detecting phy address\n"); +	if (priv->phyaddr == -1) { +		/* detect the PHY address */ +		for (i = 31; i >= 0; i--) { +			phyread(dev, i, PHY_DETECT_REG, &phyreg); +			if ((phyreg != 0xFFFF) && +			    ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { +				/* Found a valid PHY address */ +				priv->phyaddr = i; +				debug("Found valid phy address, %d\n", i); +				return; +			} +		} +	} +	printf("PHY is not detected\n"); +} +  static int zynq_gem_setup_mac(struct eth_device *dev)  {  	u32 i, macaddrlow, macaddrhigh; @@ -226,7 +280,7 @@ static int zynq_gem_setup_mac(struct eth_device *dev)  static int zynq_gem_init(struct eth_device *dev, bd_t * bis)  { -	u32 i; +	u32 i, rclk, clk = 0;  	struct phy_device *phydev;  	const u32 stat_size = (sizeof(struct zynq_gem_regs) -  				offsetof(struct zynq_gem_regs, stat)) / 4; @@ -239,59 +293,92 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)  			SUPPORTED_1000baseT_Half |  			SUPPORTED_1000baseT_Full; -	/* Disable all interrupts */ -	writel(0xFFFFFFFF, ®s->idr); +	if (!priv->init) { +		/* Disable all interrupts */ +		writel(0xFFFFFFFF, ®s->idr); -	/* Disable the receiver & transmitter */ -	writel(0, ®s->nwctrl); -	writel(0, ®s->txsr); -	writel(0, ®s->rxsr); -	writel(0, ®s->phymntnc); +		/* Disable the receiver & transmitter */ +		writel(0, ®s->nwctrl); +		writel(0, ®s->txsr); +		writel(0, ®s->rxsr); +		writel(0, ®s->phymntnc); -	/* Clear the Hash registers for the mac address pointed by AddressPtr */ -	writel(0x0, ®s->hashl); -	/* Write bits [63:32] in TOP */ -	writel(0x0, ®s->hashh); +		/* Clear the Hash registers for the mac address +		 * pointed by AddressPtr +		 */ +		writel(0x0, ®s->hashl); +		/* Write bits [63:32] in TOP */ +		writel(0x0, ®s->hashh); -	/* Clear all counters */ -	for (i = 0; i <= stat_size; i++) -		readl(®s->stat[i]); +		/* Clear all counters */ +		for (i = 0; i <= stat_size; i++) +			readl(®s->stat[i]); -	/* Setup RxBD space */ -	memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd)); -	/* Create the RxBD ring */ -	memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers)); +		/* Setup RxBD space */ +		memset(&(priv->rx_bd), 0, sizeof(priv->rx_bd)); +		/* Create the RxBD ring */ +		memset(&(priv->rxbuffers), 0, sizeof(priv->rxbuffers)); -	for (i = 0; i < RX_BUF; i++) { -		priv->rx_bd[i].status = 0xF0000000; -		priv->rx_bd[i].addr = (u32)((char *) &(priv->rxbuffers) + +		for (i = 0; i < RX_BUF; i++) { +			priv->rx_bd[i].status = 0xF0000000; +			priv->rx_bd[i].addr = +					(u32)((char *)&(priv->rxbuffers) +  							(i * PKTSIZE_ALIGN)); -	} -	/* WRAP bit to last BD */ -	priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; -	/* Write RxBDs to IP */ -	writel((u32) &(priv->rx_bd), ®s->rxqbase); +		} +		/* WRAP bit to last BD */ +		priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; +		/* Write RxBDs to IP */ +		writel((u32)&(priv->rx_bd), ®s->rxqbase); -	/* MAC Setup */ -	/* Setup Network Configuration register */ -	writel(ZYNQ_GEM_NWCFG_INIT, ®s->nwcfg); +		/* Setup for DMA Configuration register */ +		writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr); -	/* Setup for DMA Configuration register */ -	writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr); +		/* Setup for Network Control register, MDIO, Rx and Tx enable */ +		setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK); -	/* Setup for Network Control register, MDIO, Rx and Tx enable */ -	setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK | -			ZYNQ_GEM_NWCTRL_RXEN_MASK | ZYNQ_GEM_NWCTRL_TXEN_MASK); +		priv->init++; +	} + +	phy_detection(dev);  	/* interface - look at tsec */  	phydev = phy_connect(priv->bus, priv->phyaddr, dev, 0); -	phydev->supported &= supported; +	phydev->supported = supported | ADVERTISED_Pause | +			    ADVERTISED_Asym_Pause;  	phydev->advertising = phydev->supported;  	priv->phydev = phydev;  	phy_config(phydev);  	phy_startup(phydev); +	switch (phydev->speed) { +	case SPEED_1000: +		writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000, +		       ®s->nwcfg); +		rclk = (0 << 4) | (1 << 0); +		clk = (1 << 20) | (8 << 8) | (0 << 4) | (1 << 0); +		break; +	case SPEED_100: +		clrsetbits_le32(®s->nwcfg, ZYNQ_GEM_NWCFG_SPEED1000, +				ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED100); +		rclk = 1 << 0; +		clk = (5 << 20) | (8 << 8) | (0 << 4) | (1 << 0); +		break; +	case SPEED_10: +		rclk = 1 << 0; +		/* FIXME untested */ +		clk = (5 << 20) | (8 << 8) | (0 << 4) | (1 << 0); +		break; +	} + +	/* Change the rclk and clk only not using EMIO interface */ +	if (!priv->emio) +		zynq_slcr_gem_clk_setup(dev->iobase != +					ZYNQ_GEM_BASEADDR0, rclk, clk); + +	setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | +					ZYNQ_GEM_NWCTRL_TXEN_MASK); +  	return 0;  } @@ -307,11 +394,10 @@ static int zynq_gem_send(struct eth_device *dev, void *ptr, int len)  	writel((u32)&(priv->tx_bd), ®s->txqbase);  	/* Setup Tx BD */ -	memset((void *) &(priv->tx_bd), 0, sizeof(struct emac_bd)); +	memset((void *)&(priv->tx_bd), 0, sizeof(struct emac_bd));  	priv->tx_bd.addr = (u32)ptr; -	priv->tx_bd.status = len | ZYNQ_GEM_TXBUF_LAST_MASK | -						ZYNQ_GEM_TXBUF_WRAP_MASK; +	priv->tx_bd.status = len | ZYNQ_GEM_TXBUF_LAST_MASK;  	/* Start transmit */  	setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_STARTTX_MASK); @@ -364,19 +450,17 @@ static int zynq_gem_recv(struct eth_device *dev)  		if ((++priv->rxbd_current) >= RX_BUF)  			priv->rxbd_current = 0; - -		return frame_len;  	} -	return 0; +	return frame_len;  }  static void zynq_gem_halt(struct eth_device *dev)  {  	struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; -	/* Disable the receiver & transmitter */ -	writel(0, ®s->nwctrl); +	clrsetbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | +						ZYNQ_GEM_NWCTRL_TXEN_MASK, 0);  }  static int zynq_gem_miiphyread(const char *devname, uchar addr, @@ -399,7 +483,7 @@ static int zynq_gem_miiphy_write(const char *devname, uchar addr,  	return phywrite(dev, addr, reg, val);  } -int zynq_gem_initialize(bd_t *bis, int base_addr) +int zynq_gem_initialize(bd_t *bis, int base_addr, int phy_addr, u32 emio)  {  	struct eth_device *dev;  	struct zynq_gem_priv *priv; @@ -415,11 +499,8 @@ int zynq_gem_initialize(bd_t *bis, int base_addr)  	}  	priv = dev->priv; -#ifdef CONFIG_PHY_ADDR -	priv->phyaddr = CONFIG_PHY_ADDR; -#else -	priv->phyaddr = -1; -#endif +	priv->phyaddr = phy_addr; +	priv->emio = emio;  	sprintf(dev->name, "Gem.%x", base_addr); |