@@ -41,8 +41,7 @@
#define GMAC_INT_DISABLE_PCS (GMAC_INT_DISABLE_RGMII | \
GMAC_INT_DISABLE_PCSLINK | \
GMAC_INT_DISABLE_PCSAN)
-#define GMAC_INT_DEFAULT_MASK (GMAC_INT_DISABLE_TIMESTAMP | \
- GMAC_INT_DISABLE_PCS)
+#define GMAC_INT_DEFAULT_MASK GMAC_INT_DISABLE_PCS
/* PMT Control and Status */
#define GMAC_PMT 0x0000002c
@@ -20,6 +20,7 @@
#include "stmmac.h"
#include "stmmac_pcs.h"
#include "dwmac1000.h"
+#include "stmmac_ptp.h"
static void dwmac1000_core_init(struct mac_device_info *hw,
struct net_device *dev)
@@ -300,9 +301,29 @@ static void dwmac1000_rgsmii(void __iomem *ioaddr, struct stmmac_extra_stats *x)
}
}
+static void dwmac1000_ptp_isr(struct stmmac_priv *priv)
+{
+ struct ptp_clock_event event;
+ u32 reg_value;
+ u64 ns;
+
+ reg_value = readl(priv->ioaddr + PTP_GMAC3_TSR);
+
+ ns = readl(priv->ioaddr + PTP_GMAC3_AUXTSLO);
+ ns += readl(priv->ioaddr + PTP_GMAC3_AUXTSHI) * 1000000000ULL;
+
+ event.timestamp = ns;
+ event.type = PTP_CLOCK_EXTTS;
+ event.index = (reg_value & PTP_GMAC3_ATSSTN_MASK) >>
+ PTP_GMAC3_ATSSTN_SHIFT;
+ ptp_clock_event(priv->ptp_clock, &event);
+}
+
static int dwmac1000_irq_status(struct mac_device_info *hw,
struct stmmac_extra_stats *x)
{
+ struct stmmac_priv *priv =
+ container_of(x, struct stmmac_priv, xstats);
void __iomem *ioaddr = hw->pcsr;
u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
u32 intr_mask = readl(ioaddr + GMAC_INT_MASK);
@@ -324,6 +345,9 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
x->irq_receive_pmt_irq_n++;
}
+ if (intr_status & GMAC_INT_STATUS_TSTAMP)
+ dwmac1000_ptp_isr(priv);
+
/* MAC tx/rx EEE LPI entry/exit interrupts */
if (intr_status & GMAC_INT_STATUS_LPIIS) {
/* Clean LPI interrupt by reading the Reg 12 */
@@ -492,7 +492,8 @@ struct stmmac_ops {
/* PTP and HW Timer helpers */
struct stmmac_hwtimestamp {
- void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
+ void (*get_hw_tstamping)(void __iomem *ioaddr, u32 *data);
+ void (*set_hw_tstamping)(void __iomem *ioaddr, u32 data);
void (*config_sub_second_increment)(void __iomem *ioaddr, u32 ptp_clock,
int gmac4, u32 *ssinc);
int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
@@ -502,8 +503,10 @@ struct stmmac_hwtimestamp {
void (*get_systime) (void __iomem *ioaddr, u64 *systime);
};
-#define stmmac_config_hw_tstamping(__priv, __args...) \
- stmmac_do_void_callback(__priv, ptp, config_hw_tstamping, __args)
+#define stmmac_get_hw_tstamping(__priv, __args...) \
+ stmmac_do_void_callback(__priv, ptp, get_hw_tstamping, __args)
+#define stmmac_set_hw_tstamping(__priv, __args...) \
+ stmmac_do_void_callback(__priv, ptp, set_hw_tstamping, __args)
#define stmmac_config_sub_second_increment(__priv, __args...) \
stmmac_do_void_callback(__priv, ptp, config_sub_second_increment, __args)
#define stmmac_init_systime(__priv, __args...) \
@@ -15,7 +15,12 @@
#include "common.h"
#include "stmmac_ptp.h"
-static void config_hw_tstamping(void __iomem *ioaddr, u32 data)
+static void get_hw_tstamping(void __iomem *ioaddr, u32 *data)
+{
+ *data = readl(ioaddr + PTP_TCR);
+}
+
+static void set_hw_tstamping(void __iomem *ioaddr, u32 data)
{
writel(data, ioaddr + PTP_TCR);
}
@@ -154,7 +159,8 @@ static void get_systime(void __iomem *ioaddr, u64 *systime)
}
const struct stmmac_hwtimestamp stmmac_ptp = {
- .config_hw_tstamping = config_hw_tstamping,
+ .get_hw_tstamping = get_hw_tstamping,
+ .set_hw_tstamping = set_hw_tstamping,
.init_systime = init_systime,
.config_sub_second_increment = config_sub_second_increment,
.config_addend = config_addend,
@@ -686,13 +686,14 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
if (!priv->hwts_tx_en && !priv->hwts_rx_en)
- stmmac_config_hw_tstamping(priv, priv->ptpaddr, 0);
+ stmmac_set_hw_tstamping(priv, priv->ptpaddr, 0);
else {
- value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
+ stmmac_get_hw_tstamping(priv, priv->ptpaddr, &value);
+ value |= (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
tstamp_all | ptp_v2 | ptp_over_ethernet |
ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
ts_master_en | snap_type_sel);
- stmmac_config_hw_tstamping(priv, priv->ptpaddr, value);
+ stmmac_set_hw_tstamping(priv, priv->ptpaddr, value);
/* program Sub Second Increment reg */
stmmac_config_sub_second_increment(priv,
@@ -45,6 +45,43 @@ static int stmmac_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
return 0;
}
+static int stmmac_extts_configure(struct stmmac_priv *priv,
+ struct ptp_clock_request *rq,
+ int on)
+{
+ u32 tsauxc, tsauxc_mask;
+
+ if (priv->ptp_clock_ops.n_ext_ts <= rq->extts.index)
+ return -ERANGE;
+
+ switch (rq->extts.index) {
+ case 0:
+ tsauxc_mask = PTP_TCR_ATSEN0;
+ break;
+ case 1:
+ tsauxc_mask = PTP_TCR_ATSEN1;
+ break;
+ case 2:
+ tsauxc_mask = PTP_TCR_ATSEN2;
+ break;
+ case 3:
+ tsauxc_mask = PTP_TCR_ATSEN3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tsauxc = readl(priv->ptpaddr);
+
+ if (on)
+ tsauxc |= tsauxc_mask;
+ else
+ tsauxc &= ~tsauxc_mask;
+
+ writel(tsauxc, priv->ptpaddr);
+ return 0;
+}
+
/**
* stmmac_adjust_time
*
@@ -158,6 +195,11 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
priv->systime_flags);
spin_unlock_irqrestore(&priv->ptp_lock, flags);
break;
+ case PTP_CLK_REQ_EXTTS:
+ spin_lock_irqsave(&priv->ptp_lock, flags);
+ ret = stmmac_extts_configure(priv, rq, on);
+ spin_unlock_irqrestore(&priv->ptp_lock, flags);
+ break;
default:
break;
}
@@ -202,6 +244,8 @@ void stmmac_ptp_register(struct stmmac_priv *priv)
stmmac_ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;
stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
+ if (priv->plat->has_gmac)
+ stmmac_ptp_clock_ops.n_ext_ts = 4;
spin_lock_init(&priv->ptp_lock);
priv->ptp_clock_ops = stmmac_ptp_clock_ops;
@@ -59,9 +59,29 @@
#define PTP_TCR_SNAPTYPSEL_1 BIT(16)
/* Enable MAC address for PTP Frame Filtering */
#define PTP_TCR_TSENMACADDR BIT(18)
+/* Clear Auxiliary Snapshot FIFO */
+#define PTP_TCR_ATSFC BIT(24)
+/* Enable Auxiliary Snapshot 0 */
+#define PTP_TCR_ATSEN0 BIT(25)
+/* Enable Auxiliary Snapshot 1 */
+#define PTP_TCR_ATSEN1 BIT(26)
+/* Enable Auxiliary Snapshot 2 */
+#define PTP_TCR_ATSEN2 BIT(27)
+/* Enable Auxiliary Snapshot 3 */
+#define PTP_TCR_ATSEN3 BIT(28)
/* SSIR defines */
#define PTP_SSIR_SSINC_MASK 0xff
#define GMAC4_PTP_SSIR_SSINC_SHIFT 16
+/* Auxiliary Timestamp Snapshot defines */
+
+#define PTP_GMAC3_TSR 0x0728 /* Timestamp Status */
+#define PTP_GMAC3_AUXTSLO 0x0730 /* Aux Timestamp - Nanoseconds Reg */
+#define PTP_GMAC3_AUXTSHI 0x0734 /* Aux Timestamp - Seconds Reg */
+
+#define PTP_GMAC3_TSR 0x0728 /* Timestamp Status */
+#define PTP_GMAC3_ATSSTN_MASK GENMASK(19, 16)
+#define PTP_GMAC3_ATSSTN_SHIFT 16
+
#endif /* __STMMAC_PTP_H__ */