1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot PTP clock driver
4 * Copyright (c) 2017 Microsemi Corporation
7 #include <soc/mscc/ocelot_ptp.h>
8 #include <soc/mscc/ocelot_sys.h>
9 #include <soc/mscc/ocelot.h>
11 int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
13 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
19 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
21 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
22 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
23 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
24 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
26 s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN) & 0xffff;
28 s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
29 ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
31 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
33 /* Deal with negative values */
34 if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) {
40 set_normalized_timespec64(ts, s, ns);
43 EXPORT_SYMBOL(ocelot_ptp_gettime64);
45 int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
46 const struct timespec64 *ts)
48 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
52 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
54 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
55 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
56 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
58 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
60 ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
62 ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
64 ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
66 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
67 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
68 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
70 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
72 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
75 EXPORT_SYMBOL(ocelot_ptp_settime64);
77 int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
79 if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
80 struct ocelot *ocelot = container_of(ptp, struct ocelot,
85 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
87 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
88 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK |
90 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
92 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
94 ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
95 ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
96 ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
98 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
99 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK |
101 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA);
103 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
105 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
107 /* Fall back using ocelot_ptp_settime64 which is not exact. */
108 struct timespec64 ts;
111 ocelot_ptp_gettime64(ptp, &ts);
113 now = ktime_to_ns(timespec64_to_ktime(ts));
114 ts = ns_to_timespec64(now + delta);
116 ocelot_ptp_settime64(ptp, &ts);
120 EXPORT_SYMBOL(ocelot_ptp_adjtime);
122 int ocelot_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
124 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
125 u32 unit = 0, direction = 0;
129 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
134 if (scaled_ppm < 0) {
135 direction = PTP_CFG_CLK_ADJ_CFG_DIR;
136 scaled_ppm = -scaled_ppm;
139 adj = PSEC_PER_SEC << 16;
140 do_div(adj, scaled_ppm);
143 /* If the adjustment value is too large, use ns instead */
144 if (adj >= (1L << 30)) {
145 unit = PTP_CFG_CLK_ADJ_FREQ_NS;
150 if (adj >= (1L << 30))
153 ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ);
154 ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction,
155 PTP_CLK_CFG_ADJ_CFG);
157 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
161 ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG);
163 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
166 EXPORT_SYMBOL(ocelot_ptp_adjfine);
168 int ocelot_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
169 enum ptp_pin_function func, unsigned int chan)
181 EXPORT_SYMBOL(ocelot_ptp_verify);
183 int ocelot_ptp_enable(struct ptp_clock_info *ptp,
184 struct ptp_clock_request *rq, int on)
186 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
187 struct timespec64 ts_phase, ts_period;
188 enum ocelot_ptp_pins ptp_pin;
197 case PTP_CLK_REQ_PEROUT:
198 /* Reject requests with unsupported flags */
199 if (rq->perout.flags & ~(PTP_PEROUT_DUTY_CYCLE |
203 pin = ptp_find_pin(ocelot->ptp_clock, PTP_PF_PEROUT,
216 ts_period.tv_sec = rq->perout.period.sec;
217 ts_period.tv_nsec = rq->perout.period.nsec;
219 if (ts_period.tv_sec == 1 && ts_period.tv_nsec == 0)
222 /* Handle turning off */
224 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
225 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
226 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
227 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
231 if (rq->perout.flags & PTP_PEROUT_PHASE) {
232 ts_phase.tv_sec = rq->perout.phase.sec;
233 ts_phase.tv_nsec = rq->perout.phase.nsec;
236 ts_phase.tv_sec = rq->perout.start.sec;
237 ts_phase.tv_nsec = rq->perout.start.nsec;
239 if (ts_phase.tv_sec || (ts_phase.tv_nsec && !pps)) {
240 dev_warn(ocelot->dev,
241 "Absolute start time not supported!\n");
242 dev_warn(ocelot->dev,
243 "Accept nsec for PPS phase adjustment, otherwise start time should be 0 0.\n");
247 /* Calculate waveform high and low times */
248 if (rq->perout.flags & PTP_PEROUT_DUTY_CYCLE) {
249 struct timespec64 ts_on;
251 ts_on.tv_sec = rq->perout.on.sec;
252 ts_on.tv_nsec = rq->perout.on.nsec;
254 wf_high = timespec64_to_ns(&ts_on);
259 wf_high = timespec64_to_ns(&ts_period);
260 wf_high = div_s64(wf_high, 2);
264 wf_low = timespec64_to_ns(&ts_period);
267 /* Handle PPS request */
269 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
270 ocelot_write_rix(ocelot, ts_phase.tv_nsec,
271 PTP_PIN_WF_LOW_PERIOD, ptp_pin);
272 ocelot_write_rix(ocelot, wf_high,
273 PTP_PIN_WF_HIGH_PERIOD, ptp_pin);
274 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK);
275 val |= PTP_PIN_CFG_SYNC;
276 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
277 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
281 /* Handle periodic clock */
282 if (wf_high > 0x3fffffff || wf_high <= 0x6)
284 if (wf_low > 0x3fffffff || wf_low <= 0x6)
287 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
288 ocelot_write_rix(ocelot, wf_low, PTP_PIN_WF_LOW_PERIOD,
290 ocelot_write_rix(ocelot, wf_high, PTP_PIN_WF_HIGH_PERIOD,
292 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK);
293 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
294 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
301 EXPORT_SYMBOL(ocelot_ptp_enable);
303 int ocelot_init_timestamp(struct ocelot *ocelot, struct ptp_clock_info *info)
305 struct ptp_clock *ptp_clock;
308 ocelot->ptp_info = *info;
310 for (i = 0; i < OCELOT_PTP_PINS_NUM; i++) {
311 struct ptp_pin_desc *p = &ocelot->ptp_pins[i];
313 snprintf(p->name, sizeof(p->name), "switch_1588_dat%d", i);
315 p->func = PTP_PF_NONE;
318 ocelot->ptp_info.pin_config = &ocelot->ptp_pins[0];
320 ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
321 if (IS_ERR(ptp_clock))
322 return PTR_ERR(ptp_clock);
323 /* Check if PHC support is missing at the configuration level */
327 ocelot->ptp_clock = ptp_clock;
329 ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
330 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
331 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
333 ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
335 /* There is no device reconfiguration, PTP Rx stamping is always
338 ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
342 EXPORT_SYMBOL(ocelot_init_timestamp);
344 int ocelot_deinit_timestamp(struct ocelot *ocelot)
346 if (ocelot->ptp_clock)
347 ptp_clock_unregister(ocelot->ptp_clock);
350 EXPORT_SYMBOL(ocelot_deinit_timestamp);