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

Commit 6f35b39a authored by Suraj Jaiswal's avatar Suraj Jaiswal
Browse files

data-kernel: EMAC: PPS Timestamp method

This change add support to changed the timestamp update method to
Fine timestamp update method instead of Coarse Timestamp
Update method since on driver we are using Fine method as default.
Also , we are chaniging default PTP clock to 96Mhz to
generate 19.2Mhz PPS frequency.

Change-Id: Id5c4a22c0163b64762422df0cb3f1e0154515f60
parent e3cf542a
Loading
Loading
Loading
Loading
+57 −16
Original line number Diff line number Diff line
@@ -1136,8 +1136,9 @@ static INT drop_tx_status_enabled(void)

static INT config_sub_second_increment(ULONG ptp_clock)
{
	ULONG val;
	ULONG VARMAC_TCR;
	double ss_inc = 0;
	double sns_inc = 0;

	MAC_TCR_RGRD(VARMAC_TCR);

@@ -1145,30 +1146,69 @@ static INT config_sub_second_increment(ULONG ptp_clock)
	/*  formula is : ((1/ptp_clock) * 1000000000) */
	/*  where, ptp_clock = 50MHz if FINE correction */
	/*  and ptp_clock = DWC_ETH_QOS_SYSCLOCK if COARSE correction */
#ifdef CONFIG_PPS_OUTPUT
	if (GET_VALUE(VARMAC_TCR, MAC_TCR_TSCFUPDT_LPOS, MAC_TCR_TSCFUPDT_HPOS) == 1) {
		EMACDBG("Using PTP clock %ld MHz\n", ptp_clock);
		val = ((1 * 1000000000ull) / ptp_clock);
		ss_inc = (double)1000000000.0 / (double)ptp_clock;
	}
	else {
		EMACDBG("Using SYSCLOCK for coarse correction\n");
		val = ((1 * 1000000000ull) / DWC_ETH_QOS_SYSCLOCK );
		ss_inc = (double)1000000000.0 / (double)DWC_ETH_QOS_SYSCLOCK;
	}
#else
	if (GET_VALUE(VARMAC_TCR, MAC_TCR_TSCFUPDT_LPOS, MAC_TCR_TSCFUPDT_HPOS) == 1) {
      val = ((1 * 1000000000ull) / DWC_ETH_QOS_DEFAULT_PTP_CLOCK);
    }
    else {
      val = ((1 * 1000000000ull) / ptp_clock);
    }
#endif
	/* 0.465ns accurecy */

	/* 0.465ns accuracy */
	if (GET_VALUE(
			VARMAC_TCR, MAC_TCR_TSCTRLSSR_LPOS,
			MAC_TCR_TSCTRLSSR_HPOS) == 0)
		val = (val * 1000) / 465;
			MAC_TCR_TSCTRLSSR_HPOS) == 0) {
		EMACDBG("using 0.465 ns accuracy");
		ss_inc /= 0.465;
 	}

	sns_inc = ss_inc - (int)ss_inc; // take remainder
	sns_inc *= 256.0; // sns_inc needs to be multiplied by 2^8, per spec.
	sns_inc += 0.5; // round to nearest int value.

	MAC_SSIR_SSINC_UDFWR(val);
	MAC_SSIR_SSINC_UDFWR((int)ss_inc);
	MAC_SSIR_SNSINC_UDFWR((int)sns_inc);
	EMACDBG("ss_inc = %d, sns_inc = %d\n", (int)ss_inc, (int)sns_inc);

	return Y_SUCCESS;
    }
/*!
 * \brief
 * \param[in]
 * \return Success or Failure
 * \retval  0 Success
 * \retval -1 Failure
 */

static INT config_default_addend(struct DWC_ETH_QOS_prv_data *pdata, ULONG ptp_clock)
{
	struct hw_if_struct *hw_if = &pdata->hw_if;
	u64 temp;

	/* formula is :
	 * addend = 2^32/freq_div_ratio;
	 *
	 * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz
	 *
	 * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK;
	 *
	 * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to
	 *       achive 20ns accuracy.
	 *
	 * 2^x * y == (y << x), hence
	 * 2^32 * 50000000 ==> (50000000 << 32)
	 */
	if (ptp_clock == DWC_ETH_QOS_SYSCLOCK) {
		// If PTP_CLOCK == SYS_CLOCK, best we can do is 2^32 - 1
		pdata->default_addend = 0xFFFFFFFF;
	} else {
		temp = (u64)((u64)ptp_clock << 32);
		pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK);
	}
	hw_if->config_addend(pdata->default_addend);
	EMACDBG("PPS: PTPCLK_Config: freq=%dHz, addend_reg=0x%x\n",
				ptp_clock, (unsigned int)pdata->default_addend);

	return Y_SUCCESS;
}
@@ -5114,6 +5154,7 @@ void DWC_ETH_QOS_init_function_ptrs_dev(struct hw_if_struct *hw_if)
	/* for hw time stamping */
	hw_if->config_hw_time_stamping = config_hw_time_stamping;
	hw_if->config_sub_second_increment = config_sub_second_increment;
	hw_if->config_default_addend = config_default_addend;
	hw_if->init_systime = init_systime;
	hw_if->config_addend = config_addend;
	hw_if->adjust_systime = adjust_systime;
+24 −113
Original line number Diff line number Diff line
@@ -4922,52 +4922,14 @@ static VOID DWC_ETH_QOS_config_timer_registers(
{
		struct timespec now;
		struct hw_if_struct *hw_if = &pdata->hw_if;
		u64 temp;

		DBGPR("-->DWC_ETH_QOS_config_timer_registers\n");

	pdata->ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK;
	/* program default addend */
	hw_if->config_default_addend(pdata, DWC_ETH_QOS_DEFAULT_PTP_CLOCK);
		/* program Sub Second Increment Reg */
#ifdef CONFIG_PPS_OUTPUT
		/* If default_addend is already programmed, then we expect that
      * sub_second_increment is also programmed already */
		if(pdata->default_addend == 0){
			hw_if->config_sub_second_increment(DWC_ETH_QOS_DEFAULT_PTP_CLOCK); // Using default 50MHz
		}
		else {
			u64 pclk;
			pclk = (u64) (pdata->default_addend) *  DWC_ETH_QOS_SYSCLOCK;
			pclk += 0x8000000;
			pclk >>= 32;
			hw_if->config_sub_second_increment((u32)pclk);
		}
#else
		hw_if->config_sub_second_increment(DWC_ETH_QOS_DEFAULT_PTP_CLOCK);
#endif
		/* formula is :
		 * addend = 2^32/freq_div_ratio;
		 *
		 * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz
		 *
		 * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK;
		 *
		 * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to
		 *       achive 20ns accuracy.
		 *
		 * 2^x * y == (y << x), hence
		 * 2^32 * 50000000 ==> (50000000 << 32)
		 */
#ifdef CONFIG_PPS_OUTPUT
		if(pdata->default_addend == 0){
			temp = (u64)((u64)DWC_ETH_QOS_DEFAULT_PTP_CLOCK  << 32);
			pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK);
			EMACDBG("Using default PTP clock = 50MHz\n");
		}
#else
		temp = (u64)((u64)DWC_ETH_QOS_DEFAULT_PTP_CLOCK << 32);
		pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK);
#endif
		hw_if->config_addend(pdata->default_addend);

		/* initialize system time */
		getnstimeofday(&now);
		hw_if->init_systime(now.tv_sec, now.tv_nsec);
@@ -5105,7 +5067,6 @@ static int ETH_PTPCLK_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data
	struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr;
	struct hw_if_struct *hw_if = &pdata->hw_if;
	int ret = 0;
	u64 val;

	if ((eth_pps_cfg->ppsout_ch < 0) ||
		(eth_pps_cfg->ppsout_ch >= pdata->hw_feat.pps_out_num))
@@ -5119,17 +5080,9 @@ static int ETH_PTPCLK_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data
			eth_pps_cfg->ptpclk_freq );
		return -1;
	}

	pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq;
	val = (u64)(1ULL << 32);
	val = val * (eth_pps_cfg->ptpclk_freq);
	val += (DWC_ETH_QOS_SYSCLOCK/2);
	val = div_u64(val, DWC_ETH_QOS_SYSCLOCK);
	if ( val > 0xFFFFFFFF) val = 0xFFFFFFFF;
	EMACDBG("PPS: PTPCLK_Config: freq=%dHz, addend_reg=0x%x\n",
				eth_pps_cfg->ptpclk_freq, (unsigned int)val);

	pdata->default_addend = val;
	ret = hw_if->config_addend((unsigned int)val);
	ret = hw_if->config_default_addend(pdata, (ULONG)eth_pps_cfg->ptpclk_freq);
	ret |= hw_if->config_sub_second_increment( (ULONG)eth_pps_cfg->ptpclk_freq);

	return ret;
@@ -5212,15 +5165,8 @@ void DWC_ETH_QOS_pps_timer_init(struct ifr_data_struct *req)

	/* Enable timestamping. This is required to start system time generator.*/
	MAC_TCR_TSENA_UDFWR(0x1);

	/* Configure MAC Sub-second and Sub-nanosecond increment register based on PTP clock. */
	MAC_SSIR_SSINC_UDFWR(0x4); // Sub-second increment value for 250MHz and 230.4MHz ptp clock

	MAC_SSIR_SNSINC_UDFWR(0x0); // Sub-nanosecond increment value for 250 MHz ptp clock
	EMACDBG("250 clock\n");

	MAC_TCR_TSUPDT_UDFWR(0x1);
	MAC_TCR_TSCFUPDT_UDFWR(0x0); // Coarse Timestamp Update method.
	MAC_TCR_TSCFUPDT_UDFWR(0x1); // Fine Timestamp Update method.

	/* Initialize MAC System Time Update register */
	MAC_STSUR_TSS_UDFWR(0x0); // MAC system time in seconds
@@ -5279,12 +5225,16 @@ int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct
	struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr;
	unsigned int val;
	int interval, width;
	int interval_ns; /*interval in nano seconds*/
	struct hw_if_struct *hw_if = &pdata->hw_if;

	if (pdata->res_data->pps_lpass_conn_en &&
		eth_pps_cfg->ptpclk_freq <= 0) {
		/* Set PTP clock to default 250 */
		eth_pps_cfg->ptpclk_freq = DWC_ETH_QOS_DEFAULT_LPASS_CLOCK;
	/* For lpass we need 19.2Mhz PPS frequency for PPS0.
	   If lpass is enabled don't allow to change the PTP clock
	   becuase if we change PTP clock then addend & subsecond increament
	   will change & We will not see 19.2Mhz for PPS0.
	*/
	if (pdata->res_data->pps_lpass_conn_en ) {
		eth_pps_cfg->ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK;
		EMACDBG("using default ptp clock \n");
	}

	if ((eth_pps_cfg->ppsout_ch < 0) ||
@@ -5303,6 +5253,12 @@ int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct
		eth_pps_cfg->ppsout_duty = 99;
	}

	/* Configure increment values */
	hw_if->config_sub_second_increment(eth_pps_cfg->ptpclk_freq);

	/* Configure addent value as Fine Timestamp method is used */
	hw_if->config_default_addend(pdata, eth_pps_cfg->ptpclk_freq);

	if(0 < eth_pps_cfg->ptpclk_freq) {
		pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq;
		interval = (eth_pps_cfg->ptpclk_freq + eth_pps_cfg->ppsout_freq/2)
@@ -5323,14 +5279,6 @@ int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct

	EMACDBG("PPS: PPSOut_Config: interval=%d, width=%d\n", interval, width);

	if (pdata->res_data->pps_lpass_conn_en) {
		//calculate interval & width
		interval_ns = (1000000000/eth_pps_cfg->ppsout_freq) ;
		interval = ((interval_ns)/4) - 1;
		width = ((interval_ns)/(2*4)) - 1;
		EMACDBG("pps_interval=%d,width=%d\n",interval,width);
	}

	switch (eth_pps_cfg->ppsout_ch) {
	case DWC_ETH_QOS_PPS_CH_0:
		if (pdata->res_data->pps_lpass_conn_en) {
@@ -5885,7 +5833,6 @@ static int DWC_ETH_QOS_handle_hwtstamp_ioctl(struct DWC_ETH_QOS_prv_data *pdata,
	u32 ts_event_en = 0;
	u32 av_8021asm_en = 0;
	u32 VARMAC_TCR = 0;
	u64 temp = 0;
	struct timespec now;

	DBGPR_PTP("-->DWC_ETH_QOS_handle_hwtstamp_ioctl\n");
@@ -6056,47 +6003,11 @@ static int DWC_ETH_QOS_handle_hwtstamp_ioctl(struct DWC_ETH_QOS_prv_data *pdata,

		hw_if->config_hw_time_stamping(VARMAC_TCR);

		/* program default addend */
		hw_if->config_default_addend(pdata, DWC_ETH_QOS_DEFAULT_PTP_CLOCK);

		/* program Sub Second Increment Reg */
#ifdef CONFIG_PPS_OUTPUT
		/* If default_addend is already programmed, then we expect that
		* sub_second_increment is also programmed already */
		if (pdata->default_addend == 0) {
		     hw_if->config_sub_second_increment(DWC_ETH_QOS_DEFAULT_PTP_CLOCK); // Using default 50MHz
		} else {
			u64 pclk;
			pclk = (u64) (pdata->default_addend) *  DWC_ETH_QOS_SYSCLOCK;
			pclk += 0x8000000;
			pclk >>= 32;
			hw_if->config_sub_second_increment((u32)pclk);
		}
#else
		hw_if->config_sub_second_increment(DWC_ETH_QOS_DEFAULT_PTP_CLOCK);
#endif
		/* formula is :
		 * addend = 2^32/freq_div_ratio;
		 *
		 * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz
		 *
		 * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK;
		 *
		 * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to
		 *       achive 20ns accuracy.
		 *
		 * 2^x * y == (y << x), hence
		 * 2^32 * 50000000 ==> (50000000 << 32)
		 *
		 */
#ifdef CONFIG_PPS_OUTPUT
		if(pdata->default_addend == 0){
			temp = (u64)((u64)DWC_ETH_QOS_DEFAULT_PTP_CLOCK << 32);
			pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK);
			EMACINFO("Using default PTP clock = 50MHz\n");
		}
#else
		temp = (u64)((u64)DWC_ETH_QOS_DEFAULT_PTP_CLOCK << 32);
		pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK);
#endif
		hw_if->config_addend(pdata->default_addend);

		/* initialize system time */
		getnstimeofday(&now);
+3 −2
Original line number Diff line number Diff line
@@ -318,9 +318,10 @@ int DWC_ETH_QOS_ptp_init(struct DWC_ETH_QOS_prv_data *pdata)
	if (pdata->res_data->pps_lpass_conn_en) {
		/*Configuring PPS0 PPS output frequency to defualt 19.2 Mhz*/
		eth_pps_cfg.ppsout_ch = 0;
		eth_pps_cfg.ptpclk_freq = DWC_ETH_QOS_DEFAULT_LPASS_CLOCK;
		eth_pps_cfg.ppsout_freq = 19200000;
		eth_pps_cfg.ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK;
		eth_pps_cfg.ppsout_freq = DWC_ETH_QOS_DEFAULT_LPASS_PPS_FREQUENCY;
		eth_pps_cfg.ppsout_start = 1;
		eth_pps_cfg.ppsout_duty = 50;
		req.ptr = (void*)&eth_pps_cfg;

		DWC_ETH_QOS_pps_timer_init(&req);
+3 −2
Original line number Diff line number Diff line
@@ -427,8 +427,8 @@ extern void *ipc_emac_log_ctxt;
#define DWC_ETH_QOS_SYSCLOCK	250000000 /* System clock is 250MHz */
#define DWC_ETH_QOS_SYSTIMEPERIOD	4 /* System time period is 4ns */

#define DWC_ETH_QOS_DEFAULT_PTP_CLOCK 50000000
#define DWC_ETH_QOS_DEFAULT_LPASS_CLOCK 250000000
#define DWC_ETH_QOS_DEFAULT_PTP_CLOCK    96000000
#define DWC_ETH_QOS_DEFAULT_LPASS_PPS_FREQUENCY 19200000

#define DWC_ETH_QOS_TX_QUEUE_CNT (pdata->tx_queue_cnt)
#define DWC_ETH_QOS_RX_QUEUE_CNT (pdata->rx_queue_cnt)
@@ -1006,6 +1006,7 @@ struct hw_if_struct {
	/* for hw time stamping */
	INT(*config_hw_time_stamping)(UINT);
	INT(*config_sub_second_increment)(unsigned long ptp_clock);
	INT(*config_default_addend)(struct DWC_ETH_QOS_prv_data *pdata, unsigned long ptp_clock);
	INT(*init_systime)(UINT, UINT);
	INT(*config_addend)(UINT);
	INT(*adjust_systime)(UINT, UINT, INT, bool);