提交 5566401f 编写于 作者: G Giuseppe CAVALLARO 提交者: David S. Miller

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: NGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 2b78d348
...@@ -39,6 +39,10 @@ Optional properties: ...@@ -39,6 +39,10 @@ Optional properties:
further clocks may be specified in derived bindings. further clocks may be specified in derived bindings.
- clock-names: One name for each entry in the clocks property, the - clock-names: One name for each entry in the clocks property, the
first one should be "stmmaceth". first one should be "stmmaceth".
- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is
available this clock is used for programming the Timestamp Addend Register.
If not passed then the system clock will be used and this is fine on some
platforms.
Examples: Examples:
......
...@@ -105,6 +105,8 @@ struct stmmac_priv { ...@@ -105,6 +105,8 @@ struct stmmac_priv {
struct ptp_clock *ptp_clock; struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_ops; struct ptp_clock_info ptp_clock_ops;
unsigned int default_addend; unsigned int default_addend;
struct clk *clk_ptp_ref;
unsigned int clk_ptp_rate;
u32 adv_ts; u32 adv_ts;
int use_riwt; int use_riwt;
int irq_wake; int irq_wake;
......
...@@ -603,16 +603,16 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) ...@@ -603,16 +603,16 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
/* calculate default added value: /* calculate default added value:
* formula is : * formula is :
* addend = (2^32)/freq_div_ratio; * addend = (2^32)/freq_div_ratio;
* where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz * where, freq_div_ratio = clk_ptp_ref_i/50MHz
* hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK; * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
* NOTE: STMMAC_SYSCLOCK should be >= 50MHz to * NOTE: clk_ptp_ref_i should be >= 50MHz to
* achive 20ns accuracy. * achive 20ns accuracy.
* *
* 2^x * y == (y << x), hence * 2^x * y == (y << x), hence
* 2^32 * 50000000 ==> (50000000 << 32) * 2^32 * 50000000 ==> (50000000 << 32)
*/ */
temp = (u64) (50000000ULL << 32); temp = (u64) (50000000ULL << 32);
priv->default_addend = div_u64(temp, STMMAC_SYSCLOCK); priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
priv->hw->ptp->config_addend(priv->ioaddr, priv->hw->ptp->config_addend(priv->ioaddr,
priv->default_addend); priv->default_addend);
...@@ -638,6 +638,16 @@ static int stmmac_init_ptp(struct stmmac_priv *priv) ...@@ -638,6 +638,16 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* Fall-back to main clock in case of no PTP ref is passed */
priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
if (IS_ERR(priv->clk_ptp_ref)) {
priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
priv->clk_ptp_ref = NULL;
} else {
clk_prepare_enable(priv->clk_ptp_ref);
priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
}
priv->adv_ts = 0; priv->adv_ts = 0;
if (priv->dma_cap.atime_stamp && priv->extend_desc) if (priv->dma_cap.atime_stamp && priv->extend_desc)
priv->adv_ts = 1; priv->adv_ts = 1;
...@@ -657,6 +667,8 @@ static int stmmac_init_ptp(struct stmmac_priv *priv) ...@@ -657,6 +667,8 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
static void stmmac_release_ptp(struct stmmac_priv *priv) static void stmmac_release_ptp(struct stmmac_priv *priv)
{ {
if (priv->clk_ptp_ref)
clk_disable_unprepare(priv->clk_ptp_ref);
stmmac_ptp_unregister(priv); stmmac_ptp_unregister(priv);
} }
......
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
#ifndef __STMMAC_PTP_H__ #ifndef __STMMAC_PTP_H__
#define __STMMAC_PTP_H__ #define __STMMAC_PTP_H__
#define STMMAC_SYSCLOCK 62500000
/* IEEE 1588 PTP register offsets */ /* IEEE 1588 PTP register offsets */
#define PTP_TCR 0x0700 /* Timestamp Control Reg */ #define PTP_TCR 0x0700 /* Timestamp Control Reg */
#define PTP_SSIR 0x0704 /* Sub-Second Increment Reg */ #define PTP_SSIR 0x0704 /* Sub-Second Increment Reg */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册