aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/stmicro
diff options
context:
space:
mode:
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>2014-08-27 04:37:49 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-29 22:54:36 -0400
commit5566401f2f10556776fd199c11d6a02a5e0b7b95 (patch)
treeb9127a13d0c5df4939c72be2fc618e38e9afaf5c /drivers/net/ethernet/stmicro
parent2b78d348f1bc3396ca1662c6a6177a7fb1ca62ff (diff)
stmmac: ptp: fix the reference clock
The PTP reference clock, used for setting the addend in the Timestamp Addend Register, was erroneously hard-coded (as reported in the databook just as example). The patch removes the macro named: STMMAC_SYSCLOCK and allows to use a reference clock (clk_ptp_ref_i) that can be passed from the platform. If not passed, the main driver clock will be used as default; note that this can be fine on some platforms. Note that, prior this patch, using the old STMMAC_SYSCLOCK on some platforms, as side effect, the ptp clock can move faster/slower than the system clock. Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/stmicro')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c20
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h2
3 files changed, 18 insertions, 6 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index ca01035634a7..128a0b723a00 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -105,6 +105,8 @@ struct stmmac_priv {
105 struct ptp_clock *ptp_clock; 105 struct ptp_clock *ptp_clock;
106 struct ptp_clock_info ptp_clock_ops; 106 struct ptp_clock_info ptp_clock_ops;
107 unsigned int default_addend; 107 unsigned int default_addend;
108 struct clk *clk_ptp_ref;
109 unsigned int clk_ptp_rate;
108 u32 adv_ts; 110 u32 adv_ts;
109 int use_riwt; 111 int use_riwt;
110 int irq_wake; 112 int irq_wake;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 51a89d4bb125..03652891fcbf 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -603,16 +603,16 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
603 /* calculate default added value: 603 /* calculate default added value:
604 * formula is : 604 * formula is :
605 * addend = (2^32)/freq_div_ratio; 605 * addend = (2^32)/freq_div_ratio;
606 * where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz 606 * where, freq_div_ratio = clk_ptp_ref_i/50MHz
607 * hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK; 607 * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
608 * NOTE: STMMAC_SYSCLOCK should be >= 50MHz to 608 * NOTE: clk_ptp_ref_i should be >= 50MHz to
609 * achive 20ns accuracy. 609 * achive 20ns accuracy.
610 * 610 *
611 * 2^x * y == (y << x), hence 611 * 2^x * y == (y << x), hence
612 * 2^32 * 50000000 ==> (50000000 << 32) 612 * 2^32 * 50000000 ==> (50000000 << 32)
613 */ 613 */
614 temp = (u64) (50000000ULL << 32); 614 temp = (u64) (50000000ULL << 32);
615 priv->default_addend = div_u64(temp, STMMAC_SYSCLOCK); 615 priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
616 priv->hw->ptp->config_addend(priv->ioaddr, 616 priv->hw->ptp->config_addend(priv->ioaddr,
617 priv->default_addend); 617 priv->default_addend);
618 618
@@ -638,6 +638,16 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
638 if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) 638 if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
639 return -EOPNOTSUPP; 639 return -EOPNOTSUPP;
640 640
641 /* Fall-back to main clock in case of no PTP ref is passed */
642 priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
643 if (IS_ERR(priv->clk_ptp_ref)) {
644 priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
645 priv->clk_ptp_ref = NULL;
646 } else {
647 clk_prepare_enable(priv->clk_ptp_ref);
648 priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
649 }
650
641 priv->adv_ts = 0; 651 priv->adv_ts = 0;
642 if (priv->dma_cap.atime_stamp && priv->extend_desc) 652 if (priv->dma_cap.atime_stamp && priv->extend_desc)
643 priv->adv_ts = 1; 653 priv->adv_ts = 1;
@@ -657,6 +667,8 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
657 667
658static void stmmac_release_ptp(struct stmmac_priv *priv) 668static void stmmac_release_ptp(struct stmmac_priv *priv)
659{ 669{
670 if (priv->clk_ptp_ref)
671 clk_disable_unprepare(priv->clk_ptp_ref);
660 stmmac_ptp_unregister(priv); 672 stmmac_ptp_unregister(priv);
661} 673}
662 674
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
index 3dbc047622fa..4535df37c227 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -25,8 +25,6 @@
25#ifndef __STMMAC_PTP_H__ 25#ifndef __STMMAC_PTP_H__
26#define __STMMAC_PTP_H__ 26#define __STMMAC_PTP_H__
27 27
28#define STMMAC_SYSCLOCK 62500000
29
30/* IEEE 1588 PTP register offsets */ 28/* IEEE 1588 PTP register offsets */
31#define PTP_TCR 0x0700 /* Timestamp Control Reg */ 29#define PTP_TCR 0x0700 /* Timestamp Control Reg */
32#define PTP_SSIR 0x0704 /* Sub-Second Increment Reg */ 30#define PTP_SSIR 0x0704 /* Sub-Second Increment Reg */