Skip to content

Commit

Permalink
stmmac: add IEEE PTPv1 and PTPv2 support.
Browse files Browse the repository at this point in the history
This patch enhances the stmmac driver to support IEEE 1588-2002
PTP (Precision Time Protocol) version 1 and IEEE 1588-2008 PPT
version 2.

Precision Time Protocol(PTP),which enables precise synchronization
of clocks in measurement and control systems implemented with
technologies such as network communication,local computing,
& distributed objects.

Both PTPv1 and PTPv2 is selected at run-time using the HW capability
register.

The PTPv1 TimeStamp support can be used on chips that have the normal
descriptor structures and PTPv2 TimeStamp support can be used on chips
that have the Extended descriptors(DES4-5-6-7). All such sanity checks
are done and verified by using HW capability register.

V2: in this version the ethtool support has been included in this patch;
Koptions have been completely removed (previously added to select
PTP and PTPv2). PTPv1 and PTPv2 is now added in a single patch instead of
two patches.
get_timestamp() and get_systemtime() L/H have been combined into single APIs.

Signed-off-by: Rayagond Kokatanur <rayagond@vayavyalabs.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Rayagond Kokatanur authored and David S. Miller committed Mar 26, 2013
1 parent cf32dee commit 891434b
Show file tree
Hide file tree
Showing 11 changed files with 732 additions and 24 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/stmicro/stmmac/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
mmc_core.o $(stmmac-y)
mmc_core.o stmmac_hwtstamp.o $(stmmac-y)
32 changes: 32 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/chain_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,40 @@ static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
}
}

static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
{
struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;

if (priv->hwts_rx_en && !priv->extend_desc)
/* NOTE: Device will overwrite des3 with timestamp value if
* 1588-2002 time stamping is enabled, hence reinitialize it
* to keep explicit chaining in the descriptor.
*/
p->des3 = (unsigned int)(priv->dma_rx_phy +
(((priv->dirty_rx) + 1) %
priv->dma_rx_size) *
sizeof(struct dma_desc));
}

static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
{
struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;

if (priv->hw->desc->get_tx_ls(p) && !priv->extend_desc)
/* NOTE: Device will overwrite des3 with timestamp value if
* 1588-2002 time stamping is enabled, hence reinitialize it
* to keep explicit chaining in the descriptor.
*/
p->des3 = (unsigned int)(priv->dma_tx_phy +
(((priv->dirty_tx + 1) %
priv->dma_tx_size) *
sizeof(struct dma_desc)));
}

const struct stmmac_chain_mode_ops chain_mode_ops = {
.init = stmmac_init_dma_chain,
.is_jumbo_frm = stmmac_is_jumbo_frm,
.jumbo_frm = stmmac_jumbo_frm,
.refill_desc3 = stmmac_refill_desc3,
.clean_desc3 = stmmac_clean_desc3,
};
22 changes: 20 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,14 @@ struct stmmac_desc_ops {
struct dma_desc *p);
void (*rx_extended_status) (void *data, struct stmmac_extra_stats *x,
struct dma_extended_desc *p);
/* Set tx timestamp enable bit */
void (*enable_tx_timestamp) (struct dma_desc *p);
/* get tx timestamp status */
int (*get_tx_timestamp_status) (struct dma_desc *p);
/* get timestamp value */
u64 (*get_timestamp) (void *desc, u32 ats);
/* get rx timestamp status */
int (*get_rx_timestamp_status) (void *desc, u32 ats);
};

struct stmmac_dma_ops {
Expand Down Expand Up @@ -398,6 +406,13 @@ struct stmmac_ops {
void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv);
};

struct stmmac_hwtimestamp {
void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
void (*config_sub_second_increment) (void __iomem *ioaddr);
int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
int (*config_addend)(void __iomem *ioaddr, u32 addend);
};

struct mac_link {
int port;
int duplex;
Expand All @@ -412,9 +427,9 @@ struct mii_regs {
struct stmmac_ring_mode_ops {
unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
void (*refill_desc3) (int bfsize, struct dma_desc *p);
void (*refill_desc3) (void *priv, struct dma_desc *p);
void (*init_desc3) (struct dma_desc *p);
void (*clean_desc3) (struct dma_desc *p);
void (*clean_desc3) (void *priv, struct dma_desc *p);
int (*set_16kib_bfsize) (int mtu);
};

Expand All @@ -423,6 +438,8 @@ struct stmmac_chain_mode_ops {
unsigned int extend_desc);
unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
void (*refill_desc3) (void *priv, struct dma_desc *p);
void (*clean_desc3) (void *priv, struct dma_desc *p);
};

struct mac_device_info {
Expand All @@ -431,6 +448,7 @@ struct mac_device_info {
const struct stmmac_dma_ops *dma;
const struct stmmac_ring_mode_ops *ring;
const struct stmmac_chain_mode_ops *chain;
const struct stmmac_hwtimestamp *ptp;
struct mii_regs mii; /* MII register Addresses */
struct mac_link link;
unsigned int synopsys_uid;
Expand Down
47 changes: 47 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/enh_desc.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,49 @@ static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
return p->des01.erx.frame_length;
}

static void enh_desc_enable_tx_timestamp(struct dma_desc *p)
{
p->des01.etx.time_stamp_enable = 1;
}

static int enh_desc_get_tx_timestamp_status(struct dma_desc *p)
{
return p->des01.etx.time_stamp_status;
}

static u64 enh_desc_get_timestamp(void *desc, u32 ats)
{
u64 ns;

if (ats) {
struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
ns = p->des6;
/* convert high/sec time stamp value to nanosecond */
ns += p->des7 * 1000000000ULL;
} else {
struct dma_desc *p = (struct dma_desc *)desc;
ns = p->des2;
ns += p->des3 * 1000000000ULL;
}

return ns;
}

static int enh_desc_get_rx_timestamp_status(void *desc, u32 ats)
{
if (ats) {
struct dma_extended_desc *p = (struct dma_extended_desc *)desc;
return p->basic.des01.erx.ipc_csum_error;
} else {
struct dma_desc *p = (struct dma_desc *)desc;
if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
/* timestamp is corrupted, hence don't store it */
return 0;
else
return 1;
}
}

const struct stmmac_desc_ops enh_desc_ops = {
.tx_status = enh_desc_get_tx_status,
.rx_status = enh_desc_get_rx_status,
Expand All @@ -395,4 +438,8 @@ const struct stmmac_desc_ops enh_desc_ops = {
.set_rx_owner = enh_desc_set_rx_owner,
.get_rx_frame_len = enh_desc_get_rx_frame_len,
.rx_extended_status = enh_desc_get_ext_status,
.enable_tx_timestamp = enh_desc_enable_tx_timestamp,
.get_tx_timestamp_status = enh_desc_get_tx_timestamp_status,
.get_timestamp = enh_desc_get_timestamp,
.get_rx_timestamp_status = enh_desc_get_rx_timestamp_status,
};
37 changes: 37 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/norm_desc.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,39 @@ static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
return p->des01.rx.frame_length;
}

static void ndesc_enable_tx_timestamp(struct dma_desc *p)
{
p->des01.tx.time_stamp_enable = 1;
}

static int ndesc_get_tx_timestamp_status(struct dma_desc *p)
{
return p->des01.tx.time_stamp_status;
}

static u64 ndesc_get_timestamp(void *desc, u32 ats)
{
struct dma_desc *p = (struct dma_desc *)desc;
u64 ns;

ns = p->des2;
/* convert high/sec time stamp value to nanosecond */
ns += p->des3 * 1000000000ULL;

return ns;
}

static int ndesc_get_rx_timestamp_status(void *desc, u32 ats)
{
struct dma_desc *p = (struct dma_desc *)desc;

if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff))
/* timestamp is corrupted, hence don't store it */
return 0;
else
return 1;
}

const struct stmmac_desc_ops ndesc_ops = {
.tx_status = ndesc_get_tx_status,
.rx_status = ndesc_get_rx_status,
Expand All @@ -235,4 +268,8 @@ const struct stmmac_desc_ops ndesc_ops = {
.set_tx_owner = ndesc_set_tx_owner,
.set_rx_owner = ndesc_set_rx_owner,
.get_rx_frame_len = ndesc_get_rx_frame_len,
.enable_tx_timestamp = ndesc_enable_tx_timestamp,
.get_tx_timestamp_status = ndesc_get_tx_timestamp_status,
.get_timestamp = ndesc_get_timestamp,
.get_rx_timestamp_status = ndesc_get_rx_timestamp_status,
};
13 changes: 8 additions & 5 deletions drivers/net/ethernet/stmicro/stmmac/ring_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,14 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
return ret;
}

static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
{
/* Fill DES3 in case of RING mode */
if (bfsize >= BUF_SIZE_8KiB)
p->des3 = p->des2 + BUF_SIZE_8KiB;
struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;

if (unlikely(priv->plat->has_gmac))
/* Fill DES3 in case of RING mode */
if (priv->dma_buf_sz >= BUF_SIZE_8KiB)
p->des3 = p->des2 + BUF_SIZE_8KiB;
}

/* In ring mode we need to fill the desc3 because it is used as buffer */
Expand All @@ -100,7 +103,7 @@ static void stmmac_init_desc3(struct dma_desc *p)
p->des3 = p->des2 + BUF_SIZE_8KiB;
}

static void stmmac_clean_desc3(struct dma_desc *p)
static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
{
if (unlikely(p->des3))
p->des3 = 0;
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ struct stmmac_priv {
unsigned int mode;
int extend_desc;
int pcs;
int hwts_tx_en;
int hwts_rx_en;
unsigned int default_addend;
u32 adv_ts;
};

extern int phyaddr;
Expand All @@ -108,6 +112,7 @@ extern int stmmac_mdio_register(struct net_device *ndev);
extern void stmmac_set_ethtool_ops(struct net_device *netdev);
extern const struct stmmac_desc_ops enh_desc_ops;
extern const struct stmmac_desc_ops ndesc_ops;
extern const struct stmmac_hwtimestamp stmmac_ptp;
int stmmac_freeze(struct net_device *ndev);
int stmmac_restore(struct net_device *ndev);
int stmmac_resume(struct net_device *ndev);
Expand Down
32 changes: 31 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/interrupt.h>
#include <linux/mii.h>
#include <linux/phy.h>
#include <linux/net_tstamp.h>
#include <asm/io.h>

#include "stmmac.h"
Expand Down Expand Up @@ -725,6 +726,35 @@ static int stmmac_set_coalesce(struct net_device *dev,
return 0;
}

static int stmmac_get_ts_info(struct net_device *dev,
struct ethtool_ts_info *info)
{
struct stmmac_priv *priv = netdev_priv(dev);

if ((priv->hwts_tx_en) && (priv->hwts_rx_en)) {

info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;

info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);

info->rx_filters = ((1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
(1 << HWTSTAMP_FILTER_ALL));
return 0;
} else
return ethtool_op_get_ts_info(dev, info);
}

static const struct ethtool_ops stmmac_ethtool_ops = {
.begin = stmmac_check_if_running,
.get_drvinfo = stmmac_ethtool_getdrvinfo,
Expand All @@ -744,7 +774,7 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
.get_eee = stmmac_ethtool_op_get_eee,
.set_eee = stmmac_ethtool_op_set_eee,
.get_sset_count = stmmac_get_sset_count,
.get_ts_info = ethtool_op_get_ts_info,
.get_ts_info = stmmac_get_ts_info,
.get_coalesce = stmmac_get_coalesce,
.set_coalesce = stmmac_set_coalesce,
};
Expand Down
Loading

0 comments on commit 891434b

Please sign in to comment.