66 */
77#include <linux/clk.h>
88#include <linux/counter.h>
9+ #include <linux/interrupt.h>
910#include <linux/mfd/syscon.h>
1011#include <linux/module.h>
1112#include <linux/mutex.h>
1213#include <linux/of.h>
14+ #include <linux/of_irq.h>
1315#include <linux/platform_device.h>
1416#include <linux/regmap.h>
17+ #include <uapi/linux/counter/microchip-tcb-capture.h>
1518#include <soc/at91/atmel_tcb.h>
1619
1720#define ATMEL_TC_CMR_MASK (ATMEL_TC_LDRA_RISING | ATMEL_TC_LDRB_FALLING | \
1821 ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_LDBDIS | \
1922 ATMEL_TC_LDBSTOP)
2023
24+ #define ATMEL_TC_DEF_IRQS (ATMEL_TC_ETRGS | ATMEL_TC_COVFS | \
25+ ATMEL_TC_LDRAS | ATMEL_TC_LDRBS | ATMEL_TC_CPCS)
26+
2127#define ATMEL_TC_QDEN BIT(8)
2228#define ATMEL_TC_POSEN BIT(9)
2329
@@ -247,6 +253,90 @@ static int mchp_tc_count_read(struct counter_device *counter,
247253 return 0 ;
248254}
249255
256+ static int mchp_tc_count_cap_read (struct counter_device * counter ,
257+ struct counter_count * count , size_t idx , u64 * val )
258+ {
259+ struct mchp_tc_data * const priv = counter_priv (counter );
260+ u32 cnt ;
261+ int ret ;
262+
263+ switch (idx ) {
264+ case COUNTER_MCHP_EXCAP_RA :
265+ ret = regmap_read (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], RA ), & cnt );
266+ break ;
267+ case COUNTER_MCHP_EXCAP_RB :
268+ ret = regmap_read (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], RB ), & cnt );
269+ break ;
270+ default :
271+ return - EINVAL ;
272+ }
273+
274+ if (ret < 0 )
275+ return ret ;
276+
277+ * val = cnt ;
278+
279+ return 0 ;
280+ }
281+
282+ static int mchp_tc_count_cap_write (struct counter_device * counter ,
283+ struct counter_count * count , size_t idx , u64 val )
284+ {
285+ struct mchp_tc_data * const priv = counter_priv (counter );
286+ int ret ;
287+
288+ if (val > U32_MAX )
289+ return - ERANGE ;
290+
291+ switch (idx ) {
292+ case COUNTER_MCHP_EXCAP_RA :
293+ ret = regmap_write (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], RA ), val );
294+ break ;
295+ case COUNTER_MCHP_EXCAP_RB :
296+ ret = regmap_write (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], RB ), val );
297+ break ;
298+ default :
299+ return - EINVAL ;
300+ }
301+
302+ return ret ;
303+ }
304+
305+ static int mchp_tc_count_compare_read (struct counter_device * counter , struct counter_count * count ,
306+ u64 * val )
307+ {
308+ struct mchp_tc_data * const priv = counter_priv (counter );
309+ u32 cnt ;
310+ int ret ;
311+
312+ ret = regmap_read (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], RC ), & cnt );
313+ if (ret < 0 )
314+ return ret ;
315+
316+ * val = cnt ;
317+
318+ return 0 ;
319+ }
320+
321+ static int mchp_tc_count_compare_write (struct counter_device * counter , struct counter_count * count ,
322+ u64 val )
323+ {
324+ struct mchp_tc_data * const priv = counter_priv (counter );
325+
326+ if (val > U32_MAX )
327+ return - ERANGE ;
328+
329+ return regmap_write (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], RC ), val );
330+ }
331+
332+ static DEFINE_COUNTER_ARRAY_CAPTURE (mchp_tc_cnt_cap_array , 2 ) ;
333+
334+ static struct counter_comp mchp_tc_count_ext [] = {
335+ COUNTER_COMP_ARRAY_CAPTURE (mchp_tc_count_cap_read , mchp_tc_count_cap_write ,
336+ mchp_tc_cnt_cap_array ),
337+ COUNTER_COMP_COMPARE (mchp_tc_count_compare_read , mchp_tc_count_compare_write ),
338+ };
339+
250340static struct counter_count mchp_tc_counts [] = {
251341 {
252342 .id = 0 ,
@@ -255,6 +345,8 @@ static struct counter_count mchp_tc_counts[] = {
255345 .num_functions = ARRAY_SIZE (mchp_tc_count_functions ),
256346 .synapses = mchp_tc_count_synapses ,
257347 .num_synapses = ARRAY_SIZE (mchp_tc_count_synapses ),
348+ .ext = mchp_tc_count_ext ,
349+ .num_ext = ARRAY_SIZE (mchp_tc_count_ext ),
258350 },
259351};
260352
@@ -294,6 +386,65 @@ static const struct of_device_id atmel_tc_of_match[] = {
294386 { /* sentinel */ }
295387};
296388
389+ static irqreturn_t mchp_tc_isr (int irq , void * dev_id )
390+ {
391+ struct counter_device * const counter = dev_id ;
392+ struct mchp_tc_data * const priv = counter_priv (counter );
393+ u32 sr , mask ;
394+
395+ regmap_read (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], SR ), & sr );
396+ regmap_read (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], IMR ), & mask );
397+
398+ sr &= mask ;
399+ if (!(sr & ATMEL_TC_ALL_IRQ ))
400+ return IRQ_NONE ;
401+
402+ if (sr & ATMEL_TC_ETRGS )
403+ counter_push_event (counter , COUNTER_EVENT_CHANGE_OF_STATE ,
404+ COUNTER_MCHP_EVCHN_CV );
405+ if (sr & ATMEL_TC_LDRAS )
406+ counter_push_event (counter , COUNTER_EVENT_CAPTURE ,
407+ COUNTER_MCHP_EVCHN_RA );
408+ if (sr & ATMEL_TC_LDRBS )
409+ counter_push_event (counter , COUNTER_EVENT_CAPTURE ,
410+ COUNTER_MCHP_EVCHN_RB );
411+ if (sr & ATMEL_TC_CPCS )
412+ counter_push_event (counter , COUNTER_EVENT_THRESHOLD ,
413+ COUNTER_MCHP_EVCHN_RC );
414+ if (sr & ATMEL_TC_COVFS )
415+ counter_push_event (counter , COUNTER_EVENT_OVERFLOW ,
416+ COUNTER_MCHP_EVCHN_CV );
417+
418+ return IRQ_HANDLED ;
419+ }
420+
421+ static void mchp_tc_irq_remove (void * ptr )
422+ {
423+ struct mchp_tc_data * priv = ptr ;
424+
425+ regmap_write (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], IDR ), ATMEL_TC_DEF_IRQS );
426+ }
427+
428+ static int mchp_tc_irq_enable (struct counter_device * const counter , int irq )
429+ {
430+ struct mchp_tc_data * const priv = counter_priv (counter );
431+ int ret = devm_request_irq (counter -> parent , irq , mchp_tc_isr , 0 ,
432+ dev_name (counter -> parent ), counter );
433+
434+ if (ret < 0 )
435+ return ret ;
436+
437+ ret = regmap_write (priv -> regmap , ATMEL_TC_REG (priv -> channel [0 ], IER ), ATMEL_TC_DEF_IRQS );
438+ if (ret < 0 )
439+ return ret ;
440+
441+ ret = devm_add_action_or_reset (counter -> parent , mchp_tc_irq_remove , priv );
442+ if (ret < 0 )
443+ return ret ;
444+
445+ return 0 ;
446+ }
447+
297448static void mchp_tc_clk_remove (void * ptr )
298449{
299450 clk_disable_unprepare ((struct clk * )ptr );
@@ -378,6 +529,15 @@ static int mchp_tc_probe(struct platform_device *pdev)
378529 counter -> num_signals = ARRAY_SIZE (mchp_tc_count_signals );
379530 counter -> signals = mchp_tc_count_signals ;
380531
532+ i = of_irq_get (np -> parent , 0 );
533+ if (i == - EPROBE_DEFER )
534+ return - EPROBE_DEFER ;
535+ if (i > 0 ) {
536+ ret = mchp_tc_irq_enable (counter , i );
537+ if (ret < 0 )
538+ return dev_err_probe (& pdev -> dev , ret , "Failed to set up IRQ" );
539+ }
540+
381541 ret = devm_counter_add (& pdev -> dev , counter );
382542 if (ret < 0 )
383543 return dev_err_probe (& pdev -> dev , ret , "Failed to add counter\n" );
0 commit comments