summaryrefslogtreecommitdiff
path: root/drivers/emac-dwc-eqos
diff options
context:
space:
mode:
authorSuraj Jaiswal <jsuraj@codeaurora.org>2019-03-11 17:13:42 +0530
committerSuraj Jaiswal <jsuraj@codeaurora.org>2019-10-25 15:09:22 +0530
commit6f35b39a62679d40883b01f0a4958c32f36ca52b (patch)
treee333c0f2c3b0a129c06539fa61c0378d38e55b8a /drivers/emac-dwc-eqos
parente3cf542a4e0dd791d3e56d3325a9f9493d11f1c4 (diff)
downloaddata-kernel-6f35b39a62679d40883b01f0a4958c32f36ca52b.tar.gz
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
Diffstat (limited to 'drivers/emac-dwc-eqos')
-rw-r--r--drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c73
-rw-r--r--drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c137
-rw-r--r--drivers/emac-dwc-eqos/DWC_ETH_QOS_ptp.c5
-rw-r--r--drivers/emac-dwc-eqos/DWC_ETH_QOS_yheader.h5
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*)&eth_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);