1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * GT641xx clockevent routines.
5 * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org>
7 #include <linux/clockchips.h>
8 #include <linux/init.h>
9 #include <linux/interrupt.h>
10 #include <linux/spinlock.h>
11 #include <linux/irq.h>
13 #include <asm/gt64120.h>
16 static DEFINE_RAW_SPINLOCK(gt641xx_timer_lock
);
17 static unsigned int gt641xx_base_clock
;
19 void gt641xx_set_base_clock(unsigned int clock
)
21 gt641xx_base_clock
= clock
;
24 int gt641xx_timer0_state(void)
26 if (GT_READ(GT_TC0_OFS
))
29 GT_WRITE(GT_TC0_OFS
, gt641xx_base_clock
/ HZ
);
30 GT_WRITE(GT_TC_CONTROL_OFS
, GT_TC_CONTROL_ENTC0_MSK
);
35 static int gt641xx_timer0_set_next_event(unsigned long delta
,
36 struct clock_event_device
*evt
)
40 raw_spin_lock(>641xx_timer_lock
);
42 ctrl
= GT_READ(GT_TC_CONTROL_OFS
);
43 ctrl
&= ~(GT_TC_CONTROL_ENTC0_MSK
| GT_TC_CONTROL_SELTC0_MSK
);
44 ctrl
|= GT_TC_CONTROL_ENTC0_MSK
;
46 GT_WRITE(GT_TC0_OFS
, delta
);
47 GT_WRITE(GT_TC_CONTROL_OFS
, ctrl
);
49 raw_spin_unlock(>641xx_timer_lock
);
54 static int gt641xx_timer0_shutdown(struct clock_event_device
*evt
)
58 raw_spin_lock(>641xx_timer_lock
);
60 ctrl
= GT_READ(GT_TC_CONTROL_OFS
);
61 ctrl
&= ~(GT_TC_CONTROL_ENTC0_MSK
| GT_TC_CONTROL_SELTC0_MSK
);
62 GT_WRITE(GT_TC_CONTROL_OFS
, ctrl
);
64 raw_spin_unlock(>641xx_timer_lock
);
68 static int gt641xx_timer0_set_oneshot(struct clock_event_device
*evt
)
72 raw_spin_lock(>641xx_timer_lock
);
74 ctrl
= GT_READ(GT_TC_CONTROL_OFS
);
75 ctrl
&= ~GT_TC_CONTROL_SELTC0_MSK
;
76 ctrl
|= GT_TC_CONTROL_ENTC0_MSK
;
77 GT_WRITE(GT_TC_CONTROL_OFS
, ctrl
);
79 raw_spin_unlock(>641xx_timer_lock
);
83 static int gt641xx_timer0_set_periodic(struct clock_event_device
*evt
)
87 raw_spin_lock(>641xx_timer_lock
);
89 ctrl
= GT_READ(GT_TC_CONTROL_OFS
);
90 ctrl
|= GT_TC_CONTROL_ENTC0_MSK
| GT_TC_CONTROL_SELTC0_MSK
;
91 GT_WRITE(GT_TC_CONTROL_OFS
, ctrl
);
93 raw_spin_unlock(>641xx_timer_lock
);
97 static void gt641xx_timer0_event_handler(struct clock_event_device
*dev
)
101 static struct clock_event_device gt641xx_timer0_clockevent
= {
102 .name
= "gt641xx-timer0",
103 .features
= CLOCK_EVT_FEAT_PERIODIC
|
104 CLOCK_EVT_FEAT_ONESHOT
,
105 .irq
= GT641XX_TIMER0_IRQ
,
106 .set_next_event
= gt641xx_timer0_set_next_event
,
107 .set_state_shutdown
= gt641xx_timer0_shutdown
,
108 .set_state_periodic
= gt641xx_timer0_set_periodic
,
109 .set_state_oneshot
= gt641xx_timer0_set_oneshot
,
110 .tick_resume
= gt641xx_timer0_shutdown
,
111 .event_handler
= gt641xx_timer0_event_handler
,
114 static irqreturn_t
gt641xx_timer0_interrupt(int irq
, void *dev_id
)
116 struct clock_event_device
*cd
= >641xx_timer0_clockevent
;
118 cd
->event_handler(cd
);
123 static int __init
gt641xx_timer0_clockevent_init(void)
125 struct clock_event_device
*cd
;
127 if (!gt641xx_base_clock
)
130 GT_WRITE(GT_TC0_OFS
, gt641xx_base_clock
/ HZ
);
132 cd
= >641xx_timer0_clockevent
;
133 cd
->rating
= 200 + gt641xx_base_clock
/ 10000000;
134 clockevent_set_clock(cd
, gt641xx_base_clock
);
135 cd
->max_delta_ns
= clockevent_delta2ns(0x7fffffff, cd
);
136 cd
->max_delta_ticks
= 0x7fffffff;
137 cd
->min_delta_ns
= clockevent_delta2ns(0x300, cd
);
138 cd
->min_delta_ticks
= 0x300;
139 cd
->cpumask
= cpumask_of(0);
141 clockevents_register_device(>641xx_timer0_clockevent
);
143 return request_irq(GT641XX_TIMER0_IRQ
, gt641xx_timer0_interrupt
,
144 IRQF_PERCPU
| IRQF_TIMER
, "gt641xx_timer0", NULL
);
146 arch_initcall(gt641xx_timer0_clockevent_init
);