This adds support for PPS output and Flexible PPS (which is equivalent
to per_out output of PTP subsystem).
Tested using an oscilloscope and the following commands:
1) Start PTP4L:
# ptp4l -A -4 -H -m -i eth0 &
2) Set Flexible PPS frequency:
# echo > /sys/class/ptp/ptpX/period
Where, ts/tns is start time and ps/pns is period time, and ptpX is ptp
of eth0.
Signed-off-by: Jose Abreu
Cc: David S. Miller
Cc: Joao Pinto
Cc: Vitor Soares
Cc: Giuseppe Cavallaro
Cc: Alexandre Torgue
---
drivers/net/ethernet/stmicro/stmmac/common.h |2 +
drivers/net/ethernet/stmicro/stmmac/dwmac4.h |1 +
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c |2 +
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c |2 +
drivers/net/ethernet/stmicro/stmmac/dwmac5.c | 68 +
drivers/net/ethernet/stmicro/stmmac/dwmac5.h | 23 +++
drivers/net/ethernet/stmicro/stmmac/hwif.h| 10 +++
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 12
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c |4 +
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c | 50 ++-
10 files changed, 170 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h
b/drivers/net/ethernet/stmicro/stmmac/common.h
index a679cb7..78fd0f8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -346,6 +346,8 @@ struct dma_features {
/* TX and RX number of queues */
unsigned int number_rx_queues;
unsigned int number_tx_queues;
+ /* PPS output */
+ unsigned int pps_out_num;
/* Alternate (enhanced) DESC mode */
unsigned int enh_desc;
/* TX and RX FIFO sizes */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index 6330a55..eb013d5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
@@ -187,6 +187,7 @@ enum power_event {
#define GMAC_HW_RXFIFOSIZE GENMASK(4, 0)
/* MAC HW features2 bitmap */
+#define GMAC_HW_FEAT_PPSOUTNUM GENMASK(26, 24)
#define GMAC_HW_FEAT_TXCHCNT GENMASK(21, 18)
#define GMAC_HW_FEAT_RXCHCNT GENMASK(15, 12)
#define GMAC_HW_FEAT_TXQCNTGENMASK(9, 6)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index a7121a7..d46e784 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -796,6 +796,8 @@ static void dwmac4_debug(void __iomem *ioaddr, struct
stmmac_extra_stats *x,
.safety_feat_irq_status = dwmac5_safety_feat_irq_status,
.safety_feat_dump = dwmac5_safety_feat_dump,
.rxp_config = dwmac5_rxp_config,
+ .pps_config = dwmac5_pps_config,
+ .flex_pps_config = dwmac5_flex_pps_config,
};
int dwmac4_setup(struct stmmac_priv *priv)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index bf8e5a1..d37f17c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -373,6 +373,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
((hw_cap & GMAC_HW_FEAT_RXQCNT) >> 0) + 1;
dma_cap->number_tx_queues =
((hw_cap & GMAC_HW_FEAT_TXQCNT) >> 6) + 1;
+ /* PPS output */
+ dma_cap->pps_out_num = (hw_cap & GMAC_HW_FEAT_PPSOUTNUM) >> 24;
/* IEEE 1588-2002 */
dma_cap->time_stamp = 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
index b2becb8..98c9cef 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
@@ -8,6 +8,7 @@
#include "dwmac4.h"
#include "dwmac5.h"
#include "stmmac.h"
+#include "stmmac_ptp.h"
struct dwmac5_error_desc {
bool valid;
@@ -494,3 +495,70 @@ int dwmac5_rxp_config(void __iomem *ioaddr, struct
stmmac_tc_entry *entries,
writel(old_val, ioaddr + GMAC_CONFIG);
return ret;
}
+
+int dwmac5_pps_config(void __iomem *ioaddr, bool enable)
+{
+ u32 val = readl(ioaddr + MAC_PPS_CONTROL);
+
+ /* There is no way to disable fixed PPS output so we just reset
+* the values to make sure its in fixed PPS mode */
+ val &= ~PPSx_MASK(0);
+ val |= TRGTMODSELx(0, 0x2);
+
+ writel(val, ioaddr + MAC_PPS_CONTROL);
+ return 0;
+}
+
+int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
+ struct stmmac_pps_cfg *cfg, bool enable,
+ u32 sub_second_inc, u32 systime_flags)
+{
+ u32 tnsec = readl(ioaddr +