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/init.h> 13 #include <linux/mc146818rtc.h> 14 #include <linux/param.h> 15 16 #include <asm/cpu-features.h> 17 #include <asm/ds1287.h> 18 #include <asm/time.h> 19 #include <asm/dec/interrupts.h> 20 #include <asm/dec/ioasic.h> 21 #include <asm/dec/machtype.h> 22 23 unsigned long read_persistent_clock(void) 24 { 25 unsigned int year, mon, day, hour, min, sec, real_year; 26 unsigned long flags; 27 28 spin_lock_irqsave(&rtc_lock, flags); 29 30 do { 31 sec = CMOS_READ(RTC_SECONDS); 32 min = CMOS_READ(RTC_MINUTES); 33 hour = CMOS_READ(RTC_HOURS); 34 day = CMOS_READ(RTC_DAY_OF_MONTH); 35 mon = CMOS_READ(RTC_MONTH); 36 year = CMOS_READ(RTC_YEAR); 37 /* 38 * The PROM will reset the year to either '72 or '73. 39 * Therefore we store the real year separately, in one 40 * of unused BBU RAM locations. 41 */ 42 real_year = CMOS_READ(RTC_DEC_YEAR); 43 } while (sec != CMOS_READ(RTC_SECONDS)); 44 45 spin_unlock_irqrestore(&rtc_lock, flags); 46 47 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 48 sec = bcd2bin(sec); 49 min = bcd2bin(min); 50 hour = bcd2bin(hour); 51 day = bcd2bin(day); 52 mon = bcd2bin(mon); 53 year = bcd2bin(year); 54 } 55 56 year += real_year - 72 + 2000; 57 58 return mktime(year, mon, day, hour, min, sec); 59 } 60 61 /* 62 * In order to set the CMOS clock precisely, rtc_mips_set_mmss has to 63 * be called 500 ms after the second nowtime has started, because when 64 * nowtime is written into the registers of the CMOS clock, it will 65 * jump to the next second precisely 500 ms later. Check the Dallas 66 * DS1287 data sheet for details. 67 */ 68 int rtc_mips_set_mmss(unsigned long nowtime) 69 { 70 int retval = 0; 71 int real_seconds, real_minutes, cmos_minutes; 72 unsigned char save_control, save_freq_select; 73 74 /* irq are locally disabled here */ 75 spin_lock(&rtc_lock); 76 /* tell the clock it's being set */ 77 save_control = CMOS_READ(RTC_CONTROL); 78 CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); 79 80 /* stop and reset prescaler */ 81 save_freq_select = CMOS_READ(RTC_FREQ_SELECT); 82 CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); 83 84 cmos_minutes = CMOS_READ(RTC_MINUTES); 85 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 86 cmos_minutes = bcd2bin(cmos_minutes); 87 88 /* 89 * since we're only adjusting minutes and seconds, 90 * don't interfere with hour overflow. This avoids 91 * messing with unknown time zones but requires your 92 * RTC not to be off by more than 15 minutes 93 */ 94 real_seconds = nowtime % 60; 95 real_minutes = nowtime / 60; 96 if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) 97 real_minutes += 30; /* correct for half hour time zone */ 98 real_minutes %= 60; 99 100 if (abs(real_minutes - cmos_minutes) < 30) { 101 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 102 real_seconds = bin2bcd(real_seconds); 103 real_minutes = bin2bcd(real_minutes); 104 } 105 CMOS_WRITE(real_seconds, RTC_SECONDS); 106 CMOS_WRITE(real_minutes, RTC_MINUTES); 107 } else { 108 printk(KERN_WARNING 109 "set_rtc_mmss: can't update from %d to %d\n", 110 cmos_minutes, real_minutes); 111 retval = -1; 112 } 113 114 /* The following flags have to be released exactly in this order, 115 * otherwise the DS1287 will not reset the oscillator and will not 116 * update precisely 500 ms later. You won't find this mentioned 117 * in the Dallas Semiconductor data sheets, but who believes data 118 * sheets anyway ... -- Markus Kuhn 119 */ 120 CMOS_WRITE(save_control, RTC_CONTROL); 121 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 122 spin_unlock(&rtc_lock); 123 124 return retval; 125 } 126 127 void __init plat_time_init(void) 128 { 129 u32 start, end; 130 int i = HZ / 10; 131 132 /* Set up the rate of periodic DS1287 interrupts. */ 133 ds1287_set_base_clock(HZ); 134 135 if (cpu_has_counter) { 136 while (!ds1287_timer_state()) 137 ; 138 139 start = read_c0_count(); 140 141 while (i--) 142 while (!ds1287_timer_state()) 143 ; 144 145 end = read_c0_count(); 146 147 mips_hpt_frequency = (end - start) * 10; 148 printk(KERN_INFO "MIPS counter frequency %dHz\n", 149 mips_hpt_frequency); 150 } else if (IOASIC) 151 /* For pre-R4k systems we use the I/O ASIC's counter. */ 152 dec_ioasic_clocksource_init(); 153 154 ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]); 155 } 156