Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/blackfin/kernel/time.c
10817 views
1
/*
2
* arch/blackfin/kernel/time.c
3
*
4
* This file contains the Blackfin-specific time handling details.
5
* Most of the stuff is located in the machine specific files.
6
*
7
* Copyright 2004-2008 Analog Devices Inc.
8
* Licensed under the GPL-2 or later.
9
*/
10
11
#include <linux/module.h>
12
#include <linux/profile.h>
13
#include <linux/interrupt.h>
14
#include <linux/time.h>
15
#include <linux/irq.h>
16
#include <linux/delay.h>
17
#include <linux/sched.h>
18
19
#include <asm/blackfin.h>
20
#include <asm/time.h>
21
#include <asm/gptimers.h>
22
23
/* This is an NTP setting */
24
#define TICK_SIZE (tick_nsec / 1000)
25
26
static struct irqaction bfin_timer_irq = {
27
.name = "Blackfin Timer Tick",
28
.flags = IRQF_DISABLED
29
};
30
31
#if defined(CONFIG_IPIPE)
32
void __init setup_system_timer0(void)
33
{
34
/* Power down the core timer, just to play safe. */
35
bfin_write_TCNTL(0);
36
37
disable_gptimers(TIMER0bit);
38
set_gptimer_status(0, TIMER_STATUS_TRUN0);
39
while (get_gptimer_status(0) & TIMER_STATUS_TRUN0)
40
udelay(10);
41
42
set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */
43
set_gptimer_period(TIMER0_id, get_sclk() / HZ);
44
set_gptimer_pwidth(TIMER0_id, 1);
45
SSYNC();
46
enable_gptimers(TIMER0bit);
47
}
48
#else
49
void __init setup_core_timer(void)
50
{
51
u32 tcount;
52
53
/* power up the timer, but don't enable it just yet */
54
bfin_write_TCNTL(1);
55
CSYNC();
56
57
/* the TSCALE prescaler counter */
58
bfin_write_TSCALE(TIME_SCALE - 1);
59
60
tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
61
bfin_write_TPERIOD(tcount);
62
bfin_write_TCOUNT(tcount);
63
64
/* now enable the timer */
65
CSYNC();
66
67
bfin_write_TCNTL(7);
68
}
69
#endif
70
71
static void __init
72
time_sched_init(irqreturn_t(*timer_routine) (int, void *))
73
{
74
#if defined(CONFIG_IPIPE)
75
setup_system_timer0();
76
bfin_timer_irq.handler = timer_routine;
77
setup_irq(IRQ_TIMER0, &bfin_timer_irq);
78
#else
79
setup_core_timer();
80
bfin_timer_irq.handler = timer_routine;
81
setup_irq(IRQ_CORETMR, &bfin_timer_irq);
82
#endif
83
}
84
85
#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
86
/*
87
* Should return useconds since last timer tick
88
*/
89
u32 arch_gettimeoffset(void)
90
{
91
unsigned long offset;
92
unsigned long clocks_per_jiffy;
93
94
#if defined(CONFIG_IPIPE)
95
clocks_per_jiffy = bfin_read_TIMER0_PERIOD();
96
offset = bfin_read_TIMER0_COUNTER() / \
97
(((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
98
99
if ((get_gptimer_status(0) & TIMER_STATUS_TIMIL0) && offset < (100000 / HZ / 2))
100
offset += (USEC_PER_SEC / HZ);
101
#else
102
clocks_per_jiffy = bfin_read_TPERIOD();
103
offset = (clocks_per_jiffy - bfin_read_TCOUNT()) / \
104
(((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
105
106
/* Check if we just wrapped the counters and maybe missed a tick */
107
if ((bfin_read_ILAT() & (1 << IRQ_CORETMR))
108
&& (offset < (100000 / HZ / 2)))
109
offset += (USEC_PER_SEC / HZ);
110
#endif
111
return offset;
112
}
113
#endif
114
115
/*
116
* timer_interrupt() needs to keep up the real-time clock,
117
* as well as call the "xtime_update()" routine every clocktick
118
*/
119
#ifdef CONFIG_CORE_TIMER_IRQ_L1
120
__attribute__((l1_text))
121
#endif
122
irqreturn_t timer_interrupt(int irq, void *dummy)
123
{
124
xtime_update(1);
125
126
#ifdef CONFIG_IPIPE
127
update_root_process_times(get_irq_regs());
128
#else
129
update_process_times(user_mode(get_irq_regs()));
130
#endif
131
profile_tick(CPU_PROFILING);
132
133
return IRQ_HANDLED;
134
}
135
136
void read_persistent_clock(struct timespec *ts)
137
{
138
time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60; /* 1 Jan 2007 */
139
ts->tv_sec = secs_since_1970;
140
ts->tv_nsec = 0;
141
}
142
143
void __init time_init(void)
144
{
145
#ifdef CONFIG_RTC_DRV_BFIN
146
/* [#2663] hack to filter junk RTC values that would cause
147
* userspace to have to deal with time values greater than
148
* 2^31 seconds (which uClibc cannot cope with yet)
149
*/
150
if ((bfin_read_RTC_STAT() & 0xC0000000) == 0xC0000000) {
151
printk(KERN_NOTICE "bfin-rtc: invalid date; resetting\n");
152
bfin_write_RTC_STAT(0);
153
}
154
#endif
155
156
time_sched_init(timer_interrupt);
157
}
158
159