1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Marvell PP2.2 TAI support
4 *
5 * Note:
6 * Do NOT use the event capture support.
7 * Do Not even set the MPP muxes to allow PTP_EVENT_REQ to be used.
8 * It will disrupt the operation of this driver, and there is nothing
9 * that this driver can do to prevent that. Even using PTP_EVENT_REQ
10 * as an output will be seen as a trigger input, which can't be masked.
11 * When ever a trigger input is seen, the action in the TCFCR0_TCF
12 * field will be performed - whether it is a set, increment, decrement
13 * read, or frequency update.
14 *
15 * Other notes (useful, not specified in the documentation):
16 * - PTP_PULSE_OUT (PTP_EVENT_REQ MPP)
17 * It looks like the hardware can't generate a pulse at nsec=0. (The
18 * output doesn't trigger if the nsec field is zero.)
19 * Note: when configured as an output via the register at 0xfX441120,
20 * the input is still very much alive, and will trigger the current TCF
21 * function.
22 * - PTP_CLK_OUT (PTP_TRIG_GEN MPP)
23 * This generates a "PPS" signal determined by the CCC registers. It
24 * seems this is not aligned to the TOD counter in any way (it may be
25 * initially, but if you specify a non-round second interval, it won't,
26 * and you can't easily get it back.)
27 * - PTP_PCLK_OUT
28 * This generates a 50% duty cycle clock based on the TOD counter, and
29 * seems it can be set to any period of 1ns resolution. It is probably
30 * limited by the TOD step size. Its period is defined by the PCLK_CCC
31 * registers. Again, its alignment to the second is questionable.
32 *
33 * Consequently, we support none of these.
34 */
35#include <linux/io.h>
36#include <linux/ptp_clock_kernel.h>
37#include <linux/slab.h>
38
39#include "mvpp2.h"
40
41#define CR0_SW_NRESET BIT(0)
42
43#define TCFCR0_PHASE_UPDATE_ENABLE BIT(8)
44#define TCFCR0_TCF_MASK (7 << 2)
45#define TCFCR0_TCF_UPDATE (0 << 2)
46#define TCFCR0_TCF_FREQUPDATE (1 << 2)
47#define TCFCR0_TCF_INCREMENT (2 << 2)
48#define TCFCR0_TCF_DECREMENT (3 << 2)
49#define TCFCR0_TCF_CAPTURE (4 << 2)
50#define TCFCR0_TCF_NOP (7 << 2)
51#define TCFCR0_TCF_TRIGGER BIT(0)
52
53#define TCSR_CAPTURE_1_VALID BIT(1)
54#define TCSR_CAPTURE_0_VALID BIT(0)
55
56struct mvpp2_tai {
57 struct ptp_clock_info caps;
58 struct ptp_clock *ptp_clock;
59 void __iomem *base;
60 spinlock_t lock;
61 u64 period; // nanosecond period in 32.32 fixed point
62 /* This timestamp is updated every two seconds */
63 struct timespec64 stamp;
64};
65
66static void mvpp2_tai_modify(void __iomem *reg, u32 mask, u32 set)
67{
68 u32 val;
69
70 val = readl_relaxed(reg) & ~mask;
71 val |= set & mask;
72 writel(val, addr: reg);
73}
74
75static void mvpp2_tai_write(u32 val, void __iomem *reg)
76{
77 writel_relaxed(val & 0xffff, reg);
78}
79
80static u32 mvpp2_tai_read(void __iomem *reg)
81{
82 return readl_relaxed(reg) & 0xffff;
83}
84
85static struct mvpp2_tai *ptp_to_tai(struct ptp_clock_info *ptp)
86{
87 return container_of(ptp, struct mvpp2_tai, caps);
88}
89
90static void mvpp22_tai_read_ts(struct timespec64 *ts, void __iomem *base)
91{
92 ts->tv_sec = (u64)mvpp2_tai_read(reg: base + 0) << 32 |
93 mvpp2_tai_read(reg: base + 4) << 16 |
94 mvpp2_tai_read(reg: base + 8);
95
96 ts->tv_nsec = mvpp2_tai_read(reg: base + 12) << 16 |
97 mvpp2_tai_read(reg: base + 16);
98
99 /* Read and discard fractional part */
100 readl_relaxed(base + 20);
101 readl_relaxed(base + 24);
102}
103
104static void mvpp2_tai_write_tlv(const struct timespec64 *ts, u32 frac,
105 void __iomem *base)
106{
107 mvpp2_tai_write(val: ts->tv_sec >> 32, reg: base + MVPP22_TAI_TLV_SEC_HIGH);
108 mvpp2_tai_write(val: ts->tv_sec >> 16, reg: base + MVPP22_TAI_TLV_SEC_MED);
109 mvpp2_tai_write(val: ts->tv_sec, reg: base + MVPP22_TAI_TLV_SEC_LOW);
110 mvpp2_tai_write(val: ts->tv_nsec >> 16, reg: base + MVPP22_TAI_TLV_NANO_HIGH);
111 mvpp2_tai_write(val: ts->tv_nsec, reg: base + MVPP22_TAI_TLV_NANO_LOW);
112 mvpp2_tai_write(val: frac >> 16, reg: base + MVPP22_TAI_TLV_FRAC_HIGH);
113 mvpp2_tai_write(val: frac, reg: base + MVPP22_TAI_TLV_FRAC_LOW);
114}
115
116static void mvpp2_tai_op(u32 op, void __iomem *base)
117{
118 /* Trigger the operation. Note that an external unmaskable
119 * event on PTP_EVENT_REQ will also trigger this action.
120 */
121 mvpp2_tai_modify(reg: base + MVPP22_TAI_TCFCR0,
122 TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER,
123 set: op | TCFCR0_TCF_TRIGGER);
124 mvpp2_tai_modify(reg: base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK,
125 TCFCR0_TCF_NOP);
126}
127
128/* The adjustment has a range of +0.5ns to -0.5ns in 2^32 steps, so has units
129 * of 2^-32 ns.
130 *
131 * units(s) = 1 / (2^32 * 10^9)
132 * fractional = abs_scaled_ppm / (2^16 * 10^6)
133 *
134 * What we want to achieve:
135 * freq_adjusted = freq_nominal * (1 + fractional)
136 * freq_delta = freq_adjusted - freq_nominal => positive = faster
137 * freq_delta = freq_nominal * (1 + fractional) - freq_nominal
138 * So: freq_delta = freq_nominal * fractional
139 *
140 * However, we are dealing with periods, so:
141 * period_adjusted = period_nominal / (1 + fractional)
142 * period_delta = period_nominal - period_adjusted => positive = faster
143 * period_delta = period_nominal * fractional / (1 + fractional)
144 *
145 * Hence:
146 * period_delta = period_nominal * abs_scaled_ppm /
147 * (2^16 * 10^6 + abs_scaled_ppm)
148 *
149 * To avoid overflow, we reduce both sides of the divide operation by a factor
150 * of 16.
151 */
152static u64 mvpp22_calc_frac_ppm(struct mvpp2_tai *tai, long abs_scaled_ppm)
153{
154 u64 val = tai->period * abs_scaled_ppm >> 4;
155
156 return div_u64(dividend: val, divisor: (1000000 << 12) + (abs_scaled_ppm >> 4));
157}
158
159static s32 mvpp22_calc_max_adj(struct mvpp2_tai *tai)
160{
161 return 1000000;
162}
163
164static int mvpp22_tai_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
165{
166 struct mvpp2_tai *tai = ptp_to_tai(ptp);
167 unsigned long flags;
168 void __iomem *base;
169 bool neg_adj;
170 s32 frac;
171 u64 val;
172
173 neg_adj = scaled_ppm < 0;
174 if (neg_adj)
175 scaled_ppm = -scaled_ppm;
176
177 val = mvpp22_calc_frac_ppm(tai, abs_scaled_ppm: scaled_ppm);
178
179 /* Convert to a signed 32-bit adjustment */
180 if (neg_adj) {
181 /* -S32_MIN warns, -val < S32_MIN fails, so go for the easy
182 * solution.
183 */
184 if (val > 0x80000000)
185 return -ERANGE;
186
187 frac = -val;
188 } else {
189 if (val > S32_MAX)
190 return -ERANGE;
191
192 frac = val;
193 }
194
195 base = tai->base;
196 spin_lock_irqsave(&tai->lock, flags);
197 mvpp2_tai_write(val: frac >> 16, reg: base + MVPP22_TAI_TLV_FRAC_HIGH);
198 mvpp2_tai_write(val: frac, reg: base + MVPP22_TAI_TLV_FRAC_LOW);
199 mvpp2_tai_op(TCFCR0_TCF_FREQUPDATE, base);
200 spin_unlock_irqrestore(lock: &tai->lock, flags);
201
202 return 0;
203}
204
205static int mvpp22_tai_adjtime(struct ptp_clock_info *ptp, s64 delta)
206{
207 struct mvpp2_tai *tai = ptp_to_tai(ptp);
208 struct timespec64 ts;
209 unsigned long flags;
210 void __iomem *base;
211 u32 tcf;
212
213 /* We can't deal with S64_MIN */
214 if (delta == S64_MIN)
215 return -ERANGE;
216
217 if (delta < 0) {
218 delta = -delta;
219 tcf = TCFCR0_TCF_DECREMENT;
220 } else {
221 tcf = TCFCR0_TCF_INCREMENT;
222 }
223
224 ts = ns_to_timespec64(nsec: delta);
225
226 base = tai->base;
227 spin_lock_irqsave(&tai->lock, flags);
228 mvpp2_tai_write_tlv(ts: &ts, frac: 0, base);
229 mvpp2_tai_op(op: tcf, base);
230 spin_unlock_irqrestore(lock: &tai->lock, flags);
231
232 return 0;
233}
234
235static int mvpp22_tai_gettimex64(struct ptp_clock_info *ptp,
236 struct timespec64 *ts,
237 struct ptp_system_timestamp *sts)
238{
239 struct mvpp2_tai *tai = ptp_to_tai(ptp);
240 unsigned long flags;
241 void __iomem *base;
242 u32 tcsr;
243 int ret;
244
245 base = tai->base;
246 spin_lock_irqsave(&tai->lock, flags);
247 /* XXX: the only way to read the PTP time is for the CPU to trigger
248 * an event. However, there is no way to distinguish between the CPU
249 * triggered event, and an external event on PTP_EVENT_REQ. So this
250 * is incompatible with external use of PTP_EVENT_REQ.
251 */
252 ptp_read_system_prets(sts);
253 mvpp2_tai_modify(reg: base + MVPP22_TAI_TCFCR0,
254 TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER,
255 TCFCR0_TCF_CAPTURE | TCFCR0_TCF_TRIGGER);
256 ptp_read_system_postts(sts);
257 mvpp2_tai_modify(reg: base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK,
258 TCFCR0_TCF_NOP);
259
260 tcsr = readl(addr: base + MVPP22_TAI_TCSR);
261 if (tcsr & TCSR_CAPTURE_1_VALID) {
262 mvpp22_tai_read_ts(ts, base: base + MVPP22_TAI_TCV1_SEC_HIGH);
263 ret = 0;
264 } else if (tcsr & TCSR_CAPTURE_0_VALID) {
265 mvpp22_tai_read_ts(ts, base: base + MVPP22_TAI_TCV0_SEC_HIGH);
266 ret = 0;
267 } else {
268 /* We don't seem to have a reading... */
269 ret = -EBUSY;
270 }
271 spin_unlock_irqrestore(lock: &tai->lock, flags);
272
273 return ret;
274}
275
276static int mvpp22_tai_settime64(struct ptp_clock_info *ptp,
277 const struct timespec64 *ts)
278{
279 struct mvpp2_tai *tai = ptp_to_tai(ptp);
280 unsigned long flags;
281 void __iomem *base;
282
283 base = tai->base;
284 spin_lock_irqsave(&tai->lock, flags);
285 mvpp2_tai_write_tlv(ts, frac: 0, base);
286
287 /* Trigger an update to load the value from the TLV registers
288 * into the TOD counter. Note that an external unmaskable event on
289 * PTP_EVENT_REQ will also trigger this action.
290 */
291 mvpp2_tai_modify(reg: base + MVPP22_TAI_TCFCR0,
292 TCFCR0_PHASE_UPDATE_ENABLE |
293 TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER,
294 TCFCR0_TCF_UPDATE | TCFCR0_TCF_TRIGGER);
295 mvpp2_tai_modify(reg: base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK,
296 TCFCR0_TCF_NOP);
297 spin_unlock_irqrestore(lock: &tai->lock, flags);
298
299 return 0;
300}
301
302static long mvpp22_tai_aux_work(struct ptp_clock_info *ptp)
303{
304 struct mvpp2_tai *tai = ptp_to_tai(ptp);
305
306 mvpp22_tai_gettimex64(ptp, ts: &tai->stamp, NULL);
307
308 return msecs_to_jiffies(m: 2000);
309}
310
311static void mvpp22_tai_set_step(struct mvpp2_tai *tai)
312{
313 void __iomem *base = tai->base;
314 u32 nano, frac;
315
316 nano = upper_32_bits(tai->period);
317 frac = lower_32_bits(tai->period);
318
319 /* As the fractional nanosecond is a signed offset, if the MSB (sign)
320 * bit is set, we have to increment the whole nanoseconds.
321 */
322 if (frac >= 0x80000000)
323 nano += 1;
324
325 mvpp2_tai_write(val: nano, reg: base + MVPP22_TAI_TOD_STEP_NANO_CR);
326 mvpp2_tai_write(val: frac >> 16, reg: base + MVPP22_TAI_TOD_STEP_FRAC_HIGH);
327 mvpp2_tai_write(val: frac, reg: base + MVPP22_TAI_TOD_STEP_FRAC_LOW);
328}
329
330static void mvpp22_tai_init(struct mvpp2_tai *tai)
331{
332 void __iomem *base = tai->base;
333
334 mvpp22_tai_set_step(tai);
335
336 /* Release the TAI reset */
337 mvpp2_tai_modify(reg: base + MVPP22_TAI_CR0, CR0_SW_NRESET, CR0_SW_NRESET);
338}
339
340int mvpp22_tai_ptp_clock_index(struct mvpp2_tai *tai)
341{
342 return ptp_clock_index(ptp: tai->ptp_clock);
343}
344
345void mvpp22_tai_tstamp(struct mvpp2_tai *tai, u32 tstamp,
346 struct skb_shared_hwtstamps *hwtstamp)
347{
348 struct timespec64 ts;
349 int delta;
350
351 /* The tstamp consists of 2 bits of seconds and 30 bits of nanoseconds.
352 * We use our stored timestamp (tai->stamp) to form a full timestamp,
353 * and we must read the seconds exactly once.
354 */
355 ts.tv_sec = READ_ONCE(tai->stamp.tv_sec);
356 ts.tv_nsec = tstamp & 0x3fffffff;
357
358 /* Calculate the delta in seconds between our stored timestamp and
359 * the value read from the queue. Allow timestamps one second in the
360 * past, otherwise consider them to be in the future.
361 */
362 delta = ((tstamp >> 30) - (ts.tv_sec & 3)) & 3;
363 if (delta == 3)
364 delta -= 4;
365 ts.tv_sec += delta;
366
367 memset(hwtstamp, 0, sizeof(*hwtstamp));
368 hwtstamp->hwtstamp = timespec64_to_ktime(ts);
369}
370
371void mvpp22_tai_start(struct mvpp2_tai *tai)
372{
373 long delay;
374
375 delay = mvpp22_tai_aux_work(ptp: &tai->caps);
376
377 ptp_schedule_worker(ptp: tai->ptp_clock, delay);
378}
379
380void mvpp22_tai_stop(struct mvpp2_tai *tai)
381{
382 ptp_cancel_worker_sync(ptp: tai->ptp_clock);
383}
384
385static void mvpp22_tai_remove(void *priv)
386{
387 struct mvpp2_tai *tai = priv;
388
389 if (!IS_ERR(ptr: tai->ptp_clock))
390 ptp_clock_unregister(ptp: tai->ptp_clock);
391}
392
393int mvpp22_tai_probe(struct device *dev, struct mvpp2 *priv)
394{
395 struct mvpp2_tai *tai;
396 int ret;
397
398 tai = devm_kzalloc(dev, size: sizeof(*tai), GFP_KERNEL);
399 if (!tai)
400 return -ENOMEM;
401
402 spin_lock_init(&tai->lock);
403
404 tai->base = priv->iface_base;
405
406 /* The step size consists of three registers - a 16-bit nanosecond step
407 * size, and a 32-bit fractional nanosecond step size split over two
408 * registers. The fractional nanosecond step size has units of 2^-32ns.
409 *
410 * To calculate this, we calculate:
411 * (10^9 + freq / 2) / (freq * 2^-32)
412 * which gives us the nanosecond step to the nearest integer in 16.32
413 * fixed point format, and the fractional part of the step size with
414 * the MSB inverted. With rounding of the fractional nanosecond, and
415 * simplification, this becomes:
416 * (10^9 << 32 + freq << 31 + (freq + 1) >> 1) / freq
417 *
418 * So:
419 * div = (10^9 << 32 + freq << 31 + (freq + 1) >> 1) / freq
420 * nano = upper_32_bits(div);
421 * frac = lower_32_bits(div) ^ 0x80000000;
422 * Will give the values for the registers.
423 *
424 * This is all seems perfect, but alas it is not when considering the
425 * whole story. The system is clocked from 25MHz, which is multiplied
426 * by a PLL to 1GHz, and then divided by three, giving 333333333Hz
427 * (recurring). This gives exactly 3ns, but using 333333333Hz with
428 * the above gives an error of 13*2^-32ns.
429 *
430 * Consequently, we use the period rather than calculating from the
431 * frequency.
432 */
433 tai->period = 3ULL << 32;
434
435 mvpp22_tai_init(tai);
436
437 tai->caps.owner = THIS_MODULE;
438 strscpy(tai->caps.name, "Marvell PP2.2", sizeof(tai->caps.name));
439 tai->caps.max_adj = mvpp22_calc_max_adj(tai);
440 tai->caps.adjfine = mvpp22_tai_adjfine;
441 tai->caps.adjtime = mvpp22_tai_adjtime;
442 tai->caps.gettimex64 = mvpp22_tai_gettimex64;
443 tai->caps.settime64 = mvpp22_tai_settime64;
444 tai->caps.do_aux_work = mvpp22_tai_aux_work;
445
446 ret = devm_add_action(dev, mvpp22_tai_remove, tai);
447 if (ret)
448 return ret;
449
450 tai->ptp_clock = ptp_clock_register(info: &tai->caps, parent: dev);
451 if (IS_ERR(ptr: tai->ptp_clock))
452 return PTR_ERR(ptr: tai->ptp_clock);
453
454 priv->tai = tai;
455
456 return 0;
457}
458

source code of linux/drivers/net/ethernet/marvell/mvpp2/mvpp2_tai.c