1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot PTP clock driver
3 *
4 * Copyright (c) 2017 Microsemi Corporation
5 * Copyright 2020 NXP
6 */
7 #include <linux/time64.h>
8
9 #include <soc/mscc/ocelot_ptp.h>
10 #include <soc/mscc/ocelot_sys.h>
11 #include <soc/mscc/ocelot.h>
12
ocelot_ptp_gettime64(struct ptp_clock_info * ptp,struct timespec64 * ts)13 int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
14 {
15 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
16 unsigned long flags;
17 time64_t s;
18 u32 val;
19 s64 ns;
20
21 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
22
23 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
24 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
25 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
26 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
27
28 s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN) & 0xffff;
29 s <<= 32;
30 s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
31 ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
32
33 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
34
35 /* Deal with negative values */
36 if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) {
37 s--;
38 ns &= 0xf;
39 ns += 999999984;
40 }
41
42 set_normalized_timespec64(ts, s, ns);
43 return 0;
44 }
45 EXPORT_SYMBOL(ocelot_ptp_gettime64);
46
ocelot_ptp_settime64(struct ptp_clock_info * ptp,const struct timespec64 * ts)47 int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
48 const struct timespec64 *ts)
49 {
50 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
51 unsigned long flags;
52 u32 val;
53
54 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
55
56 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
57 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
58 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
59
60 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
61
62 ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
63 TOD_ACC_PIN);
64 ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
65 TOD_ACC_PIN);
66 ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
67
68 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
69 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
70 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
71
72 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
73
74 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
75 return 0;
76 }
77 EXPORT_SYMBOL(ocelot_ptp_settime64);
78
ocelot_ptp_adjtime(struct ptp_clock_info * ptp,s64 delta)79 int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
80 {
81 if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
82 struct ocelot *ocelot = container_of(ptp, struct ocelot,
83 ptp_info);
84 unsigned long flags;
85 u32 val;
86
87 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
88
89 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
90 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK |
91 PTP_PIN_CFG_DOM);
92 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
93
94 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
95
96 ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
97 ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
98 ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
99
100 val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
101 val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK |
102 PTP_PIN_CFG_DOM);
103 val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA);
104
105 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
106
107 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
108 } else {
109 /* Fall back using ocelot_ptp_settime64 which is not exact. */
110 struct timespec64 ts;
111 u64 now;
112
113 ocelot_ptp_gettime64(ptp, &ts);
114
115 now = ktime_to_ns(timespec64_to_ktime(ts));
116 ts = ns_to_timespec64(now + delta);
117
118 ocelot_ptp_settime64(ptp, &ts);
119 }
120 return 0;
121 }
122 EXPORT_SYMBOL(ocelot_ptp_adjtime);
123
ocelot_ptp_adjfine(struct ptp_clock_info * ptp,long scaled_ppm)124 int ocelot_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
125 {
126 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
127 u32 unit = 0, direction = 0;
128 unsigned long flags;
129 u64 adj = 0;
130
131 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
132
133 if (!scaled_ppm)
134 goto disable_adj;
135
136 if (scaled_ppm < 0) {
137 direction = PTP_CFG_CLK_ADJ_CFG_DIR;
138 scaled_ppm = -scaled_ppm;
139 }
140
141 adj = PSEC_PER_SEC << 16;
142 do_div(adj, scaled_ppm);
143 do_div(adj, 1000);
144
145 /* If the adjustment value is too large, use ns instead */
146 if (adj >= (1L << 30)) {
147 unit = PTP_CFG_CLK_ADJ_FREQ_NS;
148 do_div(adj, 1000);
149 }
150
151 /* Still too big */
152 if (adj >= (1L << 30))
153 goto disable_adj;
154
155 ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ);
156 ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction,
157 PTP_CLK_CFG_ADJ_CFG);
158
159 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
160 return 0;
161
162 disable_adj:
163 ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG);
164
165 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
166 return 0;
167 }
168 EXPORT_SYMBOL(ocelot_ptp_adjfine);
169
ocelot_ptp_verify(struct ptp_clock_info * ptp,unsigned int pin,enum ptp_pin_function func,unsigned int chan)170 int ocelot_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
171 enum ptp_pin_function func, unsigned int chan)
172 {
173 switch (func) {
174 case PTP_PF_NONE:
175 case PTP_PF_PEROUT:
176 break;
177 case PTP_PF_EXTTS:
178 case PTP_PF_PHYSYNC:
179 return -1;
180 }
181 return 0;
182 }
183 EXPORT_SYMBOL(ocelot_ptp_verify);
184
ocelot_ptp_enable(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)185 int ocelot_ptp_enable(struct ptp_clock_info *ptp,
186 struct ptp_clock_request *rq, int on)
187 {
188 struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
189 struct timespec64 ts_phase, ts_period;
190 enum ocelot_ptp_pins ptp_pin;
191 unsigned long flags;
192 bool pps = false;
193 int pin = -1;
194 s64 wf_high;
195 s64 wf_low;
196 u32 val;
197
198 switch (rq->type) {
199 case PTP_CLK_REQ_PEROUT:
200 /* Reject requests with unsupported flags */
201 if (rq->perout.flags & ~(PTP_PEROUT_DUTY_CYCLE |
202 PTP_PEROUT_PHASE))
203 return -EOPNOTSUPP;
204
205 pin = ptp_find_pin(ocelot->ptp_clock, PTP_PF_PEROUT,
206 rq->perout.index);
207 if (pin == 0)
208 ptp_pin = PTP_PIN_0;
209 else if (pin == 1)
210 ptp_pin = PTP_PIN_1;
211 else if (pin == 2)
212 ptp_pin = PTP_PIN_2;
213 else if (pin == 3)
214 ptp_pin = PTP_PIN_3;
215 else
216 return -EBUSY;
217
218 ts_period.tv_sec = rq->perout.period.sec;
219 ts_period.tv_nsec = rq->perout.period.nsec;
220
221 if (ts_period.tv_sec == 1 && ts_period.tv_nsec == 0)
222 pps = true;
223
224 /* Handle turning off */
225 if (!on) {
226 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
227 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
228 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
229 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
230 break;
231 }
232
233 if (rq->perout.flags & PTP_PEROUT_PHASE) {
234 ts_phase.tv_sec = rq->perout.phase.sec;
235 ts_phase.tv_nsec = rq->perout.phase.nsec;
236 } else {
237 /* Compatibility */
238 ts_phase.tv_sec = rq->perout.start.sec;
239 ts_phase.tv_nsec = rq->perout.start.nsec;
240 }
241 if (ts_phase.tv_sec || (ts_phase.tv_nsec && !pps)) {
242 dev_warn(ocelot->dev,
243 "Absolute start time not supported!\n");
244 dev_warn(ocelot->dev,
245 "Accept nsec for PPS phase adjustment, otherwise start time should be 0 0.\n");
246 return -EINVAL;
247 }
248
249 /* Calculate waveform high and low times */
250 if (rq->perout.flags & PTP_PEROUT_DUTY_CYCLE) {
251 struct timespec64 ts_on;
252
253 ts_on.tv_sec = rq->perout.on.sec;
254 ts_on.tv_nsec = rq->perout.on.nsec;
255
256 wf_high = timespec64_to_ns(&ts_on);
257 } else {
258 if (pps) {
259 wf_high = 1000;
260 } else {
261 wf_high = timespec64_to_ns(&ts_period);
262 wf_high = div_s64(wf_high, 2);
263 }
264 }
265
266 wf_low = timespec64_to_ns(&ts_period);
267 wf_low -= wf_high;
268
269 /* Handle PPS request */
270 if (pps) {
271 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
272 ocelot_write_rix(ocelot, ts_phase.tv_nsec,
273 PTP_PIN_WF_LOW_PERIOD, ptp_pin);
274 ocelot_write_rix(ocelot, wf_high,
275 PTP_PIN_WF_HIGH_PERIOD, ptp_pin);
276 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK);
277 val |= PTP_PIN_CFG_SYNC;
278 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
279 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
280 break;
281 }
282
283 /* Handle periodic clock */
284 if (wf_high > 0x3fffffff || wf_high <= 0x6)
285 return -EINVAL;
286 if (wf_low > 0x3fffffff || wf_low <= 0x6)
287 return -EINVAL;
288
289 spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
290 ocelot_write_rix(ocelot, wf_low, PTP_PIN_WF_LOW_PERIOD,
291 ptp_pin);
292 ocelot_write_rix(ocelot, wf_high, PTP_PIN_WF_HIGH_PERIOD,
293 ptp_pin);
294 val = PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_CLOCK);
295 ocelot_write_rix(ocelot, val, PTP_PIN_CFG, ptp_pin);
296 spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
297 break;
298 default:
299 return -EOPNOTSUPP;
300 }
301 return 0;
302 }
303 EXPORT_SYMBOL(ocelot_ptp_enable);
304
ocelot_init_timestamp(struct ocelot * ocelot,const struct ptp_clock_info * info)305 int ocelot_init_timestamp(struct ocelot *ocelot,
306 const struct ptp_clock_info *info)
307 {
308 struct ptp_clock *ptp_clock;
309 int i;
310
311 ocelot->ptp_info = *info;
312
313 for (i = 0; i < OCELOT_PTP_PINS_NUM; i++) {
314 struct ptp_pin_desc *p = &ocelot->ptp_pins[i];
315
316 snprintf(p->name, sizeof(p->name), "switch_1588_dat%d", i);
317 p->index = i;
318 p->func = PTP_PF_NONE;
319 }
320
321 ocelot->ptp_info.pin_config = &ocelot->ptp_pins[0];
322
323 ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
324 if (IS_ERR(ptp_clock))
325 return PTR_ERR(ptp_clock);
326 /* Check if PHC support is missing at the configuration level */
327 if (!ptp_clock)
328 return 0;
329
330 ocelot->ptp_clock = ptp_clock;
331
332 ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
333 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
334 ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
335
336 ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
337
338 /* There is no device reconfiguration, PTP Rx stamping is always
339 * enabled.
340 */
341 ocelot->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
342
343 return 0;
344 }
345 EXPORT_SYMBOL(ocelot_init_timestamp);
346
ocelot_deinit_timestamp(struct ocelot * ocelot)347 int ocelot_deinit_timestamp(struct ocelot *ocelot)
348 {
349 if (ocelot->ptp_clock)
350 ptp_clock_unregister(ocelot->ptp_clock);
351 return 0;
352 }
353 EXPORT_SYMBOL(ocelot_deinit_timestamp);
354