diff options
Diffstat (limited to 'drivers/net/macb.c')
-rw-r--r-- | drivers/net/macb.c | 91 |
1 files changed, 79 insertions, 12 deletions
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index f9373db0b9..e62aefcd0d 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -52,6 +52,22 @@ DECLARE_GLOBAL_DATA_PTR; #define MACB_TX_TIMEOUT 1000 #define MACB_AUTONEG_TIMEOUT 5000000 +#ifdef CONFIG_MACB_ZYNQ +/* INCR4 AHB bursts */ +#define MACB_ZYNQ_GEM_DMACR_BLENGTH 0x00000004 +/* Use full configured addressable space (8 Kb) */ +#define MACB_ZYNQ_GEM_DMACR_RXSIZE 0x00000300 +/* Use full configured addressable space (4 Kb) */ +#define MACB_ZYNQ_GEM_DMACR_TXSIZE 0x00000400 +/* Set RXBUF with use of 128 byte */ +#define MACB_ZYNQ_GEM_DMACR_RXBUF 0x00020000 +#define MACB_ZYNQ_GEM_DMACR_INIT \ + (MACB_ZYNQ_GEM_DMACR_BLENGTH | \ + MACB_ZYNQ_GEM_DMACR_RXSIZE | \ + MACB_ZYNQ_GEM_DMACR_TXSIZE | \ + MACB_ZYNQ_GEM_DMACR_RXBUF) +#endif + struct macb_dma_desc { u32 addr; u32 ctrl; @@ -461,13 +477,25 @@ static int macb_phy_find(struct macb_device *macb, const char *name) phy_id = macb_mdio_read(macb, MII_PHYSID1); if (phy_id != 0xffff) { printf("%s: PHY present at %d\n", name, i); - return 1; + return 0; } } /* PHY isn't up to snuff */ printf("%s: PHY not found\n", name); + return -ENODEV; +} + +/** + * macb_linkspd_cb - Linkspeed change callback function + * @regs: Base Register of MACB devices + * @speed: Linkspeed + * Returns 0 when operation success and negative errno number + * when operation failed. + */ +int __weak macb_linkspd_cb(void *regs, unsigned int speed) +{ return 0; } @@ -483,18 +511,20 @@ static int macb_phy_init(struct macb_device *macb, const char *name) u32 ncfgr; u16 phy_id, status, adv, lpa; int media, speed, duplex; + int ret; int i; arch_get_mdio_control(name); /* Auto-detect phy_addr */ - if (!macb_phy_find(macb, name)) - return 0; + ret = macb_phy_find(macb, name); + if (ret) + return ret; /* Check if the PHY is up to snuff... */ phy_id = macb_mdio_read(macb, MII_PHYSID1); if (phy_id == 0xffff) { printf("%s: No PHY present\n", name); - return 0; + return -ENODEV; } #ifdef CONFIG_PHYLIB @@ -530,7 +560,7 @@ static int macb_phy_init(struct macb_device *macb, const char *name) if (!(status & BMSR_LSTATUS)) { printf("%s: link down (status: 0x%04x)\n", name, status); - return 0; + return -ENETDOWN; } /* First check for GMAC and that it is GiB capable */ @@ -554,7 +584,11 @@ static int macb_phy_init(struct macb_device *macb, const char *name) macb_writel(macb, NCFGR, ncfgr); - return 1; + ret = macb_linkspd_cb(macb->regs, _1000BASET); + if (ret) + return ret; + + return 0; } } @@ -573,13 +607,21 @@ static int macb_phy_init(struct macb_device *macb, const char *name) ncfgr = macb_readl(macb, NCFGR); ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE)); - if (speed) + if (speed) { ncfgr |= MACB_BIT(SPD); + ret = macb_linkspd_cb(macb->regs, _100BASET); + } else { + ret = macb_linkspd_cb(macb->regs, _10BASET); + } + + if (ret) + return ret; + if (duplex) ncfgr |= MACB_BIT(FD); macb_writel(macb, NCFGR, ncfgr); - return 1; + return 0; } static int gmac_init_multi_queues(struct macb_device *macb) @@ -616,6 +658,7 @@ static int _macb_init(struct macb_device *macb, const char *name) struct macb_device *macb = dev_get_priv(dev); #endif unsigned long paddr; + int ret; int i; /* @@ -649,6 +692,10 @@ static int _macb_init(struct macb_device *macb, const char *name) macb->tx_tail = 0; macb->next_rx_tail = 0; +#ifdef CONFIG_MACB_ZYNQ + macb_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT); +#endif + macb_writel(macb, RBQP, macb->rx_ring_dma); macb_writel(macb, TBQP, macb->tx_ring_dma); @@ -709,11 +756,12 @@ static int _macb_init(struct macb_device *macb, const char *name) } #ifdef CONFIG_DM_ETH - if (!macb_phy_init(dev, name)) + ret = macb_phy_init(dev, name); #else - if (!macb_phy_init(macb, name)) + ret = macb_phy_init(macb, name); #endif - return -1; + if (ret) + return ret; /* Enable TX and RX */ macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); @@ -1013,9 +1061,15 @@ static int macb_enable_clk(struct udevice *dev) if (ret) return -EINVAL; + /* + * Zynq clock driver didn't support for enable or disable + * clock. Hence, clk_enable() didn't apply for Zynq + */ +#ifndef CONFIG_MACB_ZYNQ ret = clk_enable(&clk); if (ret) return ret; +#endif clk_rate = clk_get_rate(&clk); if (!clk_rate) @@ -1083,12 +1137,24 @@ static int macb_eth_remove(struct udevice *dev) return 0; } +/** + * macb_late_eth_ofdata_to_platdata + * @dev: udevice struct + * Returns 0 when operation success and negative errno number + * when operation failed. + */ +int __weak macb_late_eth_ofdata_to_platdata(struct udevice *dev) +{ + return 0; +} + static int macb_eth_ofdata_to_platdata(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); pdata->iobase = devfdt_get_addr(dev); - return 0; + + return macb_late_eth_ofdata_to_platdata(dev); } static const struct udevice_id macb_eth_ids[] = { @@ -1097,6 +1163,7 @@ static const struct udevice_id macb_eth_ids[] = { { .compatible = "atmel,sama5d2-gem" }, { .compatible = "atmel,sama5d3-gem" }, { .compatible = "atmel,sama5d4-gem" }, + { .compatible = "cdns,zynq-gem" }, { } }; |