aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/chain_mode.c32
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h22
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/enh_desc.c47
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/norm_desc.c37
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/ring_mode.c13
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h5
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c32
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c108
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c384
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h74
11 files changed, 732 insertions, 24 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index ae995a367c91..1aca0e6881bd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -4,4 +4,4 @@ stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
4stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ 4stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
5 chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ 5 chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
6 dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \ 6 dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
7 mmc_core.o $(stmmac-y) 7 mmc_core.o stmmac_hwtstamp.o $(stmmac-y)
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index 63b6031e304a..37a3f93b487d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -122,8 +122,40 @@ static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
122 } 122 }
123} 123}
124 124
125static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
126{
127 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
128
129 if (priv->hwts_rx_en && !priv->extend_desc)
130 /* NOTE: Device will overwrite des3 with timestamp value if
131 * 1588-2002 time stamping is enabled, hence reinitialize it
132 * to keep explicit chaining in the descriptor.
133 */
134 p->des3 = (unsigned int)(priv->dma_rx_phy +
135 (((priv->dirty_rx) + 1) %
136 priv->dma_rx_size) *
137 sizeof(struct dma_desc));
138}
139
140static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
141{
142 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
143
144 if (priv->hw->desc->get_tx_ls(p) && !priv->extend_desc)
145 /* NOTE: Device will overwrite des3 with timestamp value if
146 * 1588-2002 time stamping is enabled, hence reinitialize it
147 * to keep explicit chaining in the descriptor.
148 */
149 p->des3 = (unsigned int)(priv->dma_tx_phy +
150 (((priv->dirty_tx + 1) %
151 priv->dma_tx_size) *
152 sizeof(struct dma_desc)));
153}
154
125const struct stmmac_chain_mode_ops chain_mode_ops = { 155const struct stmmac_chain_mode_ops chain_mode_ops = {
126 .init = stmmac_init_dma_chain, 156 .init = stmmac_init_dma_chain,
127 .is_jumbo_frm = stmmac_is_jumbo_frm, 157 .is_jumbo_frm = stmmac_is_jumbo_frm,
128 .jumbo_frm = stmmac_jumbo_frm, 158 .jumbo_frm = stmmac_jumbo_frm,
159 .refill_desc3 = stmmac_refill_desc3,
160 .clean_desc3 = stmmac_clean_desc3,
129}; 161};
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 942fdce3ab93..6fa975c55234 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -339,6 +339,14 @@ struct stmmac_desc_ops {
339 struct dma_desc *p); 339 struct dma_desc *p);
340 void (*rx_extended_status) (void *data, struct stmmac_extra_stats *x, 340 void (*rx_extended_status) (void *data, struct stmmac_extra_stats *x,
341 struct dma_extended_desc *p); 341 struct dma_extended_desc *p);
342 /* Set tx timestamp enable bit */
343 void (*enable_tx_timestamp) (struct dma_desc *p);
344 /* get tx timestamp status */
345 int (*get_tx_timestamp_status) (struct dma_desc *p);
346 /* get timestamp value */
347 u64 (*get_timestamp) (void *desc, u32 ats);
348 /* get rx timestamp status */
349 int (*get_rx_timestamp_status) (void *desc, u32 ats);
342}; 350};
343 351
344struct stmmac_dma_ops { 352struct stmmac_dma_ops {
@@ -398,6 +406,13 @@ struct stmmac_ops {
398 void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv); 406 void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv);
399}; 407};
400 408
409struct stmmac_hwtimestamp {
410 void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
411 void (*config_sub_second_increment) (void __iomem *ioaddr);
412 int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
413 int (*config_addend)(void __iomem *ioaddr, u32 addend);
414};
415
401struct mac_link { 416struct mac_link {
402 int port; 417 int port;
403 int duplex; 418 int duplex;
@@ -412,9 +427,9 @@ struct mii_regs {
412struct stmmac_ring_mode_ops { 427struct stmmac_ring_mode_ops {
413 unsigned int (*is_jumbo_frm) (int len, int ehn_desc); 428 unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
414 unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum); 429 unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
415 void (*refill_desc3) (int bfsize, struct dma_desc *p); 430 void (*refill_desc3) (void *priv, struct dma_desc *p);
416 void (*init_desc3) (struct dma_desc *p); 431 void (*init_desc3) (struct dma_desc *p);
417 void (*clean_desc3) (struct dma_desc *p); 432 void (*clean_desc3) (void *priv, struct dma_desc *p);
418 int (*set_16kib_bfsize) (int mtu); 433 int (*set_16kib_bfsize) (int mtu);
419}; 434};
420 435
@@ -423,6 +438,8 @@ struct stmmac_chain_mode_ops {
423 unsigned int extend_desc); 438 unsigned int extend_desc);
424 unsigned int (*is_jumbo_frm) (int len, int ehn_desc); 439 unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
425 unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum); 440 unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
441 void (*refill_desc3) (void *priv, struct dma_desc *p);
442 void (*clean_desc3) (void *priv, struct dma_desc *p);
426}; 443};
427 444
428struct mac_device_info { 445struct mac_device_info {
@@ -431,6 +448,7 @@ struct mac_device_info {
431 const struct stmmac_dma_ops *dma; 448 const struct stmmac_dma_ops *dma;
432 const struct stmmac_ring_mode_ops *ring; 449 const struct stmmac_ring_mode_ops *ring;
433 const struct stmmac_chain_mode_ops *chain; 450 const struct stmmac_chain_mode_ops *chain;
451 const struct stmmac_hwtimestamp *ptp;
434 struct mii_regs mii; /* MII register Addresses */ 452 struct mii_regs mii; /* MII register Addresses */
435 struct mac_link link; 453 struct mac_link link;
436 unsigned int synopsys_uid; 454 unsigned int synopsys_uid;
diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
index c1b9ab23b3c5..0fbc8fafa706 100644
--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
@@ -378,6 +378,49 @@ static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
378 return p->des01.erx.frame_length; 378 return p->des01.erx.frame_length;
379} 379}
380 380
381static void enh_desc_enable_tx_timestamp(struct dma_desc *p)
382{
383 p->des01.etx.time_stamp_enable = 1;
384}
385
386static int enh_desc_get_tx_timestamp_status(struct dma_desc *p)
387{
388 return p->des01.etx.time_stamp_status;
389}
390
391static u64 enh_desc_get_timestamp(void *desc, u32 ats)
392{
393 u64 ns;
394
395 if (ats) {
396 struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
397 ns = p->des6;
398 /* convert high/sec time stamp value to nanosecond */
399 ns += p->des7 * 1000000000ULL;
400 } else {
401 struct dma_desc *p = (struct dma_desc *)desc;
402 ns = p->des2;
403 ns += p->des3 * 1000000000ULL;
404 }
405
406 return ns;
407}
408
409static int enh_desc_get_rx_timestamp_status(void *desc, u32 ats)
410{
411 if (ats) {
412 struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
413 return p->basic.des01.erx.ipc_csum_error;
414 } else {
415 struct dma_desc *p = (struct dma_desc *)desc;
416 if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
417 /* timestamp is corrupted, hence don't store it */
418 return 0;
419 else
420 return 1;
421 }
422}
423
381const struct stmmac_desc_ops enh_desc_ops = { 424const struct stmmac_desc_ops enh_desc_ops = {
382 .tx_status = enh_desc_get_tx_status, 425 .tx_status = enh_desc_get_tx_status,
383 .rx_status = enh_desc_get_rx_status, 426 .rx_status = enh_desc_get_rx_status,
@@ -395,4 +438,8 @@ const struct stmmac_desc_ops enh_desc_ops = {
395 .set_rx_owner = enh_desc_set_rx_owner, 438 .set_rx_owner = enh_desc_set_rx_owner,
396 .get_rx_frame_len = enh_desc_get_rx_frame_len, 439 .get_rx_frame_len = enh_desc_get_rx_frame_len,
397 .rx_extended_status = enh_desc_get_ext_status, 440 .rx_extended_status = enh_desc_get_ext_status,
441 .enable_tx_timestamp = enh_desc_enable_tx_timestamp,
442 .get_tx_timestamp_status = enh_desc_get_tx_timestamp_status,
443 .get_timestamp = enh_desc_get_timestamp,
444 .get_rx_timestamp_status = enh_desc_get_rx_timestamp_status,
398}; 445};
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index 47d509435ebb..7cbcea348c3d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -219,6 +219,39 @@ static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
219 return p->des01.rx.frame_length; 219 return p->des01.rx.frame_length;
220} 220}
221 221
222static void ndesc_enable_tx_timestamp(struct dma_desc *p)
223{
224 p->des01.tx.time_stamp_enable = 1;
225}
226
227static int ndesc_get_tx_timestamp_status(struct dma_desc *p)
228{
229 return p->des01.tx.time_stamp_status;
230}
231
232static u64 ndesc_get_timestamp(void *desc, u32 ats)
233{
234 struct dma_desc *p = (struct dma_desc *)desc;
235 u64 ns;
236
237 ns = p->des2;
238 /* convert high/sec time stamp value to nanosecond */
239 ns += p->des3 * 1000000000ULL;
240
241 return ns;
242}
243
244static int ndesc_get_rx_timestamp_status(void *desc, u32 ats)
245{
246 struct dma_desc *p = (struct dma_desc *)desc;
247
248 if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
249 /* timestamp is corrupted, hence don't store it */
250 return 0;
251 else
252 return 1;
253}
254
222const struct stmmac_desc_ops ndesc_ops = { 255const struct stmmac_desc_ops ndesc_ops = {
223 .tx_status = ndesc_get_tx_status, 256 .tx_status = ndesc_get_tx_status,
224 .rx_status = ndesc_get_rx_status, 257 .rx_status = ndesc_get_rx_status,
@@ -235,4 +268,8 @@ const struct stmmac_desc_ops ndesc_ops = {
235 .set_tx_owner = ndesc_set_tx_owner, 268 .set_tx_owner = ndesc_set_tx_owner,
236 .set_rx_owner = ndesc_set_rx_owner, 269 .set_rx_owner = ndesc_set_rx_owner,
237 .get_rx_frame_len = ndesc_get_rx_frame_len, 270 .get_rx_frame_len = ndesc_get_rx_frame_len,
271 .enable_tx_timestamp = ndesc_enable_tx_timestamp,
272 .get_tx_timestamp_status = ndesc_get_tx_timestamp_status,
273 .get_timestamp = ndesc_get_timestamp,
274 .get_rx_timestamp_status = ndesc_get_rx_timestamp_status,
238}; 275};
diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
index 43fc699b21cc..d0265a7d5a54 100644
--- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c
@@ -87,11 +87,14 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
87 return ret; 87 return ret;
88} 88}
89 89
90static void stmmac_refill_desc3(int bfsize, struct dma_desc *p) 90static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
91{ 91{
92 /* Fill DES3 in case of RING mode */ 92 struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
93 if (bfsize >= BUF_SIZE_8KiB) 93
94 p->des3 = p->des2 + BUF_SIZE_8KiB; 94 if (unlikely(priv->plat->has_gmac))
95 /* Fill DES3 in case of RING mode */
96 if (priv->dma_buf_sz >= BUF_SIZE_8KiB)
97 p->des3 = p->des2 + BUF_SIZE_8KiB;
95} 98}
96 99
97/* In ring mode we need to fill the desc3 because it is used as buffer */ 100/* In ring mode we need to fill the desc3 because it is used as buffer */
@@ -100,7 +103,7 @@ static void stmmac_init_desc3(struct dma_desc *p)
100 p->des3 = p->des2 + BUF_SIZE_8KiB; 103 p->des3 = p->des2 + BUF_SIZE_8KiB;
101} 104}
102 105
103static void stmmac_clean_desc3(struct dma_desc *p) 106static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
104{ 107{
105 if (unlikely(p->des3)) 108 if (unlikely(p->des3))
106 p->des3 = 0; 109 p->des3 = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 5176cae44b03..a21d1b9c9094 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -99,6 +99,10 @@ struct stmmac_priv {
99 unsigned int mode; 99 unsigned int mode;
100 int extend_desc; 100 int extend_desc;
101 int pcs; 101 int pcs;
102 int hwts_tx_en;
103 int hwts_rx_en;
104 unsigned int default_addend;
105 u32 adv_ts;
102}; 106};
103 107
104extern int phyaddr; 108extern int phyaddr;
@@ -108,6 +112,7 @@ extern int stmmac_mdio_register(struct net_device *ndev);
108extern void stmmac_set_ethtool_ops(struct net_device *netdev); 112extern void stmmac_set_ethtool_ops(struct net_device *netdev);
109extern const struct stmmac_desc_ops enh_desc_ops; 113extern const struct stmmac_desc_ops enh_desc_ops;
110extern const struct stmmac_desc_ops ndesc_ops; 114extern const struct stmmac_desc_ops ndesc_ops;
115extern const struct stmmac_hwtimestamp stmmac_ptp;
111int stmmac_freeze(struct net_device *ndev); 116int stmmac_freeze(struct net_device *ndev);
112int stmmac_restore(struct net_device *ndev); 117int stmmac_restore(struct net_device *ndev);
113int stmmac_resume(struct net_device *ndev); 118int stmmac_resume(struct net_device *ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 54e15db516fe..5b340c23fd6b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -27,6 +27,7 @@
27#include <linux/interrupt.h> 27#include <linux/interrupt.h>
28#include <linux/mii.h> 28#include <linux/mii.h>
29#include <linux/phy.h> 29#include <linux/phy.h>
30#include <linux/net_tstamp.h>
30#include <asm/io.h> 31#include <asm/io.h>
31 32
32#include "stmmac.h" 33#include "stmmac.h"
@@ -725,6 +726,35 @@ static int stmmac_set_coalesce(struct net_device *dev,
725 return 0; 726 return 0;
726} 727}
727 728
729static int stmmac_get_ts_info(struct net_device *dev,
730 struct ethtool_ts_info *info)
731{
732 struct stmmac_priv *priv = netdev_priv(dev);
733
734 if ((priv->hwts_tx_en) && (priv->hwts_rx_en)) {
735
736 info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
737 SOF_TIMESTAMPING_RX_HARDWARE |
738 SOF_TIMESTAMPING_RAW_HARDWARE;
739
740 info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
741
742 info->rx_filters = ((1 << HWTSTAMP_FILTER_NONE) |
743 (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
744 (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
745 (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
746 (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
747 (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
748 (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
749 (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
750 (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
751 (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
752 (1 << HWTSTAMP_FILTER_ALL));
753 return 0;
754 } else
755 return ethtool_op_get_ts_info(dev, info);
756}
757
728static const struct ethtool_ops stmmac_ethtool_ops = { 758static const struct ethtool_ops stmmac_ethtool_ops = {
729 .begin = stmmac_check_if_running, 759 .begin = stmmac_check_if_running,
730 .get_drvinfo = stmmac_ethtool_getdrvinfo, 760 .get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -744,7 +774,7 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
744 .get_eee = stmmac_ethtool_op_get_eee, 774 .get_eee = stmmac_ethtool_op_get_eee,
745 .set_eee = stmmac_ethtool_op_set_eee, 775 .set_eee = stmmac_ethtool_op_set_eee,
746 .get_sset_count = stmmac_get_sset_count, 776 .get_sset_count = stmmac_get_sset_count,
747 .get_ts_info = ethtool_op_get_ts_info, 777 .get_ts_info = stmmac_get_ts_info,
748 .get_coalesce = stmmac_get_coalesce, 778 .get_coalesce = stmmac_get_coalesce,
749 .set_coalesce = stmmac_set_coalesce, 779 .set_coalesce = stmmac_set_coalesce,
750}; 780};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
new file mode 100644
index 000000000000..380baeb016a9
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
@@ -0,0 +1,108 @@
1/*******************************************************************************
2 Copyright (C) 2013 Vayavya Labs Pvt Ltd
3
4 This implements all the API for managing HW timestamp & PTP.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms and conditions of the GNU General Public License,
8 version 2, as published by the Free Software Foundation.
9
10 This program is distributed in the hope it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19 The full GNU General Public License is included in this distribution in
20 the file called "COPYING".
21
22 Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
23 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
24*******************************************************************************/
25
26#include <linux/io.h>
27#include <linux/delay.h>
28#include "common.h"
29#include "stmmac_ptp.h"
30
31static void stmmac_config_hw_tstamping(void __iomem *ioaddr, u32 data)
32{
33 writel(data, ioaddr + PTP_TCR);
34}
35
36static void stmmac_config_sub_second_increment(void __iomem *ioaddr)
37{
38 u32 value = readl(ioaddr + PTP_TCR);
39 unsigned long data;
40
41 /* Convert the ptp_clock to nano second
42 * formula = (1/ptp_clock) * 1000000000
43 * where, ptp_clock = 50MHz.
44 */
45 data = (1000000000ULL / 50000000);
46
47 /* 0.465ns accuracy */
48 if (value & PTP_TCR_TSCTRLSSR)
49 data = (data * 100) / 465;
50
51 writel(data, ioaddr + PTP_SSIR);
52}
53
54static int stmmac_init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)
55{
56 int limit;
57 u32 value;
58
59 writel(sec, ioaddr + PTP_STSUR);
60 writel(nsec, ioaddr + PTP_STNSUR);
61 /* issue command to initialize the system time value */
62 value = readl(ioaddr + PTP_TCR);
63 value |= PTP_TCR_TSINIT;
64 writel(value, ioaddr + PTP_TCR);
65
66 /* wait for present system time initialize to complete */
67 limit = 10;
68 while (limit--) {
69 if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSINIT))
70 break;
71 mdelay(10);
72 }
73 if (limit < 0)
74 return -EBUSY;
75
76 return 0;
77}
78
79static int stmmac_config_addend(void __iomem *ioaddr, u32 addend)
80{
81 u32 value;
82 int limit;
83
84 writel(addend, ioaddr + PTP_TAR);
85 /* issue command to update the addend value */
86 value = readl(ioaddr + PTP_TCR);
87 value |= PTP_TCR_TSADDREG;
88 writel(value, ioaddr + PTP_TCR);
89
90 /* wait for present addend update to complete */
91 limit = 10;
92 while (limit--) {
93 if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSADDREG))
94 break;
95 mdelay(10);
96 }
97 if (limit < 0)
98 return -EBUSY;
99
100 return 0;
101}
102
103const struct stmmac_hwtimestamp stmmac_ptp = {
104 .config_hw_tstamping = stmmac_config_hw_tstamping,
105 .init_systime = stmmac_init_systime,
106 .config_sub_second_increment = stmmac_config_sub_second_increment,
107 .config_addend = stmmac_config_addend,
108};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 180eed7168c1..6906772069e3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -47,6 +47,8 @@
47#include <linux/debugfs.h> 47#include <linux/debugfs.h>
48#include <linux/seq_file.h> 48#include <linux/seq_file.h>
49#endif 49#endif
50#include <linux/net_tstamp.h>
51#include "stmmac_ptp.h"
50#include "stmmac.h" 52#include "stmmac.h"
51 53
52#undef STMMAC_DEBUG 54#undef STMMAC_DEBUG
@@ -311,6 +313,327 @@ static void stmmac_eee_adjust(struct stmmac_priv *priv)
311 priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link); 313 priv->hw->mac->set_eee_pls(priv->ioaddr, priv->phydev->link);
312} 314}
313 315
316/* stmmac_get_tx_hwtstamp:
317 * @priv : pointer to private device structure.
318 * @entry : descriptor index to be used.
319 * @skb : the socket buffer
320 * Description :
321 * This function will read timestamp from the descriptor & pass it to stack.
322 * and also perform some sanity checks.
323 */
324static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
325 unsigned int entry,
326 struct sk_buff *skb)
327{
328 struct skb_shared_hwtstamps shhwtstamp;
329 u64 ns;
330 void *desc = NULL;
331
332 if (!priv->hwts_tx_en)
333 return;
334
335 /* if skb doesn't support hw tstamp */
336 if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
337 return;
338
339 if (priv->adv_ts)
340 desc = (priv->dma_etx + entry);
341 else
342 desc = (priv->dma_tx + entry);
343
344 /* check tx tstamp status */
345 if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc))
346 return;
347
348 /* get the valid tstamp */
349 ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
350
351 memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
352 shhwtstamp.hwtstamp = ns_to_ktime(ns);
353 /* pass tstamp to stack */
354 skb_tstamp_tx(skb, &shhwtstamp);
355
356 return;
357}
358
359/* stmmac_get_rx_hwtstamp:
360 * @priv : pointer to private device structure.
361 * @entry : descriptor index to be used.
362 * @skb : the socket buffer
363 * Description :
364 * This function will read received packet's timestamp from the descriptor
365 * and pass it to stack. It also perform some sanity checks.
366 */
367static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv,
368 unsigned int entry,
369 struct sk_buff *skb)
370{
371 struct skb_shared_hwtstamps *shhwtstamp = NULL;
372 u64 ns;
373 void *desc = NULL;
374
375 if (!priv->hwts_rx_en)
376 return;
377
378 if (priv->adv_ts)
379 desc = (priv->dma_erx + entry);
380 else
381 desc = (priv->dma_rx + entry);
382
383 /* if rx tstamp is not valid */
384 if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts))
385 return;
386
387 /* get valid tstamp */
388 ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
389 shhwtstamp = skb_hwtstamps(skb);
390 memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
391 shhwtstamp->hwtstamp = ns_to_ktime(ns);
392}
393
394/**
395 * stmmac_hwtstamp_ioctl - control hardware timestamping.
396 * @dev: device pointer.
397 * @ifr: An IOCTL specefic structure, that can contain a pointer to
398 * a proprietary structure used to pass information to the driver.
399 * Description:
400 * This function configures the MAC to enable/disable both outgoing(TX)
401 * and incoming(RX) packets time stamping based on user input.
402 * Return Value:
403 * 0 on success and an appropriate -ve integer on failure.
404 */
405static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
406{
407 struct stmmac_priv *priv = netdev_priv(dev);
408 struct hwtstamp_config config;
409 struct timespec now;
410 u64 temp = 0;
411 u32 ptp_v2 = 0;
412 u32 tstamp_all = 0;
413 u32 ptp_over_ipv4_udp = 0;
414 u32 ptp_over_ipv6_udp = 0;
415 u32 ptp_over_ethernet = 0;
416 u32 snap_type_sel = 0;
417 u32 ts_master_en = 0;
418 u32 ts_event_en = 0;
419 u32 value = 0;
420
421 if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
422 netdev_alert(priv->dev, "No support for HW time stamping\n");
423 priv->hwts_tx_en = 0;
424 priv->hwts_rx_en = 0;
425
426 return -EOPNOTSUPP;
427 }
428
429 if (copy_from_user(&config, ifr->ifr_data,
430 sizeof(struct hwtstamp_config)))
431 return -EFAULT;
432
433 pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
434 __func__, config.flags, config.tx_type, config.rx_filter);
435
436 /* reserved for future extensions */
437 if (config.flags)
438 return -EINVAL;
439
440 switch (config.tx_type) {
441 case HWTSTAMP_TX_OFF:
442 priv->hwts_tx_en = 0;
443 break;
444 case HWTSTAMP_TX_ON:
445 priv->hwts_tx_en = 1;
446 break;
447 default:
448 return -ERANGE;
449 }
450
451 if (priv->adv_ts) {
452 switch (config.rx_filter) {
453 /* time stamp no incoming packet at all */
454 case HWTSTAMP_FILTER_NONE:
455 config.rx_filter = HWTSTAMP_FILTER_NONE;
456 break;
457
458 /* PTP v1, UDP, any kind of event packet */
459 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
460 config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
461 /* take time stamp for all event messages */
462 snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
463
464 ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
465 ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
466 break;
467
468 /* PTP v1, UDP, Sync packet */
469 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
470 config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
471 /* take time stamp for SYNC messages only */
472 ts_event_en = PTP_TCR_TSEVNTENA;
473
474 ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
475 ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
476 break;
477
478 /* PTP v1, UDP, Delay_req packet */
479 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
480 config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
481 /* take time stamp for Delay_Req messages only */
482 ts_master_en = PTP_TCR_TSMSTRENA;
483 ts_event_en = PTP_TCR_TSEVNTENA;
484
485 ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
486 ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
487 break;
488
489 /* PTP v2, UDP, any kind of event packet */
490 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
491 config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
492 ptp_v2 = PTP_TCR_TSVER2ENA;
493 /* take time stamp for all event messages */
494 snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
495
496 ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
497 ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
498 break;
499
500 /* PTP v2, UDP, Sync packet */
501 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
502 config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
503 ptp_v2 = PTP_TCR_TSVER2ENA;
504 /* take time stamp for SYNC messages only */
505 ts_event_en = PTP_TCR_TSEVNTENA;
506
507 ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
508 ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
509 break;
510
511 /* PTP v2, UDP, Delay_req packet */
512 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
513 config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
514 ptp_v2 = PTP_TCR_TSVER2ENA;
515 /* take time stamp for Delay_Req messages only */
516 ts_master_en = PTP_TCR_TSMSTRENA;
517 ts_event_en = PTP_TCR_TSEVNTENA;
518
519 ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
520 ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
521 break;
522
523 /* PTP v2/802.AS1, any layer, any kind of event packet */
524 case HWTSTAMP_FILTER_PTP_V2_EVENT:
525 config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
526 ptp_v2 = PTP_TCR_TSVER2ENA;
527 /* take time stamp for all event messages */
528 snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
529
530 ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
531 ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
532 ptp_over_ethernet = PTP_TCR_TSIPENA;
533 break;
534
535 /* PTP v2/802.AS1, any layer, Sync packet */
536 case HWTSTAMP_FILTER_PTP_V2_SYNC:
537 config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
538 ptp_v2 = PTP_TCR_TSVER2ENA;
539 /* take time stamp for SYNC messages only */
540 ts_event_en = PTP_TCR_TSEVNTENA;
541
542 ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
543 ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
544 ptp_over_ethernet = PTP_TCR_TSIPENA;
545 break;
546
547 /* PTP v2/802.AS1, any layer, Delay_req packet */
548 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
549 config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
550 ptp_v2 = PTP_TCR_TSVER2ENA;
551 /* take time stamp for Delay_Req messages only */
552 ts_master_en = PTP_TCR_TSMSTRENA;
553 ts_event_en = PTP_TCR_TSEVNTENA;
554
555 ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
556 ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
557 ptp_over_ethernet = PTP_TCR_TSIPENA;
558 break;
559
560 /* time stamp any incoming packet */
561 case HWTSTAMP_FILTER_ALL:
562 config.rx_filter = HWTSTAMP_FILTER_ALL;
563 tstamp_all = PTP_TCR_TSENALL;
564 break;
565
566 default:
567 return -ERANGE;
568 }
569 } else {
570 switch (config.rx_filter) {
571 case HWTSTAMP_FILTER_NONE:
572 config.rx_filter = HWTSTAMP_FILTER_NONE;
573 break;
574 default:
575 /* PTP v1, UDP, any kind of event packet */
576 config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
577 break;
578 }
579 }
580 priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
581
582 if (!priv->hwts_tx_en && !priv->hwts_rx_en)
583 priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
584 else {
585 value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
586 tstamp_all | ptp_v2 | ptp_over_ethernet |
587 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
588 ts_master_en | snap_type_sel);
589
590 priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
591
592 /* program Sub Second Increment reg */
593 priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
594
595 /* calculate default added value:
596 * formula is :
597 * addend = (2^32)/freq_div_ratio;
598 * where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz
599 * hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK;
600 * NOTE: STMMAC_SYSCLOCK should be >= 50MHz to
601 * achive 20ns accuracy.
602 *
603 * 2^x * y == (y << x), hence
604 * 2^32 * 50000000 ==> (50000000 << 32)
605 */
606 temp = (u64)(50000000ULL << 32);
607 priv->default_addend = div_u64(temp, STMMAC_SYSCLOCK);
608 priv->hw->ptp->config_addend(priv->ioaddr,
609 priv->default_addend);
610
611 /* initialize system time */
612 getnstimeofday(&now);
613 priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
614 now.tv_nsec);
615 }
616
617 return copy_to_user(ifr->ifr_data, &config,
618 sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
619}
620
621static void stmmac_init_ptp(struct stmmac_priv *priv)
622{
623 if (priv->dma_cap.time_stamp) {
624 pr_debug("IEEE 1588-2002 Time Stamp supported\n");
625 priv->adv_ts = 0;
626 }
627 if (priv->dma_cap.atime_stamp && priv->extend_desc) {
628 pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
629 priv->adv_ts = 1;
630 }
631
632 priv->hw->ptp = &stmmac_ptp;
633 priv->hwts_tx_en = 0;
634 priv->hwts_rx_en = 0;
635}
636
314/** 637/**
315 * stmmac_adjust_link 638 * stmmac_adjust_link
316 * @dev: net device structure 639 * @dev: net device structure
@@ -856,6 +1179,8 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
856 priv->xstats.tx_pkt_n++; 1179 priv->xstats.tx_pkt_n++;
857 } else 1180 } else
858 priv->dev->stats.tx_errors++; 1181 priv->dev->stats.tx_errors++;
1182
1183 stmmac_get_tx_hwtstamp(priv, entry, skb);
859 } 1184 }
860 TX_DBG("%s: curr %d, dirty %d\n", __func__, 1185 TX_DBG("%s: curr %d, dirty %d\n", __func__,
861 priv->cur_tx, priv->dirty_tx); 1186 priv->cur_tx, priv->dirty_tx);
@@ -867,8 +1192,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
867 DMA_TO_DEVICE); 1192 DMA_TO_DEVICE);
868 priv->tx_skbuff_dma[entry] = 0; 1193 priv->tx_skbuff_dma[entry] = 0;
869 } 1194 }
870 if (priv->mode == STMMAC_RING_MODE) 1195 priv->hw->ring->clean_desc3(priv, p);
871 priv->hw->ring->clean_desc3(p);
872 1196
873 if (likely(skb != NULL)) { 1197 if (likely(skb != NULL)) {
874 dev_kfree_skb(skb); 1198 dev_kfree_skb(skb);
@@ -1243,6 +1567,8 @@ static int stmmac_open(struct net_device *dev)
1243 1567
1244 stmmac_mmc_setup(priv); 1568 stmmac_mmc_setup(priv);
1245 1569
1570 stmmac_init_ptp(priv);
1571
1246#ifdef CONFIG_STMMAC_DEBUG_FS 1572#ifdef CONFIG_STMMAC_DEBUG_FS
1247 ret = stmmac_init_fs(dev); 1573 ret = stmmac_init_fs(dev);
1248 if (ret < 0) 1574 if (ret < 0)
@@ -1507,7 +1833,15 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
1507 1833
1508 dev->stats.tx_bytes += skb->len; 1834 dev->stats.tx_bytes += skb->len;
1509 1835
1510 skb_tx_timestamp(skb); 1836 if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
1837 priv->hwts_tx_en)) {
1838 /* declare that device is doing timestamping */
1839 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
1840 priv->hw->desc->enable_tx_timestamp(first);
1841 }
1842
1843 if (!priv->hwts_tx_en)
1844 skb_tx_timestamp(skb);
1511 1845
1512 priv->hw->dma->enable_dma_transmission(priv->ioaddr); 1846 priv->hw->dma->enable_dma_transmission(priv->ioaddr);
1513 1847
@@ -1545,9 +1879,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
1545 1879
1546 p->des2 = priv->rx_skbuff_dma[entry]; 1880 p->des2 = priv->rx_skbuff_dma[entry];
1547 1881
1548 if (unlikely((priv->mode == STMMAC_RING_MODE) && 1882 priv->hw->ring->refill_desc3(priv, p);
1549 (priv->plat->has_gmac)))
1550 priv->hw->ring->refill_desc3(bfsize, p);
1551 1883
1552 RX_DBG(KERN_INFO "\trefill entry #%d\n", entry); 1884 RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
1553 } 1885 }
@@ -1604,9 +1936,20 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
1604 &priv->xstats, 1936 &priv->xstats,
1605 priv->dma_erx + 1937 priv->dma_erx +
1606 entry); 1938 entry);
1607 if (unlikely(status == discard_frame)) 1939 if (unlikely(status == discard_frame)) {
1608 priv->dev->stats.rx_errors++; 1940 priv->dev->stats.rx_errors++;
1609 else { 1941 if (priv->hwts_rx_en && !priv->extend_desc) {
1942 /* DESC2 & DESC3 will be overwitten by device
1943 * with timestamp value, hence reinitialize
1944 * them in stmmac_rx_refill() function so that
1945 * device can reuse it.
1946 */
1947 priv->rx_skbuff[entry] = NULL;
1948 dma_unmap_single(priv->device,
1949 priv->rx_skbuff_dma[entry],
1950 priv->dma_buf_sz, DMA_FROM_DEVICE);
1951 }
1952 } else {
1610 struct sk_buff *skb; 1953 struct sk_buff *skb;
1611 int frame_len; 1954 int frame_len;
1612 1955
@@ -1635,6 +1978,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
1635 prefetch(skb->data - NET_IP_ALIGN); 1978 prefetch(skb->data - NET_IP_ALIGN);
1636 priv->rx_skbuff[entry] = NULL; 1979 priv->rx_skbuff[entry] = NULL;
1637 1980
1981 stmmac_get_rx_hwtstamp(priv, entry, skb);
1982
1638 skb_put(skb, frame_len); 1983 skb_put(skb, frame_len);
1639 dma_unmap_single(priv->device, 1984 dma_unmap_single(priv->device,
1640 priv->rx_skbuff_dma[entry], 1985 priv->rx_skbuff_dma[entry],
@@ -1855,21 +2200,30 @@ static void stmmac_poll_controller(struct net_device *dev)
1855 * a proprietary structure used to pass information to the driver. 2200 * a proprietary structure used to pass information to the driver.
1856 * @cmd: IOCTL command 2201 * @cmd: IOCTL command
1857 * Description: 2202 * Description:
1858 * Currently there are no special functionality supported in IOCTL, just the 2203 * Currently it supports just the phy_mii_ioctl(...) and HW time stamping.
1859 * phy_mii_ioctl(...) can be invoked.
1860 */ 2204 */
1861static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 2205static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1862{ 2206{
1863 struct stmmac_priv *priv = netdev_priv(dev); 2207 struct stmmac_priv *priv = netdev_priv(dev);
1864 int ret; 2208 int ret = -EOPNOTSUPP;
1865 2209
1866 if (!netif_running(dev)) 2210 if (!netif_running(dev))
1867 return -EINVAL; 2211 return -EINVAL;
1868 2212
1869 if (!priv->phydev) 2213 switch (cmd) {
1870 return -EINVAL; 2214 case SIOCGMIIPHY:
1871 2215 case SIOCGMIIREG:
1872 ret = phy_mii_ioctl(priv->phydev, rq, cmd); 2216 case SIOCSMIIREG:
2217 if (!priv->phydev)
2218 return -EINVAL;
2219 ret = phy_mii_ioctl(priv->phydev, rq, cmd);
2220 break;
2221 case SIOCSHWTSTAMP:
2222 ret = stmmac_hwtstamp_ioctl(dev, rq);
2223 break;
2224 default:
2225 break;
2226 }
1873 2227
1874 return ret; 2228 return ret;
1875} 2229}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
new file mode 100644
index 000000000000..3dbc047622fa
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -0,0 +1,74 @@
1/******************************************************************************
2 PTP Header file
3
4 Copyright (C) 2013 Vayavya Labs Pvt Ltd
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms and conditions of the GNU General Public License,
8 version 2, as published by the Free Software Foundation.
9
10 This program is distributed in the hope it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19 The full GNU General Public License is included in this distribution in
20 the file called "COPYING".
21
22 Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
23******************************************************************************/
24
25#ifndef __STMMAC_PTP_H__
26#define __STMMAC_PTP_H__
27
28#define STMMAC_SYSCLOCK 62500000
29
30/* IEEE 1588 PTP register offsets */
31#define PTP_TCR 0x0700 /* Timestamp Control Reg */
32#define PTP_SSIR 0x0704 /* Sub-Second Increment Reg */
33#define PTP_STSR 0x0708 /* System Time – Seconds Regr */
34#define PTP_STNSR 0x070C /* System Time – Nanoseconds Reg */
35#define PTP_STSUR 0x0710 /* System Time – Seconds Update Reg */
36#define PTP_STNSUR 0x0714 /* System Time – Nanoseconds Update Reg */
37#define PTP_TAR 0x0718 /* Timestamp Addend Reg */
38#define PTP_TTSR 0x071C /* Target Time Seconds Reg */
39#define PTP_TTNSR 0x0720 /* Target Time Nanoseconds Reg */
40#define PTP_STHWSR 0x0724 /* System Time - Higher Word Seconds Reg */
41#define PTP_TSR 0x0728 /* Timestamp Status */
42
43#define PTP_STNSUR_ADDSUB_SHIFT 31
44
45/* PTP TCR defines */
46#define PTP_TCR_TSENA 0x00000001 /* Timestamp Enable */
47#define PTP_TCR_TSCFUPDT 0x00000002 /* Timestamp Fine/Coarse Update */
48#define PTP_TCR_TSINIT 0x00000004 /* Timestamp Initialize */
49#define PTP_TCR_TSUPDT 0x00000008 /* Timestamp Update */
50/* Timestamp Interrupt Trigger Enable */
51#define PTP_TCR_TSTRIG 0x00000010
52#define PTP_TCR_TSADDREG 0x00000020 /* Addend Reg Update */
53#define PTP_TCR_TSENALL 0x00000100 /* Enable Timestamp for All Frames */
54/* Timestamp Digital or Binary Rollover Control */
55#define PTP_TCR_TSCTRLSSR 0x00000200
56
57/* Enable PTP packet Processing for Version 2 Format */
58#define PTP_TCR_TSVER2ENA 0x00000400
59/* Enable Processing of PTP over Ethernet Frames */
60#define PTP_TCR_TSIPENA 0x00000800
61/* Enable Processing of PTP Frames Sent over IPv6-UDP */
62#define PTP_TCR_TSIPV6ENA 0x00001000
63/* Enable Processing of PTP Frames Sent over IPv4-UDP */
64#define PTP_TCR_TSIPV4ENA 0x00002000
65/* Enable Timestamp Snapshot for Event Messages */
66#define PTP_TCR_TSEVNTENA 0x00004000
67/* Enable Snapshot for Messages Relevant to Master */
68#define PTP_TCR_TSMSTRENA 0x00008000
69/* Select PTP packets for Taking Snapshots */
70#define PTP_TCR_SNAPTYPSEL_1 0x00010000
71/* Enable MAC address for PTP Frame Filtering */
72#define PTP_TCR_TSENMACADDR 0x00040000
73
74#endif /* __STMMAC_PTP_H__ */