Skip to content

Commit

Permalink
net: macb: Add support for PTP timestamps in DMA descriptors
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Rafal Ozieblo authored and davem330 committed Jun 30, 2017
1 parent b079115 commit 7b42961
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 37 deletions.
10 changes: 9 additions & 1 deletion drivers/net/ethernet/cadence/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
117 changes: 88 additions & 29 deletions drivers/net/ethernet/cadence/macb.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,33 +79,84 @@
#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

Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand All @@ -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
}
Expand Down Expand Up @@ -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);
Expand Down
32 changes: 25 additions & 7 deletions drivers/net/ethernet/cadence/macb.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

#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
Expand Down Expand Up @@ -269,6 +273,10 @@
#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

Expand Down Expand Up @@ -425,6 +433,11 @@
#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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
};

Expand Down

0 comments on commit 7b42961

Please sign in to comment.