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>
This commit is contained in:
parent
2b78d348f1
commit
5566401f2f
|
@ -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 {
|
||||||
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)
|
||||||
/* 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)
|
||||||
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)
|
||||||
|
|
||||||
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 @@
|
||||||
#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 */
|
||||||
|
|
Loading…
Reference in New Issue