diff options
| author | Bo Shen <voice.shen@atmel.com> | 2013-04-24 15:59:28 +0800 | 
|---|---|---|
| committer | Joe Hershberger <joe.hershberger@ni.com> | 2013-06-24 19:11:16 -0500 | 
| commit | d256be29f86b7c4e98435f7047a3e9c44dd7e0f4 (patch) | |
| tree | d30d9fc9d293743ca7b543072ee018213d6e4ad5 /drivers | |
| parent | b1a0006eba76ad72ba2cbaefc948dc7b511e8d2d (diff) | |
| download | olio-uboot-2014.01-d256be29f86b7c4e98435f7047a3e9c44dd7e0f4.tar.xz olio-uboot-2014.01-d256be29f86b7c4e98435f7047a3e9c44dd7e0f4.zip | |
net: macb: add support for gigabit MAC
Add gigabit MAC support in macb driver
  - using IP version to distinguish whether MAC is GMAC
Signed-off-by: Bo Shen <voice.shen@atmel.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/net/macb.c | 149 | ||||
| -rw-r--r-- | drivers/net/macb.h | 55 | 
2 files changed, 167 insertions, 37 deletions
| diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 602682500..b7802a2fe 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -107,6 +107,11 @@ struct macb_device {  };  #define to_macb(_nd) container_of(_nd, struct macb_device, netdev) +static int macb_is_gem(struct macb_device *macb) +{ +	return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2; +} +  static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value)  {  	unsigned long netctl; @@ -427,28 +432,64 @@ static int macb_phy_init(struct macb_device *macb)  		printf("%s: link down (status: 0x%04x)\n",  		       netdev->name, status);  		return 0; -	} else { -		adv = macb_mdio_read(macb, MII_ADVERTISE); -		lpa = macb_mdio_read(macb, MII_LPA); -		media = mii_nway_result(lpa & adv); -		speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) -			 ? 1 : 0); -		duplex = (media & ADVERTISE_FULL) ? 1 : 0; -		printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", -		       netdev->name, -		       speed ? "100" : "10", -		       duplex ? "full" : "half", -		       lpa); +	} + +	/* First check for GMAC */ +	if (macb_is_gem(macb)) { +		lpa = macb_mdio_read(macb, MII_STAT1000); +		if (lpa & (1 << 11)) { +			speed = 1000; +			duplex = 1; +		} else { +		       if (lpa & (1 << 10)) { +				speed = 1000; +				duplex = 1; +			} else { +				speed = 0; +			} +		} -		ncfgr = macb_readl(macb, NCFGR); -		ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); -		if (speed) -			ncfgr |= MACB_BIT(SPD); -		if (duplex) -			ncfgr |= MACB_BIT(FD); -		macb_writel(macb, NCFGR, ncfgr); -		return 1; +		if (speed == 1000) { +			printf("%s: link up, %dMbps %s-duplex (lpa: 0x%04x)\n", +			       netdev->name, +			       speed, +			       duplex ? "full" : "half", +			       lpa); + +			ncfgr = macb_readl(macb, NCFGR); +			ncfgr &= ~(GEM_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD)); +			if (speed) +				ncfgr |= GEM_BIT(GBE); +			if (duplex) +				ncfgr |= MACB_BIT(FD); +			macb_writel(macb, NCFGR, ncfgr); + +			return 1; +		}  	} + +	/* fall back for EMAC checking */ +	adv = macb_mdio_read(macb, MII_ADVERTISE); +	lpa = macb_mdio_read(macb, MII_LPA); +	media = mii_nway_result(lpa & adv); +	speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) +		 ? 1 : 0); +	duplex = (media & ADVERTISE_FULL) ? 1 : 0; +	printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", +	       netdev->name, +	       speed ? "100" : "10", +	       duplex ? "full" : "half", +	       lpa); + +	ncfgr = macb_readl(macb, NCFGR); +	ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); +	if (speed) +		ncfgr |= MACB_BIT(SPD); +	if (duplex) +		ncfgr |= MACB_BIT(FD); +	macb_writel(macb, NCFGR, ncfgr); + +	return 1;  }  static int macb_init(struct eth_device *netdev, bd_t *bd) @@ -483,6 +524,13 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)  	macb_writel(macb, RBQP, macb->rx_ring_dma);  	macb_writel(macb, TBQP, macb->tx_ring_dma); +	if (macb_is_gem(macb)) { +#ifdef CONFIG_RGMII +		gem_writel(macb, UR, GEM_BIT(RGMII)); +#else +		gem_writel(macb, UR, 0); +#endif +	} else {  	/* choose RMII or MII mode. This depends on the board */  #ifdef CONFIG_RMII  #ifdef CONFIG_AT91FAMILY @@ -497,6 +545,7 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)  	macb_writel(macb, USRIO, MACB_BIT(MII));  #endif  #endif /* CONFIG_RMII */ +	}  	if (!macb_phy_init(macb))  		return -1; @@ -540,11 +589,48 @@ static int macb_write_hwaddr(struct eth_device *dev)  	return 0;  } +static u32 macb_mdc_clk_div(int id, struct macb_device *macb) +{ +	u32 config; +	unsigned long macb_hz = get_macb_pclk_rate(id); + +	if (macb_hz < 20000000) +		config = MACB_BF(CLK, MACB_CLK_DIV8); +	else if (macb_hz < 40000000) +		config = MACB_BF(CLK, MACB_CLK_DIV16); +	else if (macb_hz < 80000000) +		config = MACB_BF(CLK, MACB_CLK_DIV32); +	else +		config = MACB_BF(CLK, MACB_CLK_DIV64); + +	return config; +} + +static u32 gem_mdc_clk_div(int id, struct macb_device *macb) +{ +	u32 config; +	unsigned long macb_hz = get_macb_pclk_rate(id); + +	if (macb_hz < 20000000) +		config = GEM_BF(CLK, GEM_CLK_DIV8); +	else if (macb_hz < 40000000) +		config = GEM_BF(CLK, GEM_CLK_DIV16); +	else if (macb_hz < 80000000) +		config = GEM_BF(CLK, GEM_CLK_DIV32); +	else if (macb_hz < 120000000) +		config = GEM_BF(CLK, GEM_CLK_DIV48); +	else if (macb_hz < 160000000) +		config = GEM_BF(CLK, GEM_CLK_DIV64); +	else +		config = GEM_BF(CLK, GEM_CLK_DIV96); + +	return config; +} +  int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)  {  	struct macb_device *macb;  	struct eth_device *netdev; -	unsigned long macb_hz;  	u32 ncfgr;  	macb = malloc(sizeof(struct macb_device)); @@ -568,7 +654,11 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)  	macb->regs = regs;  	macb->phy_addr = phy_addr; -	sprintf(netdev->name, "macb%d", id); +	if (macb_is_gem(macb)) +		sprintf(netdev->name, "gmac%d", id); +	else +		sprintf(netdev->name, "macb%d", id); +  	netdev->init = macb_init;  	netdev->halt = macb_halt;  	netdev->send = macb_send; @@ -579,15 +669,12 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)  	 * Do some basic initialization so that we at least can talk  	 * to the PHY  	 */ -	macb_hz = get_macb_pclk_rate(id); -	if (macb_hz < 20000000) -		ncfgr = MACB_BF(CLK, MACB_CLK_DIV8); -	else if (macb_hz < 40000000) -		ncfgr = MACB_BF(CLK, MACB_CLK_DIV16); -	else if (macb_hz < 80000000) -		ncfgr = MACB_BF(CLK, MACB_CLK_DIV32); -	else -		ncfgr = MACB_BF(CLK, MACB_CLK_DIV64); +	if (macb_is_gem(macb)) { +		ncfgr = gem_mdc_clk_div(id, macb); +		ncfgr |= GEM_BF(DBW, 1); +	} else { +		ncfgr = macb_mdc_clk_div(id, macb); +	}  	macb_writel(macb, NCFGR, ncfgr); diff --git a/drivers/net/macb.h b/drivers/net/macb.h index f92a20c70..68eef00c0 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -26,6 +26,7 @@  #define MACB_NCR				0x0000  #define MACB_NCFGR				0x0004  #define MACB_NSR				0x0008 +#define GEM_UR					0x000c  #define MACB_TSR				0x0014  #define MACB_RBQP				0x0018  #define MACB_TBQP				0x001c @@ -71,6 +72,7 @@  #define MACB_TPQ				0x00bc  #define MACB_USRIO				0x00c0  #define MACB_WOL				0x00c4 +#define MACB_MID				0x00fc  /* Bitfields in NCR */  #define MACB_LB_OFFSET				0 @@ -138,6 +140,13 @@  #define MACB_IRXFCS_OFFSET			19  #define MACB_IRXFCS_SIZE			1 +#define GEM_GBE_OFFSET				10 +#define GEM_GBE_SIZE				1 +#define GEM_CLK_OFFSET				18 +#define GEM_CLK_SIZE				3 +#define GEM_DBW_OFFSET				21 +#define GEM_DBW_SIZE				2 +  /* Bitfields in NSR */  #define MACB_NSR_LINK_OFFSET			0  #define MACB_NSR_LINK_SIZE			1 @@ -146,6 +155,10 @@  #define MACB_IDLE_OFFSET			2  #define MACB_IDLE_SIZE				1 +/* Bitfields in UR */ +#define GEM_RGMII_OFFSET			0 +#define GEM_RGMII_SIZE				1 +  /* Bitfields in TSR */  #define MACB_UBR_OFFSET				0  #define MACB_UBR_SIZE				1 @@ -240,12 +253,25 @@  #define MACB_WOL_MTI_OFFSET			19  #define MACB_WOL_MTI_SIZE			1 +/* Bitfields in MID */ +#define MACB_IDNUM_OFFSET			16 +#define MACB_IDNUM_SIZE				16 + +/* Bitfields in DCFG1 */  /* Constants for CLK */  #define MACB_CLK_DIV8				0  #define MACB_CLK_DIV16				1  #define MACB_CLK_DIV32				2  #define MACB_CLK_DIV64				3 +/* GEM specific constants for CLK */ +#define GEM_CLK_DIV8				0 +#define GEM_CLK_DIV16				1 +#define GEM_CLK_DIV32				2 +#define GEM_CLK_DIV48				3 +#define GEM_CLK_DIV64				4 +#define GEM_CLK_DIV96				5 +  /* Constants for MAN register */  #define MACB_MAN_SOF				1  #define MACB_MAN_WRITE				1 @@ -255,21 +281,38 @@  /* Bit manipulation macros */  #define MACB_BIT(name)					\  	(1 << MACB_##name##_OFFSET) -#define MACB_BF(name,value)				\ +#define MACB_BF(name, value)				\  	(((value) & ((1 << MACB_##name##_SIZE) - 1))	\  	 << MACB_##name##_OFFSET) -#define MACB_BFEXT(name,value)\ +#define MACB_BFEXT(name, value)\  	(((value) >> MACB_##name##_OFFSET)		\  	 & ((1 << MACB_##name##_SIZE) - 1)) -#define MACB_BFINS(name,value,old)			\ +#define MACB_BFINS(name, value, old)			\  	(((old) & ~(((1 << MACB_##name##_SIZE) - 1)	\  		    << MACB_##name##_OFFSET))		\ -	 | MACB_BF(name,value)) +	 | MACB_BF(name, value)) + +#define GEM_BIT(name)					\ +	(1 << GEM_##name##_OFFSET) +#define GEM_BF(name, value)				\ +	(((value) & ((1 << GEM_##name##_SIZE) - 1))	\ +	 << GEM_##name##_OFFSET) +#define GEM_BFEXT(name, value)\ +	(((value) >> GEM_##name##_OFFSET)		\ +	 & ((1 << GEM_##name##_SIZE) - 1)) +#define GEM_BFINS(name, value, old)			\ +	(((old) & ~(((1 << GEM_##name##_SIZE) - 1)	\ +		    << GEM_##name##_OFFSET))		\ +	 | GEM_BF(name, value))  /* Register access macros */ -#define macb_readl(port,reg)				\ +#define macb_readl(port, reg)				\  	readl((port)->regs + MACB_##reg) -#define macb_writel(port,reg,value)			\ +#define macb_writel(port, reg, value)			\  	writel((value), (port)->regs + MACB_##reg) +#define gem_readl(port, reg)				\ +	readl((port)->regs + GEM_##reg) +#define gem_writel(port, reg, value)			\ +	writel((value), (port)->regs + GEM_##reg)  #endif /* __DRIVERS_MACB_H__ */ |