summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
index b164ae22e35f..4e86cdf2bc9f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -135,7 +135,10 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
{
struct stmmac_priv *priv =
container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+ void __iomem *ptpaddr = priv->ptpaddr;
+ void __iomem *ioaddr = priv->hw->pcsr;
struct stmmac_pps_cfg *cfg;
+ u32 intr_value, acr_value;
int ret = -EOPNOTSUPP;
unsigned long flags;
@@ -159,6 +162,37 @@ 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:
+ priv->plat->ext_snapshot_en = on;
+ mutex_lock(&priv->aux_ts_lock);
+ acr_value = readl(ptpaddr + PTP_ACR);
+ acr_value &= ~PTP_ACR_MASK;
+ if (on) {
+ /* Enable External snapshot trigger */
+ acr_value |= priv->plat->ext_snapshot_num;
+ acr_value |= PTP_ACR_ATSFC;
+ netdev_dbg(priv->dev, "Auxiliary Snapshot %d enabled.\n",
+ priv->plat->ext_snapshot_num >>
+ PTP_ACR_ATSEN_SHIFT);
+ /* Enable Timestamp Interrupt */
+ intr_value = readl(ioaddr + GMAC_INT_EN);
+ intr_value |= GMAC_INT_TSIE;
+ writel(intr_value, ioaddr + GMAC_INT_EN);
+
+ } else {
+ netdev_dbg(priv->dev, "Auxiliary Snapshot %d disabled.\n",
+ priv->plat->ext_snapshot_num >>
+ PTP_ACR_ATSEN_SHIFT);
+ /* Disable Timestamp Interrupt */
+ intr_value = readl(ioaddr + GMAC_INT_EN);
+ intr_value &= ~GMAC_INT_TSIE;
+ writel(intr_value, ioaddr + GMAC_INT_EN);
+ }
+ writel(acr_value, ptpaddr + PTP_ACR);
+ mutex_unlock(&priv->aux_ts_lock);
+ ret = 0;
+ break;
+
default:
break;
}
@@ -202,7 +236,7 @@ static struct ptp_clock_info stmmac_ptp_clock_ops = {
.name = "stmmac ptp",
.max_adj = 62500000,
.n_alarm = 0,
- .n_ext_ts = 0,
+ .n_ext_ts = 0, /* will be overwritten in stmmac_ptp_register */
.n_per_out = 0, /* will be overwritten in stmmac_ptp_register */
.n_pins = 0,
.pps = 0,
@@ -237,8 +271,10 @@ 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;
+ stmmac_ptp_clock_ops.n_ext_ts = priv->dma_cap.aux_snapshot_n;
spin_lock_init(&priv->ptp_lock);
+ mutex_init(&priv->aux_ts_lock);
priv->ptp_clock_ops = stmmac_ptp_clock_ops;
priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
@@ -264,4 +300,6 @@ void stmmac_ptp_unregister(struct stmmac_priv *priv)
pr_debug("Removed PTP HW clock successfully on %s\n",
priv->dev->name);
}
+
+ mutex_destroy(&priv->aux_ts_lock);
}