@@ -41,6 +41,20 @@ void idpf_ptp_get_features_access(const struct idpf_adapter *adapter)
4141 ptp -> get_dev_clk_time_access = idpf_ptp_get_access (adapter ,
4242 direct ,
4343 mailbox );
44+
45+ /* Set the device clock time */
46+ direct = VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME ;
47+ mailbox = VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME ;
48+ ptp -> set_dev_clk_time_access = idpf_ptp_get_access (adapter ,
49+ direct ,
50+ mailbox );
51+
52+ /* Adjust the device clock time */
53+ direct = VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK ;
54+ mailbox = VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK_MB ;
55+ ptp -> adj_dev_clk_time_access = idpf_ptp_get_access (adapter ,
56+ direct ,
57+ mailbox );
4458}
4559
4660/**
@@ -177,6 +191,157 @@ static int idpf_ptp_gettimex64(struct ptp_clock_info *info,
177191 return 0 ;
178192}
179193
194+ /**
195+ * idpf_ptp_settime64 - Set the time of the clock
196+ * @info: the driver's PTP info structure
197+ * @ts: timespec64 structure that holds the new time value
198+ *
199+ * Set the device clock to the user input value. The conversion from timespec
200+ * to ns happens in the write function.
201+ *
202+ * Return: 0 on success, -errno otherwise.
203+ */
204+ static int idpf_ptp_settime64 (struct ptp_clock_info * info ,
205+ const struct timespec64 * ts )
206+ {
207+ struct idpf_adapter * adapter = idpf_ptp_info_to_adapter (info );
208+ enum idpf_ptp_access access ;
209+ int err ;
210+ u64 ns ;
211+
212+ access = adapter -> ptp -> set_dev_clk_time_access ;
213+ if (access != IDPF_PTP_MAILBOX )
214+ return - EOPNOTSUPP ;
215+
216+ ns = timespec64_to_ns (ts );
217+
218+ err = idpf_ptp_set_dev_clk_time (adapter , ns );
219+ if (err ) {
220+ pci_err (adapter -> pdev , "Failed to set the time, err: %pe\n" ,
221+ ERR_PTR (err ));
222+ return err ;
223+ }
224+
225+ return 0 ;
226+ }
227+
228+ /**
229+ * idpf_ptp_adjtime_nonatomic - Do a non-atomic clock adjustment
230+ * @info: the driver's PTP info structure
231+ * @delta: Offset in nanoseconds to adjust the time by
232+ *
233+ * Return: 0 on success, -errno otherwise.
234+ */
235+ static int idpf_ptp_adjtime_nonatomic (struct ptp_clock_info * info , s64 delta )
236+ {
237+ struct timespec64 now , then ;
238+ int err ;
239+
240+ err = idpf_ptp_gettimex64 (info , & now , NULL );
241+ if (err )
242+ return err ;
243+
244+ then = ns_to_timespec64 (delta );
245+ now = timespec64_add (now , then );
246+
247+ return idpf_ptp_settime64 (info , & now );
248+ }
249+
250+ /**
251+ * idpf_ptp_adjtime - Adjust the time of the clock by the indicated delta
252+ * @info: the driver's PTP info structure
253+ * @delta: Offset in nanoseconds to adjust the time by
254+ *
255+ * Return: 0 on success, -errno otherwise.
256+ */
257+ static int idpf_ptp_adjtime (struct ptp_clock_info * info , s64 delta )
258+ {
259+ struct idpf_adapter * adapter = idpf_ptp_info_to_adapter (info );
260+ enum idpf_ptp_access access ;
261+ int err ;
262+
263+ access = adapter -> ptp -> adj_dev_clk_time_access ;
264+ if (access != IDPF_PTP_MAILBOX )
265+ return - EOPNOTSUPP ;
266+
267+ /* Hardware only supports atomic adjustments using signed 32-bit
268+ * integers. For any adjustment outside this range, perform
269+ * a non-atomic get->adjust->set flow.
270+ */
271+ if (delta > S32_MAX || delta < S32_MIN )
272+ return idpf_ptp_adjtime_nonatomic (info , delta );
273+
274+ err = idpf_ptp_adj_dev_clk_time (adapter , delta );
275+ if (err ) {
276+ pci_err (adapter -> pdev , "Failed to adjust the clock with delta %lld err: %pe\n" ,
277+ delta , ERR_PTR (err ));
278+ return err ;
279+ }
280+
281+ return 0 ;
282+ }
283+
284+ /**
285+ * idpf_ptp_adjfine - Adjust clock increment rate
286+ * @info: the driver's PTP info structure
287+ * @scaled_ppm: Parts per million with 16-bit fractional field
288+ *
289+ * Adjust the frequency of the clock by the indicated scaled ppm from the
290+ * base frequency.
291+ *
292+ * Return: 0 on success, -errno otherwise.
293+ */
294+ static int idpf_ptp_adjfine (struct ptp_clock_info * info , long scaled_ppm )
295+ {
296+ struct idpf_adapter * adapter = idpf_ptp_info_to_adapter (info );
297+ enum idpf_ptp_access access ;
298+ u64 incval , diff ;
299+ int err ;
300+
301+ access = adapter -> ptp -> adj_dev_clk_time_access ;
302+ if (access != IDPF_PTP_MAILBOX )
303+ return - EOPNOTSUPP ;
304+
305+ incval = adapter -> ptp -> base_incval ;
306+
307+ diff = adjust_by_scaled_ppm (incval , scaled_ppm );
308+ err = idpf_ptp_adj_dev_clk_fine (adapter , diff );
309+ if (err )
310+ pci_err (adapter -> pdev , "Failed to adjust clock increment rate for scaled ppm %ld %pe\n" ,
311+ scaled_ppm , ERR_PTR (err ));
312+
313+ return 0 ;
314+ }
315+
316+ /**
317+ * idpf_ptp_verify_pin - Verify if pin supports requested pin function
318+ * @info: the driver's PTP info structure
319+ * @pin: Pin index
320+ * @func: Assigned function
321+ * @chan: Assigned channel
322+ *
323+ * Return: EOPNOTSUPP as not supported yet.
324+ */
325+ static int idpf_ptp_verify_pin (struct ptp_clock_info * info , unsigned int pin ,
326+ enum ptp_pin_function func , unsigned int chan )
327+ {
328+ return - EOPNOTSUPP ;
329+ }
330+
331+ /**
332+ * idpf_ptp_gpio_enable - Enable/disable ancillary features of PHC
333+ * @info: the driver's PTP info structure
334+ * @rq: The requested feature to change
335+ * @on: Enable/disable flag
336+ *
337+ * Return: EOPNOTSUPP as not supported yet.
338+ */
339+ static int idpf_ptp_gpio_enable (struct ptp_clock_info * info ,
340+ struct ptp_clock_request * rq , int on )
341+ {
342+ return - EOPNOTSUPP ;
343+ }
344+
180345/**
181346 * idpf_ptp_set_caps - Set PTP capabilities
182347 * @adapter: Driver specific private structure
@@ -191,7 +356,13 @@ static void idpf_ptp_set_caps(const struct idpf_adapter *adapter)
191356 KBUILD_MODNAME , pci_name (adapter -> pdev ));
192357
193358 info -> owner = THIS_MODULE ;
359+ info -> max_adj = adapter -> ptp -> max_adj ;
194360 info -> gettimex64 = idpf_ptp_gettimex64 ;
361+ info -> settime64 = idpf_ptp_settime64 ;
362+ info -> adjfine = idpf_ptp_adjfine ;
363+ info -> adjtime = idpf_ptp_adjtime ;
364+ info -> verify = idpf_ptp_verify_pin ;
365+ info -> enable = idpf_ptp_gpio_enable ;
195366}
196367
197368/**
@@ -234,6 +405,7 @@ static int idpf_ptp_create_clock(const struct idpf_adapter *adapter)
234405 */
235406int idpf_ptp_init (struct idpf_adapter * adapter )
236407{
408+ struct timespec64 ts ;
237409 int err ;
238410
239411 if (!idpf_is_cap_ena (adapter , IDPF_OTHER_CAPS , VIRTCHNL2_CAP_PTP )) {
@@ -261,12 +433,34 @@ int idpf_ptp_init(struct idpf_adapter *adapter)
261433 if (err )
262434 goto free_ptp ;
263435
436+ /* Write the default increment time value if the clock adjustments
437+ * are enabled.
438+ */
439+ if (adapter -> ptp -> adj_dev_clk_time_access != IDPF_PTP_NONE ) {
440+ err = idpf_ptp_adj_dev_clk_fine (adapter ,
441+ adapter -> ptp -> base_incval );
442+ if (err )
443+ goto remove_clock ;
444+ }
445+
446+ /* Write the initial time value if the set time operation is enabled */
447+ if (adapter -> ptp -> set_dev_clk_time_access != IDPF_PTP_NONE ) {
448+ ts = ktime_to_timespec64 (ktime_get_real ());
449+ err = idpf_ptp_settime64 (& adapter -> ptp -> info , & ts );
450+ if (err )
451+ goto remove_clock ;
452+ }
453+
264454 spin_lock_init (& adapter -> ptp -> read_dev_clk_lock );
265455
266456 pci_dbg (adapter -> pdev , "PTP init successful\n" );
267457
268458 return 0 ;
269459
460+ remove_clock :
461+ ptp_clock_unregister (adapter -> ptp -> clock );
462+ adapter -> ptp -> clock = NULL ;
463+
270464free_ptp :
271465 kfree (adapter -> ptp );
272466 adapter -> ptp = NULL ;
0 commit comments