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