1 // SPDX-License-Identifier: GPL-2.0
3 * Ingenic XBurst SoCs SYSOST clocks driver
4 * Copyright (c) 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
7 #include <linux/bitops.h>
9 #include <linux/clk-provider.h>
10 #include <linux/clockchips.h>
11 #include <linux/clocksource.h>
12 #include <linux/interrupt.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/of_address.h>
15 #include <linux/of_irq.h>
16 #include <linux/sched_clock.h>
17 #include <linux/slab.h>
18 #include <linux/syscore_ops.h>
20 #include <dt-bindings/clock/ingenic,sysost.h>
22 /* OST register offsets */
23 #define OST_REG_OSTCCR 0x00
24 #define OST_REG_OSTCR 0x08
25 #define OST_REG_OSTFR 0x0c
26 #define OST_REG_OSTMR 0x10
27 #define OST_REG_OST1DFR 0x14
28 #define OST_REG_OST1CNT 0x18
29 #define OST_REG_OST2CNTL 0x20
30 #define OST_REG_OSTCNT2HBUF 0x24
31 #define OST_REG_OSTESR 0x34
32 #define OST_REG_OSTECR 0x38
34 /* bits within the OSTCCR register */
35 #define OSTCCR_PRESCALE1_MASK 0x3
36 #define OSTCCR_PRESCALE2_MASK 0xc
37 #define OSTCCR_PRESCALE1_LSB 0
38 #define OSTCCR_PRESCALE2_LSB 2
40 /* bits within the OSTCR register */
41 #define OSTCR_OST1CLR BIT(0)
42 #define OSTCR_OST2CLR BIT(1)
44 /* bits within the OSTFR register */
45 #define OSTFR_FFLAG BIT(0)
47 /* bits within the OSTMR register */
48 #define OSTMR_FMASK BIT(0)
50 /* bits within the OSTESR register */
51 #define OSTESR_OST1ENS BIT(0)
52 #define OSTESR_OST2ENS BIT(1)
54 /* bits within the OSTECR register */
55 #define OSTECR_OST1ENC BIT(0)
56 #define OSTECR_OST2ENC BIT(1)
58 struct ingenic_soc_info
{
59 unsigned int num_channels
;
62 struct ingenic_ost_clk_info
{
63 struct clk_init_data init_data
;
67 struct ingenic_ost_clk
{
70 struct ingenic_ost
*ost
;
71 const struct ingenic_ost_clk_info
*info
;
76 const struct ingenic_soc_info
*soc_info
;
77 struct clk
*clk
, *percpu_timer_clk
, *global_timer_clk
;
78 struct clock_event_device cevt
;
79 struct clocksource cs
;
82 struct clk_hw_onecell_data
*clocks
;
85 static struct ingenic_ost
*ingenic_ost
;
87 static inline struct ingenic_ost_clk
*to_ost_clk(struct clk_hw
*hw
)
89 return container_of(hw
, struct ingenic_ost_clk
, hw
);
92 static unsigned long ingenic_ost_percpu_timer_recalc_rate(struct clk_hw
*hw
,
93 unsigned long parent_rate
)
95 struct ingenic_ost_clk
*ost_clk
= to_ost_clk(hw
);
96 const struct ingenic_ost_clk_info
*info
= ost_clk
->info
;
97 unsigned int prescale
;
99 prescale
= readl(ost_clk
->ost
->base
+ info
->ostccr_reg
);
101 prescale
= (prescale
& OSTCCR_PRESCALE1_MASK
) >> OSTCCR_PRESCALE1_LSB
;
103 return parent_rate
>> (prescale
* 2);
106 static unsigned long ingenic_ost_global_timer_recalc_rate(struct clk_hw
*hw
,
107 unsigned long parent_rate
)
109 struct ingenic_ost_clk
*ost_clk
= to_ost_clk(hw
);
110 const struct ingenic_ost_clk_info
*info
= ost_clk
->info
;
111 unsigned int prescale
;
113 prescale
= readl(ost_clk
->ost
->base
+ info
->ostccr_reg
);
115 prescale
= (prescale
& OSTCCR_PRESCALE2_MASK
) >> OSTCCR_PRESCALE2_LSB
;
117 return parent_rate
>> (prescale
* 2);
120 static u8
ingenic_ost_get_prescale(unsigned long rate
, unsigned long req_rate
)
124 for (prescale
= 0; prescale
< 2; prescale
++)
125 if ((rate
>> (prescale
* 2)) <= req_rate
)
128 return 2; /* /16 divider */
131 static long ingenic_ost_round_rate(struct clk_hw
*hw
, unsigned long req_rate
,
132 unsigned long *parent_rate
)
134 unsigned long rate
= *parent_rate
;
140 prescale
= ingenic_ost_get_prescale(rate
, req_rate
);
142 return rate
>> (prescale
* 2);
145 static int ingenic_ost_percpu_timer_set_rate(struct clk_hw
*hw
, unsigned long req_rate
,
146 unsigned long parent_rate
)
148 struct ingenic_ost_clk
*ost_clk
= to_ost_clk(hw
);
149 const struct ingenic_ost_clk_info
*info
= ost_clk
->info
;
150 u8 prescale
= ingenic_ost_get_prescale(parent_rate
, req_rate
);
153 val
= readl(ost_clk
->ost
->base
+ info
->ostccr_reg
);
154 val
= (val
& ~OSTCCR_PRESCALE1_MASK
) | (prescale
<< OSTCCR_PRESCALE1_LSB
);
155 writel(val
, ost_clk
->ost
->base
+ info
->ostccr_reg
);
160 static int ingenic_ost_global_timer_set_rate(struct clk_hw
*hw
, unsigned long req_rate
,
161 unsigned long parent_rate
)
163 struct ingenic_ost_clk
*ost_clk
= to_ost_clk(hw
);
164 const struct ingenic_ost_clk_info
*info
= ost_clk
->info
;
165 u8 prescale
= ingenic_ost_get_prescale(parent_rate
, req_rate
);
168 val
= readl(ost_clk
->ost
->base
+ info
->ostccr_reg
);
169 val
= (val
& ~OSTCCR_PRESCALE2_MASK
) | (prescale
<< OSTCCR_PRESCALE2_LSB
);
170 writel(val
, ost_clk
->ost
->base
+ info
->ostccr_reg
);
175 static const struct clk_ops ingenic_ost_percpu_timer_ops
= {
176 .recalc_rate
= ingenic_ost_percpu_timer_recalc_rate
,
177 .round_rate
= ingenic_ost_round_rate
,
178 .set_rate
= ingenic_ost_percpu_timer_set_rate
,
181 static const struct clk_ops ingenic_ost_global_timer_ops
= {
182 .recalc_rate
= ingenic_ost_global_timer_recalc_rate
,
183 .round_rate
= ingenic_ost_round_rate
,
184 .set_rate
= ingenic_ost_global_timer_set_rate
,
187 static const char * const ingenic_ost_clk_parents
[] = { "ext" };
189 static const struct ingenic_ost_clk_info ingenic_ost_clk_info
[] = {
190 [OST_CLK_PERCPU_TIMER
] = {
192 .name
= "percpu timer",
193 .parent_names
= ingenic_ost_clk_parents
,
194 .num_parents
= ARRAY_SIZE(ingenic_ost_clk_parents
),
195 .ops
= &ingenic_ost_percpu_timer_ops
,
196 .flags
= CLK_SET_RATE_UNGATE
,
198 .ostccr_reg
= OST_REG_OSTCCR
,
201 [OST_CLK_GLOBAL_TIMER
] = {
203 .name
= "global timer",
204 .parent_names
= ingenic_ost_clk_parents
,
205 .num_parents
= ARRAY_SIZE(ingenic_ost_clk_parents
),
206 .ops
= &ingenic_ost_global_timer_ops
,
207 .flags
= CLK_SET_RATE_UNGATE
,
209 .ostccr_reg
= OST_REG_OSTCCR
,
213 static u64 notrace
ingenic_ost_global_timer_read_cntl(void)
215 struct ingenic_ost
*ost
= ingenic_ost
;
218 count
= readl(ost
->base
+ OST_REG_OST2CNTL
);
223 static u64 notrace
ingenic_ost_clocksource_read(struct clocksource
*cs
)
225 return ingenic_ost_global_timer_read_cntl();
228 static inline struct ingenic_ost
*to_ingenic_ost(struct clock_event_device
*evt
)
230 return container_of(evt
, struct ingenic_ost
, cevt
);
233 static int ingenic_ost_cevt_set_state_shutdown(struct clock_event_device
*evt
)
235 struct ingenic_ost
*ost
= to_ingenic_ost(evt
);
237 writel(OSTECR_OST1ENC
, ost
->base
+ OST_REG_OSTECR
);
242 static int ingenic_ost_cevt_set_next(unsigned long next
,
243 struct clock_event_device
*evt
)
245 struct ingenic_ost
*ost
= to_ingenic_ost(evt
);
247 writel((u32
)~OSTFR_FFLAG
, ost
->base
+ OST_REG_OSTFR
);
248 writel(next
, ost
->base
+ OST_REG_OST1DFR
);
249 writel(OSTCR_OST1CLR
, ost
->base
+ OST_REG_OSTCR
);
250 writel(OSTESR_OST1ENS
, ost
->base
+ OST_REG_OSTESR
);
251 writel((u32
)~OSTMR_FMASK
, ost
->base
+ OST_REG_OSTMR
);
256 static irqreturn_t
ingenic_ost_cevt_cb(int irq
, void *dev_id
)
258 struct clock_event_device
*evt
= dev_id
;
259 struct ingenic_ost
*ost
= to_ingenic_ost(evt
);
261 writel(OSTECR_OST1ENC
, ost
->base
+ OST_REG_OSTECR
);
263 if (evt
->event_handler
)
264 evt
->event_handler(evt
);
269 static int __init
ingenic_ost_register_clock(struct ingenic_ost
*ost
,
270 unsigned int idx
, const struct ingenic_ost_clk_info
*info
,
271 struct clk_hw_onecell_data
*clocks
)
273 struct ingenic_ost_clk
*ost_clk
;
276 ost_clk
= kzalloc(sizeof(*ost_clk
), GFP_KERNEL
);
280 ost_clk
->hw
.init
= &info
->init_data
;
282 ost_clk
->info
= info
;
285 /* Reset clock divider */
286 val
= readl(ost
->base
+ info
->ostccr_reg
);
287 val
&= ~(OSTCCR_PRESCALE1_MASK
| OSTCCR_PRESCALE2_MASK
);
288 writel(val
, ost
->base
+ info
->ostccr_reg
);
290 err
= clk_hw_register(NULL
, &ost_clk
->hw
);
296 clocks
->hws
[idx
] = &ost_clk
->hw
;
301 static struct clk
* __init
ingenic_ost_get_clock(struct device_node
*np
, int id
)
303 struct of_phandle_args args
;
309 return of_clk_get_from_provider(&args
);
312 static int __init
ingenic_ost_percpu_timer_init(struct device_node
*np
,
313 struct ingenic_ost
*ost
)
315 unsigned int timer_virq
, channel
= OST_CLK_PERCPU_TIMER
;
319 ost
->percpu_timer_clk
= ingenic_ost_get_clock(np
, channel
);
320 if (IS_ERR(ost
->percpu_timer_clk
))
321 return PTR_ERR(ost
->percpu_timer_clk
);
323 err
= clk_prepare_enable(ost
->percpu_timer_clk
);
327 rate
= clk_get_rate(ost
->percpu_timer_clk
);
330 goto err_clk_disable
;
333 timer_virq
= of_irq_get(np
, 0);
336 goto err_clk_disable
;
339 snprintf(ost
->name
, sizeof(ost
->name
), "OST percpu timer");
341 err
= request_irq(timer_virq
, ingenic_ost_cevt_cb
, IRQF_TIMER
,
342 ost
->name
, &ost
->cevt
);
344 goto err_irq_dispose_mapping
;
346 ost
->cevt
.cpumask
= cpumask_of(smp_processor_id());
347 ost
->cevt
.features
= CLOCK_EVT_FEAT_ONESHOT
;
348 ost
->cevt
.name
= ost
->name
;
349 ost
->cevt
.rating
= 400;
350 ost
->cevt
.set_state_shutdown
= ingenic_ost_cevt_set_state_shutdown
;
351 ost
->cevt
.set_next_event
= ingenic_ost_cevt_set_next
;
353 clockevents_config_and_register(&ost
->cevt
, rate
, 4, 0xffffffff);
357 err_irq_dispose_mapping
:
358 irq_dispose_mapping(timer_virq
);
360 clk_disable_unprepare(ost
->percpu_timer_clk
);
362 clk_put(ost
->percpu_timer_clk
);
366 static int __init
ingenic_ost_global_timer_init(struct device_node
*np
,
367 struct ingenic_ost
*ost
)
369 unsigned int channel
= OST_CLK_GLOBAL_TIMER
;
370 struct clocksource
*cs
= &ost
->cs
;
374 ost
->global_timer_clk
= ingenic_ost_get_clock(np
, channel
);
375 if (IS_ERR(ost
->global_timer_clk
))
376 return PTR_ERR(ost
->global_timer_clk
);
378 err
= clk_prepare_enable(ost
->global_timer_clk
);
382 rate
= clk_get_rate(ost
->global_timer_clk
);
385 goto err_clk_disable
;
388 /* Clear counter CNT registers */
389 writel(OSTCR_OST2CLR
, ost
->base
+ OST_REG_OSTCR
);
391 /* Enable OST channel */
392 writel(OSTESR_OST2ENS
, ost
->base
+ OST_REG_OSTESR
);
394 cs
->name
= "ingenic-ost";
396 cs
->flags
= CLOCK_SOURCE_IS_CONTINUOUS
;
397 cs
->mask
= CLOCKSOURCE_MASK(32);
398 cs
->read
= ingenic_ost_clocksource_read
;
400 err
= clocksource_register_hz(cs
, rate
);
402 goto err_clk_disable
;
407 clk_disable_unprepare(ost
->global_timer_clk
);
409 clk_put(ost
->global_timer_clk
);
413 static const struct ingenic_soc_info x1000_soc_info
= {
417 static const struct of_device_id __maybe_unused ingenic_ost_of_match
[] __initconst
= {
418 { .compatible
= "ingenic,x1000-ost", .data
= &x1000_soc_info
, },
422 static int __init
ingenic_ost_probe(struct device_node
*np
)
424 const struct of_device_id
*id
= of_match_node(ingenic_ost_of_match
, np
);
425 struct ingenic_ost
*ost
;
429 ost
= kzalloc(sizeof(*ost
), GFP_KERNEL
);
433 ost
->base
= of_io_request_and_map(np
, 0, of_node_full_name(np
));
434 if (IS_ERR(ost
->base
)) {
435 pr_err("%s: Failed to map OST registers\n", __func__
);
436 ret
= PTR_ERR(ost
->base
);
440 ost
->clk
= of_clk_get_by_name(np
, "ost");
441 if (IS_ERR(ost
->clk
)) {
442 ret
= PTR_ERR(ost
->clk
);
443 pr_crit("%s: Cannot get OST clock\n", __func__
);
447 ret
= clk_prepare_enable(ost
->clk
);
449 pr_crit("%s: Unable to enable OST clock\n", __func__
);
453 ost
->soc_info
= id
->data
;
455 ost
->clocks
= kzalloc(struct_size(ost
->clocks
, hws
, ost
->soc_info
->num_channels
),
459 goto err_clk_disable
;
462 ost
->clocks
->num
= ost
->soc_info
->num_channels
;
464 for (i
= 0; i
< ost
->clocks
->num
; i
++) {
465 ret
= ingenic_ost_register_clock(ost
, i
, &ingenic_ost_clk_info
[i
], ost
->clocks
);
467 pr_crit("%s: Cannot register clock %d\n", __func__
, i
);
468 goto err_unregister_ost_clocks
;
472 ret
= of_clk_add_hw_provider(np
, of_clk_hw_onecell_get
, ost
->clocks
);
474 pr_crit("%s: Cannot add OF clock provider\n", __func__
);
475 goto err_unregister_ost_clocks
;
482 err_unregister_ost_clocks
:
483 for (i
= 0; i
< ost
->clocks
->num
; i
++)
484 if (ost
->clocks
->hws
[i
])
485 clk_hw_unregister(ost
->clocks
->hws
[i
]);
488 clk_disable_unprepare(ost
->clk
);
496 static int __init
ingenic_ost_init(struct device_node
*np
)
498 struct ingenic_ost
*ost
;
502 ret
= ingenic_ost_probe(np
);
504 pr_crit("%s: Failed to initialize OST clocks: %d\n", __func__
, ret
);
508 of_node_clear_flag(np
, OF_POPULATED
);
514 ret
= ingenic_ost_global_timer_init(np
, ost
);
516 pr_crit("%s: Unable to init global timer: %x\n", __func__
, ret
);
517 goto err_free_ingenic_ost
;
520 ret
= ingenic_ost_percpu_timer_init(np
, ost
);
522 goto err_ost_global_timer_cleanup
;
524 /* Register the sched_clock at the end as there's no way to undo it */
525 rate
= clk_get_rate(ost
->global_timer_clk
);
526 sched_clock_register(ingenic_ost_global_timer_read_cntl
, 32, rate
);
530 err_ost_global_timer_cleanup
:
531 clocksource_unregister(&ost
->cs
);
532 clk_disable_unprepare(ost
->global_timer_clk
);
533 clk_put(ost
->global_timer_clk
);
534 err_free_ingenic_ost
:
539 TIMER_OF_DECLARE(x1000_ost
, "ingenic,x1000-ost", ingenic_ost_init
);