1b179b72fSPaul Mundt /* 25ac54964SPaul Mundt * arch/sh/kernel/time.c 3b179b72fSPaul Mundt * 4b179b72fSPaul Mundt * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka 5b179b72fSPaul Mundt * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> 6b179b72fSPaul Mundt * Copyright (C) 2002 - 2009 Paul Mundt 7b179b72fSPaul Mundt * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> 8b179b72fSPaul Mundt * 95ac54964SPaul Mundt * This file is subject to the terms and conditions of the GNU General Public 105ac54964SPaul Mundt * License. See the file "COPYING" in the main directory of this archive 115ac54964SPaul Mundt * for more details. 12b179b72fSPaul Mundt */ 13b179b72fSPaul Mundt #include <linux/kernel.h> 14b179b72fSPaul Mundt #include <linux/module.h> 15b179b72fSPaul Mundt #include <linux/init.h> 16b179b72fSPaul Mundt #include <linux/profile.h> 17b179b72fSPaul Mundt #include <linux/timex.h> 18b179b72fSPaul Mundt #include <linux/sched.h> 19b179b72fSPaul Mundt #include <linux/clockchips.h> 20b179b72fSPaul Mundt #include <linux/platform_device.h> 21b179b72fSPaul Mundt #include <linux/smp.h> 22b179b72fSPaul Mundt #include <linux/rtc.h> 23b179b72fSPaul Mundt #include <asm/clock.h> 24b179b72fSPaul Mundt #include <asm/rtc.h> 25b179b72fSPaul Mundt 26b179b72fSPaul Mundt /* Dummy RTC ops */ 27b179b72fSPaul Mundt static void null_rtc_get_time(struct timespec *tv) 28b179b72fSPaul Mundt { 29b179b72fSPaul Mundt tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0); 30b179b72fSPaul Mundt tv->tv_nsec = 0; 31b179b72fSPaul Mundt } 32b179b72fSPaul Mundt 33b179b72fSPaul Mundt static int null_rtc_set_time(const time_t secs) 34b179b72fSPaul Mundt { 35b179b72fSPaul Mundt return 0; 36b179b72fSPaul Mundt } 37b179b72fSPaul Mundt 38b179b72fSPaul Mundt void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; 39b179b72fSPaul Mundt int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; 40b179b72fSPaul Mundt 416d134b9eSPaul Mundt #ifdef CONFIG_GENERIC_CMOS_UPDATE 426d134b9eSPaul Mundt unsigned long read_persistent_clock(void) 436d134b9eSPaul Mundt { 446d134b9eSPaul Mundt struct timespec tv; 456d134b9eSPaul Mundt rtc_sh_get_time(&tv); 466d134b9eSPaul Mundt return tv.tv_sec; 476d134b9eSPaul Mundt } 486d134b9eSPaul Mundt 496d134b9eSPaul Mundt int update_persistent_clock(struct timespec now) 506d134b9eSPaul Mundt { 516d134b9eSPaul Mundt return rtc_sh_set_time(now.tv_sec); 526d134b9eSPaul Mundt } 536d134b9eSPaul Mundt #endif 546d134b9eSPaul Mundt 55b179b72fSPaul Mundt unsigned int get_rtc_time(struct rtc_time *tm) 56b179b72fSPaul Mundt { 57b179b72fSPaul Mundt if (rtc_sh_get_time != null_rtc_get_time) { 58b179b72fSPaul Mundt struct timespec tv; 59b179b72fSPaul Mundt 60b179b72fSPaul Mundt rtc_sh_get_time(&tv); 61b179b72fSPaul Mundt rtc_time_to_tm(tv.tv_sec, tm); 62b179b72fSPaul Mundt } 63b179b72fSPaul Mundt 64b179b72fSPaul Mundt return RTC_24H; 65b179b72fSPaul Mundt } 66b179b72fSPaul Mundt EXPORT_SYMBOL(get_rtc_time); 67b179b72fSPaul Mundt 68b179b72fSPaul Mundt int set_rtc_time(struct rtc_time *tm) 69b179b72fSPaul Mundt { 70b179b72fSPaul Mundt unsigned long secs; 71b179b72fSPaul Mundt 72b179b72fSPaul Mundt rtc_tm_to_time(tm, &secs); 73b179b72fSPaul Mundt return rtc_sh_set_time(secs); 74b179b72fSPaul Mundt } 75b179b72fSPaul Mundt EXPORT_SYMBOL(set_rtc_time); 76b179b72fSPaul Mundt 77b179b72fSPaul Mundt static int __init rtc_generic_init(void) 78b179b72fSPaul Mundt { 79b179b72fSPaul Mundt struct platform_device *pdev; 80b179b72fSPaul Mundt 81b179b72fSPaul Mundt if (rtc_sh_get_time == null_rtc_get_time) 82b179b72fSPaul Mundt return -ENODEV; 83b179b72fSPaul Mundt 84b179b72fSPaul Mundt pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); 85b179b72fSPaul Mundt if (IS_ERR(pdev)) 86b179b72fSPaul Mundt return PTR_ERR(pdev); 87b179b72fSPaul Mundt 88b179b72fSPaul Mundt return 0; 89b179b72fSPaul Mundt } 90b179b72fSPaul Mundt module_init(rtc_generic_init); 91b179b72fSPaul Mundt 92b179b72fSPaul Mundt void (*board_time_init)(void); 93b179b72fSPaul Mundt 94b179b72fSPaul Mundt void __init time_init(void) 95b179b72fSPaul Mundt { 96b179b72fSPaul Mundt if (board_time_init) 97b179b72fSPaul Mundt board_time_init(); 98b179b72fSPaul Mundt 99b179b72fSPaul Mundt clk_init(); 100b179b72fSPaul Mundt 101b179b72fSPaul Mundt rtc_sh_get_time(&xtime); 102b179b72fSPaul Mundt set_normalized_timespec(&wall_to_monotonic, 103b179b72fSPaul Mundt -xtime.tv_sec, -xtime.tv_nsec); 104b179b72fSPaul Mundt 105b179b72fSPaul Mundt #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 106b179b72fSPaul Mundt local_timer_setup(smp_processor_id()); 107b179b72fSPaul Mundt #endif 108b179b72fSPaul Mundt 1091d29ebebSPaul Mundt /* 1101d29ebebSPaul Mundt * Make sure all compiled-in early timers register themselves. 1116fe32a46SPaul Mundt * 1126fe32a46SPaul Mundt * Run probe() for two "earlytimer" devices, these will be the 1136fe32a46SPaul Mundt * clockevents and clocksource devices respectively. In the event 1146fe32a46SPaul Mundt * that only a clockevents device is available, we -ENODEV on the 1156fe32a46SPaul Mundt * clocksource and the jiffies clocksource is used transparently 1166fe32a46SPaul Mundt * instead. No error handling is necessary here. 1171d29ebebSPaul Mundt */ 1181d29ebebSPaul Mundt early_platform_driver_register_all("earlytimer"); 1196fe32a46SPaul Mundt early_platform_driver_probe("earlytimer", 2, 0); 120b179b72fSPaul Mundt } 121