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 40 static 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 */ 92 static 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 149 static int dec_timer_state(void) 150 { 151 return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0; 152 } 153 154 static void dec_timer_ack(void) 155 { 156 CMOS_READ(RTC_REG_C); /* Ack the RTC interrupt. */ 157 } 158 159 static 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 168 static void dec_ioasic_hpt_init(unsigned int count) 169 { 170 ioasic_write(IO_REG_FCTR, ioasic_read(IO_REG_FCTR) - count); 171 } 172 173 174 void __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 192 EXPORT_SYMBOL(do_settimeofday); 193 194 void __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 } 201