0001
0002
0003
0004
0005
0006
0007 #include <linux/time64.h>
0008
0009 #include <soc/mscc/ocelot_ptp.h>
0010 #include <soc/mscc/ocelot_sys.h>
0011 #include <soc/mscc/ocelot.h>
0012
0013 int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
0014 {
0015 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
0016 unsigned long flags;
0017 time64_t s;
0018 u32 val;
0019 s64 ns;
0020
0021 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0022
0023 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0024 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
0025 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
0026 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0027
0028 s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN) & 0xffff;
0029 s <<= 32;
0030 s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
0031 ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
0032
0033 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0034
0035
0036 if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) {
0037 s--;
0038 ns &= 0xf;
0039 ns += 999999984;
0040 }
0041
0042 set_normalized_timespec64(ts, s, ns);
0043 return 0;
0044 }
0045 EXPORT_SYMBOL(ocelot_ptp_gettime64);
0046
0047 int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
0048 const struct timespec64 *ts)
0049 {
0050 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
0051 unsigned long flags;
0052 u32 val;
0053
0054 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0055
0056 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0057 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
0058 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
0059
0060 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0061
0062 ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
0063 TOD_ACC_PIN);
0064 ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
0065 TOD_ACC_PIN);
0066 ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
0067
0068 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0069 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
0070 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
0071
0072 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0073
0074 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0075
0076 if (ocelot->ops->tas_clock_adjust)
0077 ocelot->ops->tas_clock_adjust(ocelot);
0078
0079 return 0;
0080 }
0081 EXPORT_SYMBOL(ocelot_ptp_settime64);
0082
0083 int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
0084 {
0085 if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
0086 struct ocelot *ocelot = container_of(ptp, struct ocelot,
0087 ptp_info);
0088 unsigned long flags;
0089 u32 val;
0090
0091 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0092
0093 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0094 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK |
0095 PTP_PIN_CFG_DOM);
0096 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
0097
0098 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0099
0100 ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
0101 ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
0102 ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
0103
0104 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
0105 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK |
0106 PTP_PIN_CFG_DOM);
0107 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA);
0108
0109 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
0110
0111 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0112
0113 if (ocelot->ops->tas_clock_adjust)
0114 ocelot->ops->tas_clock_adjust(ocelot);
0115 } else {
0116
0117 struct timespec64 ts;
0118 u64 now;
0119
0120 ocelot_ptp_gettime64(ptp, &ts);
0121
0122 now = ktime_to_ns(timespec64_to_ktime(ts));
0123 ts = ns_to_timespec64(now + delta);
0124
0125 ocelot_ptp_settime64(ptp, &ts);
0126 }
0127
0128 return 0;
0129 }
0130 EXPORT_SYMBOL(ocelot_ptp_adjtime);
0131
0132 int ocelot_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
0133 {
0134 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
0135 u32 unit = 0, direction = 0;
0136 unsigned long flags;
0137 u64 adj = 0;
0138
0139 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0140
0141 if (!scaled_ppm)
0142 goto disable_adj;
0143
0144 if (scaled_ppm < 0) {
0145 direction = PTP_CFG_CLK_ADJ_CFG_DIR;
0146 scaled_ppm = -scaled_ppm;
0147 }
0148
0149 adj = PSEC_PER_SEC << 16;
0150 do_div(adj, scaled_ppm);
0151 do_div(adj, 1000);
0152
0153
0154 if (adj >= (1L << 30)) {
0155 unit = PTP_CFG_CLK_ADJ_FREQ_NS;
0156 do_div(adj, 1000);
0157 }
0158
0159
0160 if (adj >= (1L << 30))
0161 goto disable_adj;
0162
0163 ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ);
0164 ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction,
0165 PTP_CLK_CFG_ADJ_CFG);
0166
0167 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0168 return 0;
0169
0170 disable_adj:
0171 ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG);
0172
0173 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0174 return 0;
0175 }
0176 EXPORT_SYMBOL(ocelot_ptp_adjfine);
0177
0178 int ocelot_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
0179 enum ptp_pin_function func, unsigned int chan)
0180 {
0181 switch (func) {
0182 case PTP_PF_NONE:
0183 case PTP_PF_PEROUT:
0184 break;
0185 case PTP_PF_EXTTS:
0186 case PTP_PF_PHYSYNC:
0187 return -1;
0188 }
0189 return 0;
0190 }
0191 EXPORT_SYMBOL(ocelot_ptp_verify);
0192
0193 int ocelot_ptp_enable(struct ptp_clock_info *ptp,
0194 struct ptp_clock_request *rq, int on)
0195 {
0196 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
0197 struct timespec64 ts_phase, ts_period;
0198 enum ocelot_ptp_pins ptp_pin;
0199 unsigned long flags;
0200 bool pps = false;
0201 int pin = -1;
0202 s64 wf_high;
0203 s64 wf_low;
0204 u32 val;
0205
0206 switch (rq->type) {
0207 case PTP_CLK_REQ_PEROUT:
0208
0209 if (rq->perout.flags & ~(PTP_PEROUT_DUTY_CYCLE |
0210 PTP_PEROUT_PHASE))
0211 return -EOPNOTSUPP;
0212
0213 pin = ptp_find_pin(ocelot->ptp_clock, PTP_PF_PEROUT,
0214 rq->perout.index);
0215 if (pin == 0)
0216 ptp_pin = PTP_PIN_0;
0217 else if (pin == 1)
0218 ptp_pin = PTP_PIN_1;
0219 else if (pin == 2)
0220 ptp_pin = PTP_PIN_2;
0221 else if (pin == 3)
0222 ptp_pin = PTP_PIN_3;
0223 else
0224 return -EBUSY;
0225
0226 ts_period.tv_sec = rq->perout.period.sec;
0227 ts_period.tv_nsec = rq->perout.period.nsec;
0228
0229 if (ts_period.tv_sec == 1 && ts_period.tv_nsec == 0)
0230 pps = true;
0231
0232
0233 if (!on) {
0234 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0235 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
0236 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
0237 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0238 break;
0239 }
0240
0241 if (rq->perout.flags & PTP_PEROUT_PHASE) {
0242 ts_phase.tv_sec = rq->perout.phase.sec;
0243 ts_phase.tv_nsec = rq->perout.phase.nsec;
0244 } else {
0245
0246 ts_phase.tv_sec = rq->perout.start.sec;
0247 ts_phase.tv_nsec = rq->perout.start.nsec;
0248 }
0249 if (ts_phase.tv_sec || (ts_phase.tv_nsec && !pps)) {
0250 dev_warn(ocelot->dev,
0251 "Absolute start time not supported!\n");
0252 dev_warn(ocelot->dev,
0253 "Accept nsec for PPS phase adjustment, otherwise start time should be 0 0.\n");
0254 return -EINVAL;
0255 }
0256
0257
0258 if (rq->perout.flags & PTP_PEROUT_DUTY_CYCLE) {
0259 struct timespec64 ts_on;
0260
0261 ts_on.tv_sec = rq->perout.on.sec;
0262 ts_on.tv_nsec = rq->perout.on.nsec;
0263
0264 wf_high = timespec64_to_ns(&ts_on);
0265 } else {
0266 if (pps) {
0267 wf_high = 1000;
0268 } else {
0269 wf_high = timespec64_to_ns(&ts_period);
0270 wf_high = div_s64(wf_high, 2);
0271 }
0272 }
0273
0274 wf_low = timespec64_to_ns(&ts_period);
0275 wf_low -= wf_high;
0276
0277
0278 if (pps) {
0279 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0280 ocelot_write_rix(ocelot, ts_phase.tv_nsec,
0281 PTP_PIN_WF_LOW_PERIOD, ptp_pin);
0282 ocelot_write_rix(ocelot, wf_high,
0283 PTP_PIN_WF_HIGH_PERIOD, ptp_pin);
0284 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK);
0285 val |= PTP_PIN_CFG_SYNC;
0286 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
0287 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0288 break;
0289 }
0290
0291
0292 if (wf_high > 0x3fffffff || wf_high <= 0x6)
0293 return -EINVAL;
0294 if (wf_low > 0x3fffffff || wf_low <= 0x6)
0295 return -EINVAL;
0296
0297 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
0298 ocelot_write_rix(ocelot, wf_low, PTP_PIN_WF_LOW_PERIOD,
0299 ptp_pin);
0300 ocelot_write_rix(ocelot, wf_high, PTP_PIN_WF_HIGH_PERIOD,
0301 ptp_pin);
0302 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK);
0303 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
0304 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
0305 break;
0306 default:
0307 return -EOPNOTSUPP;
0308 }
0309 return 0;
0310 }
0311 EXPORT_SYMBOL(ocelot_ptp_enable);
0312
0313 int ocelot_init_timestamp(struct ocelot *ocelot,
0314 const struct ptp_clock_info *info)
0315 {
0316 struct ptp_clock *ptp_clock;
0317 int i;
0318
0319 ocelot->ptp_info = *info;
0320
0321 for (i = 0; i < OCELOT_PTP_PINS_NUM; i++) {
0322 struct ptp_pin_desc *p = &ocelot->ptp_pins[i];
0323
0324 snprintf(p->name, sizeof(p->name), "switch_1588_dat%d", i);
0325 p->index = i;
0326 p->func = PTP_PF_NONE;
0327 }
0328
0329 ocelot->ptp_info.pin_config = &ocelot->ptp_pins[0];
0330
0331 ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
0332 if (IS_ERR(ptp_clock))
0333 return PTR_ERR(ptp_clock);
0334
0335 if (!ptp_clock)
0336 return 0;
0337
0338 ocelot->ptp_clock = ptp_clock;
0339
0340 ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
0341 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
0342 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
0343
0344 ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
0345
0346
0347
0348
0349 ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
0350
0351 return 0;
0352 }
0353 EXPORT_SYMBOL(ocelot_init_timestamp);
0354
0355 int ocelot_deinit_timestamp(struct ocelot *ocelot)
0356 {
0357 if (ocelot->ptp_clock)
0358 ptp_clock_unregister(ocelot->ptp_clock);
0359 return 0;
0360 }
0361 EXPORT_SYMBOL(ocelot_deinit_timestamp);