1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/clocksource/timer-oxnas-rps.c
5 * Copyright (C) 2009 Oxford Semiconductor Ltd
6 * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
7 * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/init.h>
13 #include <linux/irq.h>
15 #include <linux/clk.h>
16 #include <linux/slab.h>
17 #include <linux/interrupt.h>
18 #include <linux/of_irq.h>
19 #include <linux/of_address.h>
20 #include <linux/clockchips.h>
21 #include <linux/sched_clock.h>
23 /* TIMER1 used as tick
24 * TIMER2 used as clocksource
27 /* Registers definitions */
29 #define TIMER_LOAD_REG 0x0
30 #define TIMER_CURR_REG 0x4
31 #define TIMER_CTRL_REG 0x8
32 #define TIMER_CLRINT_REG 0xC
36 #define TIMER_MAX_VAL (BIT(TIMER_BITS) - 1)
38 #define TIMER_PERIODIC BIT(6)
39 #define TIMER_ENABLE BIT(7)
41 #define TIMER_DIV1 (0)
42 #define TIMER_DIV16 (1 << 2)
43 #define TIMER_DIV256 (2 << 2)
45 #define TIMER1_REG_OFFSET 0
46 #define TIMER2_REG_OFFSET 0x20
48 /* Clockevent & Clocksource data */
50 struct oxnas_rps_timer
{
51 struct clock_event_device clkevent
;
52 void __iomem
*clksrc_base
;
53 void __iomem
*clkevt_base
;
54 unsigned long timer_period
;
55 unsigned int timer_prescaler
;
60 static irqreturn_t
oxnas_rps_timer_irq(int irq
, void *dev_id
)
62 struct oxnas_rps_timer
*rps
= dev_id
;
64 writel_relaxed(0, rps
->clkevt_base
+ TIMER_CLRINT_REG
);
66 rps
->clkevent
.event_handler(&rps
->clkevent
);
71 static void oxnas_rps_timer_config(struct oxnas_rps_timer
*rps
,
73 unsigned int periodic
)
75 uint32_t cfg
= rps
->timer_prescaler
;
81 cfg
|= TIMER_PERIODIC
;
83 writel_relaxed(period
, rps
->clkevt_base
+ TIMER_LOAD_REG
);
84 writel_relaxed(cfg
, rps
->clkevt_base
+ TIMER_CTRL_REG
);
87 static int oxnas_rps_timer_shutdown(struct clock_event_device
*evt
)
89 struct oxnas_rps_timer
*rps
=
90 container_of(evt
, struct oxnas_rps_timer
, clkevent
);
92 oxnas_rps_timer_config(rps
, 0, 0);
97 static int oxnas_rps_timer_set_periodic(struct clock_event_device
*evt
)
99 struct oxnas_rps_timer
*rps
=
100 container_of(evt
, struct oxnas_rps_timer
, clkevent
);
102 oxnas_rps_timer_config(rps
, rps
->timer_period
, 1);
107 static int oxnas_rps_timer_set_oneshot(struct clock_event_device
*evt
)
109 struct oxnas_rps_timer
*rps
=
110 container_of(evt
, struct oxnas_rps_timer
, clkevent
);
112 oxnas_rps_timer_config(rps
, rps
->timer_period
, 0);
117 static int oxnas_rps_timer_next_event(unsigned long delta
,
118 struct clock_event_device
*evt
)
120 struct oxnas_rps_timer
*rps
=
121 container_of(evt
, struct oxnas_rps_timer
, clkevent
);
123 oxnas_rps_timer_config(rps
, delta
, 0);
128 static int __init
oxnas_rps_clockevent_init(struct oxnas_rps_timer
*rps
)
130 ulong clk_rate
= clk_get_rate(rps
->clk
);
133 /* Start with prescaler 1 */
134 rps
->timer_prescaler
= TIMER_DIV1
;
135 rps
->timer_period
= DIV_ROUND_UP(clk_rate
, HZ
);
136 timer_rate
= clk_rate
;
138 if (rps
->timer_period
> TIMER_MAX_VAL
) {
139 rps
->timer_prescaler
= TIMER_DIV16
;
140 timer_rate
= clk_rate
/ 16;
141 rps
->timer_period
= DIV_ROUND_UP(timer_rate
, HZ
);
143 if (rps
->timer_period
> TIMER_MAX_VAL
) {
144 rps
->timer_prescaler
= TIMER_DIV256
;
145 timer_rate
= clk_rate
/ 256;
146 rps
->timer_period
= DIV_ROUND_UP(timer_rate
, HZ
);
149 rps
->clkevent
.name
= "oxnas-rps";
150 rps
->clkevent
.features
= CLOCK_EVT_FEAT_PERIODIC
|
151 CLOCK_EVT_FEAT_ONESHOT
|
152 CLOCK_EVT_FEAT_DYNIRQ
;
153 rps
->clkevent
.tick_resume
= oxnas_rps_timer_shutdown
;
154 rps
->clkevent
.set_state_shutdown
= oxnas_rps_timer_shutdown
;
155 rps
->clkevent
.set_state_periodic
= oxnas_rps_timer_set_periodic
;
156 rps
->clkevent
.set_state_oneshot
= oxnas_rps_timer_set_oneshot
;
157 rps
->clkevent
.set_next_event
= oxnas_rps_timer_next_event
;
158 rps
->clkevent
.rating
= 200;
159 rps
->clkevent
.cpumask
= cpu_possible_mask
;
160 rps
->clkevent
.irq
= rps
->irq
;
161 clockevents_config_and_register(&rps
->clkevent
,
166 pr_info("Registered clock event rate %luHz prescaler %x period %lu\n",
168 rps
->timer_prescaler
,
176 static void __iomem
*timer_sched_base
;
178 static u64 notrace
oxnas_rps_read_sched_clock(void)
180 return ~readl_relaxed(timer_sched_base
);
183 static int __init
oxnas_rps_clocksource_init(struct oxnas_rps_timer
*rps
)
185 ulong clk_rate
= clk_get_rate(rps
->clk
);
188 /* use prescale 16 */
189 clk_rate
= clk_rate
/ 16;
191 writel_relaxed(TIMER_MAX_VAL
, rps
->clksrc_base
+ TIMER_LOAD_REG
);
192 writel_relaxed(TIMER_PERIODIC
| TIMER_ENABLE
| TIMER_DIV16
,
193 rps
->clksrc_base
+ TIMER_CTRL_REG
);
195 timer_sched_base
= rps
->clksrc_base
+ TIMER_CURR_REG
;
196 sched_clock_register(oxnas_rps_read_sched_clock
,
197 TIMER_BITS
, clk_rate
);
198 ret
= clocksource_mmio_init(timer_sched_base
,
199 "oxnas_rps_clocksource_timer",
200 clk_rate
, 250, TIMER_BITS
,
201 clocksource_mmio_readl_down
);
203 pr_err("can't register clocksource\n");
207 pr_info("Registered clocksource rate %luHz\n", clk_rate
);
212 static int __init
oxnas_rps_timer_init(struct device_node
*np
)
214 struct oxnas_rps_timer
*rps
;
218 rps
= kzalloc(sizeof(*rps
), GFP_KERNEL
);
222 rps
->clk
= of_clk_get(np
, 0);
223 if (IS_ERR(rps
->clk
)) {
224 ret
= PTR_ERR(rps
->clk
);
228 ret
= clk_prepare_enable(rps
->clk
);
232 base
= of_iomap(np
, 0);
235 goto err_clk_prepare
;
238 rps
->irq
= irq_of_parse_and_map(np
, 0);
244 rps
->clkevt_base
= base
+ TIMER1_REG_OFFSET
;
245 rps
->clksrc_base
= base
+ TIMER2_REG_OFFSET
;
248 writel_relaxed(0, rps
->clkevt_base
+ TIMER_CTRL_REG
);
249 writel_relaxed(0, rps
->clksrc_base
+ TIMER_CTRL_REG
);
250 writel_relaxed(0, rps
->clkevt_base
+ TIMER_LOAD_REG
);
251 writel_relaxed(0, rps
->clksrc_base
+ TIMER_LOAD_REG
);
252 writel_relaxed(0, rps
->clkevt_base
+ TIMER_CLRINT_REG
);
253 writel_relaxed(0, rps
->clksrc_base
+ TIMER_CLRINT_REG
);
255 ret
= request_irq(rps
->irq
, oxnas_rps_timer_irq
,
256 IRQF_TIMER
| IRQF_IRQPOLL
,
261 ret
= oxnas_rps_clocksource_init(rps
);
265 ret
= oxnas_rps_clockevent_init(rps
);
272 free_irq(rps
->irq
, rps
);
276 clk_disable_unprepare(rps
->clk
);
285 TIMER_OF_DECLARE(ox810se_rps
,
286 "oxsemi,ox810se-rps-timer", oxnas_rps_timer_init
);
287 TIMER_OF_DECLARE(ox820_rps
,
288 "oxsemi,ox820-rps-timer", oxnas_rps_timer_init
);