1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 1991, 1992, 1995 Linus Torvalds 4 * Copyright (C) 2000, 2003 Maciej W. Rozycki 5 * 6 * This file contains the time handling details for PC-style clocks as 7 * found in some MIPS systems. 8 * 9 */ 10 #include <linux/bcd.h> 11 #include <linux/init.h> 12 #include <linux/mc146818rtc.h> 13 #include <linux/param.h> 14 15 #include <asm/cpu-features.h> 16 #include <asm/ds1287.h> 17 #include <asm/time.h> 18 #include <asm/dec/interrupts.h> 19 #include <asm/dec/ioasic.h> 20 #include <asm/dec/machtype.h> 21 22 void read_persistent_clock64(struct timespec64 *ts) 23 { 24 unsigned int year, mon, day, hour, min, sec, real_year; 25 unsigned long flags; 26 27 spin_lock_irqsave(&rtc_lock, flags); 28 29 do { 30 sec = CMOS_READ(RTC_SECONDS); 31 min = CMOS_READ(RTC_MINUTES); 32 hour = CMOS_READ(RTC_HOURS); 33 day = CMOS_READ(RTC_DAY_OF_MONTH); 34 mon = CMOS_READ(RTC_MONTH); 35 year = CMOS_READ(RTC_YEAR); 36 /* 37 * The PROM will reset the year to either '72 or '73. 38 * Therefore we store the real year separately, in one 39 * of unused BBU RAM locations. 40 */ 41 real_year = CMOS_READ(RTC_DEC_YEAR); 42 } while (sec != CMOS_READ(RTC_SECONDS)); 43 44 spin_unlock_irqrestore(&rtc_lock, flags); 45 46 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 47 sec = bcd2bin(sec); 48 min = bcd2bin(min); 49 hour = bcd2bin(hour); 50 day = bcd2bin(day); 51 mon = bcd2bin(mon); 52 year = bcd2bin(year); 53 } 54 55 year += real_year - 72 + 2000; 56 57 ts->tv_sec = mktime64(year, mon, day, hour, min, sec); 58 ts->tv_nsec = 0; 59 } 60 61 /* 62 * In order to set the CMOS clock precisely, update_persistent_clock64 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 update_persistent_clock64(struct timespec64 now) 69 { 70 time64_t nowtime = now.tv_sec; 71 int retval = 0; 72 int real_seconds, real_minutes, cmos_minutes; 73 unsigned char save_control, save_freq_select; 74 75 /* irq are locally disabled here */ 76 spin_lock(&rtc_lock); 77 /* tell the clock it's being set */ 78 save_control = CMOS_READ(RTC_CONTROL); 79 CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); 80 81 /* stop and reset prescaler */ 82 save_freq_select = CMOS_READ(RTC_FREQ_SELECT); 83 CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); 84 85 cmos_minutes = CMOS_READ(RTC_MINUTES); 86 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 87 cmos_minutes = bcd2bin(cmos_minutes); 88 89 /* 90 * since we're only adjusting minutes and seconds, 91 * don't interfere with hour overflow. This avoids 92 * messing with unknown time zones but requires your 93 * RTC not to be off by more than 15 minutes 94 */ 95 real_minutes = div_s64_rem(nowtime, 60, &real_seconds); 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_once(KERN_NOTICE 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 int ioasic_clock = 0; 130 u32 start, end; 131 int i = HZ / 8; 132 133 /* Set up the rate of periodic DS1287 interrupts. */ 134 ds1287_set_base_clock(HZ); 135 136 /* On some I/O ASIC systems we have the I/O ASIC's counter. */ 137 if (IOASIC) 138 ioasic_clock = dec_ioasic_clocksource_init() == 0; 139 if (cpu_has_counter) { 140 ds1287_timer_state(); 141 while (!ds1287_timer_state()) 142 ; 143 144 start = read_c0_count(); 145 146 while (i--) 147 while (!ds1287_timer_state()) 148 ; 149 150 end = read_c0_count(); 151 152 mips_hpt_frequency = (end - start) * 8; 153 printk(KERN_INFO "MIPS counter frequency %dHz\n", 154 mips_hpt_frequency); 155 156 /* 157 * All R4k DECstations suffer from the CP0 Count erratum, 158 * so we can't use the timer as a clock source, and a clock 159 * event both at a time. An accurate wall clock is more 160 * important than a high-precision interval timer so only 161 * use the timer as a clock source, and not a clock event 162 * if there's no I/O ASIC counter available to serve as a 163 * clock source. 164 */ 165 if (!ioasic_clock) { 166 init_r4k_clocksource(); 167 mips_hpt_frequency = 0; 168 } 169 } 170 171 ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]); 172 } 173
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.