Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.21 136 lines 3.8 kB view raw
1/* 2 * linux/arch/sh/kernel/rtc-mpc1211.c -- MPC-1211 on-chip RTC support 3 * 4 * Copyright (C) 2002 Saito.K & Jeanne 5 * 6 */ 7 8#include <linux/init.h> 9#include <linux/kernel.h> 10#include <linux/sched.h> 11#include <linux/time.h> 12#include <linux/bcd.h> 13#include <linux/mc146818rtc.h> 14 15unsigned long get_cmos_time(void) 16{ 17 unsigned int year, mon, day, hour, min, sec; 18 19 spin_lock(&rtc_lock); 20 21 do { 22 sec = CMOS_READ(RTC_SECONDS); 23 min = CMOS_READ(RTC_MINUTES); 24 hour = CMOS_READ(RTC_HOURS); 25 day = CMOS_READ(RTC_DAY_OF_MONTH); 26 mon = CMOS_READ(RTC_MONTH); 27 year = CMOS_READ(RTC_YEAR); 28 } while (sec != CMOS_READ(RTC_SECONDS)); 29 30 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 31 BCD_TO_BIN(sec); 32 BCD_TO_BIN(min); 33 BCD_TO_BIN(hour); 34 BCD_TO_BIN(day); 35 BCD_TO_BIN(mon); 36 BCD_TO_BIN(year); 37 } 38 39 spin_unlock(&rtc_lock); 40 41 year += 1900; 42 if (year < 1970) 43 year += 100; 44 45 return mktime(year, mon, day, hour, min, sec); 46} 47 48void mpc1211_rtc_gettimeofday(struct timeval *tv) 49{ 50 51 tv->tv_sec = get_cmos_time(); 52 tv->tv_usec = 0; 53} 54 55/* arc/i386/kernel/time.c */ 56/* 57 * In order to set the CMOS clock precisely, set_rtc_mmss has to be 58 * called 500 ms after the second nowtime has started, because when 59 * nowtime is written into the registers of the CMOS clock, it will 60 * jump to the next second precisely 500 ms later. Check the Motorola 61 * MC146818A or Dallas DS12887 data sheet for details. 62 * 63 * BUG: This routine does not handle hour overflow properly; it just 64 * sets the minutes. Usually you'll only notice that after reboot! 65 */ 66static int set_rtc_mmss(unsigned long nowtime) 67{ 68 int retval = 0; 69 int real_seconds, real_minutes, cmos_minutes; 70 unsigned char save_control, save_freq_select; 71 72 /* gets recalled with irq locally disabled */ 73 spin_lock(&rtc_lock); 74 save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ 75 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); 76 77 save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ 78 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); 79 80 cmos_minutes = CMOS_READ(RTC_MINUTES); 81 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 82 BCD_TO_BIN(cmos_minutes); 83 84 /* 85 * since we're only adjusting minutes and seconds, 86 * don't interfere with hour overflow. This avoids 87 * messing with unknown time zones but requires your 88 * RTC not to be off by more than 15 minutes 89 */ 90 real_seconds = nowtime % 60; 91 real_minutes = nowtime / 60; 92 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) 93 real_minutes += 30; /* correct for half hour time zone */ 94 real_minutes %= 60; 95 96 if (abs(real_minutes - cmos_minutes) < 30) { 97 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 98 BIN_TO_BCD(real_seconds); 99 BIN_TO_BCD(real_minutes); 100 } 101 CMOS_WRITE(real_seconds,RTC_SECONDS); 102 CMOS_WRITE(real_minutes,RTC_MINUTES); 103 } else { 104 printk(KERN_WARNING 105 "set_rtc_mmss: can't update from %d to %d\n", 106 cmos_minutes, real_minutes); 107 retval = -1; 108 } 109 110 /* The following flags have to be released exactly in this order, 111 * otherwise the DS12887 (popular MC146818A clone with integrated 112 * battery and quartz) will not reset the oscillator and will not 113 * update precisely 500 ms later. You won't find this mentioned in 114 * the Dallas Semiconductor data sheets, but who believes data 115 * sheets anyway ... -- Markus Kuhn 116 */ 117 CMOS_WRITE(save_control, RTC_CONTROL); 118 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 119 spin_unlock(&rtc_lock); 120 121 return retval; 122} 123 124int mpc1211_rtc_settimeofday(const struct timeval *tv) 125{ 126 unsigned long nowtime = tv->tv_sec; 127 128 return set_rtc_mmss(nowtime); 129} 130 131void mpc1211_time_init(void) 132{ 133 rtc_sh_get_time = mpc1211_rtc_gettimeofday; 134 rtc_sh_set_time = mpc1211_rtc_settimeofday; 135} 136