net: macb: Add support for PTP timestamps in DMA descriptors

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>
This commit is contained in:
Rafal Ozieblo 2017-06-29 07:12:51 +01:00 committed by David S. Miller
parent b079115937
commit 7b42961480
3 changed files with 122 additions and 37 deletions

View File

@ -29,7 +29,15 @@ config MACB
support for the MACB/GEM chip. support for the MACB/GEM chip.
To compile this driver as a module, choose M here: the module 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 config MACB_PCI
tristate "Cadence PCI MACB/GEM support" tristate "Cadence PCI MACB/GEM support"

View File

@ -79,33 +79,84 @@
#define MACB_HALT_TIMEOUT 1230 #define MACB_HALT_TIMEOUT 1230
/* DMA buffer descriptor might be different size /* 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) static unsigned int macb_dma_desc_get_size(struct macb *bp)
{ {
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #ifdef MACB_EXT_DESC
if (bp->hw_dma_cap == HW_DMA_CAP_64B) unsigned int desc_size;
return sizeof(struct macb_dma_desc) + sizeof(struct macb_dma_desc_64);
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 #endif
return sizeof(struct macb_dma_desc); 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 #ifdef MACB_EXT_DESC
/* Dma buffer descriptor is 4 words length (instead of 2 words) switch (bp->hw_dma_cap) {
* for 64b GEM. case HW_DMA_CAP_64B:
*/ case HW_DMA_CAP_PTP:
if (bp->hw_dma_cap == HW_DMA_CAP_64B) desc_idx <<= 1;
idx <<= 1; break;
case HW_DMA_CAP_64B_PTP:
desc_idx *= 3;
break;
default:
break;
}
return desc_idx;
#endif #endif
return idx; return desc_idx;
} }
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc) 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 #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 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
struct macb_dma_desc_64 *desc_64; 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 = macb_64b_desc(bp, desc);
desc_64->addrh = upper_32_bits(addr); 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 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
struct macb_dma_desc_64 *desc_64; 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 = macb_64b_desc(bp, desc);
addr = ((u64)(desc_64->addrh) << 32); 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 */ /* Reinitialize the TX desc queue */
queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma)); queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #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)); queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
#endif #endif
/* Make TX ring reflect state of hardware */ /* Make TX ring reflect state of hardware */
@ -1942,8 +1993,12 @@ static void macb_configure_dma(struct macb *bp)
dmacfg &= ~GEM_BIT(TXCOEN); dmacfg &= ~GEM_BIT(TXCOEN);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #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); 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 #endif
netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n", netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
dmacfg); dmacfg);
@ -1992,13 +2047,13 @@ static void macb_init_hw(struct macb *bp)
/* Initialize TX and RX buffers */ /* Initialize TX and RX buffers */
macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma)); macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma));
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #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)); macb_writel(bp, RBQPH, upper_32_bits(bp->rx_ring_dma));
#endif #endif
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma)); queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #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)); queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
#endif #endif
@ -2600,6 +2655,12 @@ static void macb_configure_caps(struct macb *bp,
dcfg = gem_readl(bp, DCFG2); dcfg = gem_readl(bp, DCFG2);
if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0) if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
bp->caps |= MACB_CAPS_FIFO_MODE; 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); 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->IMR = GEM_IMR(hw_q - 1);
queue->TBQP = GEM_TBQP(hw_q - 1); queue->TBQP = GEM_TBQP(hw_q - 1);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #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); queue->TBQPH = GEM_TBQPH(hw_q - 1);
#endif #endif
} else { } else {
@ -2748,7 +2809,7 @@ static int macb_init(struct platform_device *pdev)
queue->IMR = MACB_IMR; queue->IMR = MACB_IMR;
queue->TBQP = MACB_TBQP; queue->TBQP = MACB_TBQP;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #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; queue->TBQPH = MACB_TBQPH;
#endif #endif
} }
@ -3328,19 +3389,17 @@ static int macb_probe(struct platform_device *pdev)
bp->wol |= MACB_WOL_HAS_MAGIC_PACKET; bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
device_init_wakeup(&pdev->dev, 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); spin_lock_init(&bp->lock);
/* setup capabilities */ /* setup capabilities */
macb_configure_caps(bp, macb_config); 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); platform_set_drvdata(pdev, dev);
dev->irq = platform_get_irq(pdev, 0); dev->irq = platform_get_irq(pdev, 0);

View File

@ -12,6 +12,10 @@
#include <linux/phy.h> #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_NBR 16
#define MACB_GREGS_VERSION 2 #define MACB_GREGS_VERSION 2
#define MACB_MAX_QUEUES 8 #define MACB_MAX_QUEUES 8
@ -269,6 +273,10 @@
#define GEM_RXBS_SIZE 8 #define GEM_RXBS_SIZE 8
#define GEM_DDRP_OFFSET 24 /* disc_when_no_ahb */ #define GEM_DDRP_OFFSET 24 /* disc_when_no_ahb */
#define GEM_DDRP_SIZE 1 #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_OFFSET 30 /* Address bus width - 64b or 32b */
#define GEM_ADDR64_SIZE 1 #define GEM_ADDR64_SIZE 1
@ -425,6 +433,11 @@
#define GEM_TX_PKT_BUFF_OFFSET 21 #define GEM_TX_PKT_BUFF_OFFSET 21
#define GEM_TX_PKT_BUFF_SIZE 1 #define GEM_TX_PKT_BUFF_SIZE 1
/* Bitfields in DCFG5. */
#define GEM_TSU_OFFSET 8
#define GEM_TSU_SIZE 1
/* Bitfields in DCFG6. */ /* Bitfields in DCFG6. */
#define GEM_PBUF_LSO_OFFSET 27 #define GEM_PBUF_LSO_OFFSET 27
#define GEM_PBUF_LSO_SIZE 1 #define GEM_PBUF_LSO_SIZE 1
@ -546,16 +559,21 @@ struct macb_dma_desc {
u32 ctrl; u32 ctrl;
}; };
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #ifdef MACB_EXT_DESC
enum macb_hw_dma_cap { #define HW_DMA_CAP_32B 0
HW_DMA_CAP_32B, #define HW_DMA_CAP_64B (1 << 0)
HW_DMA_CAP_64B, #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 { struct macb_dma_desc_64 {
u32 addrh; u32 addrh;
u32 resvd; u32 resvd;
}; };
struct macb_dma_desc_ptp {
u32 ts_1;
u32 ts_2;
};
#endif #endif
/* DMA descriptor bitfields */ /* DMA descriptor bitfields */
@ -955,8 +973,8 @@ struct macb {
u32 wol; u32 wol;
struct macb_ptp_info *ptp_info; /* macb-ptp interface */ struct macb_ptp_info *ptp_info; /* macb-ptp interface */
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #ifdef MACB_EXT_DESC
enum macb_hw_dma_cap hw_dma_cap; uint8_t hw_dma_cap;
#endif #endif
}; };