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.12-rc2 200 lines 5.8 kB view raw
1/* 2 * linux/arch/mips/dec/time.c 3 * 4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds 5 * Copyright (C) 2000, 2003 Maciej W. Rozycki 6 * 7 * This file contains the time handling details for PC-style clocks as 8 * found in some MIPS systems. 9 * 10 */ 11#include <linux/bcd.h> 12#include <linux/errno.h> 13#include <linux/init.h> 14#include <linux/interrupt.h> 15#include <linux/kernel.h> 16#include <linux/mc146818rtc.h> 17#include <linux/mm.h> 18#include <linux/module.h> 19#include <linux/param.h> 20#include <linux/sched.h> 21#include <linux/string.h> 22#include <linux/time.h> 23#include <linux/types.h> 24 25#include <asm/bootinfo.h> 26#include <asm/cpu.h> 27#include <asm/div64.h> 28#include <asm/io.h> 29#include <asm/irq.h> 30#include <asm/mipsregs.h> 31#include <asm/sections.h> 32#include <asm/time.h> 33 34#include <asm/dec/interrupts.h> 35#include <asm/dec/ioasic.h> 36#include <asm/dec/ioasic_addrs.h> 37#include <asm/dec/machtype.h> 38 39 40static unsigned long dec_rtc_get_time(void) 41{ 42 unsigned int year, mon, day, hour, min, sec, real_year; 43 int i; 44 45 /* The Linux interpretation of the DS1287 clock register contents: 46 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the 47 * RTC registers show the second which has precisely just started. 48 * Let's hope other operating systems interpret the RTC the same way. 49 */ 50 /* read RTC exactly on falling edge of update flag */ 51 for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ 52 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) 53 break; 54 for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ 55 if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) 56 break; 57 /* Isn't this overkill? UIP above should guarantee consistency */ 58 do { 59 sec = CMOS_READ(RTC_SECONDS); 60 min = CMOS_READ(RTC_MINUTES); 61 hour = CMOS_READ(RTC_HOURS); 62 day = CMOS_READ(RTC_DAY_OF_MONTH); 63 mon = CMOS_READ(RTC_MONTH); 64 year = CMOS_READ(RTC_YEAR); 65 } while (sec != CMOS_READ(RTC_SECONDS)); 66 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 67 sec = BCD2BIN(sec); 68 min = BCD2BIN(min); 69 hour = BCD2BIN(hour); 70 day = BCD2BIN(day); 71 mon = BCD2BIN(mon); 72 year = BCD2BIN(year); 73 } 74 /* 75 * The PROM will reset the year to either '72 or '73. 76 * Therefore we store the real year separately, in one 77 * of unused BBU RAM locations. 78 */ 79 real_year = CMOS_READ(RTC_DEC_YEAR); 80 year += real_year - 72 + 2000; 81 82 return mktime(year, mon, day, hour, min, sec); 83} 84 85/* 86 * In order to set the CMOS clock precisely, dec_rtc_set_mmss has to 87 * be called 500 ms after the second nowtime has started, because when 88 * nowtime is written into the registers of the CMOS clock, it will 89 * jump to the next second precisely 500 ms later. Check the Dallas 90 * DS1287 data sheet for details. 91 */ 92static int dec_rtc_set_mmss(unsigned long nowtime) 93{ 94 int retval = 0; 95 int real_seconds, real_minutes, cmos_minutes; 96 unsigned char save_control, save_freq_select; 97 98 /* tell the clock it's being set */ 99 save_control = CMOS_READ(RTC_CONTROL); 100 CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); 101 102 /* stop and reset prescaler */ 103 save_freq_select = CMOS_READ(RTC_FREQ_SELECT); 104 CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); 105 106 cmos_minutes = CMOS_READ(RTC_MINUTES); 107 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 108 cmos_minutes = BCD2BIN(cmos_minutes); 109 110 /* 111 * since we're only adjusting minutes and seconds, 112 * don't interfere with hour overflow. This avoids 113 * messing with unknown time zones but requires your 114 * RTC not to be off by more than 15 minutes 115 */ 116 real_seconds = nowtime % 60; 117 real_minutes = nowtime / 60; 118 if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) 119 real_minutes += 30; /* correct for half hour time zone */ 120 real_minutes %= 60; 121 122 if (abs(real_minutes - cmos_minutes) < 30) { 123 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 124 real_seconds = BIN2BCD(real_seconds); 125 real_minutes = BIN2BCD(real_minutes); 126 } 127 CMOS_WRITE(real_seconds, RTC_SECONDS); 128 CMOS_WRITE(real_minutes, RTC_MINUTES); 129 } else { 130 printk(KERN_WARNING 131 "set_rtc_mmss: can't update from %d to %d\n", 132 cmos_minutes, real_minutes); 133 retval = -1; 134 } 135 136 /* The following flags have to be released exactly in this order, 137 * otherwise the DS1287 will not reset the oscillator and will not 138 * update precisely 500 ms later. You won't find this mentioned 139 * in the Dallas Semiconductor data sheets, but who believes data 140 * sheets anyway ... -- Markus Kuhn 141 */ 142 CMOS_WRITE(save_control, RTC_CONTROL); 143 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 144 145 return retval; 146} 147 148 149static int dec_timer_state(void) 150{ 151 return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0; 152} 153 154static void dec_timer_ack(void) 155{ 156 CMOS_READ(RTC_REG_C); /* Ack the RTC interrupt. */ 157} 158 159static unsigned int dec_ioasic_hpt_read(void) 160{ 161 /* 162 * The free-running counter is 32-bit which is good for about 163 * 2 minutes, 50 seconds at possible count rates of up to 25MHz. 164 */ 165 return ioasic_read(IO_REG_FCTR); 166} 167 168static void dec_ioasic_hpt_init(unsigned int count) 169{ 170 ioasic_write(IO_REG_FCTR, ioasic_read(IO_REG_FCTR) - count); 171} 172 173 174void __init dec_time_init(void) 175{ 176 rtc_get_time = dec_rtc_get_time; 177 rtc_set_mmss = dec_rtc_set_mmss; 178 179 mips_timer_state = dec_timer_state; 180 mips_timer_ack = dec_timer_ack; 181 182 if (!cpu_has_counter && IOASIC) { 183 /* For pre-R4k systems we use the I/O ASIC's counter. */ 184 mips_hpt_read = dec_ioasic_hpt_read; 185 mips_hpt_init = dec_ioasic_hpt_init; 186 } 187 188 /* Set up the rate of periodic DS1287 interrupts. */ 189 CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A); 190} 191 192EXPORT_SYMBOL(do_settimeofday); 193 194void __init dec_timer_setup(struct irqaction *irq) 195{ 196 setup_irq(dec_interrupt[DEC_IRQ_RTC], irq); 197 198 /* Enable periodic DS1287 interrupts. */ 199 CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B); 200}