1 // SPDX-License-Identifier: GPL-2.0+
3 // Copyright 2017-2019 NXP
5 #include <linux/interrupt.h>
6 #include <linux/clockchips.h>
7 #include <linux/of_address.h>
8 #include <linux/of_irq.h>
12 #define CMP_OFFSET 0x10000
16 #define CMPCV_LO (CMP_OFFSET + 0x20)
17 #define CMPCV_HI (CMP_OFFSET + 0x24)
18 #define CMPCR (CMP_OFFSET + 0x2c)
20 #define SYS_CTR_EN 0x1
21 #define SYS_CTR_IRQ_MASK 0x2
23 #define SYS_CTR_CLK_DIV 0x3
25 static void __iomem
*sys_ctr_base
;
28 static void sysctr_timer_enable(bool enable
)
30 writel(enable
? cmpcr
| SYS_CTR_EN
: cmpcr
, sys_ctr_base
+ CMPCR
);
33 static void sysctr_irq_acknowledge(void)
36 * clear the enable bit(EN =0) will clear
37 * the status bit(ISTAT = 0), then the interrupt
38 * signal will be negated(acknowledged).
40 sysctr_timer_enable(false);
43 static inline u64
sysctr_read_counter(void)
45 u32 cnt_hi
, tmp_hi
, cnt_lo
;
48 cnt_hi
= readl_relaxed(sys_ctr_base
+ CNTCV_HI
);
49 cnt_lo
= readl_relaxed(sys_ctr_base
+ CNTCV_LO
);
50 tmp_hi
= readl_relaxed(sys_ctr_base
+ CNTCV_HI
);
51 } while (tmp_hi
!= cnt_hi
);
53 return ((u64
) cnt_hi
<< 32) | cnt_lo
;
56 static int sysctr_set_next_event(unsigned long delta
,
57 struct clock_event_device
*evt
)
62 sysctr_timer_enable(false);
64 next
= sysctr_read_counter();
68 cmp_hi
= (next
>> 32) & 0x00fffff;
69 cmp_lo
= next
& 0xffffffff;
71 writel_relaxed(cmp_hi
, sys_ctr_base
+ CMPCV_HI
);
72 writel_relaxed(cmp_lo
, sys_ctr_base
+ CMPCV_LO
);
74 sysctr_timer_enable(true);
79 static int sysctr_set_state_oneshot(struct clock_event_device
*evt
)
84 static int sysctr_set_state_shutdown(struct clock_event_device
*evt
)
86 sysctr_timer_enable(false);
91 static irqreturn_t
sysctr_timer_interrupt(int irq
, void *dev_id
)
93 struct clock_event_device
*evt
= dev_id
;
95 sysctr_irq_acknowledge();
97 evt
->event_handler(evt
);
102 static struct timer_of to_sysctr
= {
103 .flags
= TIMER_OF_IRQ
| TIMER_OF_CLOCK
| TIMER_OF_BASE
,
105 .name
= "i.MX system counter timer",
106 .features
= CLOCK_EVT_FEAT_ONESHOT
|
107 CLOCK_EVT_FEAT_DYNIRQ
,
108 .set_state_oneshot
= sysctr_set_state_oneshot
,
109 .set_next_event
= sysctr_set_next_event
,
110 .set_state_shutdown
= sysctr_set_state_shutdown
,
114 .handler
= sysctr_timer_interrupt
,
115 .flags
= IRQF_TIMER
| IRQF_IRQPOLL
,
122 static void __init
sysctr_clockevent_init(void)
124 to_sysctr
.clkevt
.cpumask
= cpumask_of(0);
126 clockevents_config_and_register(&to_sysctr
.clkevt
,
127 timer_of_rate(&to_sysctr
),
131 static int __init
sysctr_timer_init(struct device_node
*np
)
135 ret
= timer_of_init(np
, &to_sysctr
);
139 /* system counter clock is divided by 3 internally */
140 to_sysctr
.of_clk
.rate
/= SYS_CTR_CLK_DIV
;
142 sys_ctr_base
= timer_of_base(&to_sysctr
);
143 cmpcr
= readl(sys_ctr_base
+ CMPCR
);
144 cmpcr
&= ~SYS_CTR_EN
;
146 sysctr_clockevent_init();
150 TIMER_OF_DECLARE(sysctr_timer
, "nxp,sysctr-timer", sysctr_timer_init
);