Skip to content

Commit f4da565

Browse files
teemintadavem330
authored andcommitted
net: stmmac: Add support for external trigger timestamping
The Synopsis MAC controller supports auxiliary snapshot feature that allows user to store a snapshot of the system time based on an external event. This patch add supports to the above mentioned feature. Users will be able to triggered capturing the time snapshot from user-space using application such as testptp or any other applications that uses the PTP_EXTTS_REQUEST ioctl request. Cc: Richard Cochran <[email protected]> Signed-off-by: Tan Tee Min <[email protected]> Co-developed-by: Wong Vee Khee <[email protected]> Signed-off-by: Wong Vee Khee <[email protected]> Acked-by: Richard Cochran <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 945c6ff commit f4da565

File tree

8 files changed

+101
-1
lines changed

8 files changed

+101
-1
lines changed

drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,13 @@ static int intel_crosststamp(ktime_t *device,
296296

297297
intel_priv = priv->plat->bsp_priv;
298298

299+
/* Both internal crosstimestamping and external triggered event
300+
* timestamping cannot be run concurrently.
301+
*/
302+
if (priv->plat->ext_snapshot_en)
303+
return -EBUSY;
304+
305+
mutex_lock(&priv->aux_ts_lock);
299306
/* Enable Internal snapshot trigger */
300307
acr_value = readl(ptpaddr + PTP_ACR);
301308
acr_value &= ~PTP_ACR_MASK;
@@ -321,6 +328,8 @@ static int intel_crosststamp(ktime_t *device,
321328
acr_value = readl(ptpaddr + PTP_ACR);
322329
acr_value |= PTP_ACR_ATSFC;
323330
writel(acr_value, ptpaddr + PTP_ACR);
331+
/* Release the mutex */
332+
mutex_unlock(&priv->aux_ts_lock);
324333

325334
/* Trigger Internal snapshot signal
326335
* Create a rising edge by just toggle the GPO1 to low
@@ -520,6 +529,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev,
520529
plat->mdio_bus_data->phy_mask |= 1 << INTEL_MGBE_XPCS_ADDR;
521530

522531
plat->int_snapshot_num = AUX_SNAPSHOT1;
532+
plat->ext_snapshot_num = AUX_SNAPSHOT0;
523533

524534
plat->has_crossts = true;
525535
plat->crosststamp = intel_crosststamp;

drivers/net/ethernet/stmicro/stmmac/hwif.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,8 @@ struct stmmac_ops {
504504
#define stmmac_fpe_irq_status(__priv, __args...) \
505505
stmmac_do_callback(__priv, mac, fpe_irq_status, __args)
506506

507+
struct stmmac_priv;
508+
507509
/* PTP and HW Timer helpers */
508510
struct stmmac_hwtimestamp {
509511
void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
@@ -515,6 +517,7 @@ struct stmmac_hwtimestamp {
515517
int add_sub, int gmac4);
516518
void (*get_systime) (void __iomem *ioaddr, u64 *systime);
517519
void (*get_ptptime)(void __iomem *ioaddr, u64 *ptp_time);
520+
void (*timestamp_interrupt)(struct stmmac_priv *priv);
518521
};
519522

520523
#define stmmac_config_hw_tstamping(__priv, __args...) \
@@ -531,6 +534,8 @@ struct stmmac_hwtimestamp {
531534
stmmac_do_void_callback(__priv, ptp, get_systime, __args)
532535
#define stmmac_get_ptptime(__priv, __args...) \
533536
stmmac_do_void_callback(__priv, ptp, get_ptptime, __args)
537+
#define stmmac_timestamp_interrupt(__priv, __args...) \
538+
stmmac_do_void_callback(__priv, ptp, timestamp_interrupt, __args)
534539

535540
/* Helpers to manage the descriptors for chain and ring modes */
536541
struct stmmac_mode_ops {

drivers/net/ethernet/stmicro/stmmac/stmmac.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ struct stmmac_priv {
250250
int use_riwt;
251251
int irq_wake;
252252
spinlock_t ptp_lock;
253+
/* Protects auxiliary snapshot registers from concurrent access. */
254+
struct mutex aux_ts_lock;
255+
253256
void __iomem *mmcaddr;
254257
void __iomem *ptpaddr;
255258
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];

drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
#include <linux/io.h>
1313
#include <linux/iopoll.h>
1414
#include <linux/delay.h>
15+
#include <linux/ptp_clock_kernel.h>
1516
#include "common.h"
1617
#include "stmmac_ptp.h"
18+
#include "dwmac4.h"
19+
#include "stmmac.h"
1720

1821
static void config_hw_tstamping(void __iomem *ioaddr, u32 data)
1922
{
@@ -163,6 +166,41 @@ static void get_ptptime(void __iomem *ptpaddr, u64 *ptp_time)
163166
*ptp_time = ns;
164167
}
165168

169+
static void timestamp_interrupt(struct stmmac_priv *priv)
170+
{
171+
u32 num_snapshot, ts_status, tsync_int;
172+
struct ptp_clock_event event;
173+
unsigned long flags;
174+
u64 ptp_time;
175+
int i;
176+
177+
tsync_int = readl(priv->ioaddr + GMAC_INT_STATUS) & GMAC_INT_TSIE;
178+
179+
if (!tsync_int)
180+
return;
181+
182+
/* Read timestamp status to clear interrupt from either external
183+
* timestamp or start/end of PPS.
184+
*/
185+
ts_status = readl(priv->ioaddr + GMAC_TIMESTAMP_STATUS);
186+
187+
if (!priv->plat->ext_snapshot_en)
188+
return;
189+
190+
num_snapshot = (ts_status & GMAC_TIMESTAMP_ATSNS_MASK) >>
191+
GMAC_TIMESTAMP_ATSNS_SHIFT;
192+
193+
for (i = 0; i < num_snapshot; i++) {
194+
spin_lock_irqsave(&priv->ptp_lock, flags);
195+
get_ptptime(priv->ptpaddr, &ptp_time);
196+
spin_unlock_irqrestore(&priv->ptp_lock, flags);
197+
event.type = PTP_CLOCK_EXTTS;
198+
event.index = 0;
199+
event.timestamp = ptp_time;
200+
ptp_clock_event(priv->ptp_clock, &event);
201+
}
202+
}
203+
166204
const struct stmmac_hwtimestamp stmmac_ptp = {
167205
.config_hw_tstamping = config_hw_tstamping,
168206
.init_systime = init_systime,
@@ -171,4 +209,5 @@ const struct stmmac_hwtimestamp stmmac_ptp = {
171209
.adjust_systime = adjust_systime,
172210
.get_systime = get_systime,
173211
.get_ptptime = get_ptptime,
212+
.timestamp_interrupt = timestamp_interrupt,
174213
};

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5687,6 +5687,8 @@ static void stmmac_common_interrupt(struct stmmac_priv *priv)
56875687
else
56885688
netif_carrier_off(priv->dev);
56895689
}
5690+
5691+
stmmac_timestamp_interrupt(priv, priv);
56905692
}
56915693
}
56925694

drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,10 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
135135
{
136136
struct stmmac_priv *priv =
137137
container_of(ptp, struct stmmac_priv, ptp_clock_ops);
138+
void __iomem *ptpaddr = priv->ptpaddr;
139+
void __iomem *ioaddr = priv->hw->pcsr;
138140
struct stmmac_pps_cfg *cfg;
141+
u32 intr_value, acr_value;
139142
int ret = -EOPNOTSUPP;
140143
unsigned long flags;
141144

@@ -159,6 +162,37 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
159162
priv->systime_flags);
160163
spin_unlock_irqrestore(&priv->ptp_lock, flags);
161164
break;
165+
case PTP_CLK_REQ_EXTTS:
166+
priv->plat->ext_snapshot_en = on;
167+
mutex_lock(&priv->aux_ts_lock);
168+
acr_value = readl(ptpaddr + PTP_ACR);
169+
acr_value &= ~PTP_ACR_MASK;
170+
if (on) {
171+
/* Enable External snapshot trigger */
172+
acr_value |= priv->plat->ext_snapshot_num;
173+
acr_value |= PTP_ACR_ATSFC;
174+
netdev_dbg(priv->dev, "Auxiliary Snapshot %d enabled.\n",
175+
priv->plat->ext_snapshot_num >>
176+
PTP_ACR_ATSEN_SHIFT);
177+
/* Enable Timestamp Interrupt */
178+
intr_value = readl(ioaddr + GMAC_INT_EN);
179+
intr_value |= GMAC_INT_TSIE;
180+
writel(intr_value, ioaddr + GMAC_INT_EN);
181+
182+
} else {
183+
netdev_dbg(priv->dev, "Auxiliary Snapshot %d disabled.\n",
184+
priv->plat->ext_snapshot_num >>
185+
PTP_ACR_ATSEN_SHIFT);
186+
/* Disable Timestamp Interrupt */
187+
intr_value = readl(ioaddr + GMAC_INT_EN);
188+
intr_value &= ~GMAC_INT_TSIE;
189+
writel(intr_value, ioaddr + GMAC_INT_EN);
190+
}
191+
writel(acr_value, ptpaddr + PTP_ACR);
192+
mutex_unlock(&priv->aux_ts_lock);
193+
ret = 0;
194+
break;
195+
162196
default:
163197
break;
164198
}
@@ -202,7 +236,7 @@ static struct ptp_clock_info stmmac_ptp_clock_ops = {
202236
.name = "stmmac ptp",
203237
.max_adj = 62500000,
204238
.n_alarm = 0,
205-
.n_ext_ts = 0,
239+
.n_ext_ts = 0, /* will be overwritten in stmmac_ptp_register */
206240
.n_per_out = 0, /* will be overwritten in stmmac_ptp_register */
207241
.n_pins = 0,
208242
.pps = 0,
@@ -237,8 +271,10 @@ void stmmac_ptp_register(struct stmmac_priv *priv)
237271
stmmac_ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;
238272

239273
stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
274+
stmmac_ptp_clock_ops.n_ext_ts = priv->dma_cap.aux_snapshot_n;
240275

241276
spin_lock_init(&priv->ptp_lock);
277+
mutex_init(&priv->aux_ts_lock);
242278
priv->ptp_clock_ops = stmmac_ptp_clock_ops;
243279

244280
priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
@@ -264,4 +300,6 @@ void stmmac_ptp_unregister(struct stmmac_priv *priv)
264300
pr_debug("Removed PTP HW clock successfully on %s\n",
265301
priv->dev->name);
266302
}
303+
304+
mutex_destroy(&priv->aux_ts_lock);
267305
}

drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
#define PTP_ACR_ATSEN1 BIT(5) /* Auxiliary Snapshot 1 Enable */
7474
#define PTP_ACR_ATSEN2 BIT(6) /* Auxiliary Snapshot 2 Enable */
7575
#define PTP_ACR_ATSEN3 BIT(7) /* Auxiliary Snapshot 3 Enable */
76+
#define PTP_ACR_ATSEN_SHIFT 5 /* Auxiliary Snapshot shift */
7677
#define PTP_ACR_MASK GENMASK(7, 4) /* Aux Snapshot Mask */
7778
#define PMC_ART_VALUE0 0x01 /* PMC_ART[15:0] timer value */
7879
#define PMC_ART_VALUE1 0x02 /* PMC_ART[31:16] timer value */

include/linux/stmmac.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ struct plat_stmmacenet_data {
238238
struct pci_dev *pdev;
239239
bool has_crossts;
240240
int int_snapshot_num;
241+
int ext_snapshot_num;
242+
bool ext_snapshot_en;
241243
bool multi_msi_en;
242244
int msi_mac_vec;
243245
int msi_wol_vec;

0 commit comments

Comments
 (0)