// SPDX-License-Identifier: GPL-2.0-only /******************************************************************************* PTP 1588 clock using the STMMAC.
/** * stmmac_adjust_freq * * @ptp: pointer to ptp_clock_info structure * @scaled_ppm: desired period change in scaled parts per million * * Description: this function will adjust the frequency of hardware clock. * * Scaled parts per million is ppm with a 16-bit binary fractional field.
*/ staticint stmmac_adjust_freq(struct ptp_clock_info *ptp, long scaled_ppm)
{ struct stmmac_priv *priv =
container_of(ptp, struct stmmac_priv, ptp_clock_ops); unsignedlong flags;
u32 addend;
/* If EST is enabled, disabled it before adjust ptp time. */ if (priv->est && priv->est->enable) {
est_rst = true;
mutex_lock(&priv->est_lock);
priv->est->enable = false;
stmmac_est_configure(priv, priv, priv->est,
priv->plat->clk_ptp_rate);
mutex_unlock(&priv->est_lock);
}
/* Calculate new basetime and re-configured EST after PTP time adjust. */ if (est_rst) { struct timespec64 current_time, time;
ktime_t current_time_ns, basetime;
u64 cycle_time;
priv->est->btr[0] = (u32)time.tv_nsec;
priv->est->btr[1] = (u32)time.tv_sec;
priv->est->enable = true;
ret = stmmac_est_configure(priv, priv, priv->est,
priv->plat->clk_ptp_rate);
mutex_unlock(&priv->est_lock); if (ret)
netdev_err(priv->dev, "failed to configure EST\n");
}
return 0;
}
/** * stmmac_get_time * * @ptp: pointer to ptp_clock_info structure * @ts: pointer to hold time/result * * Description: this function will read the current time from the * hardware clock and store it in @ts.
*/ staticint stmmac_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts)
{ struct stmmac_priv *priv =
container_of(ptp, struct stmmac_priv, ptp_clock_ops); unsignedlong flags;
u64 ns = 0;
/** * stmmac_set_time * * @ptp: pointer to ptp_clock_info structure * @ts: time value to set * * Description: this function will set the current time on the * hardware clock.
*/ staticint stmmac_set_time(struct ptp_clock_info *ptp, conststruct timespec64 *ts)
{ struct stmmac_priv *priv =
container_of(ptp, struct stmmac_priv, ptp_clock_ops); unsignedlong flags;
/** * stmmac_get_syncdevicetime * @device: current device time * @system: system counter value read synchronously with device time * @ctx: context provided by timekeeping code * Description: Read device and system clock simultaneously and return the * corrected clock values in ns.
**/ staticint stmmac_get_syncdevicetime(ktime_t *device, struct system_counterval_t *system, void *ctx)
{ struct stmmac_priv *priv = (struct stmmac_priv *)ctx;
if (priv->plat->crosststamp) return priv->plat->crosststamp(device, system, ctx); else return -EOPNOTSUPP;
}
/** * stmmac_ptp_register * @priv: driver private structure * Description: this function will register the ptp clock driver * to kernel. It also does some house keeping work.
*/ void stmmac_ptp_register(struct stmmac_priv *priv)
{ int i;
for (i = 0; i < priv->dma_cap.pps_out_num; i++) { if (i >= STMMAC_PPS_MAX) break;
priv->pps[i].available = true;
}
/* Calculate the clock domain crossing (CDC) error if necessary */
priv->plat->cdc_error_adj = 0; if (priv->plat->has_gmac4)
priv->plat->cdc_error_adj = (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;
/* Update the ptp clock parameters based on feature discovery, when * available
*/ if (priv->dma_cap.pps_out_num)
priv->ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
if (priv->dma_cap.aux_snapshot_n)
priv->ptp_clock_ops.n_ext_ts = priv->dma_cap.aux_snapshot_n;
if (priv->plat->ptp_max_adj)
priv->ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.