2
* System timer for Freescale STMP37XX/STMP378X
4
* Embedded Alley Solutions, Inc <source@embeddedalley.com>
6
* Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
7
* Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
11
* The code contained herein is licensed under the GNU General Public
12
* License. You may obtain a copy of the GNU General Public License
13
* Version 2 or later at the following locations:
15
* http://www.opensource.org/licenses/gpl-license.html
16
* http://www.gnu.org/copyleft/gpl.html
18
#include <linux/kernel.h>
19
#include <linux/init.h>
20
#include <linux/spinlock.h>
21
#include <linux/clocksource.h>
22
#include <linux/clockchips.h>
24
#include <linux/irq.h>
25
#include <linux/interrupt.h>
27
#include <asm/mach/time.h>
28
#include <mach/stmp3xxx.h>
29
#include <mach/platform.h>
30
#include <mach/regs-timrot.h>
33
stmp3xxx_timer_interrupt(int irq, void *dev_id)
35
struct clock_event_device *c = dev_id;
38
if (__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0) &
39
BM_TIMROT_TIMCTRLn_IRQ) {
40
stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ,
41
REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0);
46
else if (__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1)
47
& BM_TIMROT_TIMCTRLn_IRQ) {
48
stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ,
49
REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1);
50
stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ_EN,
51
REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1);
52
__raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1);
58
static cycle_t stmp3xxx_clock_read(struct clocksource *cs)
60
return ~((__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1)
65
stmp3xxx_timrot_set_next_event(unsigned long delta,
66
struct clock_event_device *dev)
68
/* reload the timer */
69
__raw_writel(delta, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0);
74
stmp3xxx_timrot_set_mode(enum clock_event_mode mode,
75
struct clock_event_device *dev)
79
static struct clock_event_device ckevt_timrot = {
81
.features = CLOCK_EVT_FEAT_ONESHOT,
83
.set_next_event = stmp3xxx_timrot_set_next_event,
84
.set_mode = stmp3xxx_timrot_set_mode,
87
static struct clocksource cksrc_stmp3xxx = {
88
.name = "cksrc_stmp3xxx",
90
.read = stmp3xxx_clock_read,
91
.mask = CLOCKSOURCE_MASK(16),
92
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
95
static struct irqaction stmp3xxx_timer_irq = {
96
.name = "stmp3xxx_timer",
97
.flags = IRQF_DISABLED | IRQF_TIMER,
98
.handler = stmp3xxx_timer_interrupt,
99
.dev_id = &ckevt_timrot,
104
* Set up timer interrupt, and return the current time in seconds.
106
static void __init stmp3xxx_init_timer(void)
108
ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
110
ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot);
111
ckevt_timrot.max_delta_ns = clockevent_delta2ns(0xFFF, &ckevt_timrot);
112
ckevt_timrot.cpumask = cpumask_of(0);
114
stmp3xxx_reset_block(REGS_TIMROT_BASE, false);
116
/* clear two timers */
117
__raw_writel(0, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0);
118
__raw_writel(0, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1);
122
(8 << BP_TIMROT_TIMCTRLn_SELECT) | /* 32 kHz */
123
BM_TIMROT_TIMCTRLn_RELOAD |
124
BM_TIMROT_TIMCTRLn_UPDATE |
125
BM_TIMROT_TIMCTRLn_IRQ_EN,
126
REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0);
128
(8 << BP_TIMROT_TIMCTRLn_SELECT) | /* 32 kHz */
129
BM_TIMROT_TIMCTRLn_RELOAD |
130
BM_TIMROT_TIMCTRLn_UPDATE |
131
BM_TIMROT_TIMCTRLn_IRQ_EN,
132
REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1);
134
__raw_writel(CLOCK_TICK_RATE / HZ - 1,
135
REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0);
136
__raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1);
138
setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq);
140
clocksource_register_hz(&cksrc_stmp3xxx, CLOCK_TICK_RATE);
141
clockevents_register_device(&ckevt_timrot);
146
void stmp3xxx_suspend_timer(void)
148
stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ_EN | BM_TIMROT_TIMCTRLn_IRQ,
149
REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0);
150
stmp3xxx_setl(BM_TIMROT_ROTCTRL_CLKGATE,
151
REGS_TIMROT_BASE + HW_TIMROT_ROTCTRL);
154
void stmp3xxx_resume_timer(void)
156
stmp3xxx_clearl(BM_TIMROT_ROTCTRL_SFTRST | BM_TIMROT_ROTCTRL_CLKGATE,
157
REGS_TIMROT_BASE + HW_TIMROT_ROTCTRL);
159
8 << BP_TIMROT_TIMCTRLn_SELECT | /* 32 kHz */
160
BM_TIMROT_TIMCTRLn_RELOAD |
161
BM_TIMROT_TIMCTRLn_UPDATE |
162
BM_TIMROT_TIMCTRLn_IRQ_EN,
163
REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0);
165
8 << BP_TIMROT_TIMCTRLn_SELECT | /* 32 kHz */
166
BM_TIMROT_TIMCTRLn_RELOAD |
167
BM_TIMROT_TIMCTRLn_UPDATE |
168
BM_TIMROT_TIMCTRLn_IRQ_EN,
169
REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1);
170
__raw_writel(CLOCK_TICK_RATE / HZ - 1,
171
REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0);
172
__raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1);
177
#define stmp3xxx_suspend_timer NULL
178
#define stmp3xxx_resume_timer NULL
180
#endif /* CONFIG_PM */
182
struct sys_timer stmp3xxx_timer = {
183
.init = stmp3xxx_init_timer,
184
.suspend = stmp3xxx_suspend_timer,
185
.resume = stmp3xxx_resume_timer,