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>
This commit is contained in:
parent
b1a0006eba
commit
d256be29f8
2 changed files with 168 additions and 38 deletions
|
@ -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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Reference in a new issue