Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95eaf3cd authored by Jose Abreu's avatar Jose Abreu Committed by David S. Miller
Browse files

net: stmmac: dwxgmac: Add Flexible PPS support



Add the support for Flexible PPS in XGMAC cores.

Signed-off-by: default avatarJose Abreu <joabreu@synopsys.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b5418e13
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -149,6 +149,25 @@
#define XGMAC_TXTIMESTAMP_NSEC		0x00000d30
#define XGMAC_TXTSSTSLO			GENMASK(30, 0)
#define XGMAC_TXTIMESTAMP_SEC		0x00000d34
#define XGMAC_PPS_CONTROL		0x00000d70
#define XGMAC_PPS_MAXIDX(x)		((((x) + 1) * 8) - 1)
#define XGMAC_PPS_MINIDX(x)		((x) * 8)
#define XGMAC_PPSx_MASK(x)		\
	GENMASK(XGMAC_PPS_MAXIDX(x), XGMAC_PPS_MINIDX(x))
#define XGMAC_TRGTMODSELx(x, val)	\
	GENMASK(XGMAC_PPS_MAXIDX(x) - 1, XGMAC_PPS_MAXIDX(x) - 2) & \
	((val) << (XGMAC_PPS_MAXIDX(x) - 2))
#define XGMAC_PPSCMDx(x, val)		\
	GENMASK(XGMAC_PPS_MINIDX(x) + 3, XGMAC_PPS_MINIDX(x)) & \
	((val) << XGMAC_PPS_MINIDX(x))
#define XGMAC_PPSCMD_START		0x2
#define XGMAC_PPSCMD_STOP		0x5
#define XGMAC_PPSEN0			BIT(4)
#define XGMAC_PPSx_TARGET_TIME_SEC(x)	(0x00000d80 + (x) * 0x10)
#define XGMAC_PPSx_TARGET_TIME_NSEC(x)	(0x00000d84 + (x) * 0x10)
#define XGMAC_TRGTBUSY0			BIT(31)
#define XGMAC_PPSx_INTERVAL(x)		(0x00000d88 + (x) * 0x10)
#define XGMAC_PPSx_WIDTH(x)		(0x00000d8c + (x) * 0x10)

/* MTL Registers */
#define XGMAC_MTL_OPMODE		0x00001000
+56 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/crc32.h>
#include <linux/iopoll.h>
#include "stmmac.h"
#include "stmmac_ptp.h"
#include "dwxgmac2.h"

static void dwxgmac2_core_init(struct mac_device_info *hw,
@@ -1011,6 +1012,60 @@ static int dwxgmac2_get_mac_tx_timestamp(struct mac_device_info *hw, u64 *ts)
	return 0;
}

static int dwxgmac2_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 + XGMAC_PPSx_TARGET_TIME_NSEC(index));
	u32 val = readl(ioaddr + XGMAC_PPS_CONTROL);
	u64 period;

	if (!cfg->available)
		return -EINVAL;
	if (tnsec & XGMAC_TRGTBUSY0)
		return -EBUSY;
	if (!sub_second_inc || !systime_flags)
		return -EINVAL;

	val &= ~XGMAC_PPSx_MASK(index);

	if (!enable) {
		val |= XGMAC_PPSCMDx(index, XGMAC_PPSCMD_STOP);
		writel(val, ioaddr + XGMAC_PPS_CONTROL);
		return 0;
	}

	val |= XGMAC_PPSCMDx(index, XGMAC_PPSCMD_START);
	val |= XGMAC_TRGTMODSELx(index, XGMAC_PPSCMD_START);
	val |= XGMAC_PPSEN0;

	writel(cfg->start.tv_sec, ioaddr + XGMAC_PPSx_TARGET_TIME_SEC(index));

	if (!(systime_flags & PTP_TCR_TSCTRLSSR))
		cfg->start.tv_nsec = (cfg->start.tv_nsec * 1000) / 465;
	writel(cfg->start.tv_nsec, ioaddr + XGMAC_PPSx_TARGET_TIME_NSEC(index));

	period = cfg->period.tv_sec * 1000000000;
	period += cfg->period.tv_nsec;

	do_div(period, sub_second_inc);

	if (period <= 1)
		return -EINVAL;

	writel(period - 1, ioaddr + XGMAC_PPSx_INTERVAL(index));

	period >>= 1;
	if (period <= 1)
		return -EINVAL;

	writel(period - 1, ioaddr + XGMAC_PPSx_WIDTH(index));

	/* Finally, activate it */
	writel(val, ioaddr + XGMAC_PPS_CONTROL);
	return 0;
}

const struct stmmac_ops dwxgmac210_ops = {
	.core_init = dwxgmac2_core_init,
	.set_mac = dwxgmac2_set_mac,
@@ -1048,6 +1103,7 @@ const struct stmmac_ops dwxgmac210_ops = {
	.update_vlan_hash = dwxgmac2_update_vlan_hash,
	.rxp_config = dwxgmac3_rxp_config,
	.get_mac_tx_timestamp = dwxgmac2_get_mac_tx_timestamp,
	.flex_pps_config = dwxgmac2_flex_pps_config,
};

int dwxgmac2_setup(struct stmmac_priv *priv)