From 416ce623fbad51af57660346ebb6f7befb88b3c9 Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Thu, 13 Dec 2012 17:22:52 +0530 Subject: net/macb: Add arch specific routine to get mdio control SPEAr310 and SPEAr320 Ethernet interfaces share same MDIO lines to control their respective phys. Currently there is a fixed configuration in which only a particular MAC can use the MDIO lines. Call an arch specific function to take control of specific mdio lines at runtime. Signed-off-by: Shiraz Hashim Signed-off-by: Vipin Kumar Acked-by: Stefan Roese --- drivers/net/macb.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net/macb.c') diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 8bacbda719..6b49f0e3e1 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -163,6 +163,11 @@ static u16 macb_mdio_read(struct macb_device *macb, u8 reg) return MACB_BFEXT(DATA, frame); } +static void __weak arch_get_mdio_control(const char *name) +{ + return; +} + #if defined(CONFIG_CMD_MII) int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value) @@ -173,6 +178,7 @@ int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value) if ( macb->phy_addr != phy_adr ) return -1; + arch_get_mdio_control(devname); *value = macb_mdio_read(macb, reg); return 0; @@ -186,6 +192,7 @@ int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value) if ( macb->phy_addr != phy_adr ) return -1; + arch_get_mdio_control(devname); macb_mdio_write(macb, reg, value); return 0; @@ -377,6 +384,7 @@ static int macb_phy_init(struct macb_device *macb) int media, speed, duplex; int i; + arch_get_mdio_control(netdev->name); #ifdef CONFIG_MACB_SEARCH_PHY /* Auto-detect phy_addr */ if (!macb_phy_find(macb)) { -- cgit From 1b8c18b9716c6991237b24cff3d38075d930c0d7 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Mon, 24 Jun 2013 19:06:38 -0500 Subject: net: Fix build regression in macb.c The added weak symbol must not be static. This was introduced in 416ce623fbad51af57660346ebb6f7befb88b3c9 Signed-off-by: Joe Hershberger --- drivers/net/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/macb.c') diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 6b49f0e3e1..81a734d874 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -163,7 +163,7 @@ static u16 macb_mdio_read(struct macb_device *macb, u8 reg) return MACB_BFEXT(DATA, frame); } -static void __weak arch_get_mdio_control(const char *name) +void __weak arch_get_mdio_control(const char *name) { return; } -- cgit From d8f64b444191d9f3ea724317e6520643c48e3117 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Wed, 24 Apr 2013 15:59:26 +0800 Subject: net: macb: using AT91FAMILY replace #ifdeferry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using CONFIG_AT91FAMILY replace #ifdeferry for atmel SoC Signed-off-by: Bo Shen Acked-by: Andreas Bießmann --- drivers/net/macb.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/net/macb.c') diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 81a734d874..ac2872074c 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -474,19 +474,13 @@ static int macb_init(struct eth_device *netdev, bd_t *bd) /* choose RMII or MII mode. This depends on the board */ #ifdef CONFIG_RMII -#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ - defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \ - defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \ - defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5) +#ifdef CONFIG_AT91FAMILY macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN)); #else macb_writel(macb, USRIO, 0); #endif #else -#if defined(CONFIG_AT91CAP9) || defined(CONFIG_AT91SAM9260) || \ - defined(CONFIG_AT91SAM9263) || defined(CONFIG_AT91SAM9G20) || \ - defined(CONFIG_AT91SAM9G45) || defined(CONFIG_AT91SAM9M10G45) || \ - defined(CONFIG_AT91SAM9XE) || defined(CONFIG_AT91SAM9X5) +#ifdef CONFIG_AT91FAMILY macb_writel(macb, USRIO, MACB_BIT(CLKEN)); #else macb_writel(macb, USRIO, MACB_BIT(MII)); -- cgit From b1a0006eba76ad72ba2cbaefc948dc7b511e8d2d Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Wed, 24 Apr 2013 15:59:27 +0800 Subject: net: macb: using phylib to configure phy device using phylib to configure phy device in macb driver Signed-off-by: Bo Shen --- drivers/net/macb.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/net/macb.c') diff --git a/drivers/net/macb.c b/drivers/net/macb.c index ac2872074c..6026825001 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -103,6 +103,7 @@ struct macb_device { const struct device *dev; struct eth_device netdev; unsigned short phy_addr; + struct mii_dev *bus; }; #define to_macb(_nd) container_of(_nd, struct macb_device, netdev) @@ -168,7 +169,7 @@ void __weak arch_get_mdio_control(const char *name) return; } -#if defined(CONFIG_CMD_MII) +#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value) { @@ -379,6 +380,9 @@ static int macb_phy_find(struct macb_device *macb) static int macb_phy_init(struct macb_device *macb) { struct eth_device *netdev = &macb->netdev; +#ifdef CONFIG_PHYLIB + struct phy_device *phydev; +#endif u32 ncfgr; u16 phy_id, status, adv, lpa; int media, speed, duplex; @@ -399,6 +403,13 @@ static int macb_phy_init(struct macb_device *macb) return 0; } +#ifdef CONFIG_PHYLIB + phydev->bus = macb->bus; + phydev->dev = netdev; + phydev->addr = macb->phy_addr; + phy_config(phydev); +#endif + status = macb_mdio_read(macb, MII_BMSR); if (!(status & BMSR_LSTATUS)) { /* Try to re-negotiate if we don't have link already. */ @@ -582,8 +593,9 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) eth_register(netdev); -#if defined(CONFIG_CMD_MII) +#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write); + macb->bus = miiphy_get_dev_by_name(netdev->name); #endif return 0; } -- cgit From d256be29f86b7c4e98435f7047a3e9c44dd7e0f4 Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Wed, 24 Apr 2013 15:59:28 +0800 Subject: 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 --- drivers/net/macb.c | 151 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 119 insertions(+), 32 deletions(-) (limited to 'drivers/net/macb.c') diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 6026825001..b7802a2fed 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); - - 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); -- cgit