diff options
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/fm/memac.c | 17 | ||||
| -rw-r--r-- | drivers/net/phy/marvell.c | 11 | ||||
| -rw-r--r-- | drivers/net/zynq_gem.c | 191 | 
3 files changed, 164 insertions, 55 deletions
| diff --git a/drivers/net/fm/memac.c b/drivers/net/fm/memac.c index 32c7054e3..d3eee248a 100644 --- a/drivers/net/fm/memac.c +++ b/drivers/net/fm/memac.c @@ -112,6 +112,23 @@ static void memac_set_interface_mode(struct fsl_enet_mac *mac,  	/* Enable automatic speed selection */  	if_mode |= IF_MODE_EN_AUTO; +	if (type == PHY_INTERFACE_MODE_RGMII) { +		if_mode &= ~IF_MODE_EN_AUTO; +		if_mode &= ~IF_MODE_SETSP_MASK; +		switch (speed) { +		case SPEED_1000: +			if_mode |= IF_MODE_SETSP_1000M; +			break; +		case SPEED_100: +			if_mode |= IF_MODE_SETSP_100M; +			break; +		case SPEED_10: +			if_mode |= IF_MODE_SETSP_10M; +		default: +			break; +		} +	} +  	debug(" %s, if_mode = %x\n", __func__,  if_mode);  	debug(" %s, if_status = %x\n", __func__,  if_status);  	out_be32(®s->if_mode, if_mode); 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/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); |