X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmacb.c;h=182331f61d15a9ae38755a5ecc803c0e182249ad;hb=cf8dcc5d02c32173b74bf1b7600dd2b990a90b13;hp=921537f8a436ec4c42b255283895da158e520ed1;hpb=0fcb9f07a1d086fc6951c08d2fc1cf6048bd54e2;p=oweals%2Fu-boot.git diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 921537f8a4..182331f61d 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -1,9 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2005-2006 Atmel Corporation - * - * SPDX-License-Identifier: GPL-2.0+ */ #include +#include #include /* @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include "macb.h" @@ -51,6 +51,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; @@ -110,8 +126,14 @@ struct macb_device { #endif unsigned short phy_addr; struct mii_dev *bus; +#ifdef CONFIG_PHYLIB + struct phy_device *phydev; +#endif #ifdef CONFIG_DM_ETH +#ifdef CONFIG_CLK + unsigned long pclk_rate; +#endif phy_interface_t phy_interface; #endif }; @@ -121,7 +143,7 @@ struct macb_device { static int macb_is_gem(struct macb_device *macb) { - return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) == 0x2; + return MACB_BFEXT(IDNUM, macb_readl(macb, MID)) >= 0x2; } #ifndef cpu_is_sama5d2 @@ -251,33 +273,35 @@ int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg, static inline void macb_invalidate_ring_desc(struct macb_device *macb, bool rx) { if (rx) - invalidate_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + - MACB_RX_DMA_DESC_SIZE); + invalidate_dcache_range(macb->rx_ring_dma, + ALIGN(macb->rx_ring_dma + MACB_RX_DMA_DESC_SIZE, + PKTALIGN)); else - invalidate_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + - MACB_TX_DMA_DESC_SIZE); + invalidate_dcache_range(macb->tx_ring_dma, + ALIGN(macb->tx_ring_dma + MACB_TX_DMA_DESC_SIZE, + PKTALIGN)); } static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx) { if (rx) flush_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + - MACB_RX_DMA_DESC_SIZE); + ALIGN(MACB_RX_DMA_DESC_SIZE, PKTALIGN)); else flush_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + - MACB_TX_DMA_DESC_SIZE); + ALIGN(MACB_TX_DMA_DESC_SIZE, PKTALIGN)); } static inline void macb_flush_rx_buffer(struct macb_device *macb) { flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + - MACB_RX_BUFFER_SIZE); + ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN)); } static inline void macb_invalidate_rx_buffer(struct macb_device *macb) { invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + - MACB_RX_BUFFER_SIZE); + ALIGN(MACB_RX_BUFFER_SIZE, PKTALIGN)); } #if defined(CONFIG_CMD_NET) @@ -441,7 +465,6 @@ static void macb_phy_reset(struct macb_device *macb, const char *name) name, status); } -#ifdef CONFIG_MACB_SEARCH_PHY static int macb_phy_find(struct macb_device *macb, const char *name) { int i; @@ -453,16 +476,27 @@ 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; } -#endif /* CONFIG_MACB_SEARCH_PHY */ #ifdef CONFIG_DM_ETH static int macb_phy_init(struct udevice *dev, const char *name) @@ -472,44 +506,41 @@ static int macb_phy_init(struct macb_device *macb, const char *name) { #ifdef CONFIG_DM_ETH struct macb_device *macb = dev_get_priv(dev); -#endif -#ifdef CONFIG_PHYLIB - struct phy_device *phydev; #endif u32 ncfgr; u16 phy_id, status, adv, lpa; int media, speed, duplex; + int ret; int i; arch_get_mdio_control(name); -#ifdef CONFIG_MACB_SEARCH_PHY /* Auto-detect phy_addr */ - if (!macb_phy_find(macb, name)) - return 0; -#endif /* CONFIG_MACB_SEARCH_PHY */ + 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 #ifdef CONFIG_DM_ETH - phydev = phy_connect(macb->bus, macb->phy_addr, dev, + macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev, macb->phy_interface); #else /* need to consider other phy interface mode */ - phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev, + macb->phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev, PHY_INTERFACE_MODE_RGMII); #endif - if (!phydev) { + if (!macb->phydev) { printf("phy_connect failed\n"); return -ENODEV; } - phy_config(phydev); + phy_config(macb->phydev); #endif status = macb_mdio_read(macb, MII_BMSR); @@ -528,7 +559,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 */ @@ -552,7 +583,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; } } @@ -571,13 +606,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) @@ -596,7 +639,7 @@ static int gmac_init_multi_queues(struct macb_device *macb) macb->dummy_desc->ctrl = TXBUF_USED; macb->dummy_desc->addr = 0; flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma + - MACB_TX_DUMMY_DMA_DESC_SIZE); + ALIGN(MACB_TX_DUMMY_DMA_DESC_SIZE, PKTALIGN)); for (i = 1; i < num_queues; i++) gem_writel_queue_TBQP(macb, macb->dummy_desc_dma, i - 1); @@ -614,6 +657,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; /* @@ -647,6 +691,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); @@ -661,7 +709,8 @@ static int _macb_init(struct macb_device *macb, const char *name) * to select interface between RMII and MII. */ #ifdef CONFIG_DM_ETH - if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) + if ((macb->phy_interface == PHY_INTERFACE_MODE_RMII) || + (macb->phy_interface == PHY_INTERFACE_MODE_RGMII)) gem_writel(macb, UR, GEM_BIT(RGMII)); else gem_writel(macb, UR, 0); @@ -706,11 +755,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)); @@ -752,7 +802,11 @@ static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr) static u32 macb_mdc_clk_div(int id, struct macb_device *macb) { u32 config; +#if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK) + unsigned long macb_hz = macb->pclk_rate; +#else unsigned long macb_hz = get_macb_pclk_rate(id); +#endif if (macb_hz < 20000000) config = MACB_BF(CLK, MACB_CLK_DIV8); @@ -769,7 +823,12 @@ static u32 macb_mdc_clk_div(int id, struct macb_device *macb) static u32 gem_mdc_clk_div(int id, struct macb_device *macb) { u32 config; + +#if defined(CONFIG_DM_ETH) && defined(CONFIG_CLK) + unsigned long macb_hz = macb->pclk_rate; +#else unsigned long macb_hz = get_macb_pclk_rate(id); +#endif if (macb_hz < 20000000) config = GEM_BF(CLK, GEM_CLK_DIV8); @@ -855,7 +914,7 @@ static int macb_recv(struct eth_device *netdev) if (length >= 0) { net_process_received_packet(packet, length); reclaim_rx_buffers(macb, macb->next_rx_tail); - } else if (length < 0) { + } else { return length; } } @@ -989,54 +1048,122 @@ static const struct eth_ops macb_eth_ops = { .write_hwaddr = macb_write_hwaddr, }; +#ifdef CONFIG_CLK +static int macb_enable_clk(struct udevice *dev) +{ + struct macb_device *macb = dev_get_priv(dev); + struct clk clk; + ulong clk_rate; + int ret; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return -EINVAL; + + /* + * If clock driver didn't support enable or disable then + * we get -ENOSYS from clk_enable(). To handle this, we + * don't fail for ret == -ENOSYS. + */ + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS) + return ret; + + clk_rate = clk_get_rate(&clk); + if (!clk_rate) + return -EINVAL; + + macb->pclk_rate = clk_rate; + + return 0; +} +#endif + static int macb_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); struct macb_device *macb = dev_get_priv(dev); - -#ifdef CONFIG_DM_ETH const char *phy_mode; + __maybe_unused int ret; - phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL); + phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", + NULL); if (phy_mode) macb->phy_interface = phy_get_interface_by_name(phy_mode); if (macb->phy_interface == -1) { debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); return -EINVAL; } -#endif macb->regs = (void *)pdata->iobase; +#ifdef CONFIG_CLK + ret = macb_enable_clk(dev); + if (ret) + return ret; +#endif + _macb_eth_initialize(macb); + #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) - int retval; - struct mii_dev *mdiodev = mdio_alloc(); - if (!mdiodev) + macb->bus = mdio_alloc(); + if (!macb->bus) return -ENOMEM; - strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); - mdiodev->read = macb_miiphy_read; - mdiodev->write = macb_miiphy_write; + strncpy(macb->bus->name, dev->name, MDIO_NAME_LEN); + macb->bus->read = macb_miiphy_read; + macb->bus->write = macb_miiphy_write; - retval = mdio_register(mdiodev); - if (retval < 0) - return retval; + ret = mdio_register(macb->bus); + if (ret < 0) + return ret; macb->bus = miiphy_get_dev_by_name(dev->name); #endif return 0; } +static int macb_eth_remove(struct udevice *dev) +{ + struct macb_device *macb = dev_get_priv(dev); + +#ifdef CONFIG_PHYLIB + free(macb->phydev); +#endif + mdio_unregister(macb->bus); + mdio_free(macb->bus); + + 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 = dev_get_addr(dev); - return 0; + pdata->iobase = (phys_addr_t)dev_remap_addr(dev); + if (!pdata->iobase) + return -EINVAL; + + return macb_late_eth_ofdata_to_platdata(dev); } static const struct udevice_id macb_eth_ids[] = { { .compatible = "cdns,macb" }, + { .compatible = "cdns,at91sam9260-macb" }, + { .compatible = "atmel,sama5d2-gem" }, + { .compatible = "atmel,sama5d3-gem" }, + { .compatible = "atmel,sama5d4-gem" }, + { .compatible = "cdns,zynq-gem" }, { } }; @@ -1046,6 +1173,7 @@ U_BOOT_DRIVER(eth_macb) = { .of_match = macb_eth_ids, .ofdata_to_platdata = macb_eth_ofdata_to_platdata, .probe = macb_eth_probe, + .remove = macb_eth_remove, .ops = &macb_eth_ops, .priv_auto_alloc_size = sizeof(struct macb_device), .platdata_auto_alloc_size = sizeof(struct eth_pdata),