Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.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 "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}