diff options
author | Rafal Ozieblo <rafalo@cadence.com> | 2017-06-29 02:14:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-30 13:11:42 -0400 |
commit | ab91f0a9b5f4b9b5b341fdc0ed457121e69c20e1 (patch) | |
tree | 5bcc4aab1d4509c2fbe87e37859c3005edcf658b /drivers/net/ethernet/cadence/macb_main.c | |
parent | b83f1527d098c04424832b0a59d75046e26bfff1 (diff) |
net: macb: Add hardware PTP support
This patch is based on original Harini's patch and Andrei's patch,
implemented in a separate file to ease the review/maintanance
and integration with other platforms.
This driver supports GEM-GXL:
- Register ptp clock framework
- Initialize PTP related registers
- HW time stamp on the PTP Ethernet packets are received using the
SO_TIMESTAMPING API. Time stamps are obtained from the dma buffer
descriptors
- add macb_ptp to compilation chain
Signed-off-by: Rafal Ozieblo <rafalo@cadence.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/cadence/macb_main.c')
-rw-r--r-- | drivers/net/ethernet/cadence/macb_main.c | 90 |
1 files changed, 84 insertions, 6 deletions
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 2d43a7619f58..41e5711544fc 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c | |||
@@ -847,6 +847,12 @@ static void macb_tx_interrupt(struct macb_queue *queue) | |||
847 | 847 | ||
848 | /* First, update TX stats if needed */ | 848 | /* First, update TX stats if needed */ |
849 | if (skb) { | 849 | if (skb) { |
850 | if (gem_ptp_do_txstamp(queue, skb, desc) == 0) { | ||
851 | /* skb now belongs to timestamp buffer | ||
852 | * and will be removed later | ||
853 | */ | ||
854 | tx_skb->skb = NULL; | ||
855 | } | ||
850 | netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n", | 856 | netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n", |
851 | macb_tx_ring_wrap(bp, tail), | 857 | macb_tx_ring_wrap(bp, tail), |
852 | skb->data); | 858 | skb->data); |
@@ -1013,6 +1019,8 @@ static int gem_rx(struct macb *bp, int budget) | |||
1013 | bp->dev->stats.rx_packets++; | 1019 | bp->dev->stats.rx_packets++; |
1014 | bp->dev->stats.rx_bytes += skb->len; | 1020 | bp->dev->stats.rx_bytes += skb->len; |
1015 | 1021 | ||
1022 | gem_ptp_do_rxstamp(bp, skb, desc); | ||
1023 | |||
1016 | #if defined(DEBUG) && defined(VERBOSE_DEBUG) | 1024 | #if defined(DEBUG) && defined(VERBOSE_DEBUG) |
1017 | netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n", | 1025 | netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n", |
1018 | skb->len, skb->csum); | 1026 | skb->len, skb->csum); |
@@ -1334,7 +1342,6 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) | |||
1334 | if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) | 1342 | if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) |
1335 | queue_writel(queue, ISR, MACB_BIT(HRESP)); | 1343 | queue_writel(queue, ISR, MACB_BIT(HRESP)); |
1336 | } | 1344 | } |
1337 | |||
1338 | status = queue_readl(queue, ISR); | 1345 | status = queue_readl(queue, ISR); |
1339 | } | 1346 | } |
1340 | 1347 | ||
@@ -1664,7 +1671,6 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1664 | 1671 | ||
1665 | /* Make newly initialized descriptor visible to hardware */ | 1672 | /* Make newly initialized descriptor visible to hardware */ |
1666 | wmb(); | 1673 | wmb(); |
1667 | |||
1668 | skb_tx_timestamp(skb); | 1674 | skb_tx_timestamp(skb); |
1669 | 1675 | ||
1670 | macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); | 1676 | macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); |
@@ -2522,6 +2528,70 @@ static int macb_set_ringparam(struct net_device *netdev, | |||
2522 | return 0; | 2528 | return 0; |
2523 | } | 2529 | } |
2524 | 2530 | ||
2531 | #ifdef CONFIG_MACB_USE_HWSTAMP | ||
2532 | static unsigned int gem_get_tsu_rate(struct macb *bp) | ||
2533 | { | ||
2534 | struct clk *tsu_clk; | ||
2535 | unsigned int tsu_rate; | ||
2536 | |||
2537 | tsu_clk = devm_clk_get(&bp->pdev->dev, "tsu_clk"); | ||
2538 | if (!IS_ERR(tsu_clk)) | ||
2539 | tsu_rate = clk_get_rate(tsu_clk); | ||
2540 | /* try pclk instead */ | ||
2541 | else if (!IS_ERR(bp->pclk)) { | ||
2542 | tsu_clk = bp->pclk; | ||
2543 | tsu_rate = clk_get_rate(tsu_clk); | ||
2544 | } else | ||
2545 | return -ENOTSUPP; | ||
2546 | return tsu_rate; | ||
2547 | } | ||
2548 | |||
2549 | static s32 gem_get_ptp_max_adj(void) | ||
2550 | { | ||
2551 | return 64000000; | ||
2552 | } | ||
2553 | |||
2554 | static int gem_get_ts_info(struct net_device *dev, | ||
2555 | struct ethtool_ts_info *info) | ||
2556 | { | ||
2557 | struct macb *bp = netdev_priv(dev); | ||
2558 | |||
2559 | if ((bp->hw_dma_cap & HW_DMA_CAP_PTP) == 0) { | ||
2560 | ethtool_op_get_ts_info(dev, info); | ||
2561 | return 0; | ||
2562 | } | ||
2563 | |||
2564 | info->so_timestamping = | ||
2565 | SOF_TIMESTAMPING_TX_SOFTWARE | | ||
2566 | SOF_TIMESTAMPING_RX_SOFTWARE | | ||
2567 | SOF_TIMESTAMPING_SOFTWARE | | ||
2568 | SOF_TIMESTAMPING_TX_HARDWARE | | ||
2569 | SOF_TIMESTAMPING_RX_HARDWARE | | ||
2570 | SOF_TIMESTAMPING_RAW_HARDWARE; | ||
2571 | info->tx_types = | ||
2572 | (1 << HWTSTAMP_TX_ONESTEP_SYNC) | | ||
2573 | (1 << HWTSTAMP_TX_OFF) | | ||
2574 | (1 << HWTSTAMP_TX_ON); | ||
2575 | info->rx_filters = | ||
2576 | (1 << HWTSTAMP_FILTER_NONE) | | ||
2577 | (1 << HWTSTAMP_FILTER_ALL); | ||
2578 | |||
2579 | info->phc_index = bp->ptp_clock ? ptp_clock_index(bp->ptp_clock) : -1; | ||
2580 | |||
2581 | return 0; | ||
2582 | } | ||
2583 | |||
2584 | static struct macb_ptp_info gem_ptp_info = { | ||
2585 | .ptp_init = gem_ptp_init, | ||
2586 | .ptp_remove = gem_ptp_remove, | ||
2587 | .get_ptp_max_adj = gem_get_ptp_max_adj, | ||
2588 | .get_tsu_rate = gem_get_tsu_rate, | ||
2589 | .get_ts_info = gem_get_ts_info, | ||
2590 | .get_hwtst = gem_get_hwtst, | ||
2591 | .set_hwtst = gem_set_hwtst, | ||
2592 | }; | ||
2593 | #endif | ||
2594 | |||
2525 | static int macb_get_ts_info(struct net_device *netdev, | 2595 | static int macb_get_ts_info(struct net_device *netdev, |
2526 | struct ethtool_ts_info *info) | 2596 | struct ethtool_ts_info *info) |
2527 | { | 2597 | { |
@@ -2655,12 +2725,16 @@ static void macb_configure_caps(struct macb *bp, | |||
2655 | dcfg = gem_readl(bp, DCFG2); | 2725 | dcfg = gem_readl(bp, DCFG2); |
2656 | if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0) | 2726 | if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0) |
2657 | bp->caps |= MACB_CAPS_FIFO_MODE; | 2727 | bp->caps |= MACB_CAPS_FIFO_MODE; |
2658 | if (IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) && gem_has_ptp(bp)) { | 2728 | #ifdef CONFIG_MACB_USE_HWSTAMP |
2729 | if (gem_has_ptp(bp)) { | ||
2659 | if (!GEM_BFEXT(TSU, gem_readl(bp, DCFG5))) | 2730 | if (!GEM_BFEXT(TSU, gem_readl(bp, DCFG5))) |
2660 | pr_err("GEM doesn't support hardware ptp.\n"); | 2731 | pr_err("GEM doesn't support hardware ptp.\n"); |
2661 | else | 2732 | else { |
2662 | bp->hw_dma_cap |= HW_DMA_CAP_PTP; | 2733 | bp->hw_dma_cap |= HW_DMA_CAP_PTP; |
2734 | bp->ptp_info = &gem_ptp_info; | ||
2735 | } | ||
2663 | } | 2736 | } |
2737 | #endif | ||
2664 | } | 2738 | } |
2665 | 2739 | ||
2666 | dev_dbg(&bp->pdev->dev, "Cadence caps 0x%08x\n", bp->caps); | 2740 | dev_dbg(&bp->pdev->dev, "Cadence caps 0x%08x\n", bp->caps); |
@@ -3266,7 +3340,9 @@ static const struct macb_config np4_config = { | |||
3266 | }; | 3340 | }; |
3267 | 3341 | ||
3268 | static const struct macb_config zynqmp_config = { | 3342 | static const struct macb_config zynqmp_config = { |
3269 | .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO, | 3343 | .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | |
3344 | MACB_CAPS_JUMBO | | ||
3345 | MACB_CAPS_GEM_HAS_PTP, | ||
3270 | .dma_burst_length = 16, | 3346 | .dma_burst_length = 16, |
3271 | .clk_init = macb_clk_init, | 3347 | .clk_init = macb_clk_init, |
3272 | .init = macb_init, | 3348 | .init = macb_init, |
@@ -3300,7 +3376,9 @@ MODULE_DEVICE_TABLE(of, macb_dt_ids); | |||
3300 | #endif /* CONFIG_OF */ | 3376 | #endif /* CONFIG_OF */ |
3301 | 3377 | ||
3302 | static const struct macb_config default_gem_config = { | 3378 | static const struct macb_config default_gem_config = { |
3303 | .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO, | 3379 | .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | |
3380 | MACB_CAPS_JUMBO | | ||
3381 | MACB_CAPS_GEM_HAS_PTP, | ||
3304 | .dma_burst_length = 16, | 3382 | .dma_burst_length = 16, |
3305 | .clk_init = macb_clk_init, | 3383 | .clk_init = macb_clk_init, |
3306 | .init = macb_init, | 3384 | .init = macb_init, |