OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [x86/] [kernel/] [time_64.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 *  "High Precision Event Timer" based timekeeping.
3
 *
4
 *  Copyright (c) 1991,1992,1995  Linus Torvalds
5
 *  Copyright (c) 1994  Alan Modra
6
 *  Copyright (c) 1995  Markus Kuhn
7
 *  Copyright (c) 1996  Ingo Molnar
8
 *  Copyright (c) 1998  Andrea Arcangeli
9
 *  Copyright (c) 2002,2006  Vojtech Pavlik
10
 *  Copyright (c) 2003  Andi Kleen
11
 *  RTC support code taken from arch/i386/kernel/timers/time_hpet.c
12
 */
13
 
14
#include <linux/kernel.h>
15
#include <linux/sched.h>
16
#include <linux/interrupt.h>
17
#include <linux/init.h>
18
#include <linux/mc146818rtc.h>
19
#include <linux/time.h>
20
#include <linux/ioport.h>
21
#include <linux/module.h>
22
#include <linux/device.h>
23
#include <linux/sysdev.h>
24
#include <linux/bcd.h>
25
#include <linux/notifier.h>
26
#include <linux/cpu.h>
27
#include <linux/kallsyms.h>
28
#include <linux/acpi.h>
29
#include <linux/clockchips.h>
30
 
31
#ifdef CONFIG_ACPI
32
#include <acpi/achware.h>       /* for PM timer frequency */
33
#include <acpi/acpi_bus.h>
34
#endif
35
#include <asm/i8253.h>
36
#include <asm/pgtable.h>
37
#include <asm/vsyscall.h>
38
#include <asm/timex.h>
39
#include <asm/proto.h>
40
#include <asm/hpet.h>
41
#include <asm/sections.h>
42
#include <linux/hpet.h>
43
#include <asm/apic.h>
44
#include <asm/hpet.h>
45
#include <asm/mpspec.h>
46
#include <asm/nmi.h>
47
#include <asm/vgtod.h>
48
 
49
DEFINE_SPINLOCK(rtc_lock);
50
EXPORT_SYMBOL(rtc_lock);
51
 
52
volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
53
 
54
unsigned long profile_pc(struct pt_regs *regs)
55
{
56
        unsigned long pc = instruction_pointer(regs);
57
 
58
        /* Assume the lock function has either no stack frame or a copy
59
           of eflags from PUSHF
60
           Eflags always has bits 22 and up cleared unlike kernel addresses. */
61
        if (!user_mode(regs) && in_lock_functions(pc)) {
62
                unsigned long *sp = (unsigned long *)regs->rsp;
63
                if (sp[0] >> 22)
64
                        return sp[0];
65
                if (sp[1] >> 22)
66
                        return sp[1];
67
        }
68
        return pc;
69
}
70
EXPORT_SYMBOL(profile_pc);
71
 
72
/*
73
 * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
74
 * ms after the second nowtime has started, because when nowtime is written
75
 * into the registers of the CMOS clock, it will jump to the next second
76
 * precisely 500 ms later. Check the Motorola MC146818A or Dallas DS12887 data
77
 * sheet for details.
78
 */
79
 
80
static int set_rtc_mmss(unsigned long nowtime)
81
{
82
        int retval = 0;
83
        int real_seconds, real_minutes, cmos_minutes;
84
        unsigned char control, freq_select;
85
        unsigned long flags;
86
 
87
/*
88
 * set_rtc_mmss is called when irqs are enabled, so disable irqs here
89
 */
90
        spin_lock_irqsave(&rtc_lock, flags);
91
/*
92
 * Tell the clock it's being set and stop it.
93
 */
94
        control = CMOS_READ(RTC_CONTROL);
95
        CMOS_WRITE(control | RTC_SET, RTC_CONTROL);
96
 
97
        freq_select = CMOS_READ(RTC_FREQ_SELECT);
98
        CMOS_WRITE(freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT);
99
 
100
        cmos_minutes = CMOS_READ(RTC_MINUTES);
101
                BCD_TO_BIN(cmos_minutes);
102
 
103
/*
104
 * since we're only adjusting minutes and seconds, don't interfere with hour
105
 * overflow. This avoids messing with unknown time zones but requires your RTC
106
 * not to be off by more than 15 minutes. Since we're calling it only when
107
 * our clock is externally synchronized using NTP, this shouldn't be a problem.
108
 */
109
 
110
        real_seconds = nowtime % 60;
111
        real_minutes = nowtime / 60;
112
        if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
113
                real_minutes += 30;             /* correct for half hour time zone */
114
        real_minutes %= 60;
115
 
116
        if (abs(real_minutes - cmos_minutes) >= 30) {
117
                printk(KERN_WARNING "time.c: can't update CMOS clock "
118
                       "from %d to %d\n", cmos_minutes, real_minutes);
119
                retval = -1;
120
        } else {
121
                BIN_TO_BCD(real_seconds);
122
                BIN_TO_BCD(real_minutes);
123
                CMOS_WRITE(real_seconds, RTC_SECONDS);
124
                CMOS_WRITE(real_minutes, RTC_MINUTES);
125
        }
126
 
127
/*
128
 * The following flags have to be released exactly in this order, otherwise the
129
 * DS12887 (popular MC146818A clone with integrated battery and quartz) will
130
 * not reset the oscillator and will not update precisely 500 ms later. You
131
 * won't find this mentioned in the Dallas Semiconductor data sheets, but who
132
 * believes data sheets anyway ... -- Markus Kuhn
133
 */
134
 
135
        CMOS_WRITE(control, RTC_CONTROL);
136
        CMOS_WRITE(freq_select, RTC_FREQ_SELECT);
137
 
138
        spin_unlock_irqrestore(&rtc_lock, flags);
139
 
140
        return retval;
141
}
142
 
143
int update_persistent_clock(struct timespec now)
144
{
145
        return set_rtc_mmss(now.tv_sec);
146
}
147
 
148
static irqreturn_t timer_event_interrupt(int irq, void *dev_id)
149
{
150
        add_pda(irq0_irqs, 1);
151
 
152
        global_clock_event->event_handler(global_clock_event);
153
 
154
        return IRQ_HANDLED;
155
}
156
 
157
unsigned long read_persistent_clock(void)
158
{
159
        unsigned int year, mon, day, hour, min, sec;
160
        unsigned long flags;
161
        unsigned century = 0;
162
 
163
        spin_lock_irqsave(&rtc_lock, flags);
164
        /*
165
         * if UIP is clear, then we have >= 244 microseconds before RTC
166
         * registers will be updated.  Spec sheet says that this is the
167
         * reliable way to read RTC - registers invalid (off bus) during update
168
         */
169
        while ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
170
                cpu_relax();
171
 
172
 
173
        /* now read all RTC registers while stable with interrupts disabled */
174
        sec = CMOS_READ(RTC_SECONDS);
175
        min = CMOS_READ(RTC_MINUTES);
176
        hour = CMOS_READ(RTC_HOURS);
177
        day = CMOS_READ(RTC_DAY_OF_MONTH);
178
        mon = CMOS_READ(RTC_MONTH);
179
        year = CMOS_READ(RTC_YEAR);
180
#ifdef CONFIG_ACPI
181
        if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
182
                                acpi_gbl_FADT.century)
183
                century = CMOS_READ(acpi_gbl_FADT.century);
184
#endif
185
        spin_unlock_irqrestore(&rtc_lock, flags);
186
 
187
        /*
188
         * We know that x86-64 always uses BCD format, no need to check the
189
         * config register.
190
         */
191
 
192
        BCD_TO_BIN(sec);
193
        BCD_TO_BIN(min);
194
        BCD_TO_BIN(hour);
195
        BCD_TO_BIN(day);
196
        BCD_TO_BIN(mon);
197
        BCD_TO_BIN(year);
198
 
199
        if (century) {
200
                BCD_TO_BIN(century);
201
                year += century * 100;
202
                printk(KERN_INFO "Extended CMOS year: %d\n", century * 100);
203
        } else {
204
                /*
205
                 * x86-64 systems only exists since 2002.
206
                 * This will work up to Dec 31, 2100
207
                 */
208
                year += 2000;
209
        }
210
 
211
        return mktime(year, mon, day, hour, min, sec);
212
}
213
 
214
/* calibrate_cpu is used on systems with fixed rate TSCs to determine
215
 * processor frequency */
216
#define TICK_COUNT 100000000
217
static unsigned int __init tsc_calibrate_cpu_khz(void)
218
{
219
        int tsc_start, tsc_now;
220
        int i, no_ctr_free;
221
        unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0;
222
        unsigned long flags;
223
 
224
        for (i = 0; i < 4; i++)
225
                if (avail_to_resrv_perfctr_nmi_bit(i))
226
                        break;
227
        no_ctr_free = (i == 4);
228
        if (no_ctr_free) {
229
                i = 3;
230
                rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
231
                wrmsrl(MSR_K7_EVNTSEL3, 0);
232
                rdmsrl(MSR_K7_PERFCTR3, pmc3);
233
        } else {
234
                reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
235
                reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
236
        }
237
        local_irq_save(flags);
238
        /* start meauring cycles, incrementing from 0 */
239
        wrmsrl(MSR_K7_PERFCTR0 + i, 0);
240
        wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
241
        rdtscl(tsc_start);
242
        do {
243
                rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
244
                tsc_now = get_cycles_sync();
245
        } while ((tsc_now - tsc_start) < TICK_COUNT);
246
 
247
        local_irq_restore(flags);
248
        if (no_ctr_free) {
249
                wrmsrl(MSR_K7_EVNTSEL3, 0);
250
                wrmsrl(MSR_K7_PERFCTR3, pmc3);
251
                wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
252
        } else {
253
                release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
254
                release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
255
        }
256
 
257
        return pmc_now * tsc_khz / (tsc_now - tsc_start);
258
}
259
 
260
static struct irqaction irq0 = {
261
        .handler        = timer_event_interrupt,
262
        .flags          = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING,
263
        .mask           = CPU_MASK_NONE,
264
        .name           = "timer"
265
};
266
 
267
void __init time_init(void)
268
{
269
        if (!hpet_enable())
270
                setup_pit_timer();
271
 
272
        setup_irq(0, &irq0);
273
 
274
        tsc_calibrate();
275
 
276
        cpu_khz = tsc_khz;
277
        if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
278
                boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
279
                boot_cpu_data.x86 == 16)
280
                cpu_khz = tsc_calibrate_cpu_khz();
281
 
282
        if (unsynchronized_tsc())
283
                mark_tsc_unstable("TSCs unsynchronized");
284
 
285
        if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
286
                vgetcpu_mode = VGETCPU_RDTSCP;
287
        else
288
                vgetcpu_mode = VGETCPU_LSL;
289
 
290
        printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
291
                cpu_khz / 1000, cpu_khz % 1000);
292
        init_tsc_clocksource();
293
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.