@@ -305,7 +305,90 @@ static void sti_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
305
305
clear_bit (pwm -> hwpwm , & pc -> configured );
306
306
}
307
307
308
+ static int sti_pwm_capture (struct pwm_chip * chip , struct pwm_device * pwm ,
309
+ struct pwm_capture * result , unsigned long timeout )
310
+ {
311
+ struct sti_pwm_chip * pc = to_sti_pwmchip (chip );
312
+ struct sti_pwm_compat_data * cdata = pc -> cdata ;
313
+ struct sti_cpt_ddata * ddata = pwm_get_chip_data (pwm );
314
+ struct device * dev = pc -> dev ;
315
+ unsigned int effective_ticks ;
316
+ unsigned long long high , low ;
317
+ int ret ;
318
+
319
+ if (pwm -> hwpwm >= cdata -> cpt_num_devs ) {
320
+ dev_err (dev , "device %u is not valid\n" , pwm -> hwpwm );
321
+ return - EINVAL ;
322
+ }
323
+
324
+ mutex_lock (& ddata -> lock );
325
+ ddata -> index = 0 ;
326
+
327
+ /* Prepare capture measurement */
328
+ regmap_write (pc -> regmap , PWM_CPT_EDGE (pwm -> hwpwm ), CPT_EDGE_RISING );
329
+ regmap_field_write (pc -> pwm_cpt_int_en , BIT (pwm -> hwpwm ));
330
+
331
+ /* Enable capture */
332
+ ret = regmap_field_write (pc -> pwm_cpt_en , 1 );
333
+ if (ret ) {
334
+ dev_err (dev , "failed to enable PWM capture %u: %d\n" ,
335
+ pwm -> hwpwm , ret );
336
+ goto out ;
337
+ }
338
+
339
+ ret = wait_event_interruptible_timeout (ddata -> wait , ddata -> index > 1 ,
340
+ msecs_to_jiffies (timeout ));
341
+
342
+ regmap_write (pc -> regmap , PWM_CPT_EDGE (pwm -> hwpwm ), CPT_EDGE_DISABLED );
343
+
344
+ if (ret == - ERESTARTSYS )
345
+ goto out ;
346
+
347
+ switch (ddata -> index ) {
348
+ case 0 :
349
+ case 1 :
350
+ /*
351
+ * Getting here could mean:
352
+ * - input signal is constant of less than 1 Hz
353
+ * - there is no input signal at all
354
+ *
355
+ * In such case the frequency is rounded down to 0
356
+ */
357
+ result -> period = 0 ;
358
+ result -> duty_cycle = 0 ;
359
+
360
+ break ;
361
+
362
+ case 2 :
363
+ /* We have everying we need */
364
+ high = ddata -> snapshot [1 ] - ddata -> snapshot [0 ];
365
+ low = ddata -> snapshot [2 ] - ddata -> snapshot [1 ];
366
+
367
+ effective_ticks = clk_get_rate (pc -> cpt_clk );
368
+
369
+ result -> period = (high + low ) * NSEC_PER_SEC ;
370
+ result -> period /= effective_ticks ;
371
+
372
+ result -> duty_cycle = high * NSEC_PER_SEC ;
373
+ result -> duty_cycle /= effective_ticks ;
374
+
375
+ break ;
376
+
377
+ default :
378
+ dev_err (dev , "internal error\n" );
379
+ break ;
380
+ }
381
+
382
+ out :
383
+ /* Disable capture */
384
+ regmap_field_write (pc -> pwm_cpt_en , 0 );
385
+
386
+ mutex_unlock (& ddata -> lock );
387
+ return ret ;
388
+ }
389
+
308
390
static const struct pwm_ops sti_pwm_ops = {
391
+ .capture = sti_pwm_capture ,
309
392
.config = sti_pwm_config ,
310
393
.enable = sti_pwm_enable ,
311
394
.disable = sti_pwm_disable ,
@@ -418,6 +501,11 @@ static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
418
501
if (IS_ERR (pc -> pwm_out_en ))
419
502
return PTR_ERR (pc -> pwm_out_en );
420
503
504
+ pc -> pwm_cpt_en = devm_regmap_field_alloc (dev , pc -> regmap ,
505
+ reg_fields [PWM_CPT_EN ]);
506
+ if (IS_ERR (pc -> pwm_cpt_en ))
507
+ return PTR_ERR (pc -> pwm_cpt_en );
508
+
421
509
pc -> pwm_cpt_int_en = devm_regmap_field_alloc (dev , pc -> regmap ,
422
510
reg_fields [PWM_CPT_INT_EN ]);
423
511
if (IS_ERR (pc -> pwm_cpt_int_en ))
0 commit comments