net: netcp: add support for phy with rgmii ids
[oweals/u-boot.git] / drivers / net / zynq_gem.c
index ee528dbc594a3cae08994e36cac40defb183d99e..3bd0093b7ab1e001939136e140fcf52b0a37e53c 100644 (file)
@@ -102,6 +102,8 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define ZYNQ_GEM_PCS_CTL_ANEG_ENBL     0x1000
 
+#define ZYNQ_GEM_DCFG_DBG6_DMA_64B     BIT(23)
+
 /* Use MII register 1 (MII status register) to detect PHY */
 #define PHY_DETECT_REG  1
 
@@ -150,7 +152,9 @@ struct zynq_gem_regs {
        u32 stat[STAT_SIZE]; /* 0x100 - Octects transmitted Low reg */
        u32 reserved9[20];
        u32 pcscntrl;
-       u32 reserved7[143];
+       u32 rserved12[36];
+       u32 dcfg6; /* 0x294 Design config reg6 */
+       u32 reserved7[106];
        u32 transmit_q1_ptr; /* 0x440 - Transmit priority queue 1 */
        u32 reserved8[15];
        u32 receive_q1_ptr; /* 0x480 - Receive priority queue 1 */
@@ -198,6 +202,7 @@ struct zynq_gem_priv {
        struct clk clk;
        u32 max_speed;
        bool int_pcs;
+       bool dma_64bit;
 };
 
 static int phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
@@ -378,6 +383,23 @@ static int zynq_gem_init(struct udevice *dev)
        struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
        struct emac_bd *dummy_rx_bd = &priv->tx_bd[TX_FREE_DESC + 2];
 
+       if (readl(&regs->dcfg6) & ZYNQ_GEM_DCFG_DBG6_DMA_64B)
+               priv->dma_64bit = true;
+       else
+               priv->dma_64bit = false;
+
+#if defined(CONFIG_PHYS_64BIT)
+       if (!priv->dma_64bit) {
+               printf("ERR: %s: Using 64-bit DMA but HW doesn't support it\n",
+                      __func__);
+               return -EINVAL;
+       }
+#else
+       if (priv->dma_64bit)
+               debug("WARN: %s: Not using 64-bit dma even HW supports it\n",
+                     __func__);
+#endif
+
        if (!priv->init) {
                /* Disable all interrupts */
                writel(0xFFFFFFFF, &regs->idr);
@@ -548,11 +570,6 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
        addr &= ~(ARCH_DMA_MINALIGN - 1);
        size = roundup(len, ARCH_DMA_MINALIGN);
        flush_dcache_range(addr, addr + size);
-
-       addr = (ulong)priv->rxbuffers;
-       addr &= ~(ARCH_DMA_MINALIGN - 1);
-       size = roundup((RX_BUF * PKTSIZE_ALIGN), ARCH_DMA_MINALIGN);
-       flush_dcache_range(addr, addr + size);
        barrier();
 
        /* Start transmit */
@@ -599,6 +616,9 @@ static int zynq_gem_recv(struct udevice *dev, int flags, uchar **packetp)
 
        *packetp = (uchar *)(uintptr_t)addr;
 
+       invalidate_dcache_range(addr, addr + roundup(PKTSIZE_ALIGN, ARCH_DMA_MINALIGN));
+       barrier();
+
        return frame_len;
 }
 
@@ -684,6 +704,9 @@ static int zynq_gem_probe(struct udevice *dev)
                return -ENOMEM;
 
        memset(priv->rxbuffers, 0, RX_BUF * PKTSIZE_ALIGN);
+       u32 addr = (ulong)priv->rxbuffers;
+       flush_dcache_range(addr, addr + roundup(RX_BUF * PKTSIZE_ALIGN, ARCH_DMA_MINALIGN));
+       barrier();
 
        /* Align bd_space to MMU_SECTION_SHIFT */
        bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);