Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only 2 : #include <linux/bcd.h> 3 : #include <linux/delay.h> 4 : #include <linux/export.h> 5 : #include <linux/mc146818rtc.h> 6 : 7 : #ifdef CONFIG_ACPI 8 : #include <linux/acpi.h> 9 : #endif 10 : 11 0 : unsigned int mc146818_get_time(struct rtc_time *time) 12 : { 13 0 : unsigned char ctrl; 14 0 : unsigned long flags; 15 0 : unsigned char century = 0; 16 0 : bool retry; 17 : 18 : #ifdef CONFIG_MACH_DECSTATION 19 : unsigned int real_year; 20 : #endif 21 : 22 : again: 23 0 : spin_lock_irqsave(&rtc_lock, flags); 24 : /* Ensure that the RTC is accessible. Bit 6 must be 0! */ 25 0 : if (WARN_ON_ONCE((CMOS_READ(RTC_VALID) & 0x40) != 0)) { 26 0 : spin_unlock_irqrestore(&rtc_lock, flags); 27 0 : memset(time, 0xff, sizeof(*time)); 28 0 : return 0; 29 : } 30 : 31 : /* 32 : * Check whether there is an update in progress during which the 33 : * readout is unspecified. The maximum update time is ~2ms. Poll 34 : * every msec for completion. 35 : * 36 : * Store the second value before checking UIP so a long lasting NMI 37 : * which happens to hit after the UIP check cannot make an update 38 : * cycle invisible. 39 : */ 40 0 : time->tm_sec = CMOS_READ(RTC_SECONDS); 41 : 42 0 : if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) { 43 0 : spin_unlock_irqrestore(&rtc_lock, flags); 44 0 : mdelay(1); 45 0 : goto again; 46 : } 47 : 48 : /* Revalidate the above readout */ 49 0 : if (time->tm_sec != CMOS_READ(RTC_SECONDS)) { 50 0 : spin_unlock_irqrestore(&rtc_lock, flags); 51 0 : goto again; 52 : } 53 : 54 : /* 55 : * Only the values that we read from the RTC are set. We leave 56 : * tm_wday, tm_yday and tm_isdst untouched. Even though the 57 : * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated 58 : * by the RTC when initially set to a non-zero value. 59 : */ 60 0 : time->tm_min = CMOS_READ(RTC_MINUTES); 61 0 : time->tm_hour = CMOS_READ(RTC_HOURS); 62 0 : time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); 63 0 : time->tm_mon = CMOS_READ(RTC_MONTH); 64 0 : time->tm_year = CMOS_READ(RTC_YEAR); 65 : #ifdef CONFIG_MACH_DECSTATION 66 : real_year = CMOS_READ(RTC_DEC_YEAR); 67 : #endif 68 : #ifdef CONFIG_ACPI 69 : if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && 70 : acpi_gbl_FADT.century) 71 : century = CMOS_READ(acpi_gbl_FADT.century); 72 : #endif 73 0 : ctrl = CMOS_READ(RTC_CONTROL); 74 : /* 75 : * Check for the UIP bit again. If it is set now then 76 : * the above values may contain garbage. 77 : */ 78 0 : retry = CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP; 79 : /* 80 : * A NMI might have interrupted the above sequence so check whether 81 : * the seconds value has changed which indicates that the NMI took 82 : * longer than the UIP bit was set. Unlikely, but possible and 83 : * there is also virt... 84 : */ 85 0 : retry |= time->tm_sec != CMOS_READ(RTC_SECONDS); 86 : 87 0 : spin_unlock_irqrestore(&rtc_lock, flags); 88 : 89 0 : if (retry) 90 0 : goto again; 91 : 92 0 : if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 93 : { 94 0 : time->tm_sec = bcd2bin(time->tm_sec); 95 0 : time->tm_min = bcd2bin(time->tm_min); 96 0 : time->tm_hour = bcd2bin(time->tm_hour); 97 0 : time->tm_mday = bcd2bin(time->tm_mday); 98 0 : time->tm_mon = bcd2bin(time->tm_mon); 99 0 : time->tm_year = bcd2bin(time->tm_year); 100 0 : century = bcd2bin(century); 101 : } 102 : 103 : #ifdef CONFIG_MACH_DECSTATION 104 : time->tm_year += real_year - 72; 105 : #endif 106 : 107 0 : if (century > 20) 108 : time->tm_year += (century - 19) * 100; 109 : 110 : /* 111 : * Account for differences between how the RTC uses the values 112 : * and how they are defined in a struct rtc_time; 113 : */ 114 0 : if (time->tm_year <= 69) 115 0 : time->tm_year += 100; 116 : 117 0 : time->tm_mon--; 118 : 119 0 : return RTC_24H; 120 : } 121 : EXPORT_SYMBOL_GPL(mc146818_get_time); 122 : 123 : /* Set the current date and time in the real time clock. */ 124 0 : int mc146818_set_time(struct rtc_time *time) 125 : { 126 0 : unsigned long flags; 127 0 : unsigned char mon, day, hrs, min, sec; 128 0 : unsigned char save_control, save_freq_select; 129 0 : unsigned int yrs; 130 : #ifdef CONFIG_MACH_DECSTATION 131 : unsigned int real_yrs, leap_yr; 132 : #endif 133 0 : unsigned char century = 0; 134 : 135 0 : yrs = time->tm_year; 136 0 : mon = time->tm_mon + 1; /* tm_mon starts at zero */ 137 0 : day = time->tm_mday; 138 0 : hrs = time->tm_hour; 139 0 : min = time->tm_min; 140 0 : sec = time->tm_sec; 141 : 142 0 : if (yrs > 255) /* They are unsigned */ 143 : return -EINVAL; 144 : 145 : #ifdef CONFIG_MACH_DECSTATION 146 : real_yrs = yrs; 147 : leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) || 148 : !((yrs + 1900) % 400)); 149 : yrs = 72; 150 : 151 : /* 152 : * We want to keep the year set to 73 until March 153 : * for non-leap years, so that Feb, 29th is handled 154 : * correctly. 155 : */ 156 : if (!leap_yr && mon < 3) { 157 : real_yrs--; 158 : yrs = 73; 159 : } 160 : #endif 161 : 162 : #ifdef CONFIG_ACPI 163 : if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && 164 : acpi_gbl_FADT.century) { 165 : century = (yrs + 1900) / 100; 166 : yrs %= 100; 167 : } 168 : #endif 169 : 170 : /* These limits and adjustments are independent of 171 : * whether the chip is in binary mode or not. 172 : */ 173 0 : if (yrs > 169) 174 : return -EINVAL; 175 : 176 0 : if (yrs >= 100) 177 0 : yrs -= 100; 178 : 179 0 : if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) 180 : || RTC_ALWAYS_BCD) { 181 0 : sec = bin2bcd(sec); 182 0 : min = bin2bcd(min); 183 0 : hrs = bin2bcd(hrs); 184 0 : day = bin2bcd(day); 185 0 : mon = bin2bcd(mon); 186 0 : yrs = bin2bcd(yrs); 187 0 : century = bin2bcd(century); 188 : } 189 : 190 0 : spin_lock_irqsave(&rtc_lock, flags); 191 0 : save_control = CMOS_READ(RTC_CONTROL); 192 0 : CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); 193 0 : save_freq_select = CMOS_READ(RTC_FREQ_SELECT); 194 0 : CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); 195 : 196 : #ifdef CONFIG_MACH_DECSTATION 197 : CMOS_WRITE(real_yrs, RTC_DEC_YEAR); 198 : #endif 199 0 : CMOS_WRITE(yrs, RTC_YEAR); 200 0 : CMOS_WRITE(mon, RTC_MONTH); 201 0 : CMOS_WRITE(day, RTC_DAY_OF_MONTH); 202 0 : CMOS_WRITE(hrs, RTC_HOURS); 203 0 : CMOS_WRITE(min, RTC_MINUTES); 204 0 : CMOS_WRITE(sec, RTC_SECONDS); 205 : #ifdef CONFIG_ACPI 206 : if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && 207 : acpi_gbl_FADT.century) 208 : CMOS_WRITE(century, acpi_gbl_FADT.century); 209 : #endif 210 : 211 0 : CMOS_WRITE(save_control, RTC_CONTROL); 212 0 : CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 213 : 214 0 : spin_unlock_irqrestore(&rtc_lock, flags); 215 : 216 0 : return 0; 217 : } 218 : EXPORT_SYMBOL_GPL(mc146818_set_time);