1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/clocksource/zevio-timer.c
5 * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
11 #include <linux/of_address.h>
12 #include <linux/of_irq.h>
13 #include <linux/clk.h>
14 #include <linux/clockchips.h>
15 #include <linux/cpumask.h>
16 #include <linux/interrupt.h>
17 #include <linux/slab.h>
19 #define IO_CURRENT_VAL 0x00
20 #define IO_DIVIDER 0x04
21 #define IO_CONTROL 0x08
23 #define IO_TIMER1 0x00
24 #define IO_TIMER2 0x0C
26 #define IO_MATCH_BEGIN 0x18
27 #define IO_MATCH(x) (IO_MATCH_BEGIN + ((x) << 2))
29 #define IO_INTR_STS 0x00
30 #define IO_INTR_ACK 0x00
31 #define IO_INTR_MSK 0x04
33 #define CNTL_STOP_TIMER (1 << 4)
34 #define CNTL_RUN_TIMER (0 << 4)
36 #define CNTL_INC (1 << 3)
37 #define CNTL_DEC (0 << 3)
40 #define CNTL_MATCH(x) ((x) + 1)
41 #define CNTL_FOREVER 7
43 /* There are 6 match registers but we only use one. */
46 #define TIMER_INTR_MSK (1 << (TIMER_MATCH))
47 #define TIMER_INTR_ALL 0x3F
51 void __iomem
*timer1
, *timer2
;
52 void __iomem
*interrupt_regs
;
55 struct clock_event_device clkevt
;
56 struct irqaction clkevt_irq
;
58 char clocksource_name
[64];
59 char clockevent_name
[64];
62 static int zevio_timer_set_event(unsigned long delta
,
63 struct clock_event_device
*dev
)
65 struct zevio_timer
*timer
= container_of(dev
, struct zevio_timer
,
68 writel(delta
, timer
->timer1
+ IO_CURRENT_VAL
);
69 writel(CNTL_RUN_TIMER
| CNTL_DEC
| CNTL_MATCH(TIMER_MATCH
),
70 timer
->timer1
+ IO_CONTROL
);
75 static int zevio_timer_shutdown(struct clock_event_device
*dev
)
77 struct zevio_timer
*timer
= container_of(dev
, struct zevio_timer
,
80 /* Disable timer interrupts */
81 writel(0, timer
->interrupt_regs
+ IO_INTR_MSK
);
82 writel(TIMER_INTR_ALL
, timer
->interrupt_regs
+ IO_INTR_ACK
);
84 writel(CNTL_STOP_TIMER
, timer
->timer1
+ IO_CONTROL
);
88 static int zevio_timer_set_oneshot(struct clock_event_device
*dev
)
90 struct zevio_timer
*timer
= container_of(dev
, struct zevio_timer
,
93 /* Enable timer interrupts */
94 writel(TIMER_INTR_MSK
, timer
->interrupt_regs
+ IO_INTR_MSK
);
95 writel(TIMER_INTR_ALL
, timer
->interrupt_regs
+ IO_INTR_ACK
);
99 static irqreturn_t
zevio_timer_interrupt(int irq
, void *dev_id
)
101 struct zevio_timer
*timer
= dev_id
;
104 intr
= readl(timer
->interrupt_regs
+ IO_INTR_ACK
);
105 if (!(intr
& TIMER_INTR_MSK
))
108 writel(TIMER_INTR_MSK
, timer
->interrupt_regs
+ IO_INTR_ACK
);
109 writel(CNTL_STOP_TIMER
, timer
->timer1
+ IO_CONTROL
);
111 if (timer
->clkevt
.event_handler
)
112 timer
->clkevt
.event_handler(&timer
->clkevt
);
117 static int __init
zevio_timer_add(struct device_node
*node
)
119 struct zevio_timer
*timer
;
123 timer
= kzalloc(sizeof(*timer
), GFP_KERNEL
);
127 timer
->base
= of_iomap(node
, 0);
132 timer
->timer1
= timer
->base
+ IO_TIMER1
;
133 timer
->timer2
= timer
->base
+ IO_TIMER2
;
135 timer
->clk
= of_clk_get(node
, 0);
136 if (IS_ERR(timer
->clk
)) {
137 ret
= PTR_ERR(timer
->clk
);
138 pr_err("Timer clock not found! (error %d)\n", ret
);
142 timer
->interrupt_regs
= of_iomap(node
, 1);
143 irqnr
= irq_of_parse_and_map(node
, 0);
145 of_address_to_resource(node
, 0, &res
);
146 scnprintf(timer
->clocksource_name
, sizeof(timer
->clocksource_name
),
147 "%llx.%pOFn_clocksource",
148 (unsigned long long)res
.start
, node
);
150 scnprintf(timer
->clockevent_name
, sizeof(timer
->clockevent_name
),
151 "%llx.%pOFn_clockevent",
152 (unsigned long long)res
.start
, node
);
154 if (timer
->interrupt_regs
&& irqnr
) {
155 timer
->clkevt
.name
= timer
->clockevent_name
;
156 timer
->clkevt
.set_next_event
= zevio_timer_set_event
;
157 timer
->clkevt
.set_state_shutdown
= zevio_timer_shutdown
;
158 timer
->clkevt
.set_state_oneshot
= zevio_timer_set_oneshot
;
159 timer
->clkevt
.tick_resume
= zevio_timer_set_oneshot
;
160 timer
->clkevt
.rating
= 200;
161 timer
->clkevt
.cpumask
= cpu_possible_mask
;
162 timer
->clkevt
.features
= CLOCK_EVT_FEAT_ONESHOT
;
163 timer
->clkevt
.irq
= irqnr
;
165 writel(CNTL_STOP_TIMER
, timer
->timer1
+ IO_CONTROL
);
166 writel(0, timer
->timer1
+ IO_DIVIDER
);
168 /* Start with timer interrupts disabled */
169 writel(0, timer
->interrupt_regs
+ IO_INTR_MSK
);
170 writel(TIMER_INTR_ALL
, timer
->interrupt_regs
+ IO_INTR_ACK
);
172 /* Interrupt to occur when timer value matches 0 */
173 writel(0, timer
->base
+ IO_MATCH(TIMER_MATCH
));
175 timer
->clkevt_irq
.name
= timer
->clockevent_name
;
176 timer
->clkevt_irq
.handler
= zevio_timer_interrupt
;
177 timer
->clkevt_irq
.dev_id
= timer
;
178 timer
->clkevt_irq
.flags
= IRQF_TIMER
| IRQF_IRQPOLL
;
180 setup_irq(irqnr
, &timer
->clkevt_irq
);
182 clockevents_config_and_register(&timer
->clkevt
,
183 clk_get_rate(timer
->clk
), 0x0001, 0xffff);
184 pr_info("Added %s as clockevent\n", timer
->clockevent_name
);
187 writel(CNTL_STOP_TIMER
, timer
->timer2
+ IO_CONTROL
);
188 writel(0, timer
->timer2
+ IO_CURRENT_VAL
);
189 writel(0, timer
->timer2
+ IO_DIVIDER
);
190 writel(CNTL_RUN_TIMER
| CNTL_FOREVER
| CNTL_INC
,
191 timer
->timer2
+ IO_CONTROL
);
193 clocksource_mmio_init(timer
->timer2
+ IO_CURRENT_VAL
,
194 timer
->clocksource_name
,
195 clk_get_rate(timer
->clk
),
197 clocksource_mmio_readw_up
);
199 pr_info("Added %s as clocksource\n", timer
->clocksource_name
);
203 iounmap(timer
->base
);
209 static int __init
zevio_timer_init(struct device_node
*node
)
211 return zevio_timer_add(node
);
214 TIMER_OF_DECLARE(zevio_timer
, "lsi,zevio-timer", zevio_timer_init
);