Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Marvell 88E6xxx Switch PTP support
  4 *
  5 * Copyright (c) 2008 Marvell Semiconductor
  6 *
  7 * Copyright (c) 2017 National Instruments
  8 *      Erik Hons <erik.hons@ni.com>
  9 *      Brandon Streiff <brandon.streiff@ni.com>
 10 *      Dane Wagner <dane.wagner@ni.com>
 11 */
 12
 13#include "chip.h"
 14#include "global1.h"
 15#include "global2.h"
 16#include "hwtstamp.h"
 17#include "ptp.h"
 18
 19#define MV88E6XXX_MAX_ADJ_PPB	1000000
 20
 21struct mv88e6xxx_cc_coeffs {
 22	u32 cc_shift;
 23	u32 cc_mult;
 24	u32 cc_mult_num;
 25	u32 cc_mult_dem;
 26};
 27
 28/* Family MV88E6250:
 29 * Raw timestamps are in units of 10-ns clock periods.
 30 *
 31 * clkadj = scaled_ppm * 10*2^28 / (10^6 * 2^16)
 32 * simplifies to
 33 * clkadj = scaled_ppm * 2^7 / 5^5
 34 */
 35#define MV88E6XXX_CC_10NS_SHIFT 28
 36static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_10ns_coeffs = {
 37	.cc_shift = MV88E6XXX_CC_10NS_SHIFT,
 38	.cc_mult = 10 << MV88E6XXX_CC_10NS_SHIFT,
 39	.cc_mult_num = 1 << 7,
 40	.cc_mult_dem = 3125ULL,
 41};
 42
 43/* Other families except MV88E6393X in internal clock mode:
 44 * Raw timestamps are in units of 8-ns clock periods.
 45 *
 46 * clkadj = scaled_ppm * 8*2^28 / (10^6 * 2^16)
 47 * simplifies to
 48 * clkadj = scaled_ppm * 2^9 / 5^6
 49 */
 50#define MV88E6XXX_CC_8NS_SHIFT 28
 51static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_8ns_coeffs = {
 52	.cc_shift = MV88E6XXX_CC_8NS_SHIFT,
 53	.cc_mult = 8 << MV88E6XXX_CC_8NS_SHIFT,
 54	.cc_mult_num = 1 << 9,
 55	.cc_mult_dem = 15625ULL
 56};
 57
 58/* Family MV88E6393X using internal clock:
 59 * Raw timestamps are in units of 4-ns clock periods.
 60 *
 61 * clkadj = scaled_ppm * 4*2^28 / (10^6 * 2^16)
 62 * simplifies to
 63 * clkadj = scaled_ppm * 2^8 / 5^6
 64 */
 65#define MV88E6XXX_CC_4NS_SHIFT 28
 66static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_4ns_coeffs = {
 67	.cc_shift = MV88E6XXX_CC_4NS_SHIFT,
 68	.cc_mult = 4 << MV88E6XXX_CC_4NS_SHIFT,
 69	.cc_mult_num = 1 << 8,
 70	.cc_mult_dem = 15625ULL
 71};
 72
 73#define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100)
 74
 75#define cc_to_chip(cc) container_of(cc, struct mv88e6xxx_chip, tstamp_cc)
 76#define dw_overflow_to_chip(dw) container_of(dw, struct mv88e6xxx_chip, \
 77					     overflow_work)
 78#define dw_tai_event_to_chip(dw) container_of(dw, struct mv88e6xxx_chip, \
 79					      tai_event_work)
 80
 81static int mv88e6xxx_tai_read(struct mv88e6xxx_chip *chip, int addr,
 82			      u16 *data, int len)
 83{
 84	if (!chip->info->ops->avb_ops->tai_read)
 85		return -EOPNOTSUPP;
 86
 87	return chip->info->ops->avb_ops->tai_read(chip, addr, data, len);
 88}
 89
 90static int mv88e6xxx_tai_write(struct mv88e6xxx_chip *chip, int addr, u16 data)
 91{
 92	if (!chip->info->ops->avb_ops->tai_write)
 93		return -EOPNOTSUPP;
 94
 95	return chip->info->ops->avb_ops->tai_write(chip, addr, data);
 96}
 97
 98/* TODO: places where this are called should be using pinctrl */
 99static int mv88e6352_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
100				   int func, int input)
101{
102	int err;
103
104	if (!chip->info->ops->gpio_ops)
105		return -EOPNOTSUPP;
106
107	err = chip->info->ops->gpio_ops->set_dir(chip, pin, input);
108	if (err)
109		return err;
110
111	return chip->info->ops->gpio_ops->set_pctl(chip, pin, func);
112}
113
114static const struct mv88e6xxx_cc_coeffs *
115mv88e6xxx_cc_coeff_get(struct mv88e6xxx_chip *chip)
116{
117	u16 period_ps;
118	int err;
119
120	err = mv88e6xxx_tai_read(chip, MV88E6XXX_TAI_CLOCK_PERIOD, &period_ps, 1);
121	if (err) {
122		dev_err(chip->dev, "failed to read cycle counter period: %d\n",
123			err);
124		return ERR_PTR(err);
125	}
126
127	switch (period_ps) {
128	case 4000:
129		return &mv88e6xxx_cc_4ns_coeffs;
130	case 8000:
131		return &mv88e6xxx_cc_8ns_coeffs;
132	case 10000:
133		return &mv88e6xxx_cc_10ns_coeffs;
134	default:
135		dev_err(chip->dev, "unexpected cycle counter period of %u ps\n",
136			period_ps);
137		return ERR_PTR(-ENODEV);
138	}
139}
140
141static u64 mv88e6352_ptp_clock_read(const struct cyclecounter *cc)
142{
143	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
144	u16 phc_time[2];
145	int err;
146
147	err = mv88e6xxx_tai_read(chip, MV88E6XXX_TAI_TIME_LO, phc_time,
148				 ARRAY_SIZE(phc_time));
149	if (err)
150		return 0;
151	else
152		return ((u32)phc_time[1] << 16) | phc_time[0];
153}
154
155static u64 mv88e6165_ptp_clock_read(const struct cyclecounter *cc)
156{
157	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
158	u16 phc_time[2];
159	int err;
160
161	err = mv88e6xxx_tai_read(chip, MV88E6XXX_PTP_GC_TIME_LO, phc_time,
162				 ARRAY_SIZE(phc_time));
163	if (err)
164		return 0;
165	else
166		return ((u32)phc_time[1] << 16) | phc_time[0];
167}
168
169/* mv88e6352_config_eventcap - configure TAI event capture
170 * @event: PTP_CLOCK_PPS (internal) or PTP_CLOCK_EXTTS (external)
171 * @rising: zero for falling-edge trigger, else rising-edge trigger
172 *
173 * This will also reset the capture sequence counter.
174 */
175static int mv88e6352_config_eventcap(struct mv88e6xxx_chip *chip, int event,
176				     int rising)
177{
178	u16 global_config;
179	u16 cap_config;
180	int err;
181
182	chip->evcap_config = MV88E6XXX_TAI_CFG_CAP_OVERWRITE |
183			     MV88E6XXX_TAI_CFG_CAP_CTR_START;
184	if (!rising)
185		chip->evcap_config |= MV88E6XXX_TAI_CFG_EVREQ_FALLING;
186
187	global_config = (chip->evcap_config | chip->trig_config);
188	err = mv88e6xxx_tai_write(chip, MV88E6XXX_TAI_CFG, global_config);
189	if (err)
190		return err;
191
192	if (event == PTP_CLOCK_PPS) {
193		cap_config = MV88E6XXX_TAI_EVENT_STATUS_CAP_TRIG;
194	} else if (event == PTP_CLOCK_EXTTS) {
195		/* if STATUS_CAP_TRIG is unset we capture PTP_EVREQ events */
196		cap_config = 0;
197	} else {
198		return -EINVAL;
199	}
200
201	/* Write the capture config; this also clears the capture counter */
202	err = mv88e6xxx_tai_write(chip, MV88E6XXX_TAI_EVENT_STATUS,
203				  cap_config);
204
205	return err;
206}
207
208static void mv88e6352_tai_event_work(struct work_struct *ugly)
209{
210	struct delayed_work *dw = to_delayed_work(ugly);
211	struct mv88e6xxx_chip *chip = dw_tai_event_to_chip(dw);
212	struct ptp_clock_event ev;
213	u16 status[4];
214	u32 raw_ts;
215	int err;
216
217	mv88e6xxx_reg_lock(chip);
218	err = mv88e6xxx_tai_read(chip, MV88E6XXX_TAI_EVENT_STATUS,
219				 status, ARRAY_SIZE(status));
220	mv88e6xxx_reg_unlock(chip);
221
222	if (err) {
223		dev_err(chip->dev, "failed to read TAI status register\n");
224		return;
225	}
226	if (status[0] & MV88E6XXX_TAI_EVENT_STATUS_ERROR) {
227		dev_warn(chip->dev, "missed event capture\n");
228		return;
229	}
230	if (!(status[0] & MV88E6XXX_TAI_EVENT_STATUS_VALID))
231		goto out;
232
233	raw_ts = ((u32)status[2] << 16) | status[1];
234
235	/* Clear the valid bit so the next timestamp can come in */
236	status[0] &= ~MV88E6XXX_TAI_EVENT_STATUS_VALID;
237	mv88e6xxx_reg_lock(chip);
238	err = mv88e6xxx_tai_write(chip, MV88E6XXX_TAI_EVENT_STATUS, status[0]);
239	mv88e6xxx_reg_unlock(chip);
240	if (err) {
241		dev_err(chip->dev, "failed to write TAI status register\n");
242		return;
243	}
244
245	/* This is an external timestamp */
246	ev.type = PTP_CLOCK_EXTTS;
247
248	/* We only have one timestamping channel. */
249	ev.index = 0;
250	mv88e6xxx_reg_lock(chip);
251	ev.timestamp = timecounter_cyc2time(&chip->tstamp_tc, raw_ts);
252	mv88e6xxx_reg_unlock(chip);
253
254	ptp_clock_event(chip->ptp_clock, &ev);
255out:
256	schedule_delayed_work(&chip->tai_event_work, TAI_EVENT_WORK_INTERVAL);
257}
258
259static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
260{
261	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
 
262	int neg_adj = 0;
263	u32 diff, mult;
264	u64 adj;
265
266	if (scaled_ppm < 0) {
267		neg_adj = 1;
268		scaled_ppm = -scaled_ppm;
269	}
270
271	mult = chip->cc_coeffs->cc_mult;
272	adj = chip->cc_coeffs->cc_mult_num;
273	adj *= scaled_ppm;
274	diff = div_u64(adj, chip->cc_coeffs->cc_mult_dem);
275
276	mv88e6xxx_reg_lock(chip);
277
278	timecounter_read(&chip->tstamp_tc);
279	chip->tstamp_cc.mult = neg_adj ? mult - diff : mult + diff;
280
281	mv88e6xxx_reg_unlock(chip);
282
283	return 0;
284}
285
286static int mv88e6xxx_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
287{
288	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
289
290	mv88e6xxx_reg_lock(chip);
291	timecounter_adjtime(&chip->tstamp_tc, delta);
292	mv88e6xxx_reg_unlock(chip);
293
294	return 0;
295}
296
297static int mv88e6xxx_ptp_gettime(struct ptp_clock_info *ptp,
298				 struct timespec64 *ts)
299{
300	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
301	u64 ns;
302
303	mv88e6xxx_reg_lock(chip);
304	ns = timecounter_read(&chip->tstamp_tc);
305	mv88e6xxx_reg_unlock(chip);
306
307	*ts = ns_to_timespec64(ns);
308
309	return 0;
310}
311
312static int mv88e6xxx_ptp_settime(struct ptp_clock_info *ptp,
313				 const struct timespec64 *ts)
314{
315	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
316	u64 ns;
317
318	ns = timespec64_to_ns(ts);
319
320	mv88e6xxx_reg_lock(chip);
321	timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc, ns);
322	mv88e6xxx_reg_unlock(chip);
323
324	return 0;
325}
326
327static int mv88e6352_ptp_enable_extts(struct mv88e6xxx_chip *chip,
328				      struct ptp_clock_request *rq, int on)
329{
330	int rising = (rq->extts.flags & PTP_RISING_EDGE);
331	int func;
332	int pin;
333	int err;
334
335	/* Reject requests with unsupported flags */
336	if (rq->extts.flags & ~(PTP_ENABLE_FEATURE |
337				PTP_RISING_EDGE |
338				PTP_FALLING_EDGE |
339				PTP_STRICT_FLAGS))
340		return -EOPNOTSUPP;
341
342	/* Reject requests to enable time stamping on both edges. */
343	if ((rq->extts.flags & PTP_STRICT_FLAGS) &&
344	    (rq->extts.flags & PTP_ENABLE_FEATURE) &&
345	    (rq->extts.flags & PTP_EXTTS_EDGES) == PTP_EXTTS_EDGES)
346		return -EOPNOTSUPP;
347
348	pin = ptp_find_pin(chip->ptp_clock, PTP_PF_EXTTS, rq->extts.index);
349
350	if (pin < 0)
351		return -EBUSY;
352
353	mv88e6xxx_reg_lock(chip);
354
355	if (on) {
356		func = MV88E6352_G2_SCRATCH_GPIO_PCTL_EVREQ;
357
358		err = mv88e6352_set_gpio_func(chip, pin, func, true);
359		if (err)
360			goto out;
361
362		schedule_delayed_work(&chip->tai_event_work,
363				      TAI_EVENT_WORK_INTERVAL);
364
365		err = mv88e6352_config_eventcap(chip, PTP_CLOCK_EXTTS, rising);
366	} else {
367		func = MV88E6352_G2_SCRATCH_GPIO_PCTL_GPIO;
368
369		err = mv88e6352_set_gpio_func(chip, pin, func, true);
370
371		cancel_delayed_work_sync(&chip->tai_event_work);
372	}
373
374out:
375	mv88e6xxx_reg_unlock(chip);
376
377	return err;
378}
379
380static int mv88e6352_ptp_enable(struct ptp_clock_info *ptp,
381				struct ptp_clock_request *rq, int on)
382{
383	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
384
385	switch (rq->type) {
386	case PTP_CLK_REQ_EXTTS:
387		return mv88e6352_ptp_enable_extts(chip, rq, on);
388	default:
389		return -EOPNOTSUPP;
390	}
391}
392
393static int mv88e6352_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
394				enum ptp_pin_function func, unsigned int chan)
395{
396	switch (func) {
397	case PTP_PF_NONE:
398	case PTP_PF_EXTTS:
399		break;
400	case PTP_PF_PEROUT:
401	case PTP_PF_PHYSYNC:
402		return -EOPNOTSUPP;
403	}
404	return 0;
405}
406
407const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
408	.clock_read = mv88e6165_ptp_clock_read,
409	.global_enable = mv88e6165_global_enable,
410	.global_disable = mv88e6165_global_disable,
411	.arr0_sts_reg = MV88E6165_PORT_PTP_ARR0_STS,
412	.arr1_sts_reg = MV88E6165_PORT_PTP_ARR1_STS,
413	.dep_sts_reg = MV88E6165_PORT_PTP_DEP_STS,
414	.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
415		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
416		(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
417		(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
418		(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
419		(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
420		(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
 
 
 
 
421};
422
423const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
424	.clock_read = mv88e6352_ptp_clock_read,
425	.ptp_enable = mv88e6352_ptp_enable,
426	.ptp_verify = mv88e6352_ptp_verify,
427	.event_work = mv88e6352_tai_event_work,
428	.port_enable = mv88e6352_hwtstamp_port_enable,
429	.port_disable = mv88e6352_hwtstamp_port_disable,
430	.n_ext_ts = 1,
431	.arr0_sts_reg = MV88E6XXX_PORT_PTP_ARR0_STS,
432	.arr1_sts_reg = MV88E6XXX_PORT_PTP_ARR1_STS,
433	.dep_sts_reg = MV88E6XXX_PORT_PTP_DEP_STS,
434	.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
435		(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
436		(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
437		(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
438		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
439		(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
440		(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
441		(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
442		(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
443		(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
 
 
 
 
444};
445
446const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
447	.clock_read = mv88e6352_ptp_clock_read,
448	.ptp_enable = mv88e6352_ptp_enable,
449	.ptp_verify = mv88e6352_ptp_verify,
450	.event_work = mv88e6352_tai_event_work,
451	.port_enable = mv88e6352_hwtstamp_port_enable,
452	.port_disable = mv88e6352_hwtstamp_port_disable,
453	.n_ext_ts = 1,
454	.arr0_sts_reg = MV88E6XXX_PORT_PTP_ARR0_STS,
455	.arr1_sts_reg = MV88E6XXX_PORT_PTP_ARR1_STS,
456	.dep_sts_reg = MV88E6XXX_PORT_PTP_DEP_STS,
457	.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
458		(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
459		(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
460		(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
461		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
462		(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
463		(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
464		(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
465		(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
466		(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
467};
468
469const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
470	.clock_read = mv88e6352_ptp_clock_read,
471	.ptp_enable = mv88e6352_ptp_enable,
472	.ptp_verify = mv88e6352_ptp_verify,
473	.event_work = mv88e6352_tai_event_work,
474	.port_enable = mv88e6352_hwtstamp_port_enable,
475	.port_disable = mv88e6352_hwtstamp_port_disable,
476	.set_ptp_cpu_port = mv88e6390_g1_set_ptp_cpu_port,
477	.n_ext_ts = 1,
478	.arr0_sts_reg = MV88E6XXX_PORT_PTP_ARR0_STS,
479	.arr1_sts_reg = MV88E6XXX_PORT_PTP_ARR1_STS,
480	.dep_sts_reg = MV88E6XXX_PORT_PTP_DEP_STS,
481	.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
482		(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
483		(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
484		(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
485		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
486		(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
487		(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
488		(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
489		(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
490		(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
491};
492
493static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
494{
495	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
496
497	if (chip->info->ops->ptp_ops->clock_read)
498		return chip->info->ops->ptp_ops->clock_read(cc);
499
500	return 0;
501}
502
503/* With a 250MHz input clock, the 32-bit timestamp counter overflows in ~17.2
504 * seconds; this task forces periodic reads so that we don't miss any.
505 */
506#define MV88E6XXX_TAI_OVERFLOW_PERIOD (HZ * 8)
507static void mv88e6xxx_ptp_overflow_check(struct work_struct *work)
508{
509	struct delayed_work *dw = to_delayed_work(work);
510	struct mv88e6xxx_chip *chip = dw_overflow_to_chip(dw);
511	struct timespec64 ts;
512
513	mv88e6xxx_ptp_gettime(&chip->ptp_clock_info, &ts);
514
515	schedule_delayed_work(&chip->overflow_work,
516			      MV88E6XXX_TAI_OVERFLOW_PERIOD);
517}
518
519int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
520{
521	const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
522	int i;
523
524	/* Set up the cycle counter */
525	chip->cc_coeffs = mv88e6xxx_cc_coeff_get(chip);
526	if (IS_ERR(chip->cc_coeffs))
527		return PTR_ERR(chip->cc_coeffs);
528
529	memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc));
530	chip->tstamp_cc.read	= mv88e6xxx_ptp_clock_read;
531	chip->tstamp_cc.mask	= CYCLECOUNTER_MASK(32);
532	chip->tstamp_cc.mult	= chip->cc_coeffs->cc_mult;
533	chip->tstamp_cc.shift	= chip->cc_coeffs->cc_shift;
534
535	timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
536			 ktime_to_ns(ktime_get_real()));
537
538	INIT_DELAYED_WORK(&chip->overflow_work, mv88e6xxx_ptp_overflow_check);
539	if (ptp_ops->event_work)
540		INIT_DELAYED_WORK(&chip->tai_event_work, ptp_ops->event_work);
541
542	chip->ptp_clock_info.owner = THIS_MODULE;
543	snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
544		 "%s", dev_name(chip->dev));
545
546	chip->ptp_clock_info.n_ext_ts	= ptp_ops->n_ext_ts;
547	chip->ptp_clock_info.n_per_out	= 0;
548	chip->ptp_clock_info.n_pins	= mv88e6xxx_num_gpio(chip);
549	chip->ptp_clock_info.pps	= 0;
550
551	for (i = 0; i < chip->ptp_clock_info.n_pins; ++i) {
552		struct ptp_pin_desc *ppd = &chip->pin_config[i];
553
554		snprintf(ppd->name, sizeof(ppd->name), "mv88e6xxx_gpio%d", i);
555		ppd->index = i;
556		ppd->func = PTP_PF_NONE;
557	}
558	chip->ptp_clock_info.pin_config = chip->pin_config;
559
560	chip->ptp_clock_info.max_adj    = MV88E6XXX_MAX_ADJ_PPB;
561	chip->ptp_clock_info.adjfine	= mv88e6xxx_ptp_adjfine;
562	chip->ptp_clock_info.adjtime	= mv88e6xxx_ptp_adjtime;
563	chip->ptp_clock_info.gettime64	= mv88e6xxx_ptp_gettime;
564	chip->ptp_clock_info.settime64	= mv88e6xxx_ptp_settime;
565	chip->ptp_clock_info.enable	= ptp_ops->ptp_enable;
566	chip->ptp_clock_info.verify	= ptp_ops->ptp_verify;
567	chip->ptp_clock_info.do_aux_work = mv88e6xxx_hwtstamp_work;
568
569	if (ptp_ops->set_ptp_cpu_port) {
570		struct dsa_port *dp;
571		int upstream = 0;
572		int err;
573
574		dsa_switch_for_each_user_port(dp, chip->ds) {
575			upstream = dsa_upstream_port(chip->ds, dp->index);
576			break;
577		}
578
579		err = ptp_ops->set_ptp_cpu_port(chip, upstream);
580		if (err) {
581			dev_err(chip->dev, "Failed to set PTP CPU destination port!\n");
582			return err;
583		}
584	}
585
586	chip->ptp_clock = ptp_clock_register(&chip->ptp_clock_info, chip->dev);
587	if (IS_ERR(chip->ptp_clock))
588		return PTR_ERR(chip->ptp_clock);
589
590	schedule_delayed_work(&chip->overflow_work,
591			      MV88E6XXX_TAI_OVERFLOW_PERIOD);
592
593	return 0;
594}
595
596void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
597{
598	if (chip->ptp_clock) {
599		cancel_delayed_work_sync(&chip->overflow_work);
600		if (chip->info->ops->ptp_ops->event_work)
601			cancel_delayed_work_sync(&chip->tai_event_work);
602
603		ptp_clock_unregister(chip->ptp_clock);
604		chip->ptp_clock = NULL;
605	}
606}
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Marvell 88E6xxx Switch PTP support
  4 *
  5 * Copyright (c) 2008 Marvell Semiconductor
  6 *
  7 * Copyright (c) 2017 National Instruments
  8 *      Erik Hons <erik.hons@ni.com>
  9 *      Brandon Streiff <brandon.streiff@ni.com>
 10 *      Dane Wagner <dane.wagner@ni.com>
 11 */
 12
 13#include "chip.h"
 
 14#include "global2.h"
 15#include "hwtstamp.h"
 16#include "ptp.h"
 17
 18#define MV88E6XXX_MAX_ADJ_PPB	1000000
 19
 
 
 
 
 
 
 
 20/* Family MV88E6250:
 21 * Raw timestamps are in units of 10-ns clock periods.
 22 *
 23 * clkadj = scaled_ppm * 10*2^28 / (10^6 * 2^16)
 24 * simplifies to
 25 * clkadj = scaled_ppm * 2^7 / 5^5
 26 */
 27#define MV88E6250_CC_SHIFT	28
 28#define MV88E6250_CC_MULT	(10 << MV88E6250_CC_SHIFT)
 29#define MV88E6250_CC_MULT_NUM	(1 << 7)
 30#define MV88E6250_CC_MULT_DEM	3125ULL
 
 
 
 31
 32/* Other families:
 33 * Raw timestamps are in units of 8-ns clock periods.
 34 *
 35 * clkadj = scaled_ppm * 8*2^28 / (10^6 * 2^16)
 36 * simplifies to
 37 * clkadj = scaled_ppm * 2^9 / 5^6
 38 */
 39#define MV88E6XXX_CC_SHIFT	28
 40#define MV88E6XXX_CC_MULT	(8 << MV88E6XXX_CC_SHIFT)
 41#define MV88E6XXX_CC_MULT_NUM	(1 << 9)
 42#define MV88E6XXX_CC_MULT_DEM	15625ULL
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 43
 44#define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100)
 45
 46#define cc_to_chip(cc) container_of(cc, struct mv88e6xxx_chip, tstamp_cc)
 47#define dw_overflow_to_chip(dw) container_of(dw, struct mv88e6xxx_chip, \
 48					     overflow_work)
 49#define dw_tai_event_to_chip(dw) container_of(dw, struct mv88e6xxx_chip, \
 50					      tai_event_work)
 51
 52static int mv88e6xxx_tai_read(struct mv88e6xxx_chip *chip, int addr,
 53			      u16 *data, int len)
 54{
 55	if (!chip->info->ops->avb_ops->tai_read)
 56		return -EOPNOTSUPP;
 57
 58	return chip->info->ops->avb_ops->tai_read(chip, addr, data, len);
 59}
 60
 61static int mv88e6xxx_tai_write(struct mv88e6xxx_chip *chip, int addr, u16 data)
 62{
 63	if (!chip->info->ops->avb_ops->tai_write)
 64		return -EOPNOTSUPP;
 65
 66	return chip->info->ops->avb_ops->tai_write(chip, addr, data);
 67}
 68
 69/* TODO: places where this are called should be using pinctrl */
 70static int mv88e6352_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
 71				   int func, int input)
 72{
 73	int err;
 74
 75	if (!chip->info->ops->gpio_ops)
 76		return -EOPNOTSUPP;
 77
 78	err = chip->info->ops->gpio_ops->set_dir(chip, pin, input);
 79	if (err)
 80		return err;
 81
 82	return chip->info->ops->gpio_ops->set_pctl(chip, pin, func);
 83}
 84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 85static u64 mv88e6352_ptp_clock_read(const struct cyclecounter *cc)
 86{
 87	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
 88	u16 phc_time[2];
 89	int err;
 90
 91	err = mv88e6xxx_tai_read(chip, MV88E6XXX_TAI_TIME_LO, phc_time,
 92				 ARRAY_SIZE(phc_time));
 93	if (err)
 94		return 0;
 95	else
 96		return ((u32)phc_time[1] << 16) | phc_time[0];
 97}
 98
 99static u64 mv88e6165_ptp_clock_read(const struct cyclecounter *cc)
100{
101	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
102	u16 phc_time[2];
103	int err;
104
105	err = mv88e6xxx_tai_read(chip, MV88E6XXX_PTP_GC_TIME_LO, phc_time,
106				 ARRAY_SIZE(phc_time));
107	if (err)
108		return 0;
109	else
110		return ((u32)phc_time[1] << 16) | phc_time[0];
111}
112
113/* mv88e6352_config_eventcap - configure TAI event capture
114 * @event: PTP_CLOCK_PPS (internal) or PTP_CLOCK_EXTTS (external)
115 * @rising: zero for falling-edge trigger, else rising-edge trigger
116 *
117 * This will also reset the capture sequence counter.
118 */
119static int mv88e6352_config_eventcap(struct mv88e6xxx_chip *chip, int event,
120				     int rising)
121{
122	u16 global_config;
123	u16 cap_config;
124	int err;
125
126	chip->evcap_config = MV88E6XXX_TAI_CFG_CAP_OVERWRITE |
127			     MV88E6XXX_TAI_CFG_CAP_CTR_START;
128	if (!rising)
129		chip->evcap_config |= MV88E6XXX_TAI_CFG_EVREQ_FALLING;
130
131	global_config = (chip->evcap_config | chip->trig_config);
132	err = mv88e6xxx_tai_write(chip, MV88E6XXX_TAI_CFG, global_config);
133	if (err)
134		return err;
135
136	if (event == PTP_CLOCK_PPS) {
137		cap_config = MV88E6XXX_TAI_EVENT_STATUS_CAP_TRIG;
138	} else if (event == PTP_CLOCK_EXTTS) {
139		/* if STATUS_CAP_TRIG is unset we capture PTP_EVREQ events */
140		cap_config = 0;
141	} else {
142		return -EINVAL;
143	}
144
145	/* Write the capture config; this also clears the capture counter */
146	err = mv88e6xxx_tai_write(chip, MV88E6XXX_TAI_EVENT_STATUS,
147				  cap_config);
148
149	return err;
150}
151
152static void mv88e6352_tai_event_work(struct work_struct *ugly)
153{
154	struct delayed_work *dw = to_delayed_work(ugly);
155	struct mv88e6xxx_chip *chip = dw_tai_event_to_chip(dw);
156	struct ptp_clock_event ev;
157	u16 status[4];
158	u32 raw_ts;
159	int err;
160
161	mv88e6xxx_reg_lock(chip);
162	err = mv88e6xxx_tai_read(chip, MV88E6XXX_TAI_EVENT_STATUS,
163				 status, ARRAY_SIZE(status));
164	mv88e6xxx_reg_unlock(chip);
165
166	if (err) {
167		dev_err(chip->dev, "failed to read TAI status register\n");
168		return;
169	}
170	if (status[0] & MV88E6XXX_TAI_EVENT_STATUS_ERROR) {
171		dev_warn(chip->dev, "missed event capture\n");
172		return;
173	}
174	if (!(status[0] & MV88E6XXX_TAI_EVENT_STATUS_VALID))
175		goto out;
176
177	raw_ts = ((u32)status[2] << 16) | status[1];
178
179	/* Clear the valid bit so the next timestamp can come in */
180	status[0] &= ~MV88E6XXX_TAI_EVENT_STATUS_VALID;
181	mv88e6xxx_reg_lock(chip);
182	err = mv88e6xxx_tai_write(chip, MV88E6XXX_TAI_EVENT_STATUS, status[0]);
183	mv88e6xxx_reg_unlock(chip);
 
 
 
 
184
185	/* This is an external timestamp */
186	ev.type = PTP_CLOCK_EXTTS;
187
188	/* We only have one timestamping channel. */
189	ev.index = 0;
190	mv88e6xxx_reg_lock(chip);
191	ev.timestamp = timecounter_cyc2time(&chip->tstamp_tc, raw_ts);
192	mv88e6xxx_reg_unlock(chip);
193
194	ptp_clock_event(chip->ptp_clock, &ev);
195out:
196	schedule_delayed_work(&chip->tai_event_work, TAI_EVENT_WORK_INTERVAL);
197}
198
199static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
200{
201	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
202	const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
203	int neg_adj = 0;
204	u32 diff, mult;
205	u64 adj;
206
207	if (scaled_ppm < 0) {
208		neg_adj = 1;
209		scaled_ppm = -scaled_ppm;
210	}
211
212	mult = ptp_ops->cc_mult;
213	adj = ptp_ops->cc_mult_num;
214	adj *= scaled_ppm;
215	diff = div_u64(adj, ptp_ops->cc_mult_dem);
216
217	mv88e6xxx_reg_lock(chip);
218
219	timecounter_read(&chip->tstamp_tc);
220	chip->tstamp_cc.mult = neg_adj ? mult - diff : mult + diff;
221
222	mv88e6xxx_reg_unlock(chip);
223
224	return 0;
225}
226
227static int mv88e6xxx_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
228{
229	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
230
231	mv88e6xxx_reg_lock(chip);
232	timecounter_adjtime(&chip->tstamp_tc, delta);
233	mv88e6xxx_reg_unlock(chip);
234
235	return 0;
236}
237
238static int mv88e6xxx_ptp_gettime(struct ptp_clock_info *ptp,
239				 struct timespec64 *ts)
240{
241	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
242	u64 ns;
243
244	mv88e6xxx_reg_lock(chip);
245	ns = timecounter_read(&chip->tstamp_tc);
246	mv88e6xxx_reg_unlock(chip);
247
248	*ts = ns_to_timespec64(ns);
249
250	return 0;
251}
252
253static int mv88e6xxx_ptp_settime(struct ptp_clock_info *ptp,
254				 const struct timespec64 *ts)
255{
256	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
257	u64 ns;
258
259	ns = timespec64_to_ns(ts);
260
261	mv88e6xxx_reg_lock(chip);
262	timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc, ns);
263	mv88e6xxx_reg_unlock(chip);
264
265	return 0;
266}
267
268static int mv88e6352_ptp_enable_extts(struct mv88e6xxx_chip *chip,
269				      struct ptp_clock_request *rq, int on)
270{
271	int rising = (rq->extts.flags & PTP_RISING_EDGE);
272	int func;
273	int pin;
274	int err;
275
276	/* Reject requests with unsupported flags */
277	if (rq->extts.flags & ~(PTP_ENABLE_FEATURE |
278				PTP_RISING_EDGE |
279				PTP_FALLING_EDGE |
280				PTP_STRICT_FLAGS))
281		return -EOPNOTSUPP;
282
283	/* Reject requests to enable time stamping on both edges. */
284	if ((rq->extts.flags & PTP_STRICT_FLAGS) &&
285	    (rq->extts.flags & PTP_ENABLE_FEATURE) &&
286	    (rq->extts.flags & PTP_EXTTS_EDGES) == PTP_EXTTS_EDGES)
287		return -EOPNOTSUPP;
288
289	pin = ptp_find_pin(chip->ptp_clock, PTP_PF_EXTTS, rq->extts.index);
290
291	if (pin < 0)
292		return -EBUSY;
293
294	mv88e6xxx_reg_lock(chip);
295
296	if (on) {
297		func = MV88E6352_G2_SCRATCH_GPIO_PCTL_EVREQ;
298
299		err = mv88e6352_set_gpio_func(chip, pin, func, true);
300		if (err)
301			goto out;
302
303		schedule_delayed_work(&chip->tai_event_work,
304				      TAI_EVENT_WORK_INTERVAL);
305
306		err = mv88e6352_config_eventcap(chip, PTP_CLOCK_EXTTS, rising);
307	} else {
308		func = MV88E6352_G2_SCRATCH_GPIO_PCTL_GPIO;
309
310		err = mv88e6352_set_gpio_func(chip, pin, func, true);
311
312		cancel_delayed_work_sync(&chip->tai_event_work);
313	}
314
315out:
316	mv88e6xxx_reg_unlock(chip);
317
318	return err;
319}
320
321static int mv88e6352_ptp_enable(struct ptp_clock_info *ptp,
322				struct ptp_clock_request *rq, int on)
323{
324	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
325
326	switch (rq->type) {
327	case PTP_CLK_REQ_EXTTS:
328		return mv88e6352_ptp_enable_extts(chip, rq, on);
329	default:
330		return -EOPNOTSUPP;
331	}
332}
333
334static int mv88e6352_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
335				enum ptp_pin_function func, unsigned int chan)
336{
337	switch (func) {
338	case PTP_PF_NONE:
339	case PTP_PF_EXTTS:
340		break;
341	case PTP_PF_PEROUT:
342	case PTP_PF_PHYSYNC:
343		return -EOPNOTSUPP;
344	}
345	return 0;
346}
347
348const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
349	.clock_read = mv88e6165_ptp_clock_read,
350	.global_enable = mv88e6165_global_enable,
351	.global_disable = mv88e6165_global_disable,
352	.arr0_sts_reg = MV88E6165_PORT_PTP_ARR0_STS,
353	.arr1_sts_reg = MV88E6165_PORT_PTP_ARR1_STS,
354	.dep_sts_reg = MV88E6165_PORT_PTP_DEP_STS,
355	.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
356		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
357		(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
358		(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
359		(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
360		(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
361		(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
362	.cc_shift = MV88E6XXX_CC_SHIFT,
363	.cc_mult = MV88E6XXX_CC_MULT,
364	.cc_mult_num = MV88E6XXX_CC_MULT_NUM,
365	.cc_mult_dem = MV88E6XXX_CC_MULT_DEM,
366};
367
368const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
369	.clock_read = mv88e6352_ptp_clock_read,
370	.ptp_enable = mv88e6352_ptp_enable,
371	.ptp_verify = mv88e6352_ptp_verify,
372	.event_work = mv88e6352_tai_event_work,
373	.port_enable = mv88e6352_hwtstamp_port_enable,
374	.port_disable = mv88e6352_hwtstamp_port_disable,
375	.n_ext_ts = 1,
376	.arr0_sts_reg = MV88E6XXX_PORT_PTP_ARR0_STS,
377	.arr1_sts_reg = MV88E6XXX_PORT_PTP_ARR1_STS,
378	.dep_sts_reg = MV88E6XXX_PORT_PTP_DEP_STS,
379	.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
380		(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
381		(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
382		(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
383		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
384		(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
385		(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
386		(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
387		(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
388		(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
389	.cc_shift = MV88E6250_CC_SHIFT,
390	.cc_mult = MV88E6250_CC_MULT,
391	.cc_mult_num = MV88E6250_CC_MULT_NUM,
392	.cc_mult_dem = MV88E6250_CC_MULT_DEM,
393};
394
395const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
396	.clock_read = mv88e6352_ptp_clock_read,
397	.ptp_enable = mv88e6352_ptp_enable,
398	.ptp_verify = mv88e6352_ptp_verify,
399	.event_work = mv88e6352_tai_event_work,
400	.port_enable = mv88e6352_hwtstamp_port_enable,
401	.port_disable = mv88e6352_hwtstamp_port_disable,
402	.n_ext_ts = 1,
403	.arr0_sts_reg = MV88E6XXX_PORT_PTP_ARR0_STS,
404	.arr1_sts_reg = MV88E6XXX_PORT_PTP_ARR1_STS,
405	.dep_sts_reg = MV88E6XXX_PORT_PTP_DEP_STS,
406	.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
407		(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
408		(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
409		(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
410		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
411		(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
412		(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
413		(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
414		(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
415		(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
416	.cc_shift = MV88E6XXX_CC_SHIFT,
417	.cc_mult = MV88E6XXX_CC_MULT,
418	.cc_mult_num = MV88E6XXX_CC_MULT_NUM,
419	.cc_mult_dem = MV88E6XXX_CC_MULT_DEM,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420};
421
422static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
423{
424	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
425
426	if (chip->info->ops->ptp_ops->clock_read)
427		return chip->info->ops->ptp_ops->clock_read(cc);
428
429	return 0;
430}
431
432/* With a 125MHz input clock, the 32-bit timestamp counter overflows in ~34.3
433 * seconds; this task forces periodic reads so that we don't miss any.
434 */
435#define MV88E6XXX_TAI_OVERFLOW_PERIOD (HZ * 16)
436static void mv88e6xxx_ptp_overflow_check(struct work_struct *work)
437{
438	struct delayed_work *dw = to_delayed_work(work);
439	struct mv88e6xxx_chip *chip = dw_overflow_to_chip(dw);
440	struct timespec64 ts;
441
442	mv88e6xxx_ptp_gettime(&chip->ptp_clock_info, &ts);
443
444	schedule_delayed_work(&chip->overflow_work,
445			      MV88E6XXX_TAI_OVERFLOW_PERIOD);
446}
447
448int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
449{
450	const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
451	int i;
452
453	/* Set up the cycle counter */
 
 
 
 
454	memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc));
455	chip->tstamp_cc.read	= mv88e6xxx_ptp_clock_read;
456	chip->tstamp_cc.mask	= CYCLECOUNTER_MASK(32);
457	chip->tstamp_cc.mult	= ptp_ops->cc_mult;
458	chip->tstamp_cc.shift	= ptp_ops->cc_shift;
459
460	timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
461			 ktime_to_ns(ktime_get_real()));
462
463	INIT_DELAYED_WORK(&chip->overflow_work, mv88e6xxx_ptp_overflow_check);
464	if (ptp_ops->event_work)
465		INIT_DELAYED_WORK(&chip->tai_event_work, ptp_ops->event_work);
466
467	chip->ptp_clock_info.owner = THIS_MODULE;
468	snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
469		 "%s", dev_name(chip->dev));
470
471	chip->ptp_clock_info.n_ext_ts	= ptp_ops->n_ext_ts;
472	chip->ptp_clock_info.n_per_out	= 0;
473	chip->ptp_clock_info.n_pins	= mv88e6xxx_num_gpio(chip);
474	chip->ptp_clock_info.pps	= 0;
475
476	for (i = 0; i < chip->ptp_clock_info.n_pins; ++i) {
477		struct ptp_pin_desc *ppd = &chip->pin_config[i];
478
479		snprintf(ppd->name, sizeof(ppd->name), "mv88e6xxx_gpio%d", i);
480		ppd->index = i;
481		ppd->func = PTP_PF_NONE;
482	}
483	chip->ptp_clock_info.pin_config = chip->pin_config;
484
485	chip->ptp_clock_info.max_adj    = MV88E6XXX_MAX_ADJ_PPB;
486	chip->ptp_clock_info.adjfine	= mv88e6xxx_ptp_adjfine;
487	chip->ptp_clock_info.adjtime	= mv88e6xxx_ptp_adjtime;
488	chip->ptp_clock_info.gettime64	= mv88e6xxx_ptp_gettime;
489	chip->ptp_clock_info.settime64	= mv88e6xxx_ptp_settime;
490	chip->ptp_clock_info.enable	= ptp_ops->ptp_enable;
491	chip->ptp_clock_info.verify	= ptp_ops->ptp_verify;
492	chip->ptp_clock_info.do_aux_work = mv88e6xxx_hwtstamp_work;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
493
494	chip->ptp_clock = ptp_clock_register(&chip->ptp_clock_info, chip->dev);
495	if (IS_ERR(chip->ptp_clock))
496		return PTR_ERR(chip->ptp_clock);
497
498	schedule_delayed_work(&chip->overflow_work,
499			      MV88E6XXX_TAI_OVERFLOW_PERIOD);
500
501	return 0;
502}
503
504void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
505{
506	if (chip->ptp_clock) {
507		cancel_delayed_work_sync(&chip->overflow_work);
508		if (chip->info->ops->ptp_ops->event_work)
509			cancel_delayed_work_sync(&chip->tai_event_work);
510
511		ptp_clock_unregister(chip->ptp_clock);
512		chip->ptp_clock = NULL;
513	}
514}