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
;
57 char clocksource_name
[64];
58 char clockevent_name
[64];
61 static int zevio_timer_set_event(unsigned long delta
,
62 struct clock_event_device
*dev
)
64 struct zevio_timer
*timer
= container_of(dev
, struct zevio_timer
,
67 writel(delta
, timer
->timer1
+ IO_CURRENT_VAL
);
68 writel(CNTL_RUN_TIMER
| CNTL_DEC
| CNTL_MATCH(TIMER_MATCH
),
69 timer
->timer1
+ IO_CONTROL
);
74 static int zevio_timer_shutdown(struct clock_event_device
*dev
)
76 struct zevio_timer
*timer
= container_of(dev
, struct zevio_timer
,
79 /* Disable timer interrupts */
80 writel(0, timer
->interrupt_regs
+ IO_INTR_MSK
);
81 writel(TIMER_INTR_ALL
, timer
->interrupt_regs
+ IO_INTR_ACK
);
83 writel(CNTL_STOP_TIMER
, timer
->timer1
+ IO_CONTROL
);
87 static int zevio_timer_set_oneshot(struct clock_event_device
*dev
)
89 struct zevio_timer
*timer
= container_of(dev
, struct zevio_timer
,
92 /* Enable timer interrupts */
93 writel(TIMER_INTR_MSK
, timer
->interrupt_regs
+ IO_INTR_MSK
);
94 writel(TIMER_INTR_ALL
, timer
->interrupt_regs
+ IO_INTR_ACK
);
98 static irqreturn_t
zevio_timer_interrupt(int irq
, void *dev_id
)
100 struct zevio_timer
*timer
= dev_id
;
103 intr
= readl(timer
->interrupt_regs
+ IO_INTR_ACK
);
104 if (!(intr
& TIMER_INTR_MSK
))
107 writel(TIMER_INTR_MSK
, timer
->interrupt_regs
+ IO_INTR_ACK
);
108 writel(CNTL_STOP_TIMER
, timer
->timer1
+ IO_CONTROL
);
110 if (timer
->clkevt
.event_handler
)
111 timer
->clkevt
.event_handler(&timer
->clkevt
);
116 static int __init
zevio_timer_add(struct device_node
*node
)
118 struct zevio_timer
*timer
;
122 timer
= kzalloc(sizeof(*timer
), GFP_KERNEL
);
126 timer
->base
= of_iomap(node
, 0);
131 timer
->timer1
= timer
->base
+ IO_TIMER1
;
132 timer
->timer2
= timer
->base
+ IO_TIMER2
;
134 timer
->clk
= of_clk_get(node
, 0);
135 if (IS_ERR(timer
->clk
)) {
136 ret
= PTR_ERR(timer
->clk
);
137 pr_err("Timer clock not found! (error %d)\n", ret
);
141 timer
->interrupt_regs
= of_iomap(node
, 1);
142 irqnr
= irq_of_parse_and_map(node
, 0);
144 of_address_to_resource(node
, 0, &res
);
145 scnprintf(timer
->clocksource_name
, sizeof(timer
->clocksource_name
),
146 "%llx.%pOFn_clocksource",
147 (unsigned long long)res
.start
, node
);
149 scnprintf(timer
->clockevent_name
, sizeof(timer
->clockevent_name
),
150 "%llx.%pOFn_clockevent",
151 (unsigned long long)res
.start
, node
);
153 if (timer
->interrupt_regs
&& irqnr
) {
154 timer
->clkevt
.name
= timer
->clockevent_name
;
155 timer
->clkevt
.set_next_event
= zevio_timer_set_event
;
156 timer
->clkevt
.set_state_shutdown
= zevio_timer_shutdown
;
157 timer
->clkevt
.set_state_oneshot
= zevio_timer_set_oneshot
;
158 timer
->clkevt
.tick_resume
= zevio_timer_set_oneshot
;
159 timer
->clkevt
.rating
= 200;
160 timer
->clkevt
.cpumask
= cpu_possible_mask
;
161 timer
->clkevt
.features
= CLOCK_EVT_FEAT_ONESHOT
;
162 timer
->clkevt
.irq
= irqnr
;
164 writel(CNTL_STOP_TIMER
, timer
->timer1
+ IO_CONTROL
);
165 writel(0, timer
->timer1
+ IO_DIVIDER
);
167 /* Start with timer interrupts disabled */
168 writel(0, timer
->interrupt_regs
+ IO_INTR_MSK
);
169 writel(TIMER_INTR_ALL
, timer
->interrupt_regs
+ IO_INTR_ACK
);
171 /* Interrupt to occur when timer value matches 0 */
172 writel(0, timer
->base
+ IO_MATCH(TIMER_MATCH
));
174 if (request_irq(irqnr
, zevio_timer_interrupt
,
175 IRQF_TIMER
| IRQF_IRQPOLL
,
176 timer
->clockevent_name
, timer
)) {
177 pr_err("%s: request_irq() failed\n",
178 timer
->clockevent_name
);
181 clockevents_config_and_register(&timer
->clkevt
,
182 clk_get_rate(timer
->clk
), 0x0001, 0xffff);
183 pr_info("Added %s as clockevent\n", timer
->clockevent_name
);
186 writel(CNTL_STOP_TIMER
, timer
->timer2
+ IO_CONTROL
);
187 writel(0, timer
->timer2
+ IO_CURRENT_VAL
);
188 writel(0, timer
->timer2
+ IO_DIVIDER
);
189 writel(CNTL_RUN_TIMER
| CNTL_FOREVER
| CNTL_INC
,
190 timer
->timer2
+ IO_CONTROL
);
192 clocksource_mmio_init(timer
->timer2
+ IO_CURRENT_VAL
,
193 timer
->clocksource_name
,
194 clk_get_rate(timer
->clk
),
196 clocksource_mmio_readw_up
);
198 pr_info("Added %s as clocksource\n", timer
->clocksource_name
);
202 iounmap(timer
->base
);
208 static int __init
zevio_timer_init(struct device_node
*node
)
210 return zevio_timer_add(node
);
213 TIMER_OF_DECLARE(zevio_timer
, "lsi,zevio-timer", zevio_timer_init
);