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