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/bitfield.h>
8 #include <linux/bitops.h>
10 #include <linux/clk-provider.h>
11 #include <linux/clockchips.h>
12 #include <linux/clocksource.h>
13 #include <linux/interrupt.h>
14 #include <linux/mfd/syscon.h>
15 #include <linux/of_address.h>
16 #include <linux/of_irq.h>
17 #include <linux/sched_clock.h>
18 #include <linux/slab.h>
19 #include <linux/syscore_ops.h>
21 #include <dt-bindings/clock/ingenic,sysost.h>
23 /* OST register offsets */
24 #define OST_REG_OSTCCR 0x00
25 #define OST_REG_OSTCR 0x08
26 #define OST_REG_OSTFR 0x0c
27 #define OST_REG_OSTMR 0x10
28 #define OST_REG_OST1DFR 0x14
29 #define OST_REG_OST1CNT 0x18
30 #define OST_REG_OST2CNTL 0x20
31 #define OST_REG_OSTCNT2HBUF 0x24
32 #define OST_REG_OSTESR 0x34
33 #define OST_REG_OSTECR 0x38
35 /* bits within the OSTCCR register */
36 #define OSTCCR_PRESCALE1_MASK 0x3
37 #define OSTCCR_PRESCALE2_MASK 0xc
39 /* bits within the OSTCR register */
40 #define OSTCR_OST1CLR BIT(0)
41 #define OSTCR_OST2CLR BIT(1)
43 /* bits within the OSTFR register */
44 #define OSTFR_FFLAG BIT(0)
46 /* bits within the OSTMR register */
47 #define OSTMR_FMASK BIT(0)
49 /* bits within the OSTESR register */
50 #define OSTESR_OST1ENS BIT(0)
51 #define OSTESR_OST2ENS BIT(1)
53 /* bits within the OSTECR register */
54 #define OSTECR_OST1ENC BIT(0)
55 #define OSTECR_OST2ENC BIT(1)
57 struct ingenic_soc_info
{
58 unsigned int num_channels
;
61 struct ingenic_ost_clk_info
{
62 struct clk_init_data init_data
;
66 struct ingenic_ost_clk
{
69 struct ingenic_ost
*ost
;
70 const struct ingenic_ost_clk_info
*info
;
75 const struct ingenic_soc_info
*soc_info
;
76 struct clk
*clk
, *percpu_timer_clk
, *global_timer_clk
;
77 struct clock_event_device cevt
;
78 struct clocksource cs
;
81 struct clk_hw_onecell_data
*clocks
;
84 static struct ingenic_ost
*ingenic_ost
;
86 static inline struct ingenic_ost_clk
*to_ost_clk(struct clk_hw
*hw
)
88 return container_of(hw
, struct ingenic_ost_clk
, hw
);
91 static unsigned long ingenic_ost_percpu_timer_recalc_rate(struct clk_hw
*hw
,
92 unsigned long parent_rate
)
94 struct ingenic_ost_clk
*ost_clk
= to_ost_clk(hw
);
95 const struct ingenic_ost_clk_info
*info
= ost_clk
->info
;
96 unsigned int prescale
;
98 prescale
= readl(ost_clk
->ost
->base
+ info
->ostccr_reg
);
100 prescale
= FIELD_GET(OSTCCR_PRESCALE1_MASK
, prescale
);
102 return parent_rate
>> (prescale
* 2);
105 static unsigned long ingenic_ost_global_timer_recalc_rate(struct clk_hw
*hw
,
106 unsigned long parent_rate
)
108 struct ingenic_ost_clk
*ost_clk
= to_ost_clk(hw
);
109 const struct ingenic_ost_clk_info
*info
= ost_clk
->info
;
110 unsigned int prescale
;
112 prescale
= readl(ost_clk
->ost
->base
+ info
->ostccr_reg
);
114 prescale
= FIELD_GET(OSTCCR_PRESCALE2_MASK
, prescale
);
116 return parent_rate
>> (prescale
* 2);
119 static u8
ingenic_ost_get_prescale(unsigned long rate
, unsigned long req_rate
)
123 for (prescale
= 0; prescale
< 2; prescale
++)
124 if ((rate
>> (prescale
* 2)) <= req_rate
)
127 return 2; /* /16 divider */
130 static long ingenic_ost_round_rate(struct clk_hw
*hw
, unsigned long req_rate
,
131 unsigned long *parent_rate
)
133 unsigned long rate
= *parent_rate
;
139 prescale
= ingenic_ost_get_prescale(rate
, req_rate
);
141 return rate
>> (prescale
* 2);
144 static int ingenic_ost_percpu_timer_set_rate(struct clk_hw
*hw
, unsigned long req_rate
,
145 unsigned long parent_rate
)
147 struct ingenic_ost_clk
*ost_clk
= to_ost_clk(hw
);
148 const struct ingenic_ost_clk_info
*info
= ost_clk
->info
;
149 u8 prescale
= ingenic_ost_get_prescale(parent_rate
, req_rate
);
152 val
= readl(ost_clk
->ost
->base
+ info
->ostccr_reg
);
153 val
&= ~OSTCCR_PRESCALE1_MASK
;
154 val
|= FIELD_PREP(OSTCCR_PRESCALE1_MASK
, prescale
);
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
&= ~OSTCCR_PRESCALE2_MASK
;
170 val
|= FIELD_PREP(OSTCCR_PRESCALE2_MASK
, prescale
);
171 writel(val
, ost_clk
->ost
->base
+ info
->ostccr_reg
);
176 static const struct clk_ops ingenic_ost_percpu_timer_ops
= {
177 .recalc_rate
= ingenic_ost_percpu_timer_recalc_rate
,
178 .round_rate
= ingenic_ost_round_rate
,
179 .set_rate
= ingenic_ost_percpu_timer_set_rate
,
182 static const struct clk_ops ingenic_ost_global_timer_ops
= {
183 .recalc_rate
= ingenic_ost_global_timer_recalc_rate
,
184 .round_rate
= ingenic_ost_round_rate
,
185 .set_rate
= ingenic_ost_global_timer_set_rate
,
188 static const char * const ingenic_ost_clk_parents
[] = { "ext" };
190 static const struct ingenic_ost_clk_info x1000_ost_clk_info
[] = {
191 [OST_CLK_PERCPU_TIMER
] = {
193 .name
= "percpu timer",
194 .parent_names
= ingenic_ost_clk_parents
,
195 .num_parents
= ARRAY_SIZE(ingenic_ost_clk_parents
),
196 .ops
= &ingenic_ost_percpu_timer_ops
,
197 .flags
= CLK_SET_RATE_UNGATE
,
199 .ostccr_reg
= OST_REG_OSTCCR
,
202 [OST_CLK_GLOBAL_TIMER
] = {
204 .name
= "global timer",
205 .parent_names
= ingenic_ost_clk_parents
,
206 .num_parents
= ARRAY_SIZE(ingenic_ost_clk_parents
),
207 .ops
= &ingenic_ost_global_timer_ops
,
208 .flags
= CLK_SET_RATE_UNGATE
,
210 .ostccr_reg
= OST_REG_OSTCCR
,
214 static u64 notrace
ingenic_ost_global_timer_read_cntl(void)
216 struct ingenic_ost
*ost
= ingenic_ost
;
219 count
= readl(ost
->base
+ OST_REG_OST2CNTL
);
224 static u64 notrace
ingenic_ost_clocksource_read(struct clocksource
*cs
)
226 return ingenic_ost_global_timer_read_cntl();
229 static inline struct ingenic_ost
*to_ingenic_ost(struct clock_event_device
*evt
)
231 return container_of(evt
, struct ingenic_ost
, cevt
);
234 static int ingenic_ost_cevt_set_state_shutdown(struct clock_event_device
*evt
)
236 struct ingenic_ost
*ost
= to_ingenic_ost(evt
);
238 writel(OSTECR_OST1ENC
, ost
->base
+ OST_REG_OSTECR
);
243 static int ingenic_ost_cevt_set_next(unsigned long next
,
244 struct clock_event_device
*evt
)
246 struct ingenic_ost
*ost
= to_ingenic_ost(evt
);
248 writel((u32
)~OSTFR_FFLAG
, ost
->base
+ OST_REG_OSTFR
);
249 writel(next
, ost
->base
+ OST_REG_OST1DFR
);
250 writel(OSTCR_OST1CLR
, ost
->base
+ OST_REG_OSTCR
);
251 writel(OSTESR_OST1ENS
, ost
->base
+ OST_REG_OSTESR
);
252 writel((u32
)~OSTMR_FMASK
, ost
->base
+ OST_REG_OSTMR
);
257 static irqreturn_t
ingenic_ost_cevt_cb(int irq
, void *dev_id
)
259 struct clock_event_device
*evt
= dev_id
;
260 struct ingenic_ost
*ost
= to_ingenic_ost(evt
);
262 writel(OSTECR_OST1ENC
, ost
->base
+ OST_REG_OSTECR
);
264 if (evt
->event_handler
)
265 evt
->event_handler(evt
);
270 static int __init
ingenic_ost_register_clock(struct ingenic_ost
*ost
,
271 unsigned int idx
, const struct ingenic_ost_clk_info
*info
,
272 struct clk_hw_onecell_data
*clocks
)
274 struct ingenic_ost_clk
*ost_clk
;
277 ost_clk
= kzalloc(sizeof(*ost_clk
), GFP_KERNEL
);
281 ost_clk
->hw
.init
= &info
->init_data
;
283 ost_clk
->info
= info
;
286 /* Reset clock divider */
287 val
= readl(ost
->base
+ info
->ostccr_reg
);
288 val
&= ~(OSTCCR_PRESCALE1_MASK
| OSTCCR_PRESCALE2_MASK
);
289 writel(val
, ost
->base
+ info
->ostccr_reg
);
291 err
= clk_hw_register(NULL
, &ost_clk
->hw
);
297 clocks
->hws
[idx
] = &ost_clk
->hw
;
302 static struct clk
* __init
ingenic_ost_get_clock(struct device_node
*np
, int id
)
304 struct of_phandle_args args
;
310 return of_clk_get_from_provider(&args
);
313 static int __init
ingenic_ost_percpu_timer_init(struct device_node
*np
,
314 struct ingenic_ost
*ost
)
316 unsigned int timer_virq
, channel
= OST_CLK_PERCPU_TIMER
;
320 ost
->percpu_timer_clk
= ingenic_ost_get_clock(np
, channel
);
321 if (IS_ERR(ost
->percpu_timer_clk
))
322 return PTR_ERR(ost
->percpu_timer_clk
);
324 err
= clk_prepare_enable(ost
->percpu_timer_clk
);
328 rate
= clk_get_rate(ost
->percpu_timer_clk
);
331 goto err_clk_disable
;
334 timer_virq
= of_irq_get(np
, 0);
337 goto err_clk_disable
;
340 snprintf(ost
->name
, sizeof(ost
->name
), "OST percpu timer");
342 err
= request_irq(timer_virq
, ingenic_ost_cevt_cb
, IRQF_TIMER
,
343 ost
->name
, &ost
->cevt
);
345 goto err_irq_dispose_mapping
;
347 ost
->cevt
.cpumask
= cpumask_of(smp_processor_id());
348 ost
->cevt
.features
= CLOCK_EVT_FEAT_ONESHOT
;
349 ost
->cevt
.name
= ost
->name
;
350 ost
->cevt
.rating
= 400;
351 ost
->cevt
.set_state_shutdown
= ingenic_ost_cevt_set_state_shutdown
;
352 ost
->cevt
.set_next_event
= ingenic_ost_cevt_set_next
;
354 clockevents_config_and_register(&ost
->cevt
, rate
, 4, 0xffffffff);
358 err_irq_dispose_mapping
:
359 irq_dispose_mapping(timer_virq
);
361 clk_disable_unprepare(ost
->percpu_timer_clk
);
363 clk_put(ost
->percpu_timer_clk
);
367 static int __init
ingenic_ost_global_timer_init(struct device_node
*np
,
368 struct ingenic_ost
*ost
)
370 unsigned int channel
= OST_CLK_GLOBAL_TIMER
;
371 struct clocksource
*cs
= &ost
->cs
;
375 ost
->global_timer_clk
= ingenic_ost_get_clock(np
, channel
);
376 if (IS_ERR(ost
->global_timer_clk
))
377 return PTR_ERR(ost
->global_timer_clk
);
379 err
= clk_prepare_enable(ost
->global_timer_clk
);
383 rate
= clk_get_rate(ost
->global_timer_clk
);
386 goto err_clk_disable
;
389 /* Clear counter CNT registers */
390 writel(OSTCR_OST2CLR
, ost
->base
+ OST_REG_OSTCR
);
392 /* Enable OST channel */
393 writel(OSTESR_OST2ENS
, ost
->base
+ OST_REG_OSTESR
);
395 cs
->name
= "ingenic-ost";
397 cs
->flags
= CLOCK_SOURCE_IS_CONTINUOUS
;
398 cs
->mask
= CLOCKSOURCE_MASK(32);
399 cs
->read
= ingenic_ost_clocksource_read
;
401 err
= clocksource_register_hz(cs
, rate
);
403 goto err_clk_disable
;
408 clk_disable_unprepare(ost
->global_timer_clk
);
410 clk_put(ost
->global_timer_clk
);
414 static const struct ingenic_soc_info x1000_soc_info
= {
418 static const struct of_device_id __maybe_unused ingenic_ost_of_matches
[] __initconst
= {
419 { .compatible
= "ingenic,x1000-ost", .data
= &x1000_soc_info
},
423 static int __init
ingenic_ost_probe(struct device_node
*np
)
425 const struct of_device_id
*id
= of_match_node(ingenic_ost_of_matches
, np
);
426 struct ingenic_ost
*ost
;
430 ost
= kzalloc(sizeof(*ost
), GFP_KERNEL
);
434 ost
->base
= of_io_request_and_map(np
, 0, of_node_full_name(np
));
435 if (IS_ERR(ost
->base
)) {
436 pr_err("%s: Failed to map OST registers\n", __func__
);
437 ret
= PTR_ERR(ost
->base
);
441 ost
->clk
= of_clk_get_by_name(np
, "ost");
442 if (IS_ERR(ost
->clk
)) {
443 ret
= PTR_ERR(ost
->clk
);
444 pr_crit("%s: Cannot get OST clock\n", __func__
);
448 ret
= clk_prepare_enable(ost
->clk
);
450 pr_crit("%s: Unable to enable OST clock\n", __func__
);
454 ost
->soc_info
= id
->data
;
456 ost
->clocks
= kzalloc(struct_size(ost
->clocks
, hws
, ost
->soc_info
->num_channels
),
460 goto err_clk_disable
;
463 ost
->clocks
->num
= ost
->soc_info
->num_channels
;
465 for (i
= 0; i
< ost
->clocks
->num
; i
++) {
466 ret
= ingenic_ost_register_clock(ost
, i
, &x1000_ost_clk_info
[i
], ost
->clocks
);
468 pr_crit("%s: Cannot register clock %d\n", __func__
, i
);
469 goto err_unregister_ost_clocks
;
473 ret
= of_clk_add_hw_provider(np
, of_clk_hw_onecell_get
, ost
->clocks
);
475 pr_crit("%s: Cannot add OF clock provider\n", __func__
);
476 goto err_unregister_ost_clocks
;
483 err_unregister_ost_clocks
:
484 for (i
= 0; i
< ost
->clocks
->num
; i
++)
485 if (ost
->clocks
->hws
[i
])
486 clk_hw_unregister(ost
->clocks
->hws
[i
]);
489 clk_disable_unprepare(ost
->clk
);
497 static int __init
ingenic_ost_init(struct device_node
*np
)
499 struct ingenic_ost
*ost
;
503 ret
= ingenic_ost_probe(np
);
505 pr_crit("%s: Failed to initialize OST clocks: %d\n", __func__
, ret
);
509 of_node_clear_flag(np
, OF_POPULATED
);
515 ret
= ingenic_ost_global_timer_init(np
, ost
);
517 pr_crit("%s: Unable to init global timer: %x\n", __func__
, ret
);
518 goto err_free_ingenic_ost
;
521 ret
= ingenic_ost_percpu_timer_init(np
, ost
);
523 goto err_ost_global_timer_cleanup
;
525 /* Register the sched_clock at the end as there's no way to undo it */
526 rate
= clk_get_rate(ost
->global_timer_clk
);
527 sched_clock_register(ingenic_ost_global_timer_read_cntl
, 32, rate
);
531 err_ost_global_timer_cleanup
:
532 clocksource_unregister(&ost
->cs
);
533 clk_disable_unprepare(ost
->global_timer_clk
);
534 clk_put(ost
->global_timer_clk
);
535 err_free_ingenic_ost
:
540 TIMER_OF_DECLARE(x1000_ost
, "ingenic,x1000-ost", ingenic_ost_init
);