xref: /openbmc/linux/drivers/ptp/ptp_idt82p33.c (revision e156e4d2)
157a10d8cSMin Li // SPDX-License-Identifier: GPL-2.0
257a10d8cSMin Li //
357a10d8cSMin Li // Copyright (C) 2018 Integrated Device Technology, Inc
457a10d8cSMin Li //
557a10d8cSMin Li 
657a10d8cSMin Li #define pr_fmt(fmt) "IDT_82p33xxx: " fmt
757a10d8cSMin Li 
857a10d8cSMin Li #include <linux/firmware.h>
9013a3e7cSMin Li #include <linux/platform_device.h>
1057a10d8cSMin Li #include <linux/module.h>
1157a10d8cSMin Li #include <linux/ptp_clock_kernel.h>
1257a10d8cSMin Li #include <linux/delay.h>
13013a3e7cSMin Li #include <linux/jiffies.h>
1457a10d8cSMin Li #include <linux/kernel.h>
1557a10d8cSMin Li #include <linux/timekeeping.h>
1657a10d8cSMin Li #include <linux/bitops.h>
17013a3e7cSMin Li #include <linux/of.h>
18013a3e7cSMin Li #include <linux/mfd/rsmu.h>
19013a3e7cSMin Li #include <linux/mfd/idt82p33_reg.h>
2057a10d8cSMin Li 
2157a10d8cSMin Li #include "ptp_private.h"
2257a10d8cSMin Li #include "ptp_idt82p33.h"
2357a10d8cSMin Li 
2457a10d8cSMin Li MODULE_DESCRIPTION("Driver for IDT 82p33xxx clock devices");
2557a10d8cSMin Li MODULE_AUTHOR("IDT support-1588 <IDT-support-1588@lm.renesas.com>");
2657a10d8cSMin Li MODULE_VERSION("1.0");
2757a10d8cSMin Li MODULE_LICENSE("GPL");
28e014ae39SMin Li MODULE_FIRMWARE(FW_FILENAME);
2957a10d8cSMin Li 
30ad3cc776SMin Li #define EXTTS_PERIOD_MS (95)
31ad3cc776SMin Li 
3257a10d8cSMin Li /* Module Parameters */
33d30e1c3dSYueHaibing static u32 phase_snap_threshold = SNAP_THRESHOLD_NS;
3457a10d8cSMin Li module_param(phase_snap_threshold, uint, 0);
3557a10d8cSMin Li MODULE_PARM_DESC(phase_snap_threshold,
36013a3e7cSMin Li "threshold (10000ns by default) below which adjtime would use double dco");
37013a3e7cSMin Li 
38013a3e7cSMin Li static char *firmware;
39013a3e7cSMin Li module_param(firmware, charp, 0);
40013a3e7cSMin Li 
41ad3cc776SMin Li static struct ptp_pin_desc pin_config[MAX_PHC_PLL][MAX_TRIG_CLK];
42ad3cc776SMin Li 
idt82p33_read(struct idt82p33 * idt82p33,u16 regaddr,u8 * buf,u16 count)43013a3e7cSMin Li static inline int idt82p33_read(struct idt82p33 *idt82p33, u16 regaddr,
44013a3e7cSMin Li 				u8 *buf, u16 count)
45013a3e7cSMin Li {
46013a3e7cSMin Li 	return regmap_bulk_read(idt82p33->regmap, regaddr, buf, count);
47013a3e7cSMin Li }
48013a3e7cSMin Li 
idt82p33_write(struct idt82p33 * idt82p33,u16 regaddr,u8 * buf,u16 count)49013a3e7cSMin Li static inline int idt82p33_write(struct idt82p33 *idt82p33, u16 regaddr,
50013a3e7cSMin Li 				 u8 *buf, u16 count)
51013a3e7cSMin Li {
52013a3e7cSMin Li 	return regmap_bulk_write(idt82p33->regmap, regaddr, buf, count);
53013a3e7cSMin Li }
5457a10d8cSMin Li 
idt82p33_byte_array_to_timespec(struct timespec64 * ts,u8 buf[TOD_BYTE_COUNT])5557a10d8cSMin Li static void idt82p33_byte_array_to_timespec(struct timespec64 *ts,
5657a10d8cSMin Li 					    u8 buf[TOD_BYTE_COUNT])
5757a10d8cSMin Li {
5857a10d8cSMin Li 	time64_t sec;
5957a10d8cSMin Li 	s32 nsec;
6057a10d8cSMin Li 	u8 i;
6157a10d8cSMin Li 
6257a10d8cSMin Li 	nsec = buf[3];
6357a10d8cSMin Li 	for (i = 0; i < 3; i++) {
6457a10d8cSMin Li 		nsec <<= 8;
6557a10d8cSMin Li 		nsec |= buf[2 - i];
6657a10d8cSMin Li 	}
6757a10d8cSMin Li 
6857a10d8cSMin Li 	sec = buf[9];
6957a10d8cSMin Li 	for (i = 0; i < 5; i++) {
7057a10d8cSMin Li 		sec <<= 8;
7157a10d8cSMin Li 		sec |= buf[8 - i];
7257a10d8cSMin Li 	}
7357a10d8cSMin Li 
7457a10d8cSMin Li 	ts->tv_sec = sec;
7557a10d8cSMin Li 	ts->tv_nsec = nsec;
7657a10d8cSMin Li }
7757a10d8cSMin Li 
idt82p33_timespec_to_byte_array(struct timespec64 const * ts,u8 buf[TOD_BYTE_COUNT])7857a10d8cSMin Li static void idt82p33_timespec_to_byte_array(struct timespec64 const *ts,
7957a10d8cSMin Li 					    u8 buf[TOD_BYTE_COUNT])
8057a10d8cSMin Li {
8157a10d8cSMin Li 	time64_t sec;
8257a10d8cSMin Li 	s32 nsec;
8357a10d8cSMin Li 	u8 i;
8457a10d8cSMin Li 
8557a10d8cSMin Li 	nsec = ts->tv_nsec;
8657a10d8cSMin Li 	sec = ts->tv_sec;
8757a10d8cSMin Li 
8857a10d8cSMin Li 	for (i = 0; i < 4; i++) {
8957a10d8cSMin Li 		buf[i] = nsec & 0xff;
9057a10d8cSMin Li 		nsec >>= 8;
9157a10d8cSMin Li 	}
9257a10d8cSMin Li 
9357a10d8cSMin Li 	for (i = 4; i < TOD_BYTE_COUNT; i++) {
9457a10d8cSMin Li 		buf[i] = sec & 0xff;
9557a10d8cSMin Li 		sec >>= 8;
9657a10d8cSMin Li 	}
9757a10d8cSMin Li }
9857a10d8cSMin Li 
idt82p33_dpll_set_mode(struct idt82p33_channel * channel,enum pll_mode mode)9957a10d8cSMin Li static int idt82p33_dpll_set_mode(struct idt82p33_channel *channel,
10057a10d8cSMin Li 				  enum pll_mode mode)
10157a10d8cSMin Li {
10257a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
10357a10d8cSMin Li 	u8 dpll_mode;
10457a10d8cSMin Li 	int err;
10557a10d8cSMin Li 
10657a10d8cSMin Li 	if (channel->pll_mode == mode)
10757a10d8cSMin Li 		return 0;
10857a10d8cSMin Li 
10957a10d8cSMin Li 	err = idt82p33_read(idt82p33, channel->dpll_mode_cnfg,
11057a10d8cSMin Li 			    &dpll_mode, sizeof(dpll_mode));
11157a10d8cSMin Li 	if (err)
11257a10d8cSMin Li 		return err;
11357a10d8cSMin Li 
11457a10d8cSMin Li 	dpll_mode &= ~(PLL_MODE_MASK << PLL_MODE_SHIFT);
11557a10d8cSMin Li 
11657a10d8cSMin Li 	dpll_mode |= (mode << PLL_MODE_SHIFT);
11757a10d8cSMin Li 
11857a10d8cSMin Li 	err = idt82p33_write(idt82p33, channel->dpll_mode_cnfg,
11957a10d8cSMin Li 			     &dpll_mode, sizeof(dpll_mode));
12057a10d8cSMin Li 	if (err)
12157a10d8cSMin Li 		return err;
12257a10d8cSMin Li 
123013a3e7cSMin Li 	channel->pll_mode = mode;
12457a10d8cSMin Li 
12557a10d8cSMin Li 	return 0;
12657a10d8cSMin Li }
12757a10d8cSMin Li 
idt82p33_set_tod_trigger(struct idt82p33_channel * channel,u8 trigger,bool write)128ad3cc776SMin Li static int idt82p33_set_tod_trigger(struct idt82p33_channel *channel,
129ad3cc776SMin Li 				    u8 trigger, bool write)
130ad3cc776SMin Li {
131ad3cc776SMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
132ad3cc776SMin Li 	int err;
133ad3cc776SMin Li 	u8 cfg;
134ad3cc776SMin Li 
135ad3cc776SMin Li 	if (trigger > WR_TRIG_SEL_MAX)
136ad3cc776SMin Li 		return -EINVAL;
137ad3cc776SMin Li 
138ad3cc776SMin Li 	err = idt82p33_read(idt82p33, channel->dpll_tod_trigger,
139ad3cc776SMin Li 			    &cfg, sizeof(cfg));
140ad3cc776SMin Li 
141ad3cc776SMin Li 	if (err)
142ad3cc776SMin Li 		return err;
143ad3cc776SMin Li 
144ad3cc776SMin Li 	if (write == true)
145ad3cc776SMin Li 		trigger = (trigger << WRITE_TRIGGER_SHIFT) |
146ad3cc776SMin Li 			  (cfg & READ_TRIGGER_MASK);
147ad3cc776SMin Li 	else
148ad3cc776SMin Li 		trigger = (trigger << READ_TRIGGER_SHIFT) |
149ad3cc776SMin Li 			  (cfg & WRITE_TRIGGER_MASK);
150ad3cc776SMin Li 
151ad3cc776SMin Li 	return idt82p33_write(idt82p33, channel->dpll_tod_trigger,
152ad3cc776SMin Li 			      &trigger, sizeof(trigger));
153ad3cc776SMin Li }
154ad3cc776SMin Li 
idt82p33_get_extts(struct idt82p33_channel * channel,struct timespec64 * ts)155ad3cc776SMin Li static int idt82p33_get_extts(struct idt82p33_channel *channel,
15657a10d8cSMin Li 			      struct timespec64 *ts)
15757a10d8cSMin Li {
15857a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
15957a10d8cSMin Li 	u8 buf[TOD_BYTE_COUNT];
16057a10d8cSMin Li 	int err;
16157a10d8cSMin Li 
162ad3cc776SMin Li 	err = idt82p33_read(idt82p33, channel->dpll_tod_sts, buf, sizeof(buf));
16357a10d8cSMin Li 
16457a10d8cSMin Li 	if (err)
16557a10d8cSMin Li 		return err;
16657a10d8cSMin Li 
167ad3cc776SMin Li 	/* Since trigger is not self clearing itself, we have to poll tod_sts */
168ad3cc776SMin Li 	if (memcmp(buf, channel->extts_tod_sts, TOD_BYTE_COUNT) == 0)
169ad3cc776SMin Li 		return -EAGAIN;
170ad3cc776SMin Li 
171ad3cc776SMin Li 	memcpy(channel->extts_tod_sts, buf, TOD_BYTE_COUNT);
172ad3cc776SMin Li 
173ad3cc776SMin Li 	idt82p33_byte_array_to_timespec(ts, buf);
174ad3cc776SMin Li 
175ad3cc776SMin Li 	if (channel->discard_next_extts) {
176ad3cc776SMin Li 		channel->discard_next_extts = false;
177ad3cc776SMin Li 		return -EAGAIN;
178ad3cc776SMin Li 	}
179ad3cc776SMin Li 
180ad3cc776SMin Li 	return 0;
181ad3cc776SMin Li }
182ad3cc776SMin Li 
map_ref_to_tod_trig_sel(int ref,u8 * trigger)183ad3cc776SMin Li static int map_ref_to_tod_trig_sel(int ref, u8 *trigger)
184ad3cc776SMin Li {
185ad3cc776SMin Li 	int err = 0;
186ad3cc776SMin Li 
187ad3cc776SMin Li 	switch (ref) {
188ad3cc776SMin Li 	case 0:
189ad3cc776SMin Li 		*trigger = HW_TOD_TRIG_SEL_IN12;
190ad3cc776SMin Li 		break;
191ad3cc776SMin Li 	case 1:
192ad3cc776SMin Li 		*trigger = HW_TOD_TRIG_SEL_IN13;
193ad3cc776SMin Li 		break;
194ad3cc776SMin Li 	case 2:
195ad3cc776SMin Li 		*trigger = HW_TOD_TRIG_SEL_IN14;
196ad3cc776SMin Li 		break;
197ad3cc776SMin Li 	default:
198ad3cc776SMin Li 		err = -EINVAL;
199ad3cc776SMin Li 	}
200ad3cc776SMin Li 
201ad3cc776SMin Li 	return err;
202ad3cc776SMin Li }
203ad3cc776SMin Li 
is_one_shot(u8 mask)204ad3cc776SMin Li static bool is_one_shot(u8 mask)
205ad3cc776SMin Li {
206ad3cc776SMin Li 	/* Treat single bit PLL masks as continuous trigger */
207ad3cc776SMin Li 	if ((mask == 1) || (mask == 2))
208ad3cc776SMin Li 		return false;
209ad3cc776SMin Li 	else
210ad3cc776SMin Li 		return true;
211ad3cc776SMin Li }
212ad3cc776SMin Li 
arm_tod_read_with_trigger(struct idt82p33_channel * channel,u8 trigger)213ad3cc776SMin Li static int arm_tod_read_with_trigger(struct idt82p33_channel *channel, u8 trigger)
214ad3cc776SMin Li {
215ad3cc776SMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
216ad3cc776SMin Li 	u8 buf[TOD_BYTE_COUNT];
217ad3cc776SMin Li 	int err;
218ad3cc776SMin Li 
219ad3cc776SMin Li 	/* Remember the current tod_sts before setting the trigger */
220ad3cc776SMin Li 	err = idt82p33_read(idt82p33, channel->dpll_tod_sts, buf, sizeof(buf));
221ad3cc776SMin Li 
222ad3cc776SMin Li 	if (err)
223ad3cc776SMin Li 		return err;
224ad3cc776SMin Li 
225ad3cc776SMin Li 	memcpy(channel->extts_tod_sts, buf, TOD_BYTE_COUNT);
226ad3cc776SMin Li 
227ad3cc776SMin Li 	err = idt82p33_set_tod_trigger(channel, trigger, false);
228ad3cc776SMin Li 
229ad3cc776SMin Li 	if (err)
230ad3cc776SMin Li 		dev_err(idt82p33->dev, "%s: err = %d", __func__, err);
231ad3cc776SMin Li 
232ad3cc776SMin Li 	return err;
233ad3cc776SMin Li }
234ad3cc776SMin Li 
idt82p33_extts_enable(struct idt82p33_channel * channel,struct ptp_clock_request * rq,int on)235ad3cc776SMin Li static int idt82p33_extts_enable(struct idt82p33_channel *channel,
236ad3cc776SMin Li 				 struct ptp_clock_request *rq, int on)
237ad3cc776SMin Li {
238ad3cc776SMin Li 	u8 index = rq->extts.index;
239ad3cc776SMin Li 	struct idt82p33 *idt82p33;
240ad3cc776SMin Li 	u8 mask = 1 << index;
241ad3cc776SMin Li 	int err = 0;
242ad3cc776SMin Li 	u8 old_mask;
243ad3cc776SMin Li 	u8 trigger;
244ad3cc776SMin Li 	int ref;
245ad3cc776SMin Li 
246ad3cc776SMin Li 	idt82p33  = channel->idt82p33;
247ad3cc776SMin Li 	old_mask = idt82p33->extts_mask;
248ad3cc776SMin Li 
249ad3cc776SMin Li 	/* Reject requests with unsupported flags */
250ad3cc776SMin Li 	if (rq->extts.flags & ~(PTP_ENABLE_FEATURE |
251ad3cc776SMin Li 				PTP_RISING_EDGE |
252ad3cc776SMin Li 				PTP_FALLING_EDGE |
253ad3cc776SMin Li 				PTP_STRICT_FLAGS))
254ad3cc776SMin Li 		return -EOPNOTSUPP;
255ad3cc776SMin Li 
256ad3cc776SMin Li 	/* Reject requests to enable time stamping on falling edge */
257ad3cc776SMin Li 	if ((rq->extts.flags & PTP_ENABLE_FEATURE) &&
258ad3cc776SMin Li 	    (rq->extts.flags & PTP_FALLING_EDGE))
259ad3cc776SMin Li 		return -EOPNOTSUPP;
260ad3cc776SMin Li 
261ad3cc776SMin Li 	if (index >= MAX_PHC_PLL)
262ad3cc776SMin Li 		return -EINVAL;
263ad3cc776SMin Li 
264ad3cc776SMin Li 	if (on) {
265ad3cc776SMin Li 		/* Return if it was already enabled */
266ad3cc776SMin Li 		if (idt82p33->extts_mask & mask)
267ad3cc776SMin Li 			return 0;
268ad3cc776SMin Li 
269ad3cc776SMin Li 		/* Use the pin configured for the channel */
270ad3cc776SMin Li 		ref = ptp_find_pin(channel->ptp_clock, PTP_PF_EXTTS, channel->plln);
271ad3cc776SMin Li 
272ad3cc776SMin Li 		if (ref < 0) {
273ad3cc776SMin Li 			dev_err(idt82p33->dev, "%s: No valid pin found for Pll%d!\n",
274ad3cc776SMin Li 				__func__, channel->plln);
275ad3cc776SMin Li 			return -EBUSY;
276ad3cc776SMin Li 		}
277ad3cc776SMin Li 
278ad3cc776SMin Li 		err = map_ref_to_tod_trig_sel(ref, &trigger);
279ad3cc776SMin Li 
280ad3cc776SMin Li 		if (err) {
281ad3cc776SMin Li 			dev_err(idt82p33->dev,
282ad3cc776SMin Li 				"%s: Unsupported ref %d!\n", __func__, ref);
283ad3cc776SMin Li 			return err;
284ad3cc776SMin Li 		}
285ad3cc776SMin Li 
286ad3cc776SMin Li 		err = arm_tod_read_with_trigger(&idt82p33->channel[index], trigger);
287ad3cc776SMin Li 
288ad3cc776SMin Li 		if (err == 0) {
289ad3cc776SMin Li 			idt82p33->extts_mask |= mask;
290ad3cc776SMin Li 			idt82p33->channel[index].tod_trigger = trigger;
291ad3cc776SMin Li 			idt82p33->event_channel[index] = channel;
292ad3cc776SMin Li 			idt82p33->extts_single_shot = is_one_shot(idt82p33->extts_mask);
293ad3cc776SMin Li 
294ad3cc776SMin Li 			if (old_mask)
295ad3cc776SMin Li 				return 0;
296ad3cc776SMin Li 
297ad3cc776SMin Li 			schedule_delayed_work(&idt82p33->extts_work,
298ad3cc776SMin Li 					      msecs_to_jiffies(EXTTS_PERIOD_MS));
299ad3cc776SMin Li 		}
300ad3cc776SMin Li 	} else {
301ad3cc776SMin Li 		idt82p33->extts_mask &= ~mask;
302ad3cc776SMin Li 		idt82p33->extts_single_shot = is_one_shot(idt82p33->extts_mask);
303ad3cc776SMin Li 
304ad3cc776SMin Li 		if (idt82p33->extts_mask == 0)
305ad3cc776SMin Li 			cancel_delayed_work(&idt82p33->extts_work);
306ad3cc776SMin Li 	}
307ad3cc776SMin Li 
308ad3cc776SMin Li 	return err;
309ad3cc776SMin Li }
310ad3cc776SMin Li 
idt82p33_extts_check_channel(struct idt82p33 * idt82p33,u8 todn)311ad3cc776SMin Li static int idt82p33_extts_check_channel(struct idt82p33 *idt82p33, u8 todn)
312ad3cc776SMin Li {
313ad3cc776SMin Li 	struct idt82p33_channel *event_channel;
314ad3cc776SMin Li 	struct ptp_clock_event event;
315ad3cc776SMin Li 	struct timespec64 ts;
316ad3cc776SMin Li 	int err;
317ad3cc776SMin Li 
318ad3cc776SMin Li 	err = idt82p33_get_extts(&idt82p33->channel[todn], &ts);
319ad3cc776SMin Li 	if (err == 0) {
320ad3cc776SMin Li 		event_channel = idt82p33->event_channel[todn];
321ad3cc776SMin Li 		event.type = PTP_CLOCK_EXTTS;
322ad3cc776SMin Li 		event.index = todn;
323ad3cc776SMin Li 		event.timestamp = timespec64_to_ns(&ts);
324ad3cc776SMin Li 		ptp_clock_event(event_channel->ptp_clock,
325ad3cc776SMin Li 				&event);
326ad3cc776SMin Li 	}
327ad3cc776SMin Li 	return err;
328ad3cc776SMin Li }
329ad3cc776SMin Li 
idt82p33_extts_enable_mask(struct idt82p33_channel * channel,u8 extts_mask,bool enable)330ad3cc776SMin Li static u8 idt82p33_extts_enable_mask(struct idt82p33_channel *channel,
331ad3cc776SMin Li 				     u8 extts_mask, bool enable)
332ad3cc776SMin Li {
333ad3cc776SMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
334ad3cc776SMin Li 	u8 trigger = channel->tod_trigger;
335ad3cc776SMin Li 	u8 mask;
336ad3cc776SMin Li 	int err;
337ad3cc776SMin Li 	int i;
338ad3cc776SMin Li 
339ad3cc776SMin Li 	if (extts_mask == 0)
340ad3cc776SMin Li 		return 0;
341ad3cc776SMin Li 
342ad3cc776SMin Li 	if (enable == false)
343ad3cc776SMin Li 		cancel_delayed_work_sync(&idt82p33->extts_work);
344ad3cc776SMin Li 
345ad3cc776SMin Li 	for (i = 0; i < MAX_PHC_PLL; i++) {
346ad3cc776SMin Li 		mask = 1 << i;
347ad3cc776SMin Li 
348ad3cc776SMin Li 		if ((extts_mask & mask) == 0)
349ad3cc776SMin Li 			continue;
350ad3cc776SMin Li 
351ad3cc776SMin Li 		if (enable) {
352ad3cc776SMin Li 			err = arm_tod_read_with_trigger(&idt82p33->channel[i], trigger);
353ad3cc776SMin Li 			if (err)
354ad3cc776SMin Li 				dev_err(idt82p33->dev,
355ad3cc776SMin Li 					"%s: Arm ToD read trigger failed, err = %d",
356ad3cc776SMin Li 					__func__, err);
357ad3cc776SMin Li 		} else {
358ad3cc776SMin Li 			err = idt82p33_extts_check_channel(idt82p33, i);
359ad3cc776SMin Li 			if (err == 0 && idt82p33->extts_single_shot)
360ad3cc776SMin Li 				/* trigger happened so we won't re-enable it */
361ad3cc776SMin Li 				extts_mask &= ~mask;
362ad3cc776SMin Li 		}
363ad3cc776SMin Li 	}
364ad3cc776SMin Li 
365ad3cc776SMin Li 	if (enable)
366ad3cc776SMin Li 		schedule_delayed_work(&idt82p33->extts_work,
367ad3cc776SMin Li 				      msecs_to_jiffies(EXTTS_PERIOD_MS));
368ad3cc776SMin Li 
369ad3cc776SMin Li 	return extts_mask;
370ad3cc776SMin Li }
371ad3cc776SMin Li 
_idt82p33_gettime(struct idt82p33_channel * channel,struct timespec64 * ts)372ad3cc776SMin Li static int _idt82p33_gettime(struct idt82p33_channel *channel,
373ad3cc776SMin Li 			     struct timespec64 *ts)
374ad3cc776SMin Li {
375ad3cc776SMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
376ad3cc776SMin Li 	u8 old_mask = idt82p33->extts_mask;
377ad3cc776SMin Li 	u8 buf[TOD_BYTE_COUNT];
378ad3cc776SMin Li 	u8 new_mask = 0;
379ad3cc776SMin Li 	int err;
380ad3cc776SMin Li 
381ad3cc776SMin Li 	/* Disable extts */
382ad3cc776SMin Li 	if (old_mask)
383ad3cc776SMin Li 		new_mask = idt82p33_extts_enable_mask(channel, old_mask, false);
384ad3cc776SMin Li 
385ad3cc776SMin Li 	err = idt82p33_set_tod_trigger(channel, HW_TOD_RD_TRIG_SEL_LSB_TOD_STS,
386ad3cc776SMin Li 				       false);
387ad3cc776SMin Li 	if (err)
388ad3cc776SMin Li 		return err;
389ad3cc776SMin Li 
390ad3cc776SMin Li 	channel->discard_next_extts = true;
391ad3cc776SMin Li 
39257a10d8cSMin Li 	if (idt82p33->calculate_overhead_flag)
39357a10d8cSMin Li 		idt82p33->start_time = ktime_get_raw();
39457a10d8cSMin Li 
39557a10d8cSMin Li 	err = idt82p33_read(idt82p33, channel->dpll_tod_sts, buf, sizeof(buf));
39657a10d8cSMin Li 
39757a10d8cSMin Li 	if (err)
39857a10d8cSMin Li 		return err;
39957a10d8cSMin Li 
400ad3cc776SMin Li 	/* Re-enable extts */
401ad3cc776SMin Li 	if (new_mask)
402ad3cc776SMin Li 		idt82p33_extts_enable_mask(channel, new_mask, true);
403ad3cc776SMin Li 
40457a10d8cSMin Li 	idt82p33_byte_array_to_timespec(ts, buf);
40557a10d8cSMin Li 
40657a10d8cSMin Li 	return 0;
40757a10d8cSMin Li }
40857a10d8cSMin Li 
40957a10d8cSMin Li /*
41057a10d8cSMin Li  *   TOD Trigger:
41157a10d8cSMin Li  *   Bits[7:4] Write 0x9, MSB write
41257a10d8cSMin Li  *   Bits[3:0] Read 0x9, LSB read
41357a10d8cSMin Li  */
41457a10d8cSMin Li 
_idt82p33_settime(struct idt82p33_channel * channel,struct timespec64 const * ts)41557a10d8cSMin Li static int _idt82p33_settime(struct idt82p33_channel *channel,
41657a10d8cSMin Li 			     struct timespec64 const *ts)
41757a10d8cSMin Li {
41857a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
41957a10d8cSMin Li 	struct timespec64 local_ts = *ts;
42057a10d8cSMin Li 	char buf[TOD_BYTE_COUNT];
42157a10d8cSMin Li 	s64 dynamic_overhead_ns;
42257a10d8cSMin Li 	int err;
42357a10d8cSMin Li 	u8 i;
42457a10d8cSMin Li 
425ad3cc776SMin Li 	err = idt82p33_set_tod_trigger(channel, HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
426ad3cc776SMin Li 				       true);
42757a10d8cSMin Li 	if (err)
42857a10d8cSMin Li 		return err;
42957a10d8cSMin Li 
430ad3cc776SMin Li 	channel->discard_next_extts = true;
431ad3cc776SMin Li 
43257a10d8cSMin Li 	if (idt82p33->calculate_overhead_flag) {
43357a10d8cSMin Li 		dynamic_overhead_ns = ktime_to_ns(ktime_get_raw())
43457a10d8cSMin Li 					- ktime_to_ns(idt82p33->start_time);
43557a10d8cSMin Li 
43657a10d8cSMin Li 		timespec64_add_ns(&local_ts, dynamic_overhead_ns);
43757a10d8cSMin Li 
43857a10d8cSMin Li 		idt82p33->calculate_overhead_flag = 0;
43957a10d8cSMin Li 	}
44057a10d8cSMin Li 
44157a10d8cSMin Li 	idt82p33_timespec_to_byte_array(&local_ts, buf);
44257a10d8cSMin Li 
44357a10d8cSMin Li 	/*
44457a10d8cSMin Li 	 * Store the new time value.
44557a10d8cSMin Li 	 */
44657a10d8cSMin Li 	for (i = 0; i < TOD_BYTE_COUNT; i++) {
44757a10d8cSMin Li 		err = idt82p33_write(idt82p33, channel->dpll_tod_cnfg + i,
44857a10d8cSMin Li 				     &buf[i], sizeof(buf[i]));
44957a10d8cSMin Li 		if (err)
45057a10d8cSMin Li 			return err;
45157a10d8cSMin Li 	}
45257a10d8cSMin Li 
45357a10d8cSMin Li 	return err;
45457a10d8cSMin Li }
45557a10d8cSMin Li 
_idt82p33_adjtime_immediate(struct idt82p33_channel * channel,s64 delta_ns)456ad3cc776SMin Li static int _idt82p33_adjtime_immediate(struct idt82p33_channel *channel,
457ad3cc776SMin Li 				       s64 delta_ns)
45857a10d8cSMin Li {
45957a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
46057a10d8cSMin Li 	struct timespec64 ts;
46157a10d8cSMin Li 	s64 now_ns;
46257a10d8cSMin Li 	int err;
46357a10d8cSMin Li 
46457a10d8cSMin Li 	idt82p33->calculate_overhead_flag = 1;
46557a10d8cSMin Li 
46657a10d8cSMin Li 	err = _idt82p33_gettime(channel, &ts);
46757a10d8cSMin Li 
46857a10d8cSMin Li 	if (err)
46957a10d8cSMin Li 		return err;
47057a10d8cSMin Li 
47157a10d8cSMin Li 	now_ns = timespec64_to_ns(&ts);
47257a10d8cSMin Li 	now_ns += delta_ns + idt82p33->tod_write_overhead_ns;
47357a10d8cSMin Li 
47457a10d8cSMin Li 	ts = ns_to_timespec64(now_ns);
47557a10d8cSMin Li 
47657a10d8cSMin Li 	err = _idt82p33_settime(channel, &ts);
47757a10d8cSMin Li 
47857a10d8cSMin Li 	return err;
47957a10d8cSMin Li }
48057a10d8cSMin Li 
_idt82p33_adjtime_internal_triggered(struct idt82p33_channel * channel,s64 delta_ns)481ad3cc776SMin Li static int _idt82p33_adjtime_internal_triggered(struct idt82p33_channel *channel,
482ad3cc776SMin Li 						s64 delta_ns)
483ad3cc776SMin Li {
484ad3cc776SMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
485ad3cc776SMin Li 	char buf[TOD_BYTE_COUNT];
486ad3cc776SMin Li 	struct timespec64 ts;
487ad3cc776SMin Li 	const u8 delay_ns = 32;
488ad3cc776SMin Li 	s32 remainder;
489ad3cc776SMin Li 	s64 ns;
490ad3cc776SMin Li 	int err;
491ad3cc776SMin Li 
492ad3cc776SMin Li 	err = _idt82p33_gettime(channel, &ts);
493ad3cc776SMin Li 
494ad3cc776SMin Li 	if (err)
495ad3cc776SMin Li 		return err;
496ad3cc776SMin Li 
497ad3cc776SMin Li 	if (ts.tv_nsec > (NSEC_PER_SEC - 5 * NSEC_PER_MSEC)) {
498ad3cc776SMin Li 		/*  Too close to miss next trigger, so skip it */
499ad3cc776SMin Li 		mdelay(6);
500ad3cc776SMin Li 		ns = (ts.tv_sec + 2) * NSEC_PER_SEC + delta_ns + delay_ns;
501ad3cc776SMin Li 	} else
502ad3cc776SMin Li 		ns = (ts.tv_sec + 1) * NSEC_PER_SEC + delta_ns + delay_ns;
503ad3cc776SMin Li 
504ad3cc776SMin Li 	ts = ns_to_timespec64(ns);
505ad3cc776SMin Li 	idt82p33_timespec_to_byte_array(&ts, buf);
506ad3cc776SMin Li 
507ad3cc776SMin Li 	/*
508ad3cc776SMin Li 	 * Store the new time value.
509ad3cc776SMin Li 	 */
510ad3cc776SMin Li 	err = idt82p33_write(idt82p33, channel->dpll_tod_cnfg, buf, sizeof(buf));
511ad3cc776SMin Li 	if (err)
512ad3cc776SMin Li 		return err;
513ad3cc776SMin Li 
514ad3cc776SMin Li 	/* Schedule to implement the workaround in one second */
515ad3cc776SMin Li 	(void)div_s64_rem(delta_ns, NSEC_PER_SEC, &remainder);
516ad3cc776SMin Li 	if (remainder != 0)
517ad3cc776SMin Li 		schedule_delayed_work(&channel->adjtime_work, HZ);
518ad3cc776SMin Li 
519ad3cc776SMin Li 	return idt82p33_set_tod_trigger(channel, HW_TOD_TRIG_SEL_TOD_PPS, true);
520ad3cc776SMin Li }
521ad3cc776SMin Li 
idt82p33_adjtime_workaround(struct work_struct * work)522ad3cc776SMin Li static void idt82p33_adjtime_workaround(struct work_struct *work)
523ad3cc776SMin Li {
524ad3cc776SMin Li 	struct idt82p33_channel *channel = container_of(work,
525ad3cc776SMin Li 							struct idt82p33_channel,
526ad3cc776SMin Li 							adjtime_work.work);
527ad3cc776SMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
528ad3cc776SMin Li 
529ad3cc776SMin Li 	mutex_lock(idt82p33->lock);
530ad3cc776SMin Li 	/* Workaround for TOD-to-output alignment issue */
531ad3cc776SMin Li 	_idt82p33_adjtime_internal_triggered(channel, 0);
532ad3cc776SMin Li 	mutex_unlock(idt82p33->lock);
533ad3cc776SMin Li }
534ad3cc776SMin Li 
_idt82p33_adjfine(struct idt82p33_channel * channel,long scaled_ppm)53557a10d8cSMin Li static int _idt82p33_adjfine(struct idt82p33_channel *channel, long scaled_ppm)
53657a10d8cSMin Li {
53757a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
53857a10d8cSMin Li 	unsigned char buf[5] = {0};
53957a10d8cSMin Li 	int err, i;
54057a10d8cSMin Li 	s64 fcw;
54157a10d8cSMin Li 
54257a10d8cSMin Li 	/*
543ad3cc776SMin Li 	 * Frequency Control Word unit is: 1.6861512 * 10^-10 ppm
54457a10d8cSMin Li 	 *
54557a10d8cSMin Li 	 * adjfreq:
546ad3cc776SMin Li 	 *       ppb * 10^14
547ad3cc776SMin Li 	 * FCW = -----------
548ad3cc776SMin Li 	 *         16861512
54957a10d8cSMin Li 	 *
55057a10d8cSMin Li 	 * adjfine:
551ad3cc776SMin Li 	 *       scaled_ppm * 5^12 * 10^5
552ad3cc776SMin Li 	 * FCW = ------------------------
553ad3cc776SMin Li 	 *            16861512 * 2^4
55457a10d8cSMin Li 	 */
55557a10d8cSMin Li 
556ad3cc776SMin Li 	fcw = scaled_ppm * 762939453125ULL;
557ad3cc776SMin Li 	fcw = div_s64(fcw, 8430756LL);
55857a10d8cSMin Li 
55957a10d8cSMin Li 	for (i = 0; i < 5; i++) {
56057a10d8cSMin Li 		buf[i] = fcw & 0xff;
56157a10d8cSMin Li 		fcw >>= 8;
56257a10d8cSMin Li 	}
56357a10d8cSMin Li 
56457a10d8cSMin Li 	err = idt82p33_dpll_set_mode(channel, PLL_MODE_DCO);
56557a10d8cSMin Li 
56657a10d8cSMin Li 	if (err)
56757a10d8cSMin Li 		return err;
56857a10d8cSMin Li 
56957a10d8cSMin Li 	err = idt82p33_write(idt82p33, channel->dpll_freq_cnfg,
57057a10d8cSMin Li 			     buf, sizeof(buf));
57157a10d8cSMin Li 
57257a10d8cSMin Li 	return err;
57357a10d8cSMin Li }
57457a10d8cSMin Li 
575ad3cc776SMin Li /* ppb = scaled_ppm * 125 / 2^13 */
idt82p33_ddco_scaled_ppm(long current_ppm,s32 ddco_ppb)576ad3cc776SMin Li static s32 idt82p33_ddco_scaled_ppm(long current_ppm, s32 ddco_ppb)
577ad3cc776SMin Li {
578ad3cc776SMin Li 	s64 scaled_ppm = div_s64(((s64)ddco_ppb << 13), 125);
579ad3cc776SMin Li 	s64 max_scaled_ppm = div_s64(((s64)DCO_MAX_PPB << 13), 125);
580ad3cc776SMin Li 
581ad3cc776SMin Li 	current_ppm += scaled_ppm;
582ad3cc776SMin Li 
583ad3cc776SMin Li 	if (current_ppm > max_scaled_ppm)
584ad3cc776SMin Li 		current_ppm = max_scaled_ppm;
585ad3cc776SMin Li 	else if (current_ppm < -max_scaled_ppm)
586ad3cc776SMin Li 		current_ppm = -max_scaled_ppm;
587ad3cc776SMin Li 
588ad3cc776SMin Li 	return (s32)current_ppm;
589ad3cc776SMin Li }
590ad3cc776SMin Li 
idt82p33_stop_ddco(struct idt82p33_channel * channel)591ad3cc776SMin Li static int idt82p33_stop_ddco(struct idt82p33_channel *channel)
592ad3cc776SMin Li {
593ad3cc776SMin Li 	int err;
594ad3cc776SMin Li 
595ad3cc776SMin Li 	err = _idt82p33_adjfine(channel, channel->current_freq);
596ad3cc776SMin Li 	if (err)
597ad3cc776SMin Li 		return err;
598ad3cc776SMin Li 
599ad3cc776SMin Li 	channel->ddco = false;
600ad3cc776SMin Li 
601ad3cc776SMin Li 	return 0;
602ad3cc776SMin Li }
603ad3cc776SMin Li 
idt82p33_start_ddco(struct idt82p33_channel * channel,s32 delta_ns)604ad3cc776SMin Li static int idt82p33_start_ddco(struct idt82p33_channel *channel, s32 delta_ns)
605ad3cc776SMin Li {
606ad3cc776SMin Li 	s32 current_ppm = channel->current_freq;
607ad3cc776SMin Li 	u32 duration_ms = MSEC_PER_SEC;
608ad3cc776SMin Li 	s32 ppb;
609ad3cc776SMin Li 	int err;
610ad3cc776SMin Li 
611ad3cc776SMin Li 	/* If the ToD correction is less than 5 nanoseconds, then skip it.
612ad3cc776SMin Li 	 * The error introduced by the ToD adjustment procedure would be bigger
613ad3cc776SMin Li 	 * than the required ToD correction
614ad3cc776SMin Li 	 */
615ad3cc776SMin Li 	if (abs(delta_ns) < DDCO_THRESHOLD_NS)
616ad3cc776SMin Li 		return 0;
617ad3cc776SMin Li 
618ad3cc776SMin Li 	/* For most cases, keep ddco duration 1 second */
619ad3cc776SMin Li 	ppb = delta_ns;
620ad3cc776SMin Li 	while (abs(ppb) > DCO_MAX_PPB) {
621ad3cc776SMin Li 		duration_ms *= 2;
622ad3cc776SMin Li 		ppb /= 2;
623ad3cc776SMin Li 	}
624ad3cc776SMin Li 
625ad3cc776SMin Li 	err = _idt82p33_adjfine(channel,
626ad3cc776SMin Li 				idt82p33_ddco_scaled_ppm(current_ppm, ppb));
627ad3cc776SMin Li 	if (err)
628ad3cc776SMin Li 		return err;
629ad3cc776SMin Li 
630ad3cc776SMin Li 	/* schedule the worker to cancel ddco */
631ad3cc776SMin Li 	ptp_schedule_worker(channel->ptp_clock,
632ad3cc776SMin Li 			    msecs_to_jiffies(duration_ms) - 1);
633ad3cc776SMin Li 	channel->ddco = true;
634ad3cc776SMin Li 
635ad3cc776SMin Li 	return 0;
636ad3cc776SMin Li }
637ad3cc776SMin Li 
idt82p33_measure_one_byte_write_overhead(struct idt82p33_channel * channel,s64 * overhead_ns)63857a10d8cSMin Li static int idt82p33_measure_one_byte_write_overhead(
63957a10d8cSMin Li 		struct idt82p33_channel *channel, s64 *overhead_ns)
64057a10d8cSMin Li {
64157a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
64257a10d8cSMin Li 	ktime_t start, stop;
643ad3cc776SMin Li 	u8 trigger = 0;
64457a10d8cSMin Li 	s64 total_ns;
64557a10d8cSMin Li 	int err;
64657a10d8cSMin Li 	u8 i;
64757a10d8cSMin Li 
64857a10d8cSMin Li 	total_ns = 0;
64957a10d8cSMin Li 	*overhead_ns = 0;
65057a10d8cSMin Li 
65157a10d8cSMin Li 	for (i = 0; i < MAX_MEASURMENT_COUNT; i++) {
65257a10d8cSMin Li 
65357a10d8cSMin Li 		start = ktime_get_raw();
65457a10d8cSMin Li 
65557a10d8cSMin Li 		err = idt82p33_write(idt82p33, channel->dpll_tod_trigger,
65657a10d8cSMin Li 				     &trigger, sizeof(trigger));
65757a10d8cSMin Li 
65857a10d8cSMin Li 		stop = ktime_get_raw();
65957a10d8cSMin Li 
66057a10d8cSMin Li 		if (err)
66157a10d8cSMin Li 			return err;
66257a10d8cSMin Li 
66357a10d8cSMin Li 		total_ns += ktime_to_ns(stop) - ktime_to_ns(start);
66457a10d8cSMin Li 	}
66557a10d8cSMin Li 
66657a10d8cSMin Li 	*overhead_ns = div_s64(total_ns, MAX_MEASURMENT_COUNT);
66757a10d8cSMin Li 
66857a10d8cSMin Li 	return err;
66957a10d8cSMin Li }
67057a10d8cSMin Li 
idt82p33_measure_one_byte_read_overhead(struct idt82p33_channel * channel,s64 * overhead_ns)671ad3cc776SMin Li static int idt82p33_measure_one_byte_read_overhead(
672ad3cc776SMin Li 		struct idt82p33_channel *channel, s64 *overhead_ns)
673ad3cc776SMin Li {
674ad3cc776SMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
675ad3cc776SMin Li 	ktime_t start, stop;
676ad3cc776SMin Li 	u8 trigger = 0;
677ad3cc776SMin Li 	s64 total_ns;
678ad3cc776SMin Li 	int err;
679ad3cc776SMin Li 	u8 i;
680ad3cc776SMin Li 
681ad3cc776SMin Li 	total_ns = 0;
682ad3cc776SMin Li 	*overhead_ns = 0;
683ad3cc776SMin Li 
684ad3cc776SMin Li 	for (i = 0; i < MAX_MEASURMENT_COUNT; i++) {
685ad3cc776SMin Li 
686ad3cc776SMin Li 		start = ktime_get_raw();
687ad3cc776SMin Li 
688ad3cc776SMin Li 		err = idt82p33_read(idt82p33, channel->dpll_tod_trigger,
689ad3cc776SMin Li 				    &trigger, sizeof(trigger));
690ad3cc776SMin Li 
691ad3cc776SMin Li 		stop = ktime_get_raw();
692ad3cc776SMin Li 
693ad3cc776SMin Li 		if (err)
694ad3cc776SMin Li 			return err;
695ad3cc776SMin Li 
696ad3cc776SMin Li 		total_ns += ktime_to_ns(stop) - ktime_to_ns(start);
697ad3cc776SMin Li 	}
698ad3cc776SMin Li 
699ad3cc776SMin Li 	*overhead_ns = div_s64(total_ns, MAX_MEASURMENT_COUNT);
700ad3cc776SMin Li 
701ad3cc776SMin Li 	return err;
702ad3cc776SMin Li }
703ad3cc776SMin Li 
idt82p33_measure_tod_write_9_byte_overhead(struct idt82p33_channel * channel)70457a10d8cSMin Li static int idt82p33_measure_tod_write_9_byte_overhead(
70557a10d8cSMin Li 		struct idt82p33_channel *channel)
70657a10d8cSMin Li {
70757a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
70857a10d8cSMin Li 	u8 buf[TOD_BYTE_COUNT];
70957a10d8cSMin Li 	ktime_t start, stop;
71057a10d8cSMin Li 	s64 total_ns;
71157a10d8cSMin Li 	int err = 0;
71257a10d8cSMin Li 	u8 i, j;
71357a10d8cSMin Li 
71457a10d8cSMin Li 	total_ns = 0;
71557a10d8cSMin Li 	idt82p33->tod_write_overhead_ns = 0;
71657a10d8cSMin Li 
71757a10d8cSMin Li 	for (i = 0; i < MAX_MEASURMENT_COUNT; i++) {
71857a10d8cSMin Li 
71957a10d8cSMin Li 		start = ktime_get_raw();
72057a10d8cSMin Li 
72157a10d8cSMin Li 		/* Need one less byte for applicable overhead */
72257a10d8cSMin Li 		for (j = 0; j < (TOD_BYTE_COUNT - 1); j++) {
72357a10d8cSMin Li 			err = idt82p33_write(idt82p33,
72457a10d8cSMin Li 					     channel->dpll_tod_cnfg + i,
72557a10d8cSMin Li 					     &buf[i], sizeof(buf[i]));
72657a10d8cSMin Li 			if (err)
72757a10d8cSMin Li 				return err;
72857a10d8cSMin Li 		}
72957a10d8cSMin Li 
73057a10d8cSMin Li 		stop = ktime_get_raw();
73157a10d8cSMin Li 
73257a10d8cSMin Li 		total_ns += ktime_to_ns(stop) - ktime_to_ns(start);
73357a10d8cSMin Li 	}
73457a10d8cSMin Li 
73557a10d8cSMin Li 	idt82p33->tod_write_overhead_ns = div_s64(total_ns,
73657a10d8cSMin Li 						  MAX_MEASURMENT_COUNT);
73757a10d8cSMin Li 
73857a10d8cSMin Li 	return err;
73957a10d8cSMin Li }
74057a10d8cSMin Li 
idt82p33_measure_settime_gettime_gap_overhead(struct idt82p33_channel * channel,s64 * overhead_ns)74157a10d8cSMin Li static int idt82p33_measure_settime_gettime_gap_overhead(
74257a10d8cSMin Li 		struct idt82p33_channel *channel, s64 *overhead_ns)
74357a10d8cSMin Li {
74457a10d8cSMin Li 	struct timespec64 ts1 = {0, 0};
74557a10d8cSMin Li 	struct timespec64 ts2;
74657a10d8cSMin Li 	int err;
74757a10d8cSMin Li 
74857a10d8cSMin Li 	*overhead_ns = 0;
74957a10d8cSMin Li 
75057a10d8cSMin Li 	err = _idt82p33_settime(channel, &ts1);
75157a10d8cSMin Li 
75257a10d8cSMin Li 	if (err)
75357a10d8cSMin Li 		return err;
75457a10d8cSMin Li 
75557a10d8cSMin Li 	err = _idt82p33_gettime(channel, &ts2);
75657a10d8cSMin Li 
75757a10d8cSMin Li 	if (!err)
75857a10d8cSMin Li 		*overhead_ns = timespec64_to_ns(&ts2) - timespec64_to_ns(&ts1);
75957a10d8cSMin Li 
76057a10d8cSMin Li 	return err;
76157a10d8cSMin Li }
76257a10d8cSMin Li 
idt82p33_measure_tod_write_overhead(struct idt82p33_channel * channel)76357a10d8cSMin Li static int idt82p33_measure_tod_write_overhead(struct idt82p33_channel *channel)
76457a10d8cSMin Li {
765ad3cc776SMin Li 	s64 trailing_overhead_ns, one_byte_write_ns, gap_ns, one_byte_read_ns;
76657a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
76757a10d8cSMin Li 	int err;
76857a10d8cSMin Li 
76957a10d8cSMin Li 	idt82p33->tod_write_overhead_ns = 0;
77057a10d8cSMin Li 
77157a10d8cSMin Li 	err = idt82p33_measure_settime_gettime_gap_overhead(channel, &gap_ns);
77257a10d8cSMin Li 
773e014ae39SMin Li 	if (err) {
774013a3e7cSMin Li 		dev_err(idt82p33->dev,
775e014ae39SMin Li 			"Failed in %s with err %d!\n", __func__, err);
77657a10d8cSMin Li 		return err;
777e014ae39SMin Li 	}
77857a10d8cSMin Li 
77957a10d8cSMin Li 	err = idt82p33_measure_one_byte_write_overhead(channel,
78057a10d8cSMin Li 						       &one_byte_write_ns);
78157a10d8cSMin Li 
78257a10d8cSMin Li 	if (err)
78357a10d8cSMin Li 		return err;
78457a10d8cSMin Li 
785ad3cc776SMin Li 	err = idt82p33_measure_one_byte_read_overhead(channel,
786ad3cc776SMin Li 						      &one_byte_read_ns);
787ad3cc776SMin Li 
788ad3cc776SMin Li 	if (err)
789ad3cc776SMin Li 		return err;
790ad3cc776SMin Li 
79157a10d8cSMin Li 	err = idt82p33_measure_tod_write_9_byte_overhead(channel);
79257a10d8cSMin Li 
79357a10d8cSMin Li 	if (err)
79457a10d8cSMin Li 		return err;
79557a10d8cSMin Li 
796ad3cc776SMin Li 	trailing_overhead_ns = gap_ns - 2 * one_byte_write_ns
797ad3cc776SMin Li 			       - one_byte_read_ns;
79857a10d8cSMin Li 
79957a10d8cSMin Li 	idt82p33->tod_write_overhead_ns -= trailing_overhead_ns;
80057a10d8cSMin Li 
80157a10d8cSMin Li 	return err;
80257a10d8cSMin Li }
80357a10d8cSMin Li 
idt82p33_check_and_set_masks(struct idt82p33 * idt82p33,u8 page,u8 offset,u8 val)80457a10d8cSMin Li static int idt82p33_check_and_set_masks(struct idt82p33 *idt82p33,
80557a10d8cSMin Li 					u8 page,
80657a10d8cSMin Li 					u8 offset,
80757a10d8cSMin Li 					u8 val)
80857a10d8cSMin Li {
80957a10d8cSMin Li 	int err = 0;
81057a10d8cSMin Li 
81157a10d8cSMin Li 	if (page == PLLMASK_ADDR_HI && offset == PLLMASK_ADDR_LO) {
81257a10d8cSMin Li 		if ((val & 0xfc) || !(val & 0x3)) {
813013a3e7cSMin Li 			dev_err(idt82p33->dev,
814013a3e7cSMin Li 				"Invalid PLL mask 0x%x\n", val);
81557a10d8cSMin Li 			err = -EINVAL;
81657a10d8cSMin Li 		} else {
81757a10d8cSMin Li 			idt82p33->pll_mask = val;
81857a10d8cSMin Li 		}
81957a10d8cSMin Li 	} else if (page == PLL0_OUTMASK_ADDR_HI &&
82057a10d8cSMin Li 		offset == PLL0_OUTMASK_ADDR_LO) {
82157a10d8cSMin Li 		idt82p33->channel[0].output_mask = val;
82257a10d8cSMin Li 	} else if (page == PLL1_OUTMASK_ADDR_HI &&
82357a10d8cSMin Li 		offset == PLL1_OUTMASK_ADDR_LO) {
82457a10d8cSMin Li 		idt82p33->channel[1].output_mask = val;
82557a10d8cSMin Li 	}
82657a10d8cSMin Li 
82757a10d8cSMin Li 	return err;
82857a10d8cSMin Li }
82957a10d8cSMin Li 
idt82p33_display_masks(struct idt82p33 * idt82p33)83057a10d8cSMin Li static void idt82p33_display_masks(struct idt82p33 *idt82p33)
83157a10d8cSMin Li {
83257a10d8cSMin Li 	u8 mask, i;
83357a10d8cSMin Li 
834013a3e7cSMin Li 	dev_info(idt82p33->dev,
83557a10d8cSMin Li 		 "pllmask = 0x%02x\n", idt82p33->pll_mask);
83657a10d8cSMin Li 
83757a10d8cSMin Li 	for (i = 0; i < MAX_PHC_PLL; i++) {
83857a10d8cSMin Li 		mask = 1 << i;
83957a10d8cSMin Li 
84057a10d8cSMin Li 		if (mask & idt82p33->pll_mask)
841013a3e7cSMin Li 			dev_info(idt82p33->dev,
84257a10d8cSMin Li 				 "PLL%d output_mask = 0x%04x\n",
84357a10d8cSMin Li 				 i, idt82p33->channel[i].output_mask);
84457a10d8cSMin Li 	}
84557a10d8cSMin Li }
84657a10d8cSMin Li 
idt82p33_sync_tod(struct idt82p33_channel * channel,bool enable)84757a10d8cSMin Li static int idt82p33_sync_tod(struct idt82p33_channel *channel, bool enable)
84857a10d8cSMin Li {
84957a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
85057a10d8cSMin Li 	u8 sync_cnfg;
85157a10d8cSMin Li 	int err;
85257a10d8cSMin Li 
85357a10d8cSMin Li 	err = idt82p33_read(idt82p33, channel->dpll_sync_cnfg,
85457a10d8cSMin Li 			    &sync_cnfg, sizeof(sync_cnfg));
85557a10d8cSMin Li 	if (err)
85657a10d8cSMin Li 		return err;
85757a10d8cSMin Li 
85857a10d8cSMin Li 	sync_cnfg &= ~SYNC_TOD;
85957a10d8cSMin Li 	if (enable)
86057a10d8cSMin Li 		sync_cnfg |= SYNC_TOD;
86157a10d8cSMin Li 
862e014ae39SMin Li 	return idt82p33_write(idt82p33, channel->dpll_sync_cnfg,
86357a10d8cSMin Li 			      &sync_cnfg, sizeof(sync_cnfg));
86457a10d8cSMin Li }
86557a10d8cSMin Li 
idt82p33_work_handler(struct ptp_clock_info * ptp)866ad3cc776SMin Li static long idt82p33_work_handler(struct ptp_clock_info *ptp)
867ad3cc776SMin Li {
868ad3cc776SMin Li 	struct idt82p33_channel *channel =
869ad3cc776SMin Li 			container_of(ptp, struct idt82p33_channel, caps);
870ad3cc776SMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
871ad3cc776SMin Li 
872ad3cc776SMin Li 	mutex_lock(idt82p33->lock);
873ad3cc776SMin Li 	(void)idt82p33_stop_ddco(channel);
874ad3cc776SMin Li 	mutex_unlock(idt82p33->lock);
875ad3cc776SMin Li 
876ad3cc776SMin Li 	/* Return a negative value here to not reschedule */
877ad3cc776SMin Li 	return -1;
878ad3cc776SMin Li }
879ad3cc776SMin Li 
idt82p33_output_enable(struct idt82p33_channel * channel,bool enable,unsigned int outn)880e014ae39SMin Li static int idt82p33_output_enable(struct idt82p33_channel *channel,
881e014ae39SMin Li 				  bool enable, unsigned int outn)
88257a10d8cSMin Li {
88357a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
88457a10d8cSMin Li 	int err;
885e014ae39SMin Li 	u8 val;
886e014ae39SMin Li 
887e014ae39SMin Li 	err = idt82p33_read(idt82p33, OUT_MUX_CNFG(outn), &val, sizeof(val));
888e014ae39SMin Li 	if (err)
889e014ae39SMin Li 		return err;
890e014ae39SMin Li 	if (enable)
891e014ae39SMin Li 		val &= ~SQUELCH_ENABLE;
892e014ae39SMin Li 	else
893e014ae39SMin Li 		val |= SQUELCH_ENABLE;
894e014ae39SMin Li 
895e014ae39SMin Li 	return idt82p33_write(idt82p33, OUT_MUX_CNFG(outn), &val, sizeof(val));
896e014ae39SMin Li }
897e014ae39SMin Li 
idt82p33_perout_enable(struct idt82p33_channel * channel,bool enable,struct ptp_perout_request * perout)898e014ae39SMin Li static int idt82p33_perout_enable(struct idt82p33_channel *channel,
899e014ae39SMin Li 				  bool enable,
900e014ae39SMin Li 				  struct ptp_perout_request *perout)
901e014ae39SMin Li {
902e014ae39SMin Li 	/* Enable/disable individual output instead */
903e014ae39SMin Li 	return idt82p33_output_enable(channel, enable, perout->index);
904e014ae39SMin Li }
905e014ae39SMin Li 
idt82p33_enable_tod(struct idt82p33_channel * channel)90657a10d8cSMin Li static int idt82p33_enable_tod(struct idt82p33_channel *channel)
90757a10d8cSMin Li {
90857a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
90957a10d8cSMin Li 	struct timespec64 ts = {0, 0};
91057a10d8cSMin Li 	int err;
91157a10d8cSMin Li 
91257a10d8cSMin Li 	err = idt82p33_measure_tod_write_overhead(channel);
91357a10d8cSMin Li 
914e014ae39SMin Li 	if (err) {
915013a3e7cSMin Li 		dev_err(idt82p33->dev,
916e014ae39SMin Li 			"Failed in %s with err %d!\n", __func__, err);
91757a10d8cSMin Li 		return err;
918e014ae39SMin Li 	}
91957a10d8cSMin Li 
92057a10d8cSMin Li 	err = _idt82p33_settime(channel, &ts);
92157a10d8cSMin Li 
92257a10d8cSMin Li 	if (err)
92357a10d8cSMin Li 		return err;
92457a10d8cSMin Li 
92557a10d8cSMin Li 	return idt82p33_sync_tod(channel, true);
92657a10d8cSMin Li }
92757a10d8cSMin Li 
idt82p33_ptp_clock_unregister_all(struct idt82p33 * idt82p33)92857a10d8cSMin Li static void idt82p33_ptp_clock_unregister_all(struct idt82p33 *idt82p33)
92957a10d8cSMin Li {
93057a10d8cSMin Li 	struct idt82p33_channel *channel;
93157a10d8cSMin Li 	u8 i;
93257a10d8cSMin Li 
93357a10d8cSMin Li 	for (i = 0; i < MAX_PHC_PLL; i++) {
93457a10d8cSMin Li 		channel = &idt82p33->channel[i];
935ad3cc776SMin Li 		cancel_delayed_work_sync(&channel->adjtime_work);
936e014ae39SMin Li 		if (channel->ptp_clock)
93757a10d8cSMin Li 			ptp_clock_unregister(channel->ptp_clock);
93857a10d8cSMin Li 	}
93957a10d8cSMin Li }
94057a10d8cSMin Li 
941ad3cc776SMin Li 
942ad3cc776SMin Li 
idt82p33_enable(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)94357a10d8cSMin Li static int idt82p33_enable(struct ptp_clock_info *ptp,
94457a10d8cSMin Li 			   struct ptp_clock_request *rq, int on)
94557a10d8cSMin Li {
94657a10d8cSMin Li 	struct idt82p33_channel *channel =
94757a10d8cSMin Li 			container_of(ptp, struct idt82p33_channel, caps);
94857a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
949013a3e7cSMin Li 	int err = -EOPNOTSUPP;
95057a10d8cSMin Li 
951013a3e7cSMin Li 	mutex_lock(idt82p33->lock);
95257a10d8cSMin Li 
953ad3cc776SMin Li 	switch (rq->type) {
954ad3cc776SMin Li 	case PTP_CLK_REQ_PEROUT:
95557a10d8cSMin Li 		if (!on)
956e014ae39SMin Li 			err = idt82p33_perout_enable(channel, false,
957e014ae39SMin Li 						     &rq->perout);
95857a10d8cSMin Li 		/* Only accept a 1-PPS aligned to the second. */
95957a10d8cSMin Li 		else if (rq->perout.start.nsec || rq->perout.period.sec != 1 ||
960013a3e7cSMin Li 			 rq->perout.period.nsec)
96157a10d8cSMin Li 			err = -ERANGE;
962013a3e7cSMin Li 		else
963e014ae39SMin Li 			err = idt82p33_perout_enable(channel, true,
964e014ae39SMin Li 						     &rq->perout);
965ad3cc776SMin Li 		break;
966ad3cc776SMin Li 	case PTP_CLK_REQ_EXTTS:
967ad3cc776SMin Li 		err = idt82p33_extts_enable(channel, rq, on);
968ad3cc776SMin Li 		break;
969ad3cc776SMin Li 	default:
970ad3cc776SMin Li 		break;
97157a10d8cSMin Li 	}
97257a10d8cSMin Li 
973013a3e7cSMin Li 	mutex_unlock(idt82p33->lock);
97457a10d8cSMin Li 
975013a3e7cSMin Li 	if (err)
976013a3e7cSMin Li 		dev_err(idt82p33->dev,
977013a3e7cSMin Li 			"Failed in %s with err %d!\n", __func__, err);
97857a10d8cSMin Li 	return err;
97957a10d8cSMin Li }
98057a10d8cSMin Li 
idt82p33_getmaxphase(__always_unused struct ptp_clock_info * ptp)981*e156e4d2SRahul Rameshbabu static s32 idt82p33_getmaxphase(__always_unused struct ptp_clock_info *ptp)
982*e156e4d2SRahul Rameshbabu {
983*e156e4d2SRahul Rameshbabu 	return WRITE_PHASE_OFFSET_LIMIT;
984*e156e4d2SRahul Rameshbabu }
985*e156e4d2SRahul Rameshbabu 
idt82p33_adjwritephase(struct ptp_clock_info * ptp,s32 offset_ns)986e014ae39SMin Li static int idt82p33_adjwritephase(struct ptp_clock_info *ptp, s32 offset_ns)
987e014ae39SMin Li {
988e014ae39SMin Li 	struct idt82p33_channel *channel =
989e014ae39SMin Li 		container_of(ptp, struct idt82p33_channel, caps);
990e014ae39SMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
991*e156e4d2SRahul Rameshbabu 	s64 offset_regval;
992e014ae39SMin Li 	u8 val[4] = {0};
993e014ae39SMin Li 	int err;
994e014ae39SMin Li 
995e014ae39SMin Li 	/* Convert from phaseoffset_fs to register value */
996*e156e4d2SRahul Rameshbabu 	offset_regval = div_s64((s64)(-offset_ns) * 1000000000ll,
997*e156e4d2SRahul Rameshbabu 				IDT_T0DPLL_PHASE_RESOL);
998e014ae39SMin Li 
999e014ae39SMin Li 	val[0] = offset_regval & 0xFF;
1000e014ae39SMin Li 	val[1] = (offset_regval >> 8) & 0xFF;
1001e014ae39SMin Li 	val[2] = (offset_regval >> 16) & 0xFF;
1002e014ae39SMin Li 	val[3] = (offset_regval >> 24) & 0x1F;
1003e014ae39SMin Li 	val[3] |= PH_OFFSET_EN;
1004e014ae39SMin Li 
1005013a3e7cSMin Li 	mutex_lock(idt82p33->lock);
1006e014ae39SMin Li 
1007e014ae39SMin Li 	err = idt82p33_dpll_set_mode(channel, PLL_MODE_WPH);
1008e014ae39SMin Li 	if (err) {
1009013a3e7cSMin Li 		dev_err(idt82p33->dev,
1010e014ae39SMin Li 			"Failed in %s with err %d!\n", __func__, err);
1011e014ae39SMin Li 		goto out;
1012e014ae39SMin Li 	}
1013e014ae39SMin Li 
1014e014ae39SMin Li 	err = idt82p33_write(idt82p33, channel->dpll_phase_cnfg, val,
1015e014ae39SMin Li 			     sizeof(val));
1016e014ae39SMin Li 
1017e014ae39SMin Li out:
1018013a3e7cSMin Li 	mutex_unlock(idt82p33->lock);
1019e014ae39SMin Li 	return err;
1020e014ae39SMin Li }
1021e014ae39SMin Li 
idt82p33_adjfine(struct ptp_clock_info * ptp,long scaled_ppm)102257a10d8cSMin Li static int idt82p33_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
102357a10d8cSMin Li {
102457a10d8cSMin Li 	struct idt82p33_channel *channel =
102557a10d8cSMin Li 			container_of(ptp, struct idt82p33_channel, caps);
102657a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
102757a10d8cSMin Li 	int err;
102857a10d8cSMin Li 
1029ad3cc776SMin Li 	if (channel->ddco == true)
1030ad3cc776SMin Li 		return 0;
1031ad3cc776SMin Li 
1032ad3cc776SMin Li 	if (scaled_ppm == channel->current_freq)
1033ad3cc776SMin Li 		return 0;
1034ad3cc776SMin Li 
1035013a3e7cSMin Li 	mutex_lock(idt82p33->lock);
103657a10d8cSMin Li 	err = _idt82p33_adjfine(channel, scaled_ppm);
1037ad3cc776SMin Li 
1038ad3cc776SMin Li 	if (err == 0)
1039ad3cc776SMin Li 		channel->current_freq = scaled_ppm;
1040013a3e7cSMin Li 	mutex_unlock(idt82p33->lock);
1041ad3cc776SMin Li 
1042e014ae39SMin Li 	if (err)
1043013a3e7cSMin Li 		dev_err(idt82p33->dev,
1044e014ae39SMin Li 			"Failed in %s with err %d!\n", __func__, err);
104557a10d8cSMin Li 	return err;
104657a10d8cSMin Li }
104757a10d8cSMin Li 
idt82p33_adjtime(struct ptp_clock_info * ptp,s64 delta_ns)104857a10d8cSMin Li static int idt82p33_adjtime(struct ptp_clock_info *ptp, s64 delta_ns)
104957a10d8cSMin Li {
105057a10d8cSMin Li 	struct idt82p33_channel *channel =
105157a10d8cSMin Li 			container_of(ptp, struct idt82p33_channel, caps);
105257a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
105357a10d8cSMin Li 	int err;
105457a10d8cSMin Li 
1055ad3cc776SMin Li 	if (channel->ddco == true)
1056ad3cc776SMin Li 		return -EBUSY;
1057ad3cc776SMin Li 
1058013a3e7cSMin Li 	mutex_lock(idt82p33->lock);
105957a10d8cSMin Li 
106057a10d8cSMin Li 	if (abs(delta_ns) < phase_snap_threshold) {
1061ad3cc776SMin Li 		err = idt82p33_start_ddco(channel, delta_ns);
1062013a3e7cSMin Li 		mutex_unlock(idt82p33->lock);
1063ad3cc776SMin Li 		return err;
106457a10d8cSMin Li 	}
106557a10d8cSMin Li 
1066ad3cc776SMin Li 	/* Use more accurate internal 1pps triggered write first */
1067ad3cc776SMin Li 	err = _idt82p33_adjtime_internal_triggered(channel, delta_ns);
1068ad3cc776SMin Li 	if (err && delta_ns > IMMEDIATE_SNAP_THRESHOLD_NS)
1069ad3cc776SMin Li 		err = _idt82p33_adjtime_immediate(channel, delta_ns);
107057a10d8cSMin Li 
1071013a3e7cSMin Li 	mutex_unlock(idt82p33->lock);
107257a10d8cSMin Li 
1073e014ae39SMin Li 	if (err)
1074013a3e7cSMin Li 		dev_err(idt82p33->dev,
1075013a3e7cSMin Li 			"Failed in %s with err %d!\n", __func__, err);
107657a10d8cSMin Li 	return err;
107757a10d8cSMin Li }
107857a10d8cSMin Li 
idt82p33_gettime(struct ptp_clock_info * ptp,struct timespec64 * ts)107957a10d8cSMin Li static int idt82p33_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
108057a10d8cSMin Li {
108157a10d8cSMin Li 	struct idt82p33_channel *channel =
108257a10d8cSMin Li 			container_of(ptp, struct idt82p33_channel, caps);
108357a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
108457a10d8cSMin Li 	int err;
108557a10d8cSMin Li 
1086013a3e7cSMin Li 	mutex_lock(idt82p33->lock);
108757a10d8cSMin Li 	err = _idt82p33_gettime(channel, ts);
1088013a3e7cSMin Li 	mutex_unlock(idt82p33->lock);
108957a10d8cSMin Li 
1090013a3e7cSMin Li 	if (err)
1091013a3e7cSMin Li 		dev_err(idt82p33->dev,
1092013a3e7cSMin Li 			"Failed in %s with err %d!\n", __func__, err);
109357a10d8cSMin Li 	return err;
109457a10d8cSMin Li }
109557a10d8cSMin Li 
idt82p33_settime(struct ptp_clock_info * ptp,const struct timespec64 * ts)109657a10d8cSMin Li static int idt82p33_settime(struct ptp_clock_info *ptp,
109757a10d8cSMin Li 			    const struct timespec64 *ts)
109857a10d8cSMin Li {
109957a10d8cSMin Li 	struct idt82p33_channel *channel =
110057a10d8cSMin Li 			container_of(ptp, struct idt82p33_channel, caps);
110157a10d8cSMin Li 	struct idt82p33 *idt82p33 = channel->idt82p33;
110257a10d8cSMin Li 	int err;
110357a10d8cSMin Li 
1104013a3e7cSMin Li 	mutex_lock(idt82p33->lock);
110557a10d8cSMin Li 	err = _idt82p33_settime(channel, ts);
1106013a3e7cSMin Li 	mutex_unlock(idt82p33->lock);
110757a10d8cSMin Li 
1108013a3e7cSMin Li 	if (err)
1109013a3e7cSMin Li 		dev_err(idt82p33->dev,
1110013a3e7cSMin Li 			"Failed in %s with err %d!\n", __func__, err);
111157a10d8cSMin Li 	return err;
111257a10d8cSMin Li }
111357a10d8cSMin Li 
idt82p33_channel_init(struct idt82p33 * idt82p33,u32 index)1114ad3cc776SMin Li static int idt82p33_channel_init(struct idt82p33 *idt82p33, u32 index)
111557a10d8cSMin Li {
1116ad3cc776SMin Li 	struct idt82p33_channel *channel = &idt82p33->channel[index];
1117ad3cc776SMin Li 
111857a10d8cSMin Li 	switch (index) {
111957a10d8cSMin Li 	case 0:
112057a10d8cSMin Li 		channel->dpll_tod_cnfg = DPLL1_TOD_CNFG;
112157a10d8cSMin Li 		channel->dpll_tod_trigger = DPLL1_TOD_TRIGGER;
112257a10d8cSMin Li 		channel->dpll_tod_sts = DPLL1_TOD_STS;
112357a10d8cSMin Li 		channel->dpll_mode_cnfg = DPLL1_OPERATING_MODE_CNFG;
112457a10d8cSMin Li 		channel->dpll_freq_cnfg = DPLL1_HOLDOVER_FREQ_CNFG;
112557a10d8cSMin Li 		channel->dpll_phase_cnfg = DPLL1_PHASE_OFFSET_CNFG;
112657a10d8cSMin Li 		channel->dpll_sync_cnfg = DPLL1_SYNC_EDGE_CNFG;
112757a10d8cSMin Li 		channel->dpll_input_mode_cnfg = DPLL1_INPUT_MODE_CNFG;
112857a10d8cSMin Li 		break;
112957a10d8cSMin Li 	case 1:
113057a10d8cSMin Li 		channel->dpll_tod_cnfg = DPLL2_TOD_CNFG;
113157a10d8cSMin Li 		channel->dpll_tod_trigger = DPLL2_TOD_TRIGGER;
113257a10d8cSMin Li 		channel->dpll_tod_sts = DPLL2_TOD_STS;
113357a10d8cSMin Li 		channel->dpll_mode_cnfg = DPLL2_OPERATING_MODE_CNFG;
113457a10d8cSMin Li 		channel->dpll_freq_cnfg = DPLL2_HOLDOVER_FREQ_CNFG;
113557a10d8cSMin Li 		channel->dpll_phase_cnfg = DPLL2_PHASE_OFFSET_CNFG;
113657a10d8cSMin Li 		channel->dpll_sync_cnfg = DPLL2_SYNC_EDGE_CNFG;
113757a10d8cSMin Li 		channel->dpll_input_mode_cnfg = DPLL2_INPUT_MODE_CNFG;
113857a10d8cSMin Li 		break;
113957a10d8cSMin Li 	default:
114057a10d8cSMin Li 		return -EINVAL;
114157a10d8cSMin Li 	}
114257a10d8cSMin Li 
1143ad3cc776SMin Li 	channel->plln = index;
1144ad3cc776SMin Li 	channel->current_freq = 0;
1145ad3cc776SMin Li 	channel->idt82p33 = idt82p33;
1146ad3cc776SMin Li 	INIT_DELAYED_WORK(&channel->adjtime_work, idt82p33_adjtime_workaround);
114757a10d8cSMin Li 
114857a10d8cSMin Li 	return 0;
114957a10d8cSMin Li }
115057a10d8cSMin Li 
idt82p33_verify_pin(struct ptp_clock_info * ptp,unsigned int pin,enum ptp_pin_function func,unsigned int chan)1151ad3cc776SMin Li static int idt82p33_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
1152ad3cc776SMin Li 			       enum ptp_pin_function func, unsigned int chan)
115357a10d8cSMin Li {
1154ad3cc776SMin Li 	switch (func) {
1155ad3cc776SMin Li 	case PTP_PF_NONE:
1156ad3cc776SMin Li 	case PTP_PF_EXTTS:
1157ad3cc776SMin Li 		break;
1158ad3cc776SMin Li 	case PTP_PF_PEROUT:
1159ad3cc776SMin Li 	case PTP_PF_PHYSYNC:
1160ad3cc776SMin Li 		return -1;
1161ad3cc776SMin Li 	}
1162ad3cc776SMin Li 	return 0;
1163ad3cc776SMin Li }
1164ad3cc776SMin Li 
idt82p33_caps_init(u32 index,struct ptp_clock_info * caps,struct ptp_pin_desc * pin_cfg,u8 max_pins)1165ad3cc776SMin Li static void idt82p33_caps_init(u32 index, struct ptp_clock_info *caps,
1166ad3cc776SMin Li 			       struct ptp_pin_desc *pin_cfg, u8 max_pins)
1167ad3cc776SMin Li {
1168ad3cc776SMin Li 	struct ptp_pin_desc *ppd;
1169ad3cc776SMin Li 	int i;
1170ad3cc776SMin Li 
117157a10d8cSMin Li 	caps->owner = THIS_MODULE;
1172013a3e7cSMin Li 	caps->max_adj = DCO_MAX_PPB;
1173ad3cc776SMin Li 	caps->n_per_out = MAX_PER_OUT;
1174ad3cc776SMin Li 	caps->n_ext_ts = MAX_PHC_PLL,
1175ad3cc776SMin Li 	caps->n_pins = max_pins,
1176ad3cc776SMin Li 	caps->adjphase = idt82p33_adjwritephase,
1177*e156e4d2SRahul Rameshbabu 	caps->getmaxphase = idt82p33_getmaxphase,
117857a10d8cSMin Li 	caps->adjfine = idt82p33_adjfine;
117957a10d8cSMin Li 	caps->adjtime = idt82p33_adjtime;
118057a10d8cSMin Li 	caps->gettime64 = idt82p33_gettime;
118157a10d8cSMin Li 	caps->settime64 = idt82p33_settime;
118257a10d8cSMin Li 	caps->enable = idt82p33_enable;
1183ad3cc776SMin Li 	caps->verify = idt82p33_verify_pin;
1184ad3cc776SMin Li 	caps->do_aux_work = idt82p33_work_handler;
1185ad3cc776SMin Li 
1186ad3cc776SMin Li 	snprintf(caps->name, sizeof(caps->name), "IDT 82P33 PLL%u", index);
1187ad3cc776SMin Li 
1188ad3cc776SMin Li 	caps->pin_config = pin_cfg;
1189ad3cc776SMin Li 
1190ad3cc776SMin Li 	for (i = 0; i < max_pins; ++i) {
1191ad3cc776SMin Li 		ppd = &pin_cfg[i];
1192ad3cc776SMin Li 
1193ad3cc776SMin Li 		ppd->index = i;
1194ad3cc776SMin Li 		ppd->func = PTP_PF_NONE;
1195ad3cc776SMin Li 		ppd->chan = index;
1196ad3cc776SMin Li 		snprintf(ppd->name, sizeof(ppd->name), "in%d", 12 + i);
1197ad3cc776SMin Li 	}
119857a10d8cSMin Li }
119957a10d8cSMin Li 
idt82p33_enable_channel(struct idt82p33 * idt82p33,u32 index)120057a10d8cSMin Li static int idt82p33_enable_channel(struct idt82p33 *idt82p33, u32 index)
120157a10d8cSMin Li {
120257a10d8cSMin Li 	struct idt82p33_channel *channel;
120357a10d8cSMin Li 	int err;
120457a10d8cSMin Li 
120557a10d8cSMin Li 	if (!(index < MAX_PHC_PLL))
120657a10d8cSMin Li 		return -EINVAL;
120757a10d8cSMin Li 
120857a10d8cSMin Li 	channel = &idt82p33->channel[index];
120957a10d8cSMin Li 
1210ad3cc776SMin Li 	err = idt82p33_channel_init(idt82p33, index);
1211e014ae39SMin Li 	if (err) {
1212013a3e7cSMin Li 		dev_err(idt82p33->dev,
1213e014ae39SMin Li 			"Channel_init failed in %s with err %d!\n",
1214e014ae39SMin Li 			__func__, err);
121557a10d8cSMin Li 		return err;
1216e014ae39SMin Li 	}
121757a10d8cSMin Li 
1218ad3cc776SMin Li 	idt82p33_caps_init(index, &channel->caps,
1219ad3cc776SMin Li 			   pin_config[index], MAX_TRIG_CLK);
122057a10d8cSMin Li 
122157a10d8cSMin Li 	channel->ptp_clock = ptp_clock_register(&channel->caps, NULL);
122257a10d8cSMin Li 
122357a10d8cSMin Li 	if (IS_ERR(channel->ptp_clock)) {
122457a10d8cSMin Li 		err = PTR_ERR(channel->ptp_clock);
122557a10d8cSMin Li 		channel->ptp_clock = NULL;
122657a10d8cSMin Li 		return err;
122757a10d8cSMin Li 	}
122857a10d8cSMin Li 
122957a10d8cSMin Li 	if (!channel->ptp_clock)
123057a10d8cSMin Li 		return -ENOTSUPP;
123157a10d8cSMin Li 
1232e014ae39SMin Li 	err = idt82p33_dpll_set_mode(channel, PLL_MODE_DCO);
1233e014ae39SMin Li 	if (err) {
1234013a3e7cSMin Li 		dev_err(idt82p33->dev,
1235e014ae39SMin Li 			"Dpll_set_mode failed in %s with err %d!\n",
1236e014ae39SMin Li 			__func__, err);
1237e014ae39SMin Li 		return err;
1238e014ae39SMin Li 	}
1239e014ae39SMin Li 
1240e014ae39SMin Li 	err = idt82p33_enable_tod(channel);
1241e014ae39SMin Li 	if (err) {
1242013a3e7cSMin Li 		dev_err(idt82p33->dev,
1243e014ae39SMin Li 			"Enable_tod failed in %s with err %d!\n",
1244e014ae39SMin Li 			__func__, err);
1245e014ae39SMin Li 		return err;
1246e014ae39SMin Li 	}
1247e014ae39SMin Li 
1248013a3e7cSMin Li 	dev_info(idt82p33->dev, "PLL%d registered as ptp%d\n",
124957a10d8cSMin Li 		 index, channel->ptp_clock->index);
125057a10d8cSMin Li 
125157a10d8cSMin Li 	return 0;
125257a10d8cSMin Li }
125357a10d8cSMin Li 
idt82p33_reset(struct idt82p33 * idt82p33,bool cold)1254ad3cc776SMin Li static int idt82p33_reset(struct idt82p33 *idt82p33, bool cold)
1255ad3cc776SMin Li {
1256ad3cc776SMin Li 	int err;
1257ad3cc776SMin Li 	u8 cfg = SOFT_RESET_EN;
1258ad3cc776SMin Li 
1259ad3cc776SMin Li 	if (cold == true)
1260ad3cc776SMin Li 		goto cold_reset;
1261ad3cc776SMin Li 
1262ad3cc776SMin Li 	err = idt82p33_read(idt82p33, REG_SOFT_RESET, &cfg, sizeof(cfg));
1263ad3cc776SMin Li 	if (err) {
1264ad3cc776SMin Li 		dev_err(idt82p33->dev,
1265ad3cc776SMin Li 			"Soft reset failed with err %d!\n", err);
1266ad3cc776SMin Li 		return err;
1267ad3cc776SMin Li 	}
1268ad3cc776SMin Li 
1269ad3cc776SMin Li 	cfg |= SOFT_RESET_EN;
1270ad3cc776SMin Li 
1271ad3cc776SMin Li cold_reset:
1272ad3cc776SMin Li 	err = idt82p33_write(idt82p33, REG_SOFT_RESET, &cfg, sizeof(cfg));
1273ad3cc776SMin Li 	if (err)
1274ad3cc776SMin Li 		dev_err(idt82p33->dev,
1275ad3cc776SMin Li 			"Cold reset failed with err %d!\n", err);
1276ad3cc776SMin Li 	return err;
1277ad3cc776SMin Li }
1278ad3cc776SMin Li 
idt82p33_load_firmware(struct idt82p33 * idt82p33)127957a10d8cSMin Li static int idt82p33_load_firmware(struct idt82p33 *idt82p33)
128057a10d8cSMin Li {
1281ad3cc776SMin Li 	char fname[128] = FW_FILENAME;
128257a10d8cSMin Li 	const struct firmware *fw;
128357a10d8cSMin Li 	struct idt82p33_fwrc *rec;
128457a10d8cSMin Li 	u8 loaddr, page, val;
128557a10d8cSMin Li 	int err;
128657a10d8cSMin Li 	s32 len;
128757a10d8cSMin Li 
1288ad3cc776SMin Li 	if (firmware) /* module parameter */
1289ad3cc776SMin Li 		snprintf(fname, sizeof(fname), "%s", firmware);
129057a10d8cSMin Li 
1291ad3cc776SMin Li 	dev_info(idt82p33->dev, "requesting firmware '%s'\n", fname);
1292ad3cc776SMin Li 
1293ad3cc776SMin Li 	err = request_firmware(&fw, fname, idt82p33->dev);
129457a10d8cSMin Li 
1295e014ae39SMin Li 	if (err) {
1296013a3e7cSMin Li 		dev_err(idt82p33->dev,
1297e014ae39SMin Li 			"Failed in %s with err %d!\n", __func__, err);
129857a10d8cSMin Li 		return err;
1299e014ae39SMin Li 	}
130057a10d8cSMin Li 
1301013a3e7cSMin Li 	dev_dbg(idt82p33->dev, "firmware size %zu bytes\n", fw->size);
130257a10d8cSMin Li 
130357a10d8cSMin Li 	rec = (struct idt82p33_fwrc *) fw->data;
130457a10d8cSMin Li 
130557a10d8cSMin Li 	for (len = fw->size; len > 0; len -= sizeof(*rec)) {
130657a10d8cSMin Li 
130757a10d8cSMin Li 		if (rec->reserved) {
1308013a3e7cSMin Li 			dev_err(idt82p33->dev,
130957a10d8cSMin Li 				"bad firmware, reserved field non-zero\n");
131057a10d8cSMin Li 			err = -EINVAL;
131157a10d8cSMin Li 		} else {
131257a10d8cSMin Li 			val = rec->value;
131357a10d8cSMin Li 			loaddr = rec->loaddr;
131457a10d8cSMin Li 			page = rec->hiaddr;
131557a10d8cSMin Li 
131657a10d8cSMin Li 			rec++;
131757a10d8cSMin Li 
131857a10d8cSMin Li 			err = idt82p33_check_and_set_masks(idt82p33, page,
131957a10d8cSMin Li 							   loaddr, val);
132057a10d8cSMin Li 		}
132157a10d8cSMin Li 
132257a10d8cSMin Li 		if (err == 0) {
132357a10d8cSMin Li 			/* Page size 128, last 4 bytes of page skipped */
1324013a3e7cSMin Li 			if (loaddr > 0x7b)
132557a10d8cSMin Li 				continue;
132657a10d8cSMin Li 
1327013a3e7cSMin Li 			err = idt82p33_write(idt82p33, REG_ADDR(page, loaddr),
132857a10d8cSMin Li 					     &val, sizeof(val));
132957a10d8cSMin Li 		}
133057a10d8cSMin Li 
133157a10d8cSMin Li 		if (err)
133257a10d8cSMin Li 			goto out;
133357a10d8cSMin Li 	}
133457a10d8cSMin Li 
133557a10d8cSMin Li 	idt82p33_display_masks(idt82p33);
133657a10d8cSMin Li out:
133757a10d8cSMin Li 	release_firmware(fw);
133857a10d8cSMin Li 	return err;
133957a10d8cSMin Li }
134057a10d8cSMin Li 
idt82p33_extts_check(struct work_struct * work)1341ad3cc776SMin Li static void idt82p33_extts_check(struct work_struct *work)
1342ad3cc776SMin Li {
1343ad3cc776SMin Li 	struct idt82p33 *idt82p33 = container_of(work, struct idt82p33,
1344ad3cc776SMin Li 						 extts_work.work);
1345ad3cc776SMin Li 	struct idt82p33_channel *channel;
1346ad3cc776SMin Li 	int err;
1347ad3cc776SMin Li 	u8 mask;
1348ad3cc776SMin Li 	int i;
1349ad3cc776SMin Li 
1350ad3cc776SMin Li 	if (idt82p33->extts_mask == 0)
1351ad3cc776SMin Li 		return;
1352ad3cc776SMin Li 
1353ad3cc776SMin Li 	mutex_lock(idt82p33->lock);
1354ad3cc776SMin Li 
1355ad3cc776SMin Li 	for (i = 0; i < MAX_PHC_PLL; i++) {
1356ad3cc776SMin Li 		mask = 1 << i;
1357ad3cc776SMin Li 
1358ad3cc776SMin Li 		if ((idt82p33->extts_mask & mask) == 0)
1359ad3cc776SMin Li 			continue;
1360ad3cc776SMin Li 
1361ad3cc776SMin Li 		err = idt82p33_extts_check_channel(idt82p33, i);
1362ad3cc776SMin Li 
1363ad3cc776SMin Li 		if (err == 0) {
1364ad3cc776SMin Li 			/* trigger clears itself, so clear the mask */
1365ad3cc776SMin Li 			if (idt82p33->extts_single_shot) {
1366ad3cc776SMin Li 				idt82p33->extts_mask &= ~mask;
1367ad3cc776SMin Li 			} else {
1368ad3cc776SMin Li 				/* Re-arm */
1369ad3cc776SMin Li 				channel = &idt82p33->channel[i];
1370ad3cc776SMin Li 				arm_tod_read_with_trigger(channel, channel->tod_trigger);
1371ad3cc776SMin Li 			}
1372ad3cc776SMin Li 		}
1373ad3cc776SMin Li 	}
1374ad3cc776SMin Li 
1375ad3cc776SMin Li 	if (idt82p33->extts_mask)
1376ad3cc776SMin Li 		schedule_delayed_work(&idt82p33->extts_work,
1377ad3cc776SMin Li 				      msecs_to_jiffies(EXTTS_PERIOD_MS));
1378ad3cc776SMin Li 
1379ad3cc776SMin Li 	mutex_unlock(idt82p33->lock);
1380ad3cc776SMin Li }
138157a10d8cSMin Li 
idt82p33_probe(struct platform_device * pdev)1382013a3e7cSMin Li static int idt82p33_probe(struct platform_device *pdev)
138357a10d8cSMin Li {
1384013a3e7cSMin Li 	struct rsmu_ddata *ddata = dev_get_drvdata(pdev->dev.parent);
138557a10d8cSMin Li 	struct idt82p33 *idt82p33;
138657a10d8cSMin Li 	int err;
138757a10d8cSMin Li 	u8 i;
138857a10d8cSMin Li 
1389013a3e7cSMin Li 	idt82p33 = devm_kzalloc(&pdev->dev,
139057a10d8cSMin Li 				sizeof(struct idt82p33), GFP_KERNEL);
139157a10d8cSMin Li 	if (!idt82p33)
139257a10d8cSMin Li 		return -ENOMEM;
139357a10d8cSMin Li 
1394013a3e7cSMin Li 	idt82p33->dev = &pdev->dev;
1395013a3e7cSMin Li 	idt82p33->mfd = pdev->dev.parent;
1396013a3e7cSMin Li 	idt82p33->lock = &ddata->lock;
1397013a3e7cSMin Li 	idt82p33->regmap = ddata->regmap;
139857a10d8cSMin Li 	idt82p33->tod_write_overhead_ns = 0;
139957a10d8cSMin Li 	idt82p33->calculate_overhead_flag = 0;
140057a10d8cSMin Li 	idt82p33->pll_mask = DEFAULT_PLL_MASK;
140157a10d8cSMin Li 	idt82p33->channel[0].output_mask = DEFAULT_OUTPUT_MASK_PLL0;
140257a10d8cSMin Li 	idt82p33->channel[1].output_mask = DEFAULT_OUTPUT_MASK_PLL1;
1403ad3cc776SMin Li 	idt82p33->extts_mask = 0;
1404ad3cc776SMin Li 	INIT_DELAYED_WORK(&idt82p33->extts_work, idt82p33_extts_check);
140557a10d8cSMin Li 
1406013a3e7cSMin Li 	mutex_lock(idt82p33->lock);
140757a10d8cSMin Li 
1408ad3cc776SMin Li 	/* cold reset before loading firmware */
1409ad3cc776SMin Li 	idt82p33_reset(idt82p33, true);
141057a10d8cSMin Li 
1411ad3cc776SMin Li 	err = idt82p33_load_firmware(idt82p33);
141257a10d8cSMin Li 	if (err)
1413013a3e7cSMin Li 		dev_warn(idt82p33->dev,
141457a10d8cSMin Li 			 "loading firmware failed with %d\n", err);
141557a10d8cSMin Li 
1416ad3cc776SMin Li 	/* soft reset after loading firmware */
1417ad3cc776SMin Li 	idt82p33_reset(idt82p33, false);
1418ad3cc776SMin Li 
141957a10d8cSMin Li 	if (idt82p33->pll_mask) {
142057a10d8cSMin Li 		for (i = 0; i < MAX_PHC_PLL; i++) {
1421ad3cc776SMin Li 			if (idt82p33->pll_mask & (1 << i))
142257a10d8cSMin Li 				err = idt82p33_enable_channel(idt82p33, i);
1423ad3cc776SMin Li 			else
1424ad3cc776SMin Li 				err = idt82p33_channel_init(idt82p33, i);
1425e014ae39SMin Li 			if (err) {
1426013a3e7cSMin Li 				dev_err(idt82p33->dev,
1427e014ae39SMin Li 					"Failed in %s with err %d!\n",
1428e014ae39SMin Li 					__func__, err);
142957a10d8cSMin Li 				break;
143057a10d8cSMin Li 			}
143157a10d8cSMin Li 		}
143257a10d8cSMin Li 	} else {
1433013a3e7cSMin Li 		dev_err(idt82p33->dev,
143457a10d8cSMin Li 			"no PLLs flagged as PHCs, nothing to do\n");
143557a10d8cSMin Li 		err = -ENODEV;
143657a10d8cSMin Li 	}
143757a10d8cSMin Li 
1438013a3e7cSMin Li 	mutex_unlock(idt82p33->lock);
143957a10d8cSMin Li 
144057a10d8cSMin Li 	if (err) {
144157a10d8cSMin Li 		idt82p33_ptp_clock_unregister_all(idt82p33);
144257a10d8cSMin Li 		return err;
144357a10d8cSMin Li 	}
144457a10d8cSMin Li 
1445013a3e7cSMin Li 	platform_set_drvdata(pdev, idt82p33);
144657a10d8cSMin Li 
144757a10d8cSMin Li 	return 0;
144857a10d8cSMin Li }
144957a10d8cSMin Li 
idt82p33_remove(struct platform_device * pdev)1450013a3e7cSMin Li static int idt82p33_remove(struct platform_device *pdev)
145157a10d8cSMin Li {
1452013a3e7cSMin Li 	struct idt82p33 *idt82p33 = platform_get_drvdata(pdev);
145357a10d8cSMin Li 
1454ad3cc776SMin Li 	cancel_delayed_work_sync(&idt82p33->extts_work);
1455ad3cc776SMin Li 
145657a10d8cSMin Li 	idt82p33_ptp_clock_unregister_all(idt82p33);
145757a10d8cSMin Li 
145857a10d8cSMin Li 	return 0;
145957a10d8cSMin Li }
146057a10d8cSMin Li 
1461013a3e7cSMin Li static struct platform_driver idt82p33_driver = {
146257a10d8cSMin Li 	.driver = {
1463013a3e7cSMin Li 		.name = "82p33x1x-phc",
146457a10d8cSMin Li 	},
146557a10d8cSMin Li 	.probe = idt82p33_probe,
146657a10d8cSMin Li 	.remove	= idt82p33_remove,
146757a10d8cSMin Li };
146857a10d8cSMin Li 
1469013a3e7cSMin Li module_platform_driver(idt82p33_driver);
1470