time.c 2.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 *  linux/arch/arm/kernel/time.c
 *
 *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
 *  Modifications for ARM (C) 1994-2001 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  This file contains the ARM-specific time handling details:
 *  reading the RTC at bootup, etc...
 */
14
#include <linux/export.h>
L
Linus Torvalds 已提交
15 16 17 18
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/init.h>
19
#include <linux/sched.h>
L
Linus Torvalds 已提交
20 21 22 23 24
#include <linux/smp.h>
#include <linux/timex.h>
#include <linux/errno.h>
#include <linux/profile.h>
#include <linux/timer.h>
25
#include <linux/clocksource.h>
26
#include <linux/irq.h>
27
#include <linux/sched_clock.h>
L
Linus Torvalds 已提交
28 29

#include <asm/thread_info.h>
30
#include <asm/stacktrace.h>
31
#include <asm/mach/arch.h>
L
Linus Torvalds 已提交
32 33
#include <asm/mach/time.h>

34 35
#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
    defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
L
Linus Torvalds 已提交
36 37 38
/* this needs a better home */
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);
39
#endif	/* pc-style 'CMOS' RTC support */
L
Linus Torvalds 已提交
40 41 42 43 44 45 46

/* change this if you have some constant time drift */
#define USECS_PER_JIFFY	(1000000/HZ)

#ifdef CONFIG_SMP
unsigned long profile_pc(struct pt_regs *regs)
{
47
	struct stackframe frame;
L
Linus Torvalds 已提交
48

49 50
	if (!in_lock_functions(regs->ARM_pc))
		return regs->ARM_pc;
L
Linus Torvalds 已提交
51

52 53 54 55 56 57 58 59 60 61 62
	frame.fp = regs->ARM_fp;
	frame.sp = regs->ARM_sp;
	frame.lr = regs->ARM_lr;
	frame.pc = regs->ARM_pc;
	do {
		int ret = unwind_frame(&frame);
		if (ret < 0)
			return 0;
	} while (in_lock_functions(frame.pc));

	return frame.pc;
L
Linus Torvalds 已提交
63 64 65 66
}
EXPORT_SYMBOL(profile_pc);
#endif

67
#ifndef CONFIG_GENERIC_CLOCKEVENTS
L
Linus Torvalds 已提交
68 69 70
/*
 * Kernel system timer support.
 */
71
void timer_tick(void)
L
Linus Torvalds 已提交
72
{
73
	profile_tick(CPU_PROFILING);
74
	xtime_update(1);
L
Linus Torvalds 已提交
75
#ifndef CONFIG_SMP
R
Russell King 已提交
76
	update_process_times(user_mode(get_irq_regs()));
L
Linus Torvalds 已提交
77 78
#endif
}
79
#endif
L
Linus Torvalds 已提交
80

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
static void dummy_clock_access(struct timespec *ts)
{
	ts->tv_sec = 0;
	ts->tv_nsec = 0;
}

static clock_access_fn __read_persistent_clock = dummy_clock_access;
static clock_access_fn __read_boot_clock = dummy_clock_access;;

void read_persistent_clock(struct timespec *ts)
{
	__read_persistent_clock(ts);
}

void read_boot_clock(struct timespec *ts)
{
	__read_boot_clock(ts);
}

int __init register_persistent_clock(clock_access_fn read_boot,
				     clock_access_fn read_persistent)
{
	/* Only allow the clockaccess functions to be registered once */
	if (__read_persistent_clock == dummy_clock_access &&
	    __read_boot_clock == dummy_clock_access) {
		if (read_boot)
			__read_boot_clock = read_boot;
		if (read_persistent)
			__read_persistent_clock = read_persistent;

		return 0;
	}

	return -EINVAL;
}

L
Linus Torvalds 已提交
117 118
void __init time_init(void)
{
119 120 121 122
	if (machine_desc->init_time)
		machine_desc->init_time();
	else
		clocksource_of_init();
L
Linus Torvalds 已提交
123
}