Skip to content

Commit 19d857c

Browse files
reid-pdavem330
authored andcommitted
stmmac: Fix calculations for ptp counters when clock input = 50Mhz.
stmmac_config_sub_second_increment set the sub second increment to 20ns. Driver is configured to use the fine adjustment method where the sub second register is incremented when the acculumator incremented by the addend register wraps overflows. This accumulator is update on every ptp clk cycle. If a ptp clk with a period of greater than 20ns was used the sub second register would not get updated correctly. Instead set the sub sec increment to twice the period of the ptp clk. This result in the addend register being set mid range and overflow the accumlator every 2 clock cycles. Signed-off-by: Phil Reid <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bf171f0 commit 19d857c

File tree

3 files changed

+15
-15
lines changed

3 files changed

+15
-15
lines changed

drivers/net/ethernet/stmicro/stmmac/common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ struct stmmac_ops {
439439
/* PTP and HW Timer helpers */
440440
struct stmmac_hwtimestamp {
441441
void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
442-
void (*config_sub_second_increment) (void __iomem *ioaddr);
442+
u32 (*config_sub_second_increment) (void __iomem *ioaddr, u32 clk_rate);
443443
int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
444444
int (*config_addend) (void __iomem *ioaddr, u32 addend);
445445
int (*adjust_systime) (void __iomem *ioaddr, u32 sec, u32 nsec,

drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,25 @@ static void stmmac_config_hw_tstamping(void __iomem *ioaddr, u32 data)
3333
writel(data, ioaddr + PTP_TCR);
3434
}
3535

36-
static void stmmac_config_sub_second_increment(void __iomem *ioaddr)
36+
static u32 stmmac_config_sub_second_increment(void __iomem *ioaddr,
37+
u32 ptp_clock)
3738
{
3839
u32 value = readl(ioaddr + PTP_TCR);
3940
unsigned long data;
4041

4142
/* Convert the ptp_clock to nano second
42-
* formula = (1/ptp_clock) * 1000000000
43+
* formula = (2/ptp_clock) * 1000000000
4344
* where, ptp_clock = 50MHz.
4445
*/
45-
data = (1000000000ULL / 50000000);
46+
data = (2000000000ULL / ptp_clock);
4647

4748
/* 0.465ns accuracy */
4849
if (!(value & PTP_TCR_TSCTRLSSR))
4950
data = (data * 1000) / 465;
5051

5152
writel(data, ioaddr + PTP_SSIR);
53+
54+
return data;
5255
}
5356

5457
static int stmmac_init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "stmmac.h"
5454
#include <linux/reset.h>
5555
#include <linux/of_mdio.h>
56+
#include "dwmac1000.h"
5657

5758
#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
5859

@@ -185,7 +186,7 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)
185186
priv->clk_csr = STMMAC_CSR_100_150M;
186187
else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
187188
priv->clk_csr = STMMAC_CSR_150_250M;
188-
else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M))
189+
else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
189190
priv->clk_csr = STMMAC_CSR_250_300M;
190191
}
191192
}
@@ -435,6 +436,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
435436
u32 ts_master_en = 0;
436437
u32 ts_event_en = 0;
437438
u32 value = 0;
439+
u32 sec_inc;
438440

439441
if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
440442
netdev_alert(priv->dev, "No support for HW time stamping\n");
@@ -598,24 +600,19 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
598600
tstamp_all | ptp_v2 | ptp_over_ethernet |
599601
ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
600602
ts_master_en | snap_type_sel);
601-
602603
priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
603604

604605
/* program Sub Second Increment reg */
605-
priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
606+
sec_inc = priv->hw->ptp->config_sub_second_increment(
607+
priv->ioaddr, priv->clk_ptp_rate);
608+
temp = div_u64(1000000000ULL, sec_inc);
606609

607610
/* calculate default added value:
608611
* formula is :
609612
* addend = (2^32)/freq_div_ratio;
610-
* where, freq_div_ratio = clk_ptp_ref_i/50MHz
611-
* hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
612-
* NOTE: clk_ptp_ref_i should be >= 50MHz to
613-
* achieve 20ns accuracy.
614-
*
615-
* 2^x * y == (y << x), hence
616-
* 2^32 * 50000000 ==> (50000000 << 32)
613+
* where, freq_div_ratio = 1e9ns/sec_inc
617614
*/
618-
temp = (u64) (50000000ULL << 32);
615+
temp = (u64)(temp << 32);
619616
priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
620617
priv->hw->ptp->config_addend(priv->ioaddr,
621618
priv->default_addend);

0 commit comments

Comments
 (0)