net: macb: Add support for Xilinx Zynq SoC
authorWilson Lee <wilson.lee@ni.com>
Wed, 23 Aug 2017 03:25:07 +0000 (20:25 -0700)
committerJoe Hershberger <joe.hershberger@ni.com>
Mon, 15 Jan 2018 18:05:14 +0000 (12:05 -0600)
Although Xilinx Zynq SoC was using MACB similar hardware. However,
U-boot MACB driver was not supporting Xilinx Zynq SoC. This patch is
to add support for the Xilinx Zynq SoC to the existing MACB network
driver.

This patch is to add Zynq GEM DMA Config, provide callback
function for different linkspeed for case of using Xilinx Zynq
Programmable Logic as GMII to RGMII converter.

This patch convert the return value to use error codes.

Signed-off-by: Wilson Lee <wilson.lee@ni.com>
Cc: Chen Yee Chew <chen.yee.chew@ni.com>
Cc: Keng Soon Cheah <keng.soon.cheah@ni.com>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Wenyou Yang <wenyou.yang@atmel.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
drivers/net/Kconfig
drivers/net/macb.c
drivers/net/macb.h

index 46b17b17ada2f66645caf3e2634245b3ada6180b..c47d59c249e417cf05b53860482fe5d1de0479fa 100644 (file)
@@ -185,6 +185,13 @@ config MACB
          GEM (Gigabit Ethernet MAC) found in some ARM SoC devices.
          Say Y to include support for the MACB/GEM chip.
 
+config MACB_ZYNQ
+       bool "Cadence MACB/GEM Ethernet Interface for Xilinx Zynq"
+       depends on MACB
+       help
+         The Cadence MACB ethernet interface was used on Zynq platform.
+         Say Y to enable support for the MACB/GEM in Zynq chip.
+
 config PCH_GBE
        bool "Intel Platform Controller Hub EG20T GMAC driver"
        depends on DM_ETH && DM_PCI
index f9373db0b9370e7afcca58caba2c3928817b87d0..e62aefcd0d6cadf257dd56807983c5a5b830f9e4 100644 (file)
@@ -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" },
        { }
 };
 
index 5bb48f449c872117081e4f79345566a924e2bb84..c39554df5fccc9039b8b5a980f4c6063c09c3682 100644 (file)
@@ -11,6 +11,7 @@
 #define MACB_NCFGR                             0x0004
 #define MACB_NSR                               0x0008
 #define GEM_UR                                 0x000c
+#define MACB_DMACFG                            0x0010
 #define MACB_TSR                               0x0014
 #define MACB_RBQP                              0x0018
 #define MACB_TBQP                              0x001c