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