@@ -165,11 +165,132 @@ int ocelot_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
165
165
}
166
166
EXPORT_SYMBOL (ocelot_ptp_adjfine );
167
167
168
+ int 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
+ }
181
+ EXPORT_SYMBOL (ocelot_ptp_verify );
182
+
183
+ int 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_start , ts_period ;
188
+ enum ocelot_ptp_pins ptp_pin ;
189
+ unsigned long flags ;
190
+ bool pps = false;
191
+ int pin = -1 ;
192
+ u32 val ;
193
+ s64 ns ;
194
+
195
+ switch (rq -> type ) {
196
+ case PTP_CLK_REQ_PEROUT :
197
+ /* Reject requests with unsupported flags */
198
+ if (rq -> perout .flags )
199
+ return - EOPNOTSUPP ;
200
+
201
+ pin = ptp_find_pin (ocelot -> ptp_clock , PTP_PF_PEROUT ,
202
+ rq -> perout .index );
203
+ if (pin == 0 )
204
+ ptp_pin = PTP_PIN_0 ;
205
+ else if (pin == 1 )
206
+ ptp_pin = PTP_PIN_1 ;
207
+ else if (pin == 2 )
208
+ ptp_pin = PTP_PIN_2 ;
209
+ else if (pin == 3 )
210
+ ptp_pin = PTP_PIN_3 ;
211
+ else
212
+ return - EBUSY ;
213
+
214
+ ts_start .tv_sec = rq -> perout .start .sec ;
215
+ ts_start .tv_nsec = rq -> perout .start .nsec ;
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
+ if (ts_start .tv_sec || (ts_start .tv_nsec && !pps )) {
223
+ dev_warn (ocelot -> dev ,
224
+ "Absolute start time not supported!\n" );
225
+ dev_warn (ocelot -> dev ,
226
+ "Accept nsec for PPS phase adjustment, otherwise start time should be 0 0.\n" );
227
+ return - EINVAL ;
228
+ }
229
+
230
+ /* Handle turning off */
231
+ if (!on ) {
232
+ spin_lock_irqsave (& ocelot -> ptp_clock_lock , flags );
233
+ val = PTP_PIN_CFG_ACTION (PTP_PIN_ACTION_IDLE );
234
+ ocelot_write_rix (ocelot , val , PTP_PIN_CFG , ptp_pin );
235
+ spin_unlock_irqrestore (& ocelot -> ptp_clock_lock , flags );
236
+ break ;
237
+ }
238
+
239
+ /* Handle PPS request */
240
+ if (pps ) {
241
+ spin_lock_irqsave (& ocelot -> ptp_clock_lock , flags );
242
+ /* Pulse generated perout.start.nsec after TOD has
243
+ * increased seconds.
244
+ * Pulse width is set to 1us.
245
+ */
246
+ ocelot_write_rix (ocelot , ts_start .tv_nsec ,
247
+ PTP_PIN_WF_LOW_PERIOD , ptp_pin );
248
+ ocelot_write_rix (ocelot , 1000 ,
249
+ PTP_PIN_WF_HIGH_PERIOD , ptp_pin );
250
+ val = PTP_PIN_CFG_ACTION (PTP_PIN_ACTION_CLOCK );
251
+ val |= PTP_PIN_CFG_SYNC ;
252
+ ocelot_write_rix (ocelot , val , PTP_PIN_CFG , ptp_pin );
253
+ spin_unlock_irqrestore (& ocelot -> ptp_clock_lock , flags );
254
+ break ;
255
+ }
256
+
257
+ /* Handle periodic clock */
258
+ ns = timespec64_to_ns (& ts_period );
259
+ ns = ns >> 1 ;
260
+ if (ns > 0x3fffffff || ns <= 0x6 )
261
+ return - EINVAL ;
262
+
263
+ spin_lock_irqsave (& ocelot -> ptp_clock_lock , flags );
264
+ ocelot_write_rix (ocelot , ns , PTP_PIN_WF_LOW_PERIOD , ptp_pin );
265
+ ocelot_write_rix (ocelot , ns , PTP_PIN_WF_HIGH_PERIOD , ptp_pin );
266
+ val = PTP_PIN_CFG_ACTION (PTP_PIN_ACTION_CLOCK );
267
+ ocelot_write_rix (ocelot , val , PTP_PIN_CFG , ptp_pin );
268
+ spin_unlock_irqrestore (& ocelot -> ptp_clock_lock , flags );
269
+ break ;
270
+ default :
271
+ return - EOPNOTSUPP ;
272
+ }
273
+ return 0 ;
274
+ }
275
+ EXPORT_SYMBOL (ocelot_ptp_enable );
276
+
168
277
int ocelot_init_timestamp (struct ocelot * ocelot , struct ptp_clock_info * info )
169
278
{
170
279
struct ptp_clock * ptp_clock ;
280
+ int i ;
171
281
172
282
ocelot -> ptp_info = * info ;
283
+
284
+ for (i = 0 ; i < OCELOT_PTP_PINS_NUM ; i ++ ) {
285
+ struct ptp_pin_desc * p = & ocelot -> ptp_pins [i ];
286
+
287
+ snprintf (p -> name , sizeof (p -> name ), "switch_1588_dat%d" , i );
288
+ p -> index = i ;
289
+ p -> func = PTP_PF_NONE ;
290
+ }
291
+
292
+ ocelot -> ptp_info .pin_config = & ocelot -> ptp_pins [0 ];
293
+
173
294
ptp_clock = ptp_clock_register (& ocelot -> ptp_info , ocelot -> dev );
174
295
if (IS_ERR (ptp_clock ))
175
296
return PTR_ERR (ptp_clock );
0 commit comments