blob: e0aa769481ff0b4da2eb96e22b6abb563b5c2986 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Paul Mundt5ac54962009-05-08 16:44:00 +09002 * arch/sh/kernel/time.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
Paul Mundt42786002009-04-28 23:12:10 +09006 * Copyright (C) 2002 - 2009 Paul Mundt
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
8 *
Paul Mundt5ac54962009-05-08 16:44:00 +09009 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/kernel.h>
Paul Mundt36ddf312006-01-16 22:14:17 -080014#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/init.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/profile.h>
Paul Mundt65e5d902006-12-06 11:24:48 +090017#include <linux/timex.h>
18#include <linux/sched.h>
Paul Mundt57be2b42007-05-09 17:33:24 +090019#include <linux/clockchips.h>
Magnus Dammeaab8912009-04-15 10:50:12 +000020#include <linux/platform_device.h>
Paul Mundt8c245942008-08-06 18:37:07 +090021#include <linux/smp.h>
Paul Mundt47c8a082009-04-27 17:34:39 +090022#include <linux/rtc.h>
Paul Mundt36ddf312006-01-16 22:14:17 -080023#include <asm/clock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <asm/rtc.h>
Paul Mundt36ddf312006-01-16 22:14:17 -080025#include <asm/timer.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
Paul Mundt36ddf312006-01-16 22:14:17 -080027struct sys_timer *sys_timer;
28
Paul Mundt91550f72006-09-27 17:45:01 +090029/* Dummy RTC ops */
30static void null_rtc_get_time(struct timespec *tv)
31{
32 tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
33 tv->tv_nsec = 0;
34}
35
36static int null_rtc_set_time(const time_t secs)
37{
38 return 0;
39}
40
41void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
42int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Paul Mundt6d134b92009-05-08 16:36:13 +090044#ifdef CONFIG_GENERIC_CMOS_UPDATE
45unsigned long read_persistent_clock(void)
46{
47 struct timespec tv;
48 rtc_sh_get_time(&tv);
49 return tv.tv_sec;
50}
51
52int update_persistent_clock(struct timespec now)
53{
54 return rtc_sh_set_time(now.tv_sec);
55}
56#endif
57
Paul Mundt47c8a082009-04-27 17:34:39 +090058unsigned int get_rtc_time(struct rtc_time *tm)
59{
60 if (rtc_sh_get_time != null_rtc_get_time) {
61 struct timespec tv;
62
63 rtc_sh_get_time(&tv);
64 rtc_time_to_tm(tv.tv_sec, tm);
65 }
66
67 return RTC_24H;
68}
69EXPORT_SYMBOL(get_rtc_time);
70
71int set_rtc_time(struct rtc_time *tm)
72{
73 unsigned long secs;
74
75 rtc_tm_to_time(tm, &secs);
76 return rtc_sh_set_time(secs);
77}
78EXPORT_SYMBOL(set_rtc_time);
79
Paul Mundt42786002009-04-28 23:12:10 +090080static int __init rtc_generic_init(void)
81{
82 struct platform_device *pdev;
83
84 if (rtc_sh_get_time == null_rtc_get_time)
85 return -ENODEV;
86
87 pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
88 if (IS_ERR(pdev))
89 return PTR_ERR(pdev);
90
91 return 0;
92}
93module_init(rtc_generic_init);
94
Linus Torvalds1da177e2005-04-16 15:20:36 -070095void (*board_time_init)(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Magnus Damm955c0772009-01-22 09:55:31 +000097struct clocksource clocksource_sh = {
Paul Mundt57be2b42007-05-09 17:33:24 +090098 .name = "SuperH",
Paul Mundt57be2b42007-05-09 17:33:24 +090099};
100
Paul Mundt57be2b42007-05-09 17:33:24 +0900101unsigned long long sched_clock(void)
102{
Magnus Damm955c0772009-01-22 09:55:31 +0000103 unsigned long long cycles;
104
105 /* jiffies based sched_clock if no clocksource is installed */
106 if (!clocksource_sh.rating)
107 return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ);
108
Magnus Damm8e196082009-04-21 12:24:00 -0700109 cycles = clocksource_sh.read(&clocksource_sh);
Magnus Damm955c0772009-01-22 09:55:31 +0000110 return cyc2ns(&clocksource_sh, cycles);
Paul Mundt57be2b42007-05-09 17:33:24 +0900111}
Paul Mundt57be2b42007-05-09 17:33:24 +0900112
Magnus Damm8e0b8422009-04-28 08:19:50 +0000113static void __init sh_late_time_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 /*
Magnus Dammeaab8912009-04-15 10:50:12 +0000116 * Make sure all compiled-in early timers register themselves.
117 * Run probe() for one "earlytimer" device.
118 */
119 early_platform_driver_register_all("earlytimer");
120 if (early_platform_driver_probe("earlytimer", 1, 0))
121 return;
122
123 /*
Paul Mundt36ddf312006-01-16 22:14:17 -0800124 * Find the timer to use as the system timer, it will be
125 * initialized for us.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 */
Paul Mundt36ddf312006-01-16 22:14:17 -0800127 sys_timer = get_sys_timer();
Magnus Damm07821d32009-01-22 09:55:49 +0000128 if (unlikely(!sys_timer))
129 panic("System timer missing.\n");
130
Paul Mundt36ddf312006-01-16 22:14:17 -0800131 printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132}
Magnus Damm8e0b8422009-04-28 08:19:50 +0000133
134void __init time_init(void)
135{
136 if (board_time_init)
137 board_time_init();
138
139 clk_init();
140
141 rtc_sh_get_time(&xtime);
142 set_normalized_timespec(&wall_to_monotonic,
143 -xtime.tv_sec, -xtime.tv_nsec);
144
145#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
146 local_timer_setup(smp_processor_id());
147#endif
148
149 late_time_init = sh_late_time_init;
150}