1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2015 ARM Limited
5 * Author: Vladimir Murzin <vladimir.murzin@arm.com>
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 #include <linux/clk.h>
11 #include <linux/clockchips.h>
12 #include <linux/clocksource.h>
13 #include <linux/err.h>
14 #include <linux/interrupt.h>
16 #include <linux/irq.h>
17 #include <linux/of_address.h>
19 #include <linux/of_irq.h>
20 #include <linux/sched_clock.h>
21 #include <linux/slab.h>
23 #define TIMER_CTRL 0x0
24 #define TIMER_CTRL_ENABLE BIT(0)
25 #define TIMER_CTRL_IE BIT(3)
27 #define TIMER_VALUE 0x4
28 #define TIMER_RELOAD 0x8
31 struct clockevent_mps2
{
33 u32 clock_count_per_tick
;
34 struct clock_event_device clkevt
;
37 static void __iomem
*sched_clock_base
;
39 static u64 notrace
mps2_sched_read(void)
41 return ~readl_relaxed(sched_clock_base
+ TIMER_VALUE
);
44 static inline struct clockevent_mps2
*to_mps2_clkevt(struct clock_event_device
*c
)
46 return container_of(c
, struct clockevent_mps2
, clkevt
);
49 static void clockevent_mps2_writel(u32 val
, struct clock_event_device
*c
, u32 offset
)
51 writel_relaxed(val
, to_mps2_clkevt(c
)->reg
+ offset
);
54 static int mps2_timer_shutdown(struct clock_event_device
*ce
)
56 clockevent_mps2_writel(0, ce
, TIMER_RELOAD
);
57 clockevent_mps2_writel(0, ce
, TIMER_CTRL
);
62 static int mps2_timer_set_next_event(unsigned long next
, struct clock_event_device
*ce
)
64 clockevent_mps2_writel(next
, ce
, TIMER_VALUE
);
65 clockevent_mps2_writel(TIMER_CTRL_IE
| TIMER_CTRL_ENABLE
, ce
, TIMER_CTRL
);
70 static int mps2_timer_set_periodic(struct clock_event_device
*ce
)
72 u32 clock_count_per_tick
= to_mps2_clkevt(ce
)->clock_count_per_tick
;
74 clockevent_mps2_writel(clock_count_per_tick
, ce
, TIMER_RELOAD
);
75 clockevent_mps2_writel(clock_count_per_tick
, ce
, TIMER_VALUE
);
76 clockevent_mps2_writel(TIMER_CTRL_IE
| TIMER_CTRL_ENABLE
, ce
, TIMER_CTRL
);
81 static irqreturn_t
mps2_timer_interrupt(int irq
, void *dev_id
)
83 struct clockevent_mps2
*ce
= dev_id
;
84 u32 status
= readl_relaxed(ce
->reg
+ TIMER_INT
);
87 pr_warn("spurious interrupt\n");
91 writel_relaxed(1, ce
->reg
+ TIMER_INT
);
93 ce
->clkevt
.event_handler(&ce
->clkevt
);
98 static int __init
mps2_clockevent_init(struct device_node
*np
)
101 struct clk
*clk
= NULL
;
102 struct clockevent_mps2
*ce
;
105 const char *name
= "mps2-clkevt";
107 ret
= of_property_read_u32(np
, "clock-frequency", &rate
);
109 clk
= of_clk_get(np
, 0);
112 pr_err("failed to get clock for clockevent: %d\n", ret
);
116 ret
= clk_prepare_enable(clk
);
118 pr_err("failed to enable clock for clockevent: %d\n", ret
);
122 rate
= clk_get_rate(clk
);
125 base
= of_iomap(np
, 0);
127 ret
= -EADDRNOTAVAIL
;
128 pr_err("failed to map register for clockevent: %d\n", ret
);
129 goto out_clk_disable
;
132 irq
= irq_of_parse_and_map(np
, 0);
135 pr_err("failed to get irq for clockevent: %d\n", ret
);
139 ce
= kzalloc(sizeof(*ce
), GFP_KERNEL
);
146 ce
->clock_count_per_tick
= DIV_ROUND_CLOSEST(rate
, HZ
);
147 ce
->clkevt
.irq
= irq
;
148 ce
->clkevt
.name
= name
;
149 ce
->clkevt
.rating
= 200;
150 ce
->clkevt
.features
= CLOCK_EVT_FEAT_PERIODIC
| CLOCK_EVT_FEAT_ONESHOT
;
151 ce
->clkevt
.cpumask
= cpu_possible_mask
;
152 ce
->clkevt
.set_state_shutdown
= mps2_timer_shutdown
,
153 ce
->clkevt
.set_state_periodic
= mps2_timer_set_periodic
,
154 ce
->clkevt
.set_state_oneshot
= mps2_timer_shutdown
,
155 ce
->clkevt
.set_next_event
= mps2_timer_set_next_event
;
157 /* Ensure timer is disabled */
158 writel_relaxed(0, base
+ TIMER_CTRL
);
160 ret
= request_irq(irq
, mps2_timer_interrupt
, IRQF_TIMER
, name
, ce
);
162 pr_err("failed to request irq for clockevent: %d\n", ret
);
166 clockevents_config_and_register(&ce
->clkevt
, rate
, 0xf, 0xffffffff);
175 /* clk_{disable, unprepare, put}() can handle NULL as a parameter */
176 clk_disable_unprepare(clk
);
183 static int __init
mps2_clocksource_init(struct device_node
*np
)
186 struct clk
*clk
= NULL
;
189 const char *name
= "mps2-clksrc";
191 ret
= of_property_read_u32(np
, "clock-frequency", &rate
);
193 clk
= of_clk_get(np
, 0);
196 pr_err("failed to get clock for clocksource: %d\n", ret
);
200 ret
= clk_prepare_enable(clk
);
202 pr_err("failed to enable clock for clocksource: %d\n", ret
);
206 rate
= clk_get_rate(clk
);
209 base
= of_iomap(np
, 0);
211 ret
= -EADDRNOTAVAIL
;
212 pr_err("failed to map register for clocksource: %d\n", ret
);
213 goto out_clk_disable
;
216 /* Ensure timer is disabled */
217 writel_relaxed(0, base
+ TIMER_CTRL
);
219 /* ... and set it up as free-running clocksource */
220 writel_relaxed(0xffffffff, base
+ TIMER_VALUE
);
221 writel_relaxed(0xffffffff, base
+ TIMER_RELOAD
);
223 writel_relaxed(TIMER_CTRL_ENABLE
, base
+ TIMER_CTRL
);
225 ret
= clocksource_mmio_init(base
+ TIMER_VALUE
, name
,
227 clocksource_mmio_readl_down
);
229 pr_err("failed to init clocksource: %d\n", ret
);
233 sched_clock_base
= base
;
234 sched_clock_register(mps2_sched_read
, 32, rate
);
241 /* clk_{disable, unprepare, put}() can handle NULL as a parameter */
242 clk_disable_unprepare(clk
);
249 static int __init
mps2_timer_init(struct device_node
*np
)
251 static int has_clocksource
, has_clockevent
;
254 if (!has_clocksource
) {
255 ret
= mps2_clocksource_init(np
);
262 if (!has_clockevent
) {
263 ret
= mps2_clockevent_init(np
);
273 TIMER_OF_DECLARE(mps2_timer
, "arm,mps2-timer", mps2_timer_init
);