1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Clocksource driver for Loongson-1 SoC
5 * Copyright (c) 2023 Keguang Zhang <keguang.zhang@gmail.com>
8 #include <linux/clockchips.h>
9 #include <linux/interrupt.h>
10 #include <linux/sizes.h>
13 /* Loongson-1 PWM Timer Register Definitions */
19 /* PWM Control Register Bits */
20 #define INT_LRC_EN BIT(11)
21 #define INT_HRC_EN BIT(10)
22 #define CNTR_RST BIT(7)
25 #define PWM_SINGLE BIT(4)
31 static DEFINE_RAW_SPINLOCK(ls1x_timer_lock
);
33 struct ls1x_clocksource
{
34 void __iomem
*reg_base
;
35 unsigned long ticks_per_jiffy
;
36 struct clocksource clksrc
;
39 static inline struct ls1x_clocksource
*to_ls1x_clksrc(struct clocksource
*c
)
41 return container_of(c
, struct ls1x_clocksource
, clksrc
);
44 static inline void ls1x_pwmtimer_set_period(unsigned int period
,
47 writel(period
, timer_of_base(to
) + PWM_LRC
);
48 writel(period
, timer_of_base(to
) + PWM_HRC
);
51 static inline void ls1x_pwmtimer_clear(struct timer_of
*to
)
53 writel(0, timer_of_base(to
) + PWM_CNTR
);
56 static inline void ls1x_pwmtimer_start(struct timer_of
*to
)
58 writel((INT_EN
| PWM_OE
| CNT_EN
), timer_of_base(to
) + PWM_CTRL
);
61 static inline void ls1x_pwmtimer_stop(struct timer_of
*to
)
63 writel(0, timer_of_base(to
) + PWM_CTRL
);
66 static inline void ls1x_pwmtimer_irq_ack(struct timer_of
*to
)
70 val
= readl(timer_of_base(to
) + PWM_CTRL
);
72 writel(val
, timer_of_base(to
) + PWM_CTRL
);
75 static irqreturn_t
ls1x_clockevent_isr(int irq
, void *dev_id
)
77 struct clock_event_device
*clkevt
= dev_id
;
78 struct timer_of
*to
= to_timer_of(clkevt
);
80 ls1x_pwmtimer_irq_ack(to
);
81 ls1x_pwmtimer_clear(to
);
82 ls1x_pwmtimer_start(to
);
84 clkevt
->event_handler(clkevt
);
89 static int ls1x_clockevent_set_state_periodic(struct clock_event_device
*clkevt
)
91 struct timer_of
*to
= to_timer_of(clkevt
);
93 raw_spin_lock(&ls1x_timer_lock
);
94 ls1x_pwmtimer_set_period(timer_of_period(to
), to
);
95 ls1x_pwmtimer_clear(to
);
96 ls1x_pwmtimer_start(to
);
97 raw_spin_unlock(&ls1x_timer_lock
);
102 static int ls1x_clockevent_tick_resume(struct clock_event_device
*clkevt
)
104 raw_spin_lock(&ls1x_timer_lock
);
105 ls1x_pwmtimer_start(to_timer_of(clkevt
));
106 raw_spin_unlock(&ls1x_timer_lock
);
111 static int ls1x_clockevent_set_state_shutdown(struct clock_event_device
*clkevt
)
113 raw_spin_lock(&ls1x_timer_lock
);
114 ls1x_pwmtimer_stop(to_timer_of(clkevt
));
115 raw_spin_unlock(&ls1x_timer_lock
);
120 static int ls1x_clockevent_set_next(unsigned long evt
,
121 struct clock_event_device
*clkevt
)
123 struct timer_of
*to
= to_timer_of(clkevt
);
125 raw_spin_lock(&ls1x_timer_lock
);
126 ls1x_pwmtimer_set_period(evt
, to
);
127 ls1x_pwmtimer_clear(to
);
128 ls1x_pwmtimer_start(to
);
129 raw_spin_unlock(&ls1x_timer_lock
);
134 static struct timer_of ls1x_to
= {
135 .flags
= TIMER_OF_IRQ
| TIMER_OF_BASE
| TIMER_OF_CLOCK
,
137 .name
= "ls1x-pwmtimer",
138 .features
= CLOCK_EVT_FEAT_PERIODIC
|
139 CLOCK_EVT_FEAT_ONESHOT
,
141 .set_next_event
= ls1x_clockevent_set_next
,
142 .set_state_periodic
= ls1x_clockevent_set_state_periodic
,
143 .set_state_oneshot
= ls1x_clockevent_set_state_shutdown
,
144 .set_state_shutdown
= ls1x_clockevent_set_state_shutdown
,
145 .tick_resume
= ls1x_clockevent_tick_resume
,
148 .handler
= ls1x_clockevent_isr
,
154 * Since the PWM timer overflows every two ticks, its not very useful
155 * to just read by itself. So use jiffies to emulate a free
158 static u64
ls1x_clocksource_read(struct clocksource
*cs
)
160 struct ls1x_clocksource
*ls1x_cs
= to_ls1x_clksrc(cs
);
164 static int old_count
;
167 raw_spin_lock_irqsave(&ls1x_timer_lock
, flags
);
169 * Although our caller may have the read side of xtime_lock,
170 * this is now a seqlock, and we are cheating in this routine
171 * by having side effects on state that we cannot undo if
172 * there is a collision on the seqlock and our caller has to
173 * retry. (Namely, old_jifs and old_count.) So we must treat
174 * jiffies as volatile despite the lock. We read jiffies
175 * before latching the timer count to guarantee that although
176 * the jiffies value might be older than the count (that is,
177 * the counter may underflow between the last point where
178 * jiffies was incremented and the point where we latch the
179 * count), it cannot be newer.
183 count
= readl(ls1x_cs
->reg_base
+ PWM_CNTR
);
186 * It's possible for count to appear to go the wrong way for this
189 * The timer counter underflows, but we haven't handled the resulting
190 * interrupt and incremented jiffies yet.
192 * Previous attempts to handle these cases intelligently were buggy, so
193 * we just do the simple thing now.
195 if (count
< old_count
&& jifs
== old_jifs
)
201 raw_spin_unlock_irqrestore(&ls1x_timer_lock
, flags
);
203 return (u64
)(jifs
* ls1x_cs
->ticks_per_jiffy
) + count
;
206 static struct ls1x_clocksource ls1x_clocksource
= {
208 .name
= "ls1x-pwmtimer",
210 .read
= ls1x_clocksource_read
,
211 .mask
= CLOCKSOURCE_MASK(CNTR_WIDTH
),
212 .flags
= CLOCK_SOURCE_IS_CONTINUOUS
,
216 static int __init
ls1x_pwm_clocksource_init(struct device_node
*np
)
218 struct timer_of
*to
= &ls1x_to
;
221 ret
= timer_of_init(np
, to
);
225 clockevents_config_and_register(&to
->clkevt
, timer_of_rate(to
),
226 0x1, GENMASK(CNTR_WIDTH
- 1, 0));
228 ls1x_clocksource
.reg_base
= timer_of_base(to
);
229 ls1x_clocksource
.ticks_per_jiffy
= timer_of_period(to
);
231 return clocksource_register_hz(&ls1x_clocksource
.clksrc
,
235 TIMER_OF_DECLARE(ls1x_pwm_clocksource
, "loongson,ls1b-pwmtimer",
236 ls1x_pwm_clocksource_init
);