• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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