1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Copyright (C) 2018 Integrated Device Technology, Inc
4*4882a593Smuzhiyun //
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #define pr_fmt(fmt) "IDT_82p33xxx: " fmt
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/firmware.h>
9*4882a593Smuzhiyun #include <linux/i2c.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/ptp_clock_kernel.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/timekeeping.h>
15*4882a593Smuzhiyun #include <linux/bitops.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include "ptp_private.h"
18*4882a593Smuzhiyun #include "ptp_idt82p33.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun MODULE_DESCRIPTION("Driver for IDT 82p33xxx clock devices");
21*4882a593Smuzhiyun MODULE_AUTHOR("IDT support-1588 <IDT-support-1588@lm.renesas.com>");
22*4882a593Smuzhiyun MODULE_VERSION("1.0");
23*4882a593Smuzhiyun MODULE_LICENSE("GPL");
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /* Module Parameters */
26*4882a593Smuzhiyun static u32 sync_tod_timeout = SYNC_TOD_TIMEOUT_SEC;
27*4882a593Smuzhiyun module_param(sync_tod_timeout, uint, 0);
28*4882a593Smuzhiyun MODULE_PARM_DESC(sync_tod_timeout,
29*4882a593Smuzhiyun "duration in second to keep SYNC_TOD on (set to 0 to keep it always on)");
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun static u32 phase_snap_threshold = SNAP_THRESHOLD_NS;
32*4882a593Smuzhiyun module_param(phase_snap_threshold, uint, 0);
33*4882a593Smuzhiyun MODULE_PARM_DESC(phase_snap_threshold,
34*4882a593Smuzhiyun "threshold (150000ns by default) below which adjtime would ignore");
35*4882a593Smuzhiyun
idt82p33_byte_array_to_timespec(struct timespec64 * ts,u8 buf[TOD_BYTE_COUNT])36*4882a593Smuzhiyun static void idt82p33_byte_array_to_timespec(struct timespec64 *ts,
37*4882a593Smuzhiyun u8 buf[TOD_BYTE_COUNT])
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun time64_t sec;
40*4882a593Smuzhiyun s32 nsec;
41*4882a593Smuzhiyun u8 i;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun nsec = buf[3];
44*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
45*4882a593Smuzhiyun nsec <<= 8;
46*4882a593Smuzhiyun nsec |= buf[2 - i];
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun sec = buf[9];
50*4882a593Smuzhiyun for (i = 0; i < 5; i++) {
51*4882a593Smuzhiyun sec <<= 8;
52*4882a593Smuzhiyun sec |= buf[8 - i];
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun ts->tv_sec = sec;
56*4882a593Smuzhiyun ts->tv_nsec = nsec;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
idt82p33_timespec_to_byte_array(struct timespec64 const * ts,u8 buf[TOD_BYTE_COUNT])59*4882a593Smuzhiyun static void idt82p33_timespec_to_byte_array(struct timespec64 const *ts,
60*4882a593Smuzhiyun u8 buf[TOD_BYTE_COUNT])
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun time64_t sec;
63*4882a593Smuzhiyun s32 nsec;
64*4882a593Smuzhiyun u8 i;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun nsec = ts->tv_nsec;
67*4882a593Smuzhiyun sec = ts->tv_sec;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
70*4882a593Smuzhiyun buf[i] = nsec & 0xff;
71*4882a593Smuzhiyun nsec >>= 8;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun for (i = 4; i < TOD_BYTE_COUNT; i++) {
75*4882a593Smuzhiyun buf[i] = sec & 0xff;
76*4882a593Smuzhiyun sec >>= 8;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
idt82p33_xfer(struct idt82p33 * idt82p33,unsigned char regaddr,unsigned char * buf,unsigned int count,int write)80*4882a593Smuzhiyun static int idt82p33_xfer(struct idt82p33 *idt82p33,
81*4882a593Smuzhiyun unsigned char regaddr,
82*4882a593Smuzhiyun unsigned char *buf,
83*4882a593Smuzhiyun unsigned int count,
84*4882a593Smuzhiyun int write)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun struct i2c_client *client = idt82p33->client;
87*4882a593Smuzhiyun struct i2c_msg msg[2];
88*4882a593Smuzhiyun int cnt;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun msg[0].addr = client->addr;
91*4882a593Smuzhiyun msg[0].flags = 0;
92*4882a593Smuzhiyun msg[0].len = 1;
93*4882a593Smuzhiyun msg[0].buf = ®addr;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun msg[1].addr = client->addr;
96*4882a593Smuzhiyun msg[1].flags = write ? 0 : I2C_M_RD;
97*4882a593Smuzhiyun msg[1].len = count;
98*4882a593Smuzhiyun msg[1].buf = buf;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun cnt = i2c_transfer(client->adapter, msg, 2);
101*4882a593Smuzhiyun if (cnt < 0) {
102*4882a593Smuzhiyun dev_err(&client->dev, "i2c_transfer returned %d\n", cnt);
103*4882a593Smuzhiyun return cnt;
104*4882a593Smuzhiyun } else if (cnt != 2) {
105*4882a593Smuzhiyun dev_err(&client->dev,
106*4882a593Smuzhiyun "i2c_transfer sent only %d of %d messages\n", cnt, 2);
107*4882a593Smuzhiyun return -EIO;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun return 0;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
idt82p33_page_offset(struct idt82p33 * idt82p33,unsigned char val)112*4882a593Smuzhiyun static int idt82p33_page_offset(struct idt82p33 *idt82p33, unsigned char val)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun int err;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun if (idt82p33->page_offset == val)
117*4882a593Smuzhiyun return 0;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun err = idt82p33_xfer(idt82p33, PAGE_ADDR, &val, sizeof(val), 1);
120*4882a593Smuzhiyun if (err)
121*4882a593Smuzhiyun dev_err(&idt82p33->client->dev,
122*4882a593Smuzhiyun "failed to set page offset %d\n", val);
123*4882a593Smuzhiyun else
124*4882a593Smuzhiyun idt82p33->page_offset = val;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun return err;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
idt82p33_rdwr(struct idt82p33 * idt82p33,unsigned int regaddr,unsigned char * buf,unsigned int count,bool write)129*4882a593Smuzhiyun static int idt82p33_rdwr(struct idt82p33 *idt82p33, unsigned int regaddr,
130*4882a593Smuzhiyun unsigned char *buf, unsigned int count, bool write)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun u8 offset, page;
133*4882a593Smuzhiyun int err;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun page = _PAGE(regaddr);
136*4882a593Smuzhiyun offset = _OFFSET(regaddr);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun err = idt82p33_page_offset(idt82p33, page);
139*4882a593Smuzhiyun if (err)
140*4882a593Smuzhiyun goto out;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun err = idt82p33_xfer(idt82p33, offset, buf, count, write);
143*4882a593Smuzhiyun out:
144*4882a593Smuzhiyun return err;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
idt82p33_read(struct idt82p33 * idt82p33,unsigned int regaddr,unsigned char * buf,unsigned int count)147*4882a593Smuzhiyun static int idt82p33_read(struct idt82p33 *idt82p33, unsigned int regaddr,
148*4882a593Smuzhiyun unsigned char *buf, unsigned int count)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun return idt82p33_rdwr(idt82p33, regaddr, buf, count, false);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
idt82p33_write(struct idt82p33 * idt82p33,unsigned int regaddr,unsigned char * buf,unsigned int count)153*4882a593Smuzhiyun static int idt82p33_write(struct idt82p33 *idt82p33, unsigned int regaddr,
154*4882a593Smuzhiyun unsigned char *buf, unsigned int count)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun return idt82p33_rdwr(idt82p33, regaddr, buf, count, true);
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
idt82p33_dpll_set_mode(struct idt82p33_channel * channel,enum pll_mode mode)159*4882a593Smuzhiyun static int idt82p33_dpll_set_mode(struct idt82p33_channel *channel,
160*4882a593Smuzhiyun enum pll_mode mode)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
163*4882a593Smuzhiyun u8 dpll_mode;
164*4882a593Smuzhiyun int err;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun if (channel->pll_mode == mode)
167*4882a593Smuzhiyun return 0;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun err = idt82p33_read(idt82p33, channel->dpll_mode_cnfg,
170*4882a593Smuzhiyun &dpll_mode, sizeof(dpll_mode));
171*4882a593Smuzhiyun if (err)
172*4882a593Smuzhiyun return err;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun dpll_mode &= ~(PLL_MODE_MASK << PLL_MODE_SHIFT);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun dpll_mode |= (mode << PLL_MODE_SHIFT);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun err = idt82p33_write(idt82p33, channel->dpll_mode_cnfg,
179*4882a593Smuzhiyun &dpll_mode, sizeof(dpll_mode));
180*4882a593Smuzhiyun if (err)
181*4882a593Smuzhiyun return err;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun channel->pll_mode = dpll_mode;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun return 0;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
_idt82p33_gettime(struct idt82p33_channel * channel,struct timespec64 * ts)188*4882a593Smuzhiyun static int _idt82p33_gettime(struct idt82p33_channel *channel,
189*4882a593Smuzhiyun struct timespec64 *ts)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
192*4882a593Smuzhiyun u8 buf[TOD_BYTE_COUNT];
193*4882a593Smuzhiyun u8 trigger;
194*4882a593Smuzhiyun int err;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun trigger = TOD_TRIGGER(HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
197*4882a593Smuzhiyun HW_TOD_RD_TRIG_SEL_LSB_TOD_STS);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun err = idt82p33_write(idt82p33, channel->dpll_tod_trigger,
201*4882a593Smuzhiyun &trigger, sizeof(trigger));
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun if (err)
204*4882a593Smuzhiyun return err;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun if (idt82p33->calculate_overhead_flag)
207*4882a593Smuzhiyun idt82p33->start_time = ktime_get_raw();
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun err = idt82p33_read(idt82p33, channel->dpll_tod_sts, buf, sizeof(buf));
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (err)
212*4882a593Smuzhiyun return err;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun idt82p33_byte_array_to_timespec(ts, buf);
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun return 0;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /*
220*4882a593Smuzhiyun * TOD Trigger:
221*4882a593Smuzhiyun * Bits[7:4] Write 0x9, MSB write
222*4882a593Smuzhiyun * Bits[3:0] Read 0x9, LSB read
223*4882a593Smuzhiyun */
224*4882a593Smuzhiyun
_idt82p33_settime(struct idt82p33_channel * channel,struct timespec64 const * ts)225*4882a593Smuzhiyun static int _idt82p33_settime(struct idt82p33_channel *channel,
226*4882a593Smuzhiyun struct timespec64 const *ts)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
229*4882a593Smuzhiyun struct timespec64 local_ts = *ts;
230*4882a593Smuzhiyun char buf[TOD_BYTE_COUNT];
231*4882a593Smuzhiyun s64 dynamic_overhead_ns;
232*4882a593Smuzhiyun unsigned char trigger;
233*4882a593Smuzhiyun int err;
234*4882a593Smuzhiyun u8 i;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun trigger = TOD_TRIGGER(HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
237*4882a593Smuzhiyun HW_TOD_RD_TRIG_SEL_LSB_TOD_STS);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun err = idt82p33_write(idt82p33, channel->dpll_tod_trigger,
240*4882a593Smuzhiyun &trigger, sizeof(trigger));
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun if (err)
243*4882a593Smuzhiyun return err;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (idt82p33->calculate_overhead_flag) {
246*4882a593Smuzhiyun dynamic_overhead_ns = ktime_to_ns(ktime_get_raw())
247*4882a593Smuzhiyun - ktime_to_ns(idt82p33->start_time);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun timespec64_add_ns(&local_ts, dynamic_overhead_ns);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun idt82p33->calculate_overhead_flag = 0;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun idt82p33_timespec_to_byte_array(&local_ts, buf);
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /*
257*4882a593Smuzhiyun * Store the new time value.
258*4882a593Smuzhiyun */
259*4882a593Smuzhiyun for (i = 0; i < TOD_BYTE_COUNT; i++) {
260*4882a593Smuzhiyun err = idt82p33_write(idt82p33, channel->dpll_tod_cnfg + i,
261*4882a593Smuzhiyun &buf[i], sizeof(buf[i]));
262*4882a593Smuzhiyun if (err)
263*4882a593Smuzhiyun return err;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun return err;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
_idt82p33_adjtime(struct idt82p33_channel * channel,s64 delta_ns)269*4882a593Smuzhiyun static int _idt82p33_adjtime(struct idt82p33_channel *channel, s64 delta_ns)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
272*4882a593Smuzhiyun struct timespec64 ts;
273*4882a593Smuzhiyun s64 now_ns;
274*4882a593Smuzhiyun int err;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun idt82p33->calculate_overhead_flag = 1;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun err = _idt82p33_gettime(channel, &ts);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun if (err)
281*4882a593Smuzhiyun return err;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun now_ns = timespec64_to_ns(&ts);
284*4882a593Smuzhiyun now_ns += delta_ns + idt82p33->tod_write_overhead_ns;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun ts = ns_to_timespec64(now_ns);
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun err = _idt82p33_settime(channel, &ts);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun return err;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
_idt82p33_adjfine(struct idt82p33_channel * channel,long scaled_ppm)293*4882a593Smuzhiyun static int _idt82p33_adjfine(struct idt82p33_channel *channel, long scaled_ppm)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
296*4882a593Smuzhiyun unsigned char buf[5] = {0};
297*4882a593Smuzhiyun int neg_adj = 0;
298*4882a593Smuzhiyun int err, i;
299*4882a593Smuzhiyun s64 fcw;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if (scaled_ppm == channel->current_freq_ppb)
302*4882a593Smuzhiyun return 0;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /*
305*4882a593Smuzhiyun * Frequency Control Word unit is: 1.68 * 10^-10 ppm
306*4882a593Smuzhiyun *
307*4882a593Smuzhiyun * adjfreq:
308*4882a593Smuzhiyun * ppb * 10^9
309*4882a593Smuzhiyun * FCW = ----------
310*4882a593Smuzhiyun * 168
311*4882a593Smuzhiyun *
312*4882a593Smuzhiyun * adjfine:
313*4882a593Smuzhiyun * scaled_ppm * 5^12
314*4882a593Smuzhiyun * FCW = -------------
315*4882a593Smuzhiyun * 168 * 2^4
316*4882a593Smuzhiyun */
317*4882a593Smuzhiyun if (scaled_ppm < 0) {
318*4882a593Smuzhiyun neg_adj = 1;
319*4882a593Smuzhiyun scaled_ppm = -scaled_ppm;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun fcw = scaled_ppm * 244140625ULL;
323*4882a593Smuzhiyun fcw = div_u64(fcw, 2688);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun if (neg_adj)
326*4882a593Smuzhiyun fcw = -fcw;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun for (i = 0; i < 5; i++) {
329*4882a593Smuzhiyun buf[i] = fcw & 0xff;
330*4882a593Smuzhiyun fcw >>= 8;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun err = idt82p33_dpll_set_mode(channel, PLL_MODE_DCO);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun if (err)
336*4882a593Smuzhiyun return err;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun err = idt82p33_write(idt82p33, channel->dpll_freq_cnfg,
339*4882a593Smuzhiyun buf, sizeof(buf));
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun if (err == 0)
342*4882a593Smuzhiyun channel->current_freq_ppb = scaled_ppm;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun return err;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
idt82p33_measure_one_byte_write_overhead(struct idt82p33_channel * channel,s64 * overhead_ns)347*4882a593Smuzhiyun static int idt82p33_measure_one_byte_write_overhead(
348*4882a593Smuzhiyun struct idt82p33_channel *channel, s64 *overhead_ns)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
351*4882a593Smuzhiyun ktime_t start, stop;
352*4882a593Smuzhiyun s64 total_ns;
353*4882a593Smuzhiyun u8 trigger;
354*4882a593Smuzhiyun int err;
355*4882a593Smuzhiyun u8 i;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun total_ns = 0;
358*4882a593Smuzhiyun *overhead_ns = 0;
359*4882a593Smuzhiyun trigger = TOD_TRIGGER(HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
360*4882a593Smuzhiyun HW_TOD_RD_TRIG_SEL_LSB_TOD_STS);
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun for (i = 0; i < MAX_MEASURMENT_COUNT; i++) {
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun start = ktime_get_raw();
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun err = idt82p33_write(idt82p33, channel->dpll_tod_trigger,
367*4882a593Smuzhiyun &trigger, sizeof(trigger));
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun stop = ktime_get_raw();
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun if (err)
372*4882a593Smuzhiyun return err;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun total_ns += ktime_to_ns(stop) - ktime_to_ns(start);
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun *overhead_ns = div_s64(total_ns, MAX_MEASURMENT_COUNT);
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun return err;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
idt82p33_measure_tod_write_9_byte_overhead(struct idt82p33_channel * channel)382*4882a593Smuzhiyun static int idt82p33_measure_tod_write_9_byte_overhead(
383*4882a593Smuzhiyun struct idt82p33_channel *channel)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
386*4882a593Smuzhiyun u8 buf[TOD_BYTE_COUNT];
387*4882a593Smuzhiyun ktime_t start, stop;
388*4882a593Smuzhiyun s64 total_ns;
389*4882a593Smuzhiyun int err = 0;
390*4882a593Smuzhiyun u8 i, j;
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun total_ns = 0;
393*4882a593Smuzhiyun idt82p33->tod_write_overhead_ns = 0;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun for (i = 0; i < MAX_MEASURMENT_COUNT; i++) {
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun start = ktime_get_raw();
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* Need one less byte for applicable overhead */
400*4882a593Smuzhiyun for (j = 0; j < (TOD_BYTE_COUNT - 1); j++) {
401*4882a593Smuzhiyun err = idt82p33_write(idt82p33,
402*4882a593Smuzhiyun channel->dpll_tod_cnfg + i,
403*4882a593Smuzhiyun &buf[i], sizeof(buf[i]));
404*4882a593Smuzhiyun if (err)
405*4882a593Smuzhiyun return err;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun stop = ktime_get_raw();
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun total_ns += ktime_to_ns(stop) - ktime_to_ns(start);
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun idt82p33->tod_write_overhead_ns = div_s64(total_ns,
414*4882a593Smuzhiyun MAX_MEASURMENT_COUNT);
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun return err;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
idt82p33_measure_settime_gettime_gap_overhead(struct idt82p33_channel * channel,s64 * overhead_ns)419*4882a593Smuzhiyun static int idt82p33_measure_settime_gettime_gap_overhead(
420*4882a593Smuzhiyun struct idt82p33_channel *channel, s64 *overhead_ns)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun struct timespec64 ts1 = {0, 0};
423*4882a593Smuzhiyun struct timespec64 ts2;
424*4882a593Smuzhiyun int err;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun *overhead_ns = 0;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun err = _idt82p33_settime(channel, &ts1);
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun if (err)
431*4882a593Smuzhiyun return err;
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun err = _idt82p33_gettime(channel, &ts2);
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun if (!err)
436*4882a593Smuzhiyun *overhead_ns = timespec64_to_ns(&ts2) - timespec64_to_ns(&ts1);
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun return err;
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun
idt82p33_measure_tod_write_overhead(struct idt82p33_channel * channel)441*4882a593Smuzhiyun static int idt82p33_measure_tod_write_overhead(struct idt82p33_channel *channel)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun s64 trailing_overhead_ns, one_byte_write_ns, gap_ns;
444*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
445*4882a593Smuzhiyun int err;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun idt82p33->tod_write_overhead_ns = 0;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun err = idt82p33_measure_settime_gettime_gap_overhead(channel, &gap_ns);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun if (err)
452*4882a593Smuzhiyun return err;
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun err = idt82p33_measure_one_byte_write_overhead(channel,
455*4882a593Smuzhiyun &one_byte_write_ns);
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun if (err)
458*4882a593Smuzhiyun return err;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun err = idt82p33_measure_tod_write_9_byte_overhead(channel);
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun if (err)
463*4882a593Smuzhiyun return err;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun trailing_overhead_ns = gap_ns - (2 * one_byte_write_ns);
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun idt82p33->tod_write_overhead_ns -= trailing_overhead_ns;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun return err;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
idt82p33_check_and_set_masks(struct idt82p33 * idt82p33,u8 page,u8 offset,u8 val)472*4882a593Smuzhiyun static int idt82p33_check_and_set_masks(struct idt82p33 *idt82p33,
473*4882a593Smuzhiyun u8 page,
474*4882a593Smuzhiyun u8 offset,
475*4882a593Smuzhiyun u8 val)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun int err = 0;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun if (page == PLLMASK_ADDR_HI && offset == PLLMASK_ADDR_LO) {
480*4882a593Smuzhiyun if ((val & 0xfc) || !(val & 0x3)) {
481*4882a593Smuzhiyun dev_err(&idt82p33->client->dev,
482*4882a593Smuzhiyun "Invalid PLL mask 0x%hhx\n", val);
483*4882a593Smuzhiyun err = -EINVAL;
484*4882a593Smuzhiyun } else {
485*4882a593Smuzhiyun idt82p33->pll_mask = val;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun } else if (page == PLL0_OUTMASK_ADDR_HI &&
488*4882a593Smuzhiyun offset == PLL0_OUTMASK_ADDR_LO) {
489*4882a593Smuzhiyun idt82p33->channel[0].output_mask = val;
490*4882a593Smuzhiyun } else if (page == PLL1_OUTMASK_ADDR_HI &&
491*4882a593Smuzhiyun offset == PLL1_OUTMASK_ADDR_LO) {
492*4882a593Smuzhiyun idt82p33->channel[1].output_mask = val;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun return err;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun
idt82p33_display_masks(struct idt82p33 * idt82p33)498*4882a593Smuzhiyun static void idt82p33_display_masks(struct idt82p33 *idt82p33)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun u8 mask, i;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun dev_info(&idt82p33->client->dev,
503*4882a593Smuzhiyun "pllmask = 0x%02x\n", idt82p33->pll_mask);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun for (i = 0; i < MAX_PHC_PLL; i++) {
506*4882a593Smuzhiyun mask = 1 << i;
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun if (mask & idt82p33->pll_mask)
509*4882a593Smuzhiyun dev_info(&idt82p33->client->dev,
510*4882a593Smuzhiyun "PLL%d output_mask = 0x%04x\n",
511*4882a593Smuzhiyun i, idt82p33->channel[i].output_mask);
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
idt82p33_sync_tod(struct idt82p33_channel * channel,bool enable)515*4882a593Smuzhiyun static int idt82p33_sync_tod(struct idt82p33_channel *channel, bool enable)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
518*4882a593Smuzhiyun u8 sync_cnfg;
519*4882a593Smuzhiyun int err;
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun if (enable == channel->sync_tod_on) {
522*4882a593Smuzhiyun if (enable && sync_tod_timeout) {
523*4882a593Smuzhiyun mod_delayed_work(system_wq, &channel->sync_tod_work,
524*4882a593Smuzhiyun sync_tod_timeout * HZ);
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun return 0;
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun err = idt82p33_read(idt82p33, channel->dpll_sync_cnfg,
530*4882a593Smuzhiyun &sync_cnfg, sizeof(sync_cnfg));
531*4882a593Smuzhiyun if (err)
532*4882a593Smuzhiyun return err;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun sync_cnfg &= ~SYNC_TOD;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun if (enable)
537*4882a593Smuzhiyun sync_cnfg |= SYNC_TOD;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun err = idt82p33_write(idt82p33, channel->dpll_sync_cnfg,
540*4882a593Smuzhiyun &sync_cnfg, sizeof(sync_cnfg));
541*4882a593Smuzhiyun if (err)
542*4882a593Smuzhiyun return err;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun channel->sync_tod_on = enable;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun if (enable && sync_tod_timeout) {
547*4882a593Smuzhiyun mod_delayed_work(system_wq, &channel->sync_tod_work,
548*4882a593Smuzhiyun sync_tod_timeout * HZ);
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun return 0;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
idt82p33_sync_tod_work_handler(struct work_struct * work)554*4882a593Smuzhiyun static void idt82p33_sync_tod_work_handler(struct work_struct *work)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun struct idt82p33_channel *channel =
557*4882a593Smuzhiyun container_of(work, struct idt82p33_channel, sync_tod_work.work);
558*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun mutex_lock(&idt82p33->reg_lock);
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun (void)idt82p33_sync_tod(channel, false);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun mutex_unlock(&idt82p33->reg_lock);
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun
idt82p33_pps_enable(struct idt82p33_channel * channel,bool enable)567*4882a593Smuzhiyun static int idt82p33_pps_enable(struct idt82p33_channel *channel, bool enable)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
570*4882a593Smuzhiyun u8 mask, outn, val;
571*4882a593Smuzhiyun int err;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun mask = channel->output_mask;
574*4882a593Smuzhiyun outn = 0;
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun while (mask) {
577*4882a593Smuzhiyun if (mask & 0x1) {
578*4882a593Smuzhiyun err = idt82p33_read(idt82p33, OUT_MUX_CNFG(outn),
579*4882a593Smuzhiyun &val, sizeof(val));
580*4882a593Smuzhiyun if (err)
581*4882a593Smuzhiyun return err;
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun if (enable)
584*4882a593Smuzhiyun val &= ~SQUELCH_ENABLE;
585*4882a593Smuzhiyun else
586*4882a593Smuzhiyun val |= SQUELCH_ENABLE;
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun err = idt82p33_write(idt82p33, OUT_MUX_CNFG(outn),
589*4882a593Smuzhiyun &val, sizeof(val));
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun if (err)
592*4882a593Smuzhiyun return err;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun mask >>= 0x1;
595*4882a593Smuzhiyun outn++;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun return 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
idt82p33_enable_tod(struct idt82p33_channel * channel)601*4882a593Smuzhiyun static int idt82p33_enable_tod(struct idt82p33_channel *channel)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
604*4882a593Smuzhiyun struct timespec64 ts = {0, 0};
605*4882a593Smuzhiyun int err;
606*4882a593Smuzhiyun u8 val;
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun val = 0;
609*4882a593Smuzhiyun err = idt82p33_write(idt82p33, channel->dpll_input_mode_cnfg,
610*4882a593Smuzhiyun &val, sizeof(val));
611*4882a593Smuzhiyun if (err)
612*4882a593Smuzhiyun return err;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun err = idt82p33_pps_enable(channel, false);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun if (err)
617*4882a593Smuzhiyun return err;
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun err = idt82p33_measure_tod_write_overhead(channel);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun if (err)
622*4882a593Smuzhiyun return err;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun err = _idt82p33_settime(channel, &ts);
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun if (err)
627*4882a593Smuzhiyun return err;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun return idt82p33_sync_tod(channel, true);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
idt82p33_ptp_clock_unregister_all(struct idt82p33 * idt82p33)632*4882a593Smuzhiyun static void idt82p33_ptp_clock_unregister_all(struct idt82p33 *idt82p33)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun struct idt82p33_channel *channel;
635*4882a593Smuzhiyun u8 i;
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun for (i = 0; i < MAX_PHC_PLL; i++) {
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun channel = &idt82p33->channel[i];
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun if (channel->ptp_clock) {
642*4882a593Smuzhiyun ptp_clock_unregister(channel->ptp_clock);
643*4882a593Smuzhiyun cancel_delayed_work_sync(&channel->sync_tod_work);
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun
idt82p33_enable(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)648*4882a593Smuzhiyun static int idt82p33_enable(struct ptp_clock_info *ptp,
649*4882a593Smuzhiyun struct ptp_clock_request *rq, int on)
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun struct idt82p33_channel *channel =
652*4882a593Smuzhiyun container_of(ptp, struct idt82p33_channel, caps);
653*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
654*4882a593Smuzhiyun int err;
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun err = -EOPNOTSUPP;
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun mutex_lock(&idt82p33->reg_lock);
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun if (rq->type == PTP_CLK_REQ_PEROUT) {
661*4882a593Smuzhiyun if (!on)
662*4882a593Smuzhiyun err = idt82p33_pps_enable(channel, false);
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun /* Only accept a 1-PPS aligned to the second. */
665*4882a593Smuzhiyun else if (rq->perout.start.nsec || rq->perout.period.sec != 1 ||
666*4882a593Smuzhiyun rq->perout.period.nsec) {
667*4882a593Smuzhiyun err = -ERANGE;
668*4882a593Smuzhiyun } else
669*4882a593Smuzhiyun err = idt82p33_pps_enable(channel, true);
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun mutex_unlock(&idt82p33->reg_lock);
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun return err;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
idt82p33_adjfine(struct ptp_clock_info * ptp,long scaled_ppm)677*4882a593Smuzhiyun static int idt82p33_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun struct idt82p33_channel *channel =
680*4882a593Smuzhiyun container_of(ptp, struct idt82p33_channel, caps);
681*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
682*4882a593Smuzhiyun int err;
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun mutex_lock(&idt82p33->reg_lock);
685*4882a593Smuzhiyun err = _idt82p33_adjfine(channel, scaled_ppm);
686*4882a593Smuzhiyun mutex_unlock(&idt82p33->reg_lock);
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun return err;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun
idt82p33_adjtime(struct ptp_clock_info * ptp,s64 delta_ns)691*4882a593Smuzhiyun static int idt82p33_adjtime(struct ptp_clock_info *ptp, s64 delta_ns)
692*4882a593Smuzhiyun {
693*4882a593Smuzhiyun struct idt82p33_channel *channel =
694*4882a593Smuzhiyun container_of(ptp, struct idt82p33_channel, caps);
695*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
696*4882a593Smuzhiyun int err;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun mutex_lock(&idt82p33->reg_lock);
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (abs(delta_ns) < phase_snap_threshold) {
701*4882a593Smuzhiyun mutex_unlock(&idt82p33->reg_lock);
702*4882a593Smuzhiyun return 0;
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun err = _idt82p33_adjtime(channel, delta_ns);
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun if (err) {
708*4882a593Smuzhiyun mutex_unlock(&idt82p33->reg_lock);
709*4882a593Smuzhiyun return err;
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun err = idt82p33_sync_tod(channel, true);
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun mutex_unlock(&idt82p33->reg_lock);
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun return err;
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
idt82p33_gettime(struct ptp_clock_info * ptp,struct timespec64 * ts)719*4882a593Smuzhiyun static int idt82p33_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun struct idt82p33_channel *channel =
722*4882a593Smuzhiyun container_of(ptp, struct idt82p33_channel, caps);
723*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
724*4882a593Smuzhiyun int err;
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun mutex_lock(&idt82p33->reg_lock);
727*4882a593Smuzhiyun err = _idt82p33_gettime(channel, ts);
728*4882a593Smuzhiyun mutex_unlock(&idt82p33->reg_lock);
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun return err;
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun
idt82p33_settime(struct ptp_clock_info * ptp,const struct timespec64 * ts)733*4882a593Smuzhiyun static int idt82p33_settime(struct ptp_clock_info *ptp,
734*4882a593Smuzhiyun const struct timespec64 *ts)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun struct idt82p33_channel *channel =
737*4882a593Smuzhiyun container_of(ptp, struct idt82p33_channel, caps);
738*4882a593Smuzhiyun struct idt82p33 *idt82p33 = channel->idt82p33;
739*4882a593Smuzhiyun int err;
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun mutex_lock(&idt82p33->reg_lock);
742*4882a593Smuzhiyun err = _idt82p33_settime(channel, ts);
743*4882a593Smuzhiyun mutex_unlock(&idt82p33->reg_lock);
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun return err;
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun
idt82p33_channel_init(struct idt82p33_channel * channel,int index)748*4882a593Smuzhiyun static int idt82p33_channel_init(struct idt82p33_channel *channel, int index)
749*4882a593Smuzhiyun {
750*4882a593Smuzhiyun switch (index) {
751*4882a593Smuzhiyun case 0:
752*4882a593Smuzhiyun channel->dpll_tod_cnfg = DPLL1_TOD_CNFG;
753*4882a593Smuzhiyun channel->dpll_tod_trigger = DPLL1_TOD_TRIGGER;
754*4882a593Smuzhiyun channel->dpll_tod_sts = DPLL1_TOD_STS;
755*4882a593Smuzhiyun channel->dpll_mode_cnfg = DPLL1_OPERATING_MODE_CNFG;
756*4882a593Smuzhiyun channel->dpll_freq_cnfg = DPLL1_HOLDOVER_FREQ_CNFG;
757*4882a593Smuzhiyun channel->dpll_phase_cnfg = DPLL1_PHASE_OFFSET_CNFG;
758*4882a593Smuzhiyun channel->dpll_sync_cnfg = DPLL1_SYNC_EDGE_CNFG;
759*4882a593Smuzhiyun channel->dpll_input_mode_cnfg = DPLL1_INPUT_MODE_CNFG;
760*4882a593Smuzhiyun break;
761*4882a593Smuzhiyun case 1:
762*4882a593Smuzhiyun channel->dpll_tod_cnfg = DPLL2_TOD_CNFG;
763*4882a593Smuzhiyun channel->dpll_tod_trigger = DPLL2_TOD_TRIGGER;
764*4882a593Smuzhiyun channel->dpll_tod_sts = DPLL2_TOD_STS;
765*4882a593Smuzhiyun channel->dpll_mode_cnfg = DPLL2_OPERATING_MODE_CNFG;
766*4882a593Smuzhiyun channel->dpll_freq_cnfg = DPLL2_HOLDOVER_FREQ_CNFG;
767*4882a593Smuzhiyun channel->dpll_phase_cnfg = DPLL2_PHASE_OFFSET_CNFG;
768*4882a593Smuzhiyun channel->dpll_sync_cnfg = DPLL2_SYNC_EDGE_CNFG;
769*4882a593Smuzhiyun channel->dpll_input_mode_cnfg = DPLL2_INPUT_MODE_CNFG;
770*4882a593Smuzhiyun break;
771*4882a593Smuzhiyun default:
772*4882a593Smuzhiyun return -EINVAL;
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun INIT_DELAYED_WORK(&channel->sync_tod_work,
776*4882a593Smuzhiyun idt82p33_sync_tod_work_handler);
777*4882a593Smuzhiyun channel->sync_tod_on = false;
778*4882a593Smuzhiyun channel->current_freq_ppb = 0;
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun return 0;
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun
idt82p33_caps_init(struct ptp_clock_info * caps)783*4882a593Smuzhiyun static void idt82p33_caps_init(struct ptp_clock_info *caps)
784*4882a593Smuzhiyun {
785*4882a593Smuzhiyun caps->owner = THIS_MODULE;
786*4882a593Smuzhiyun caps->max_adj = 92000;
787*4882a593Smuzhiyun caps->adjfine = idt82p33_adjfine;
788*4882a593Smuzhiyun caps->adjtime = idt82p33_adjtime;
789*4882a593Smuzhiyun caps->gettime64 = idt82p33_gettime;
790*4882a593Smuzhiyun caps->settime64 = idt82p33_settime;
791*4882a593Smuzhiyun caps->enable = idt82p33_enable;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun
idt82p33_enable_channel(struct idt82p33 * idt82p33,u32 index)794*4882a593Smuzhiyun static int idt82p33_enable_channel(struct idt82p33 *idt82p33, u32 index)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun struct idt82p33_channel *channel;
797*4882a593Smuzhiyun int err;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun if (!(index < MAX_PHC_PLL))
800*4882a593Smuzhiyun return -EINVAL;
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun channel = &idt82p33->channel[index];
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun err = idt82p33_channel_init(channel, index);
805*4882a593Smuzhiyun if (err)
806*4882a593Smuzhiyun return err;
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun channel->idt82p33 = idt82p33;
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun idt82p33_caps_init(&channel->caps);
811*4882a593Smuzhiyun snprintf(channel->caps.name, sizeof(channel->caps.name),
812*4882a593Smuzhiyun "IDT 82P33 PLL%u", index);
813*4882a593Smuzhiyun channel->caps.n_per_out = hweight8(channel->output_mask);
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun err = idt82p33_dpll_set_mode(channel, PLL_MODE_DCO);
816*4882a593Smuzhiyun if (err)
817*4882a593Smuzhiyun return err;
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun err = idt82p33_enable_tod(channel);
820*4882a593Smuzhiyun if (err)
821*4882a593Smuzhiyun return err;
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun channel->ptp_clock = ptp_clock_register(&channel->caps, NULL);
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun if (IS_ERR(channel->ptp_clock)) {
826*4882a593Smuzhiyun err = PTR_ERR(channel->ptp_clock);
827*4882a593Smuzhiyun channel->ptp_clock = NULL;
828*4882a593Smuzhiyun return err;
829*4882a593Smuzhiyun }
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun if (!channel->ptp_clock)
832*4882a593Smuzhiyun return -ENOTSUPP;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun dev_info(&idt82p33->client->dev, "PLL%d registered as ptp%d\n",
835*4882a593Smuzhiyun index, channel->ptp_clock->index);
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun return 0;
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun
idt82p33_load_firmware(struct idt82p33 * idt82p33)840*4882a593Smuzhiyun static int idt82p33_load_firmware(struct idt82p33 *idt82p33)
841*4882a593Smuzhiyun {
842*4882a593Smuzhiyun const struct firmware *fw;
843*4882a593Smuzhiyun struct idt82p33_fwrc *rec;
844*4882a593Smuzhiyun u8 loaddr, page, val;
845*4882a593Smuzhiyun int err;
846*4882a593Smuzhiyun s32 len;
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun dev_dbg(&idt82p33->client->dev,
849*4882a593Smuzhiyun "requesting firmware '%s'\n", FW_FILENAME);
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun err = request_firmware(&fw, FW_FILENAME, &idt82p33->client->dev);
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun if (err)
854*4882a593Smuzhiyun return err;
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun dev_dbg(&idt82p33->client->dev, "firmware size %zu bytes\n", fw->size);
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun rec = (struct idt82p33_fwrc *) fw->data;
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun for (len = fw->size; len > 0; len -= sizeof(*rec)) {
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun if (rec->reserved) {
863*4882a593Smuzhiyun dev_err(&idt82p33->client->dev,
864*4882a593Smuzhiyun "bad firmware, reserved field non-zero\n");
865*4882a593Smuzhiyun err = -EINVAL;
866*4882a593Smuzhiyun } else {
867*4882a593Smuzhiyun val = rec->value;
868*4882a593Smuzhiyun loaddr = rec->loaddr;
869*4882a593Smuzhiyun page = rec->hiaddr;
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun rec++;
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun err = idt82p33_check_and_set_masks(idt82p33, page,
874*4882a593Smuzhiyun loaddr, val);
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun if (err == 0) {
878*4882a593Smuzhiyun /* maximum 8 pages */
879*4882a593Smuzhiyun if (page >= PAGE_NUM)
880*4882a593Smuzhiyun continue;
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun /* Page size 128, last 4 bytes of page skipped */
883*4882a593Smuzhiyun if (((loaddr > 0x7b) && (loaddr <= 0x7f))
884*4882a593Smuzhiyun || loaddr > 0xfb)
885*4882a593Smuzhiyun continue;
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun err = idt82p33_write(idt82p33, _ADDR(page, loaddr),
888*4882a593Smuzhiyun &val, sizeof(val));
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun if (err)
892*4882a593Smuzhiyun goto out;
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun idt82p33_display_masks(idt82p33);
896*4882a593Smuzhiyun out:
897*4882a593Smuzhiyun release_firmware(fw);
898*4882a593Smuzhiyun return err;
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun
idt82p33_probe(struct i2c_client * client,const struct i2c_device_id * id)902*4882a593Smuzhiyun static int idt82p33_probe(struct i2c_client *client,
903*4882a593Smuzhiyun const struct i2c_device_id *id)
904*4882a593Smuzhiyun {
905*4882a593Smuzhiyun struct idt82p33 *idt82p33;
906*4882a593Smuzhiyun int err;
907*4882a593Smuzhiyun u8 i;
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun (void)id;
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun idt82p33 = devm_kzalloc(&client->dev,
912*4882a593Smuzhiyun sizeof(struct idt82p33), GFP_KERNEL);
913*4882a593Smuzhiyun if (!idt82p33)
914*4882a593Smuzhiyun return -ENOMEM;
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun mutex_init(&idt82p33->reg_lock);
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun idt82p33->client = client;
919*4882a593Smuzhiyun idt82p33->page_offset = 0xff;
920*4882a593Smuzhiyun idt82p33->tod_write_overhead_ns = 0;
921*4882a593Smuzhiyun idt82p33->calculate_overhead_flag = 0;
922*4882a593Smuzhiyun idt82p33->pll_mask = DEFAULT_PLL_MASK;
923*4882a593Smuzhiyun idt82p33->channel[0].output_mask = DEFAULT_OUTPUT_MASK_PLL0;
924*4882a593Smuzhiyun idt82p33->channel[1].output_mask = DEFAULT_OUTPUT_MASK_PLL1;
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun mutex_lock(&idt82p33->reg_lock);
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun err = idt82p33_load_firmware(idt82p33);
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun if (err)
931*4882a593Smuzhiyun dev_warn(&idt82p33->client->dev,
932*4882a593Smuzhiyun "loading firmware failed with %d\n", err);
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun if (idt82p33->pll_mask) {
935*4882a593Smuzhiyun for (i = 0; i < MAX_PHC_PLL; i++) {
936*4882a593Smuzhiyun if (idt82p33->pll_mask & (1 << i)) {
937*4882a593Smuzhiyun err = idt82p33_enable_channel(idt82p33, i);
938*4882a593Smuzhiyun if (err)
939*4882a593Smuzhiyun break;
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun } else {
943*4882a593Smuzhiyun dev_err(&idt82p33->client->dev,
944*4882a593Smuzhiyun "no PLLs flagged as PHCs, nothing to do\n");
945*4882a593Smuzhiyun err = -ENODEV;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun mutex_unlock(&idt82p33->reg_lock);
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun if (err) {
951*4882a593Smuzhiyun idt82p33_ptp_clock_unregister_all(idt82p33);
952*4882a593Smuzhiyun return err;
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun i2c_set_clientdata(client, idt82p33);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun return 0;
958*4882a593Smuzhiyun }
959*4882a593Smuzhiyun
idt82p33_remove(struct i2c_client * client)960*4882a593Smuzhiyun static int idt82p33_remove(struct i2c_client *client)
961*4882a593Smuzhiyun {
962*4882a593Smuzhiyun struct idt82p33 *idt82p33 = i2c_get_clientdata(client);
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun idt82p33_ptp_clock_unregister_all(idt82p33);
965*4882a593Smuzhiyun mutex_destroy(&idt82p33->reg_lock);
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun return 0;
968*4882a593Smuzhiyun }
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun #ifdef CONFIG_OF
971*4882a593Smuzhiyun static const struct of_device_id idt82p33_dt_id[] = {
972*4882a593Smuzhiyun { .compatible = "idt,82p33810" },
973*4882a593Smuzhiyun { .compatible = "idt,82p33813" },
974*4882a593Smuzhiyun { .compatible = "idt,82p33814" },
975*4882a593Smuzhiyun { .compatible = "idt,82p33831" },
976*4882a593Smuzhiyun { .compatible = "idt,82p33910" },
977*4882a593Smuzhiyun { .compatible = "idt,82p33913" },
978*4882a593Smuzhiyun { .compatible = "idt,82p33914" },
979*4882a593Smuzhiyun { .compatible = "idt,82p33931" },
980*4882a593Smuzhiyun {},
981*4882a593Smuzhiyun };
982*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, idt82p33_dt_id);
983*4882a593Smuzhiyun #endif
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun static const struct i2c_device_id idt82p33_i2c_id[] = {
986*4882a593Smuzhiyun { "idt82p33810", },
987*4882a593Smuzhiyun { "idt82p33813", },
988*4882a593Smuzhiyun { "idt82p33814", },
989*4882a593Smuzhiyun { "idt82p33831", },
990*4882a593Smuzhiyun { "idt82p33910", },
991*4882a593Smuzhiyun { "idt82p33913", },
992*4882a593Smuzhiyun { "idt82p33914", },
993*4882a593Smuzhiyun { "idt82p33931", },
994*4882a593Smuzhiyun {},
995*4882a593Smuzhiyun };
996*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, idt82p33_i2c_id);
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun static struct i2c_driver idt82p33_driver = {
999*4882a593Smuzhiyun .driver = {
1000*4882a593Smuzhiyun .of_match_table = of_match_ptr(idt82p33_dt_id),
1001*4882a593Smuzhiyun .name = "idt82p33",
1002*4882a593Smuzhiyun },
1003*4882a593Smuzhiyun .probe = idt82p33_probe,
1004*4882a593Smuzhiyun .remove = idt82p33_remove,
1005*4882a593Smuzhiyun .id_table = idt82p33_i2c_id,
1006*4882a593Smuzhiyun };
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun module_i2c_driver(idt82p33_driver);
1009