0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "stmmac.h"
0011 #include "stmmac_ptp.h"
0012 #include "dwmac4.h"
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 static int stmmac_adjust_freq(struct ptp_clock_info *ptp, s32 ppb)
0023 {
0024 struct stmmac_priv *priv =
0025 container_of(ptp, struct stmmac_priv, ptp_clock_ops);
0026 unsigned long flags;
0027 u32 diff, addend;
0028 int neg_adj = 0;
0029 u64 adj;
0030
0031 if (ppb < 0) {
0032 neg_adj = 1;
0033 ppb = -ppb;
0034 }
0035
0036 addend = priv->default_addend;
0037 adj = addend;
0038 adj *= ppb;
0039 diff = div_u64(adj, 1000000000ULL);
0040 addend = neg_adj ? (addend - diff) : (addend + diff);
0041
0042 write_lock_irqsave(&priv->ptp_lock, flags);
0043 stmmac_config_addend(priv, priv->ptpaddr, addend);
0044 write_unlock_irqrestore(&priv->ptp_lock, flags);
0045
0046 return 0;
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
0058 {
0059 struct stmmac_priv *priv =
0060 container_of(ptp, struct stmmac_priv, ptp_clock_ops);
0061 unsigned long flags;
0062 u32 sec, nsec;
0063 u32 quotient, reminder;
0064 int neg_adj = 0;
0065 bool xmac, est_rst = false;
0066 int ret;
0067
0068 xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;
0069
0070 if (delta < 0) {
0071 neg_adj = 1;
0072 delta = -delta;
0073 }
0074
0075 quotient = div_u64_rem(delta, 1000000000ULL, &reminder);
0076 sec = quotient;
0077 nsec = reminder;
0078
0079
0080 if (priv->plat->est && priv->plat->est->enable) {
0081 est_rst = true;
0082 mutex_lock(&priv->plat->est->lock);
0083 priv->plat->est->enable = false;
0084 stmmac_est_configure(priv, priv->ioaddr, priv->plat->est,
0085 priv->plat->clk_ptp_rate);
0086 mutex_unlock(&priv->plat->est->lock);
0087 }
0088
0089 write_lock_irqsave(&priv->ptp_lock, flags);
0090 stmmac_adjust_systime(priv, priv->ptpaddr, sec, nsec, neg_adj, xmac);
0091 write_unlock_irqrestore(&priv->ptp_lock, flags);
0092
0093
0094 if (est_rst) {
0095 struct timespec64 current_time, time;
0096 ktime_t current_time_ns, basetime;
0097 u64 cycle_time;
0098
0099 mutex_lock(&priv->plat->est->lock);
0100 priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time);
0101 current_time_ns = timespec64_to_ktime(current_time);
0102 time.tv_nsec = priv->plat->est->btr_reserve[0];
0103 time.tv_sec = priv->plat->est->btr_reserve[1];
0104 basetime = timespec64_to_ktime(time);
0105 cycle_time = (u64)priv->plat->est->ctr[1] * NSEC_PER_SEC +
0106 priv->plat->est->ctr[0];
0107 time = stmmac_calc_tas_basetime(basetime,
0108 current_time_ns,
0109 cycle_time);
0110
0111 priv->plat->est->btr[0] = (u32)time.tv_nsec;
0112 priv->plat->est->btr[1] = (u32)time.tv_sec;
0113 priv->plat->est->enable = true;
0114 ret = stmmac_est_configure(priv, priv->ioaddr, priv->plat->est,
0115 priv->plat->clk_ptp_rate);
0116 mutex_unlock(&priv->plat->est->lock);
0117 if (ret)
0118 netdev_err(priv->dev, "failed to configure EST\n");
0119 }
0120
0121 return 0;
0122 }
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 static int stmmac_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts)
0134 {
0135 struct stmmac_priv *priv =
0136 container_of(ptp, struct stmmac_priv, ptp_clock_ops);
0137 unsigned long flags;
0138 u64 ns = 0;
0139
0140 read_lock_irqsave(&priv->ptp_lock, flags);
0141 stmmac_get_systime(priv, priv->ptpaddr, &ns);
0142 read_unlock_irqrestore(&priv->ptp_lock, flags);
0143
0144 *ts = ns_to_timespec64(ns);
0145
0146 return 0;
0147 }
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 static int stmmac_set_time(struct ptp_clock_info *ptp,
0159 const struct timespec64 *ts)
0160 {
0161 struct stmmac_priv *priv =
0162 container_of(ptp, struct stmmac_priv, ptp_clock_ops);
0163 unsigned long flags;
0164
0165 write_lock_irqsave(&priv->ptp_lock, flags);
0166 stmmac_init_systime(priv, priv->ptpaddr, ts->tv_sec, ts->tv_nsec);
0167 write_unlock_irqrestore(&priv->ptp_lock, flags);
0168
0169 return 0;
0170 }
0171
0172 static int stmmac_enable(struct ptp_clock_info *ptp,
0173 struct ptp_clock_request *rq, int on)
0174 {
0175 struct stmmac_priv *priv =
0176 container_of(ptp, struct stmmac_priv, ptp_clock_ops);
0177 void __iomem *ptpaddr = priv->ptpaddr;
0178 struct stmmac_pps_cfg *cfg;
0179 int ret = -EOPNOTSUPP;
0180 unsigned long flags;
0181 u32 acr_value;
0182
0183 switch (rq->type) {
0184 case PTP_CLK_REQ_PEROUT:
0185
0186 if (rq->perout.flags)
0187 return -EOPNOTSUPP;
0188
0189 cfg = &priv->pps[rq->perout.index];
0190
0191 cfg->start.tv_sec = rq->perout.start.sec;
0192 cfg->start.tv_nsec = rq->perout.start.nsec;
0193 cfg->period.tv_sec = rq->perout.period.sec;
0194 cfg->period.tv_nsec = rq->perout.period.nsec;
0195
0196 write_lock_irqsave(&priv->ptp_lock, flags);
0197 ret = stmmac_flex_pps_config(priv, priv->ioaddr,
0198 rq->perout.index, cfg, on,
0199 priv->sub_second_inc,
0200 priv->systime_flags);
0201 write_unlock_irqrestore(&priv->ptp_lock, flags);
0202 break;
0203 case PTP_CLK_REQ_EXTTS:
0204 priv->plat->ext_snapshot_en = on;
0205 mutex_lock(&priv->aux_ts_lock);
0206 acr_value = readl(ptpaddr + PTP_ACR);
0207 acr_value &= ~PTP_ACR_MASK;
0208 if (on) {
0209
0210 acr_value |= priv->plat->ext_snapshot_num;
0211 acr_value |= PTP_ACR_ATSFC;
0212 netdev_dbg(priv->dev, "Auxiliary Snapshot %d enabled.\n",
0213 priv->plat->ext_snapshot_num >>
0214 PTP_ACR_ATSEN_SHIFT);
0215 } else {
0216 netdev_dbg(priv->dev, "Auxiliary Snapshot %d disabled.\n",
0217 priv->plat->ext_snapshot_num >>
0218 PTP_ACR_ATSEN_SHIFT);
0219 }
0220 writel(acr_value, ptpaddr + PTP_ACR);
0221 mutex_unlock(&priv->aux_ts_lock);
0222 ret = 0;
0223 break;
0224
0225 default:
0226 break;
0227 }
0228
0229 return ret;
0230 }
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 static int stmmac_get_syncdevicetime(ktime_t *device,
0241 struct system_counterval_t *system,
0242 void *ctx)
0243 {
0244 struct stmmac_priv *priv = (struct stmmac_priv *)ctx;
0245
0246 if (priv->plat->crosststamp)
0247 return priv->plat->crosststamp(device, system, ctx);
0248 else
0249 return -EOPNOTSUPP;
0250 }
0251
0252 static int stmmac_getcrosststamp(struct ptp_clock_info *ptp,
0253 struct system_device_crosststamp *xtstamp)
0254 {
0255 struct stmmac_priv *priv =
0256 container_of(ptp, struct stmmac_priv, ptp_clock_ops);
0257
0258 return get_device_system_crosststamp(stmmac_get_syncdevicetime,
0259 priv, NULL, xtstamp);
0260 }
0261
0262
0263 static struct ptp_clock_info stmmac_ptp_clock_ops = {
0264 .owner = THIS_MODULE,
0265 .name = "stmmac ptp",
0266 .max_adj = 62500000,
0267 .n_alarm = 0,
0268 .n_ext_ts = 0,
0269 .n_per_out = 0,
0270 .n_pins = 0,
0271 .pps = 0,
0272 .adjfreq = stmmac_adjust_freq,
0273 .adjtime = stmmac_adjust_time,
0274 .gettime64 = stmmac_get_time,
0275 .settime64 = stmmac_set_time,
0276 .enable = stmmac_enable,
0277 .getcrosststamp = stmmac_getcrosststamp,
0278 };
0279
0280
0281
0282
0283
0284
0285
0286 void stmmac_ptp_register(struct stmmac_priv *priv)
0287 {
0288 int i;
0289
0290 for (i = 0; i < priv->dma_cap.pps_out_num; i++) {
0291 if (i >= STMMAC_PPS_MAX)
0292 break;
0293 priv->pps[i].available = true;
0294 }
0295
0296 if (priv->plat->ptp_max_adj)
0297 stmmac_ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;
0298
0299
0300 priv->plat->cdc_error_adj = 0;
0301 if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate)
0302 priv->plat->cdc_error_adj = (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;
0303
0304 stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
0305 stmmac_ptp_clock_ops.n_ext_ts = priv->dma_cap.aux_snapshot_n;
0306
0307 rwlock_init(&priv->ptp_lock);
0308 mutex_init(&priv->aux_ts_lock);
0309 priv->ptp_clock_ops = stmmac_ptp_clock_ops;
0310
0311 priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
0312 priv->device);
0313 if (IS_ERR(priv->ptp_clock)) {
0314 netdev_err(priv->dev, "ptp_clock_register failed\n");
0315 priv->ptp_clock = NULL;
0316 } else if (priv->ptp_clock)
0317 netdev_info(priv->dev, "registered PTP clock\n");
0318 }
0319
0320
0321
0322
0323
0324
0325
0326 void stmmac_ptp_unregister(struct stmmac_priv *priv)
0327 {
0328 if (priv->ptp_clock) {
0329 ptp_clock_unregister(priv->ptp_clock);
0330 priv->ptp_clock = NULL;
0331 pr_debug("Removed PTP HW clock successfully on %s\n",
0332 priv->dev->name);
0333 }
0334
0335 mutex_destroy(&priv->aux_ts_lock);
0336 }