diff options
Diffstat (limited to 'drivers/emac-dwc-eqos')
-rw-r--r-- | drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c | 73 | ||||
-rw-r--r-- | drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c | 137 | ||||
-rw-r--r-- | drivers/emac-dwc-eqos/DWC_ETH_QOS_ptp.c | 5 | ||||
-rw-r--r-- | drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h | 5 |
4 files changed, 87 insertions, 133 deletions
diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c index b5facb6..7ce0a31 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c @@ -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; + } - MAC_SSIR_SSINC_UDFWR(val); + 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((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; diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c index b69ce6d..da0df86 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c @@ -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); diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_ptp.c b/drivers/emac-dwc-eqos/DWC_ETH_QOS_ptp.c index d47221b..1bcead3 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_ptp.c +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_ptp.c @@ -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*)ð_pps_cfg; DWC_ETH_QOS_pps_timer_init(&req); diff --git a/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h b/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h index 67fdd03..ee29121 100644 --- a/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h +++ b/drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h @@ -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); |