]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
net: macb: Add support for PTP timestamps in DMA descriptors
authorRafal Ozieblo <rafalo@cadence.com>
Thu, 29 Jun 2017 06:12:51 +0000 (07:12 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 30 Jun 2017 17:11:41 +0000 (13:11 -0400)
This patch adds support for PTP timestamps in
DMA buffer descriptors. It checks capability at runtime
and uses appropriate buffer descriptor.

Signed-off-by: Rafal Ozieblo <rafalo@cadence.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h

index 608bea171956873508256e024c11e0de2396c119..427d65a1a1261095a402b833660c83da0113e4c7 100644 (file)
@@ -29,7 +29,15 @@ config MACB
          support for the MACB/GEM chip.
 
          To compile this driver as a module, choose M here: the module
-         will be called macb.
+         will be macb.
+
+config MACB_USE_HWSTAMP
+       bool "Use IEEE 1588 hwstamp"
+       depends on MACB
+       default y
+       imply PTP_1588_CLOCK
+       ---help---
+         Enable IEEE 1588 Precision Time Protocol (PTP) support for MACB.
 
 config MACB_PCI
        tristate "Cadence PCI MACB/GEM support"
index 3ae9d8071ded533c317eb5a39d1900bb99510db3..2d43a7619f58abed1a20e219c7cfba1e23d89d88 100644 (file)
 #define MACB_HALT_TIMEOUT      1230
 
 /* DMA buffer descriptor might be different size
- * depends on hardware configuration.
+ * depends on hardware configuration:
+ *
+ * 1. dma address width 32 bits:
+ *    word 1: 32 bit address of Data Buffer
+ *    word 2: control
+ *
+ * 2. dma address width 64 bits:
+ *    word 1: 32 bit address of Data Buffer
+ *    word 2: control
+ *    word 3: upper 32 bit address of Data Buffer
+ *    word 4: unused
+ *
+ * 3. dma address width 32 bits with hardware timestamping:
+ *    word 1: 32 bit address of Data Buffer
+ *    word 2: control
+ *    word 3: timestamp word 1
+ *    word 4: timestamp word 2
+ *
+ * 4. dma address width 64 bits with hardware timestamping:
+ *    word 1: 32 bit address of Data Buffer
+ *    word 2: control
+ *    word 3: upper 32 bit address of Data Buffer
+ *    word 4: unused
+ *    word 5: timestamp word 1
+ *    word 6: timestamp word 2
  */
 static unsigned int macb_dma_desc_get_size(struct macb *bp)
 {
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
-               return sizeof(struct macb_dma_desc) + sizeof(struct macb_dma_desc_64);
+#ifdef MACB_EXT_DESC
+       unsigned int desc_size;
+
+       switch (bp->hw_dma_cap) {
+       case HW_DMA_CAP_64B:
+               desc_size = sizeof(struct macb_dma_desc)
+                       + sizeof(struct macb_dma_desc_64);
+               break;
+       case HW_DMA_CAP_PTP:
+               desc_size = sizeof(struct macb_dma_desc)
+                       + sizeof(struct macb_dma_desc_ptp);
+               break;
+       case HW_DMA_CAP_64B_PTP:
+               desc_size = sizeof(struct macb_dma_desc)
+                       + sizeof(struct macb_dma_desc_64)
+                       + sizeof(struct macb_dma_desc_ptp);
+               break;
+       default:
+               desc_size = sizeof(struct macb_dma_desc);
+       }
+       return desc_size;
 #endif
        return sizeof(struct macb_dma_desc);
 }
 
-static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int idx)
+static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int desc_idx)
 {
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       /* Dma buffer descriptor is 4 words length (instead of 2 words)
-        * for 64b GEM.
-        */
-       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
-               idx <<= 1;
+#ifdef MACB_EXT_DESC
+       switch (bp->hw_dma_cap) {
+       case HW_DMA_CAP_64B:
+       case HW_DMA_CAP_PTP:
+               desc_idx <<= 1;
+               break;
+       case HW_DMA_CAP_64B_PTP:
+               desc_idx *= 3;
+               break;
+       default:
+               break;
+       }
+       return desc_idx;
 #endif
-       return idx;
+       return desc_idx;
 }
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)
 {
-       return (struct macb_dma_desc_64 *)((void *)desc + sizeof(struct macb_dma_desc));
+       if (bp->hw_dma_cap & HW_DMA_CAP_64B)
+               return (struct macb_dma_desc_64 *)((void *)desc + sizeof(struct macb_dma_desc));
+       return NULL;
 }
 #endif
 
@@ -621,7 +672,7 @@ static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
        struct macb_dma_desc_64 *desc_64;
 
-       if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+       if (bp->hw_dma_cap & HW_DMA_CAP_64B) {
                desc_64 = macb_64b_desc(bp, desc);
                desc_64->addrh = upper_32_bits(addr);
        }
@@ -635,7 +686,7 @@ static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc *desc)
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
        struct macb_dma_desc_64 *desc_64;
 
-       if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+       if (bp->hw_dma_cap & HW_DMA_CAP_64B) {
                desc_64 = macb_64b_desc(bp, desc);
                addr = ((u64)(desc_64->addrh) << 32);
        }
@@ -734,7 +785,7 @@ static void macb_tx_error_task(struct work_struct *work)
        /* Reinitialize the TX desc queue */
        queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+       if (bp->hw_dma_cap & HW_DMA_CAP_64B)
                queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
 #endif
        /* Make TX ring reflect state of hardware */
@@ -1942,8 +1993,12 @@ static void macb_configure_dma(struct macb *bp)
                        dmacfg &= ~GEM_BIT(TXCOEN);
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-               if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+               if (bp->hw_dma_cap & HW_DMA_CAP_64B)
                        dmacfg |= GEM_BIT(ADDR64);
+#endif
+#ifdef CONFIG_MACB_USE_HWSTAMP
+               if (bp->hw_dma_cap & HW_DMA_CAP_PTP)
+                       dmacfg |= GEM_BIT(RXEXT) | GEM_BIT(TXEXT);
 #endif
                netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
                           dmacfg);
@@ -1992,13 +2047,13 @@ static void macb_init_hw(struct macb *bp)
        /* Initialize TX and RX buffers */
        macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+       if (bp->hw_dma_cap & HW_DMA_CAP_64B)
                macb_writel(bp, RBQPH, upper_32_bits(bp->rx_ring_dma));
 #endif
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
                queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-               if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+               if (bp->hw_dma_cap & HW_DMA_CAP_64B)
                        queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
 #endif
 
@@ -2600,6 +2655,12 @@ static void macb_configure_caps(struct macb *bp,
                dcfg = gem_readl(bp, DCFG2);
                if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
                        bp->caps |= MACB_CAPS_FIFO_MODE;
+               if (IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) && gem_has_ptp(bp)) {
+                       if (!GEM_BFEXT(TSU, gem_readl(bp, DCFG5)))
+                               pr_err("GEM doesn't support hardware ptp.\n");
+                       else
+                               bp->hw_dma_cap |= HW_DMA_CAP_PTP;
+               }
        }
 
        dev_dbg(&bp->pdev->dev, "Cadence caps 0x%08x\n", bp->caps);
@@ -2737,7 +2798,7 @@ static int macb_init(struct platform_device *pdev)
                        queue->IMR  = GEM_IMR(hw_q - 1);
                        queue->TBQP = GEM_TBQP(hw_q - 1);
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-                       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+                       if (bp->hw_dma_cap & HW_DMA_CAP_64B)
                                queue->TBQPH = GEM_TBQPH(hw_q - 1);
 #endif
                } else {
@@ -2748,7 +2809,7 @@ static int macb_init(struct platform_device *pdev)
                        queue->IMR  = MACB_IMR;
                        queue->TBQP = MACB_TBQP;
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-                       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+                       if (bp->hw_dma_cap & HW_DMA_CAP_64B)
                                queue->TBQPH = MACB_TBQPH;
 #endif
                }
@@ -3328,19 +3389,17 @@ static int macb_probe(struct platform_device *pdev)
                bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
        device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
 
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
-               dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
-               bp->hw_dma_cap = HW_DMA_CAP_64B;
-       } else
-               bp->hw_dma_cap = HW_DMA_CAP_32B;
-#endif
-
        spin_lock_init(&bp->lock);
 
        /* setup capabilities */
        macb_configure_caps(bp, macb_config);
 
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+       if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
+               dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+               bp->hw_dma_cap |= HW_DMA_CAP_64B;
+       }
+#endif
        platform_set_drvdata(pdev, dev);
 
        dev->irq = platform_get_irq(pdev, 0);
index 2510661102bade67116d5e85bd551d10c64ad54b..3aefa380f345353edc08c0591e8ec242cc83db0f 100644 (file)
 
 #include <linux/phy.h>
 
+#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) || defined(CONFIG_MACB_USE_HWSTAMP)
+#define MACB_EXT_DESC
+#endif
+
 #define MACB_GREGS_NBR 16
 #define MACB_GREGS_VERSION 2
 #define MACB_MAX_QUEUES 8
 #define GEM_RXBS_SIZE          8
 #define GEM_DDRP_OFFSET                24 /* disc_when_no_ahb */
 #define GEM_DDRP_SIZE          1
+#define GEM_RXEXT_OFFSET       28 /* RX extended Buffer Descriptor mode */
+#define GEM_RXEXT_SIZE         1
+#define GEM_TXEXT_OFFSET       29 /* TX extended Buffer Descriptor mode */
+#define GEM_TXEXT_SIZE         1
 #define GEM_ADDR64_OFFSET      30 /* Address bus width - 64b or 32b */
 #define GEM_ADDR64_SIZE                1
 
 #define GEM_TX_PKT_BUFF_OFFSET                 21
 #define GEM_TX_PKT_BUFF_SIZE                   1
 
+
+/* Bitfields in DCFG5. */
+#define GEM_TSU_OFFSET                         8
+#define GEM_TSU_SIZE                           1
+
 /* Bitfields in DCFG6. */
 #define GEM_PBUF_LSO_OFFSET                    27
 #define GEM_PBUF_LSO_SIZE                      1
@@ -546,16 +559,21 @@ struct macb_dma_desc {
        u32     ctrl;
 };
 
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-enum macb_hw_dma_cap {
-       HW_DMA_CAP_32B,
-       HW_DMA_CAP_64B,
-};
+#ifdef MACB_EXT_DESC
+#define HW_DMA_CAP_32B         0
+#define HW_DMA_CAP_64B         (1 << 0)
+#define HW_DMA_CAP_PTP         (1 << 1)
+#define HW_DMA_CAP_64B_PTP     (HW_DMA_CAP_64B | HW_DMA_CAP_PTP)
 
 struct macb_dma_desc_64 {
        u32 addrh;
        u32 resvd;
 };
+
+struct macb_dma_desc_ptp {
+       u32     ts_1;
+       u32     ts_2;
+};
 #endif
 
 /* DMA descriptor bitfields */
@@ -955,8 +973,8 @@ struct macb {
        u32                     wol;
 
        struct macb_ptp_info    *ptp_info;      /* macb-ptp interface */
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       enum macb_hw_dma_cap hw_dma_cap;
+#ifdef MACB_EXT_DESC
+       uint8_t hw_dma_cap;
 #endif
 };