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

Commit 50c8ec0c authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "net: stmmac: Add support for pps alignment feature"

parents 0363b88a 17380029
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -263,6 +263,15 @@ int ethqos_handle_prv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
		if (copy_from_user(&eth_pps_cfg, (void __user *)req.ptr,
				   sizeof(struct pps_cfg)))
			return -EFAULT;

		if (eth_pps_cfg.ppsout_ch < 0 ||
		    eth_pps_cfg.ppsout_ch >= pdata->dma_cap.pps_out_num)
			ret = -EOPNOTSUPP;
		else if ((eth_pps_cfg.ppsout_align == 1) &&
			 ((eth_pps_cfg.ppsout_ch != DWC_ETH_QOS_PPS_CH_0) &&
			 (eth_pps_cfg.ppsout_ch != DWC_ETH_QOS_PPS_CH_3)))
			ret = -EOPNOTSUPP;
		else
			ret = ppsout_config(pdata, &eth_pps_cfg);
		break;
	case ETHQOS_AVB_ALGORITHM:
+8 −0
Original line number Diff line number Diff line
@@ -42,6 +42,12 @@
#define MAC_PPSX_INTERVAL(x)		(0x00000b88 + ((x) * 0x10))
#define MAC_PPSX_WIDTH(x)		(0x00000b8c + ((x) * 0x10))

#define PPS_START_DELAY 100000000
#define ONE_NS 1000000000
#define PPS_ADJUST_NS 32

#define DWC_ETH_QOS_PPS_CH_0 0
#define DWC_ETH_QOS_PPS_CH_1 1
#define DWC_ETH_QOS_PPS_CH_2 2
#define DWC_ETH_QOS_PPS_CH_3 3

@@ -164,6 +170,8 @@ struct pps_cfg {
	unsigned int ppsout_ch;
	unsigned int ppsout_duty;
	unsigned int ppsout_start;
	unsigned int ppsout_align;
	unsigned int ppsout_align_ns;
};

struct ifr_data_struct {
+44 −12
Original line number Diff line number Diff line
@@ -46,12 +46,38 @@ static int strlcmp(const char *s, const char *t, size_t n)
	return ret;
}

static void align_target_time_reg(u32 ch, void __iomem *ioaddr,
				  struct pps_cfg *eth_pps_cfg,
				  unsigned int align_ns)
{
	unsigned int system_s, system_ns, temp_system_s;

	system_s = readl_relaxed(ioaddr + 0xb00 + PTP_STSR);
	system_ns = readl_relaxed(ioaddr + 0xb00 + PTP_STNSR);
	temp_system_s = readl_relaxed(ioaddr + 0xb00 + PTP_STSR);

	if (temp_system_s != system_s) { // second roll over
		system_s = readl_relaxed(ioaddr + 0xb00 + PTP_STSR);
		system_ns = readl_relaxed(ioaddr + 0xb00 + PTP_STNSR);
	}

	system_ns += PPS_START_DELAY;
	if (system_ns >= align_ns)
		system_s += 1;

	writel_relaxed(system_s, ioaddr +
		       MAC_PPSX_TARGET_TIME_SEC(eth_pps_cfg->ppsout_ch));

	writel_relaxed(align_ns, ioaddr +
		       MAC_PPSX_TARGET_TIME_NSEC(eth_pps_cfg->ppsout_ch));
}

static u32 pps_config_sub_second_increment(void __iomem *ioaddr,
					   u32 ptp_clock, int gmac4)
{
	u32 value = readl_relaxed(ioaddr + PTP_TCR);
	unsigned long data;
	unsigned int sns_inc = 0;
	u64 data;
	u64 sns_inc = 0;
	u32 reg_value;
	u32 reg_value2;
	/* For GMAC3.x, 4.x versions, convert the ptp_clock to nano second
@@ -59,16 +85,16 @@ static u32 pps_config_sub_second_increment(void __iomem *ioaddr,
	 * where ptp_clock is 50MHz if fine method is used to update system
	 */
	if (value & PTP_TCR_TSCFUPDT) {
		data = (1000000000ULL / ptp_clock);
		data = div_u64((1000000000ULL), ptp_clock);
		sns_inc = 1000000000ull - (data * ptp_clock);
		sns_inc = (sns_inc * 256) / ptp_clock;
		sns_inc = div_u64((sns_inc * 256), ptp_clock);

	} else {
		data = (1000000000ULL / ptp_clock);
		data = div_u64((1000000000ULL), ptp_clock);
	}
	/* 0.465ns accuracy */
	if (!(value & PTP_TCR_TSCTRLSSR))
		data = (data * 1000) / 465;
		data = div_u64((data * 1000), 465);

	data &= PTP_SSIR_SSINC_MASK;

@@ -163,10 +189,11 @@ static void ethqos_unregister_pps_isr(struct stmmac_priv *priv, int ch)
int ppsout_config(struct stmmac_priv *priv, struct pps_cfg *eth_pps_cfg)
{
	int interval, width;
	u32 sub_second_inc, value;
	u32 sub_second_inc;
	void __iomem *ioaddr = priv->ioaddr;
	u32 val;
	u64 temp;
	u32 align_ns = 0;

	if (!eth_pps_cfg->ppsout_start) {
		ppsout_stop(priv, eth_pps_cfg);
@@ -176,11 +203,6 @@ int ppsout_config(struct stmmac_priv *priv, struct pps_cfg *eth_pps_cfg)
		return 0;
	}

	value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSUPDT);
	priv->hw->ptp->config_hw_tstamping(priv->ptpaddr, value);
	priv->hw->ptp->init_systime(priv->ptpaddr, 0, 0);
	priv->hw->ptp->adjust_systime(priv->ptpaddr, 0, 0, 0, 1);

	val = readl_relaxed(ioaddr + MAC_PPS_CONTROL);

	sub_second_inc = pps_config_sub_second_increment
@@ -216,6 +238,16 @@ int ppsout_config(struct stmmac_priv *priv, struct pps_cfg *eth_pps_cfg)
	if (width < 0)
		width = 0;

	if (eth_pps_cfg->ppsout_align == 1) {
		align_ns = eth_pps_cfg->ppsout_align_ns;
		if (align_ns < PPS_ADJUST_NS)
			align_ns += (ONE_NS - PPS_ADJUST_NS);
		else
			align_ns -= PPS_ADJUST_NS;
		align_target_time_reg(eth_pps_cfg->ppsout_ch,
				      priv->ioaddr, eth_pps_cfg, align_ns);
	}

	writel_relaxed(interval, ioaddr +
		       MAC_PPSX_INTERVAL(eth_pps_cfg->ppsout_ch));