^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright 2017-2019 NXP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/clockchips.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "timer-of.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define CMP_OFFSET 0x10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define CNTCV_LO 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define CNTCV_HI 0xc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define CMPCV_LO (CMP_OFFSET + 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define CMPCV_HI (CMP_OFFSET + 0x24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define CMPCR (CMP_OFFSET + 0x2c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define SYS_CTR_EN 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define SYS_CTR_IRQ_MASK 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define SYS_CTR_CLK_DIV 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static void __iomem *sys_ctr_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static u32 cmpcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static void sysctr_timer_enable(bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) writel(enable ? cmpcr | SYS_CTR_EN : cmpcr, sys_ctr_base + CMPCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static void sysctr_irq_acknowledge(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * clear the enable bit(EN =0) will clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * the status bit(ISTAT = 0), then the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * signal will be negated(acknowledged).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) sysctr_timer_enable(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static inline u64 sysctr_read_counter(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u32 cnt_hi, tmp_hi, cnt_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) cnt_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) cnt_lo = readl_relaxed(sys_ctr_base + CNTCV_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) tmp_hi = readl_relaxed(sys_ctr_base + CNTCV_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) } while (tmp_hi != cnt_hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return ((u64) cnt_hi << 32) | cnt_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int sysctr_set_next_event(unsigned long delta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u32 cmp_hi, cmp_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u64 next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) sysctr_timer_enable(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) next = sysctr_read_counter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) next += delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) cmp_hi = (next >> 32) & 0x00fffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) cmp_lo = next & 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) writel_relaxed(cmp_hi, sys_ctr_base + CMPCV_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) writel_relaxed(cmp_lo, sys_ctr_base + CMPCV_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) sysctr_timer_enable(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static int sysctr_set_state_oneshot(struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static int sysctr_set_state_shutdown(struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) sysctr_timer_enable(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static irqreturn_t sysctr_timer_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct clock_event_device *evt = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) sysctr_irq_acknowledge();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) evt->event_handler(evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static struct timer_of to_sysctr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .clkevt = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .name = "i.MX system counter timer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .features = CLOCK_EVT_FEAT_ONESHOT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) CLOCK_EVT_FEAT_DYNIRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .set_state_oneshot = sysctr_set_state_oneshot,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .set_next_event = sysctr_set_next_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .set_state_shutdown = sysctr_set_state_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .rating = 200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .of_irq = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .handler = sysctr_timer_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .flags = IRQF_TIMER | IRQF_IRQPOLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .of_clk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .name = "per",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static void __init sysctr_clockevent_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) to_sysctr.clkevt.cpumask = cpumask_of(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) clockevents_config_and_register(&to_sysctr.clkevt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) timer_of_rate(&to_sysctr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 0xff, 0x7fffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int __init sysctr_timer_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ret = timer_of_init(np, &to_sysctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* system counter clock is divided by 3 internally */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) to_sysctr.of_clk.rate /= SYS_CTR_CLK_DIV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) sys_ctr_base = timer_of_base(&to_sysctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) cmpcr = readl(sys_ctr_base + CMPCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) cmpcr &= ~SYS_CTR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) sysctr_clockevent_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) TIMER_OF_DECLARE(sysctr_timer, "nxp,sysctr-timer", sysctr_timer_init);