]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
net: macb: Add DMA 64-bit address support for macb
authorPadmarao Begari <padmarao.begari@microchip.com>
Fri, 15 Jan 2021 02:50:36 +0000 (08:20 +0530)
committerAndes <uboot@andestech.com>
Mon, 18 Jan 2021 03:06:38 +0000 (11:06 +0800)
Enable 32-bit or 64-bit DMA in the macb driver based on the macb
hardware compatibility and it is configured with structure macb_config
in the driver.

The Microchip PolarFire SoC Memory Protection Unit(MPU) gives the 64-bit
DMA access with the GEM, the MPU transactions on the AXI bus is 64-bit
not 32-bit So 64-bit DMA is enabled for the Microchip PolarFire SoC GEM.

Signed-off-by: Padmarao Begari <padmarao.begari@microchip.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
Tested-by: Bin Meng <bin.meng@windriver.com>
drivers/net/macb.c
drivers/net/macb.h

index e287c29e69fa170991899576a2d2c611cfc07d46..0c2ac811fb125a74fd6017361556121a45b53b2e 100644 (file)
@@ -83,7 +83,16 @@ struct macb_dma_desc {
        u32     ctrl;
 };
 
-#define DMA_DESC_BYTES(n)      (n * sizeof(struct macb_dma_desc))
+struct macb_dma_desc_64 {
+       u32 addrh;
+       u32 unused;
+};
+
+#define HW_DMA_CAP_32B         0
+#define HW_DMA_CAP_64B         1
+
+#define DMA_DESC_SIZE          16
+#define DMA_DESC_BYTES(n)      ((n) * DMA_DESC_SIZE)
 #define MACB_TX_DMA_DESC_SIZE  (DMA_DESC_BYTES(MACB_TX_RING_SIZE))
 #define MACB_RX_DMA_DESC_SIZE  (DMA_DESC_BYTES(MACB_RX_RING_SIZE))
 #define MACB_TX_DUMMY_DMA_DESC_SIZE    (DMA_DESC_BYTES(1))
@@ -137,6 +146,7 @@ struct macb_device {
 
 struct macb_config {
        unsigned int            dma_burst_length;
+       unsigned int            hw_dma_cap;
 
        int                     (*clk_init)(struct udevice *dev, ulong rate);
 };
@@ -307,6 +317,24 @@ static inline void macb_invalidate_rx_buffer(struct macb_device *macb)
 
 #if defined(CONFIG_CMD_NET)
 
+static struct macb_dma_desc_64 *macb_64b_desc(struct macb_dma_desc *desc)
+{
+       return (struct macb_dma_desc_64 *)((void *)desc
+               + sizeof(struct macb_dma_desc));
+}
+
+static void macb_set_addr(struct macb_device *macb, struct macb_dma_desc *desc,
+                         ulong addr)
+{
+       struct macb_dma_desc_64 *desc_64;
+
+       if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+               desc_64 = macb_64b_desc(desc);
+               desc_64->addrh = upper_32_bits(addr);
+       }
+       desc->addr = lower_32_bits(addr);
+}
+
 static int _macb_send(struct macb_device *macb, const char *name, void *packet,
                      int length)
 {
@@ -325,8 +353,12 @@ static int _macb_send(struct macb_device *macb, const char *name, void *packet,
                macb->tx_head++;
        }
 
+       if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+               tx_head = tx_head * 2;
+
        macb->tx_ring[tx_head].ctrl = ctrl;
-       macb->tx_ring[tx_head].addr = paddr;
+       macb_set_addr(macb, &macb->tx_ring[tx_head], paddr);
+
        barrier();
        macb_flush_ring_desc(macb, TX);
        macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
@@ -363,19 +395,28 @@ static void reclaim_rx_buffers(struct macb_device *macb,
                               unsigned int new_tail)
 {
        unsigned int i;
+       unsigned int count;
 
        i = macb->rx_tail;
 
        macb_invalidate_ring_desc(macb, RX);
        while (i > new_tail) {
-               macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED);
+               if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+                       count = i * 2;
+               else
+                       count = i;
+               macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED);
                i++;
                if (i > MACB_RX_RING_SIZE)
                        i = 0;
        }
 
        while (i < new_tail) {
-               macb->rx_ring[i].addr &= ~MACB_BIT(RX_USED);
+               if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+                       count = i * 2;
+               else
+                       count = i;
+               macb->rx_ring[count].addr &= ~MACB_BIT(RX_USED);
                i++;
        }
 
@@ -390,16 +431,25 @@ static int _macb_recv(struct macb_device *macb, uchar **packetp)
        void *buffer;
        int length;
        u32 status;
+       u8 flag = false;
 
        macb->wrapped = false;
        for (;;) {
                macb_invalidate_ring_desc(macb, RX);
 
+               if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+                       next_rx_tail = next_rx_tail * 2;
+
                if (!(macb->rx_ring[next_rx_tail].addr & MACB_BIT(RX_USED)))
                        return -EAGAIN;
 
                status = macb->rx_ring[next_rx_tail].ctrl;
                if (status & MACB_BIT(RX_SOF)) {
+                       if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+                               next_rx_tail = next_rx_tail / 2;
+                               flag = true;
+                       }
+
                        if (next_rx_tail != macb->rx_tail)
                                reclaim_rx_buffers(macb, next_rx_tail);
                        macb->wrapped = false;
@@ -426,11 +476,22 @@ static int _macb_recv(struct macb_device *macb, uchar **packetp)
                                *packetp = buffer;
                        }
 
+                       if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+                               if (!flag)
+                                       next_rx_tail = next_rx_tail / 2;
+                       }
+
                        if (++next_rx_tail >= MACB_RX_RING_SIZE)
                                next_rx_tail = 0;
                        macb->next_rx_tail = next_rx_tail;
                        return length;
                } else {
+                       if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+                               if (!flag)
+                                       next_rx_tail = next_rx_tail / 2;
+                               flag = false;
+                       }
+
                        if (++next_rx_tail >= MACB_RX_RING_SIZE) {
                                macb->wrapped = true;
                                next_rx_tail = 0;
@@ -718,6 +779,7 @@ static int gmac_init_multi_queues(struct macb_device *macb)
 {
        int i, num_queues = 1;
        u32 queue_mask;
+       unsigned long paddr;
 
        /* bit 0 is never set but queue 0 always exists */
        queue_mask = gem_readl(macb, DCFG6) & 0xff;
@@ -731,10 +793,18 @@ static int gmac_init_multi_queues(struct macb_device *macb)
        macb->dummy_desc->addr = 0;
        flush_dcache_range(macb->dummy_desc_dma, macb->dummy_desc_dma +
                        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);
-
+       paddr = macb->dummy_desc_dma;
+
+       for (i = 1; i < num_queues; i++) {
+               gem_writel_queue_TBQP(macb, lower_32_bits(paddr), i - 1);
+               gem_writel_queue_RBQP(macb, lower_32_bits(paddr), i - 1);
+               if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+                       gem_writel_queue_TBQPH(macb, upper_32_bits(paddr),
+                                              i - 1);
+                       gem_writel_queue_RBQPH(macb, upper_32_bits(paddr),
+                                              i - 1);
+               }
+       }
        return 0;
 }
 
@@ -760,6 +830,9 @@ static void gmac_configure_dma(struct macb_device *macb)
                dmacfg &= ~GEM_BIT(ENDIA_DESC);
 
        dmacfg &= ~GEM_BIT(ADDR64);
+       if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+               dmacfg |= GEM_BIT(ADDR64);
+
        gem_writel(macb, DMACFG, dmacfg);
 }
 
@@ -775,6 +848,7 @@ static int _macb_init(struct macb_device *macb, const char *name)
        unsigned long paddr;
        int ret;
        int i;
+       int count;
 
        /*
         * macb_halt should have been called at some point before now,
@@ -786,20 +860,28 @@ static int _macb_init(struct macb_device *macb, const char *name)
        for (i = 0; i < MACB_RX_RING_SIZE; i++) {
                if (i == (MACB_RX_RING_SIZE - 1))
                        paddr |= MACB_BIT(RX_WRAP);
-               macb->rx_ring[i].addr = paddr;
-               macb->rx_ring[i].ctrl = 0;
+               if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+                       count = i * 2;
+               else
+                       count = i;
+               macb->rx_ring[count].ctrl = 0;
+               macb_set_addr(macb, &macb->rx_ring[count], paddr);
                paddr += macb->rx_buffer_size;
        }
        macb_flush_ring_desc(macb, RX);
        macb_flush_rx_buffer(macb);
 
        for (i = 0; i < MACB_TX_RING_SIZE; i++) {
-               macb->tx_ring[i].addr = 0;
+               if (macb->config->hw_dma_cap & HW_DMA_CAP_64B)
+                       count = i * 2;
+               else
+                       count = i;
+               macb_set_addr(macb, &macb->tx_ring[count], 0);
                if (i == (MACB_TX_RING_SIZE - 1))
-                       macb->tx_ring[i].ctrl = MACB_BIT(TX_USED) |
+                       macb->tx_ring[count].ctrl = MACB_BIT(TX_USED) |
                                MACB_BIT(TX_WRAP);
                else
-                       macb->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+                       macb->tx_ring[count].ctrl = MACB_BIT(TX_USED);
        }
        macb_flush_ring_desc(macb, TX);
 
@@ -812,8 +894,12 @@ static int _macb_init(struct macb_device *macb, const char *name)
        gem_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);
+       macb_writel(macb, RBQP, lower_32_bits(macb->rx_ring_dma));
+       macb_writel(macb, TBQP, lower_32_bits(macb->tx_ring_dma));
+       if (macb->config->hw_dma_cap & HW_DMA_CAP_64B) {
+               macb_writel(macb, RBQPH, upper_32_bits(macb->rx_ring_dma));
+               macb_writel(macb, TBQPH, upper_32_bits(macb->tx_ring_dma));
+       }
 
        if (macb_is_gem(macb)) {
                /* Initialize DMA properties */
@@ -1217,6 +1303,7 @@ static int macb_enable_clk(struct udevice *dev)
 
 static const struct macb_config default_gem_config = {
        .dma_burst_length = 16,
+       .hw_dma_cap = HW_DMA_CAP_32B,
        .clk_init = NULL,
 };
 
@@ -1227,8 +1314,8 @@ static int macb_eth_probe(struct udevice *dev)
        const char *phy_mode;
        int ret;
 
-       phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
-                              NULL);
+       phy_mode = dev_read_prop(dev, "phy-mode", NULL);
+
        if (phy_mode)
                macb->phy_interface = phy_get_interface_by_name(phy_mode);
        if (macb->phy_interface == -1) {
@@ -1304,13 +1391,21 @@ static int macb_eth_of_to_plat(struct udevice *dev)
        return macb_late_eth_of_to_plat(dev);
 }
 
+static const struct macb_config microchip_config = {
+       .dma_burst_length = 16,
+       .hw_dma_cap = HW_DMA_CAP_64B,
+       .clk_init = NULL,
+};
+
 static const struct macb_config sama5d4_config = {
        .dma_burst_length = 4,
+       .hw_dma_cap = HW_DMA_CAP_32B,
        .clk_init = NULL,
 };
 
 static const struct macb_config sifive_config = {
        .dma_burst_length = 16,
+       .hw_dma_cap = HW_DMA_CAP_32B,
        .clk_init = macb_sifive_clk_init,
 };
 
@@ -1324,6 +1419,8 @@ static const struct udevice_id macb_eth_ids[] = {
        { .compatible = "cdns,zynq-gem" },
        { .compatible = "sifive,fu540-c000-gem",
          .data = (ulong)&sifive_config },
+       { .compatible = "microchip,mpfs-mss-gem",
+         .data = (ulong)&microchip_config },
        { }
 };
 
index 9b16383eba469f56cd4a973677e29634f2d11d50..72b84ae96edcfed123612a359952a1b98e3cb19f 100644 (file)
 #define GEM_RX_CSUM_CHECKED_MASK               2
 #define gem_writel_queue_TBQP(port, value, queue_num)  \
        writel((value), (port)->regs + GEM_TBQP(queue_num))
+#define gem_writel_queue_TBQPH(port, value, queue_num) \
+       writel((value), (port)->regs + GEM_TBQPH(queue_num))
+#define gem_writel_queue_RBQP(port, value, queue_num)  \
+       writel((value), (port)->regs + GEM_RBQP(queue_num))
+#define gem_writel_queue_RBQPH(port, value, queue_num) \
+       writel((value), (port)->regs + GEM_RBQPH(queue_num))
 
 #endif /* __DRIVERS_MACB_H__ */