Branch data 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 : : /* 12 : : * Returns true if a clock update is in progress 13 : : */ 14 : 312 : static inline unsigned char mc146818_is_updating(void) 15 : : { 16 : 312 : unsigned char uip; 17 : 312 : unsigned long flags; 18 : : 19 : 312 : spin_lock_irqsave(&rtc_lock, flags); 20 : 312 : uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); 21 : 312 : spin_unlock_irqrestore(&rtc_lock, flags); 22 : 312 : return uip; 23 : : } 24 : : 25 : 312 : unsigned int mc146818_get_time(struct rtc_time *time) 26 : : { 27 : 312 : unsigned char ctrl; 28 : 312 : unsigned long flags; 29 : 312 : unsigned char century = 0; 30 : : 31 : : #ifdef CONFIG_MACH_DECSTATION 32 : : unsigned int real_year; 33 : : #endif 34 : : 35 : : /* 36 : : * read RTC once any update in progress is done. The update 37 : : * can take just over 2ms. We wait 20ms. There is no need to 38 : : * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. 39 : : * If you need to know *exactly* when a second has started, enable 40 : : * periodic update complete interrupts, (via ioctl) and then 41 : : * immediately read /dev/rtc which will block until you get the IRQ. 42 : : * Once the read clears, read the RTC time (again via ioctl). Easy. 43 : : */ 44 [ - + ]: 312 : if (mc146818_is_updating()) 45 [ # # ]: 0 : mdelay(20); 46 : : 47 : : /* 48 : : * Only the values that we read from the RTC are set. We leave 49 : : * tm_wday, tm_yday and tm_isdst untouched. Even though the 50 : : * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated 51 : : * by the RTC when initially set to a non-zero value. 52 : : */ 53 : 312 : spin_lock_irqsave(&rtc_lock, flags); 54 : 312 : time->tm_sec = CMOS_READ(RTC_SECONDS); 55 : 312 : time->tm_min = CMOS_READ(RTC_MINUTES); 56 : 312 : time->tm_hour = CMOS_READ(RTC_HOURS); 57 : 312 : time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); 58 : 312 : time->tm_mon = CMOS_READ(RTC_MONTH); 59 : 312 : time->tm_year = CMOS_READ(RTC_YEAR); 60 : : #ifdef CONFIG_MACH_DECSTATION 61 : : real_year = CMOS_READ(RTC_DEC_YEAR); 62 : : #endif 63 : : #ifdef CONFIG_ACPI 64 [ - + ]: 312 : if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && 65 [ # # ]: 0 : acpi_gbl_FADT.century) 66 : 0 : century = CMOS_READ(acpi_gbl_FADT.century); 67 : : #endif 68 : 312 : ctrl = CMOS_READ(RTC_CONTROL); 69 : 312 : spin_unlock_irqrestore(&rtc_lock, flags); 70 : : 71 : 312 : if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 72 : : { 73 [ - + ]: 312 : time->tm_sec = bcd2bin(time->tm_sec); 74 [ - + ]: 312 : time->tm_min = bcd2bin(time->tm_min); 75 [ - + ]: 312 : time->tm_hour = bcd2bin(time->tm_hour); 76 [ - + ]: 312 : time->tm_mday = bcd2bin(time->tm_mday); 77 [ - + ]: 312 : time->tm_mon = bcd2bin(time->tm_mon); 78 [ - + ]: 312 : time->tm_year = bcd2bin(time->tm_year); 79 [ - + ]: 312 : century = bcd2bin(century); 80 : : } 81 : : 82 : : #ifdef CONFIG_MACH_DECSTATION 83 : : time->tm_year += real_year - 72; 84 : : #endif 85 : : 86 [ - + ]: 312 : if (century > 20) 87 : 0 : time->tm_year += (century - 19) * 100; 88 : : 89 : : /* 90 : : * Account for differences between how the RTC uses the values 91 : : * and how they are defined in a struct rtc_time; 92 : : */ 93 [ + - ]: 312 : if (time->tm_year <= 69) 94 : 312 : time->tm_year += 100; 95 : : 96 : 312 : time->tm_mon--; 97 : : 98 : 312 : return RTC_24H; 99 : : } 100 : : EXPORT_SYMBOL_GPL(mc146818_get_time); 101 : : 102 : : /* Set the current date and time in the real time clock. */ 103 : 0 : int mc146818_set_time(struct rtc_time *time) 104 : : { 105 : 0 : unsigned long flags; 106 : 0 : unsigned char mon, day, hrs, min, sec; 107 : 0 : unsigned char save_control, save_freq_select; 108 : 0 : unsigned int yrs; 109 : : #ifdef CONFIG_MACH_DECSTATION 110 : : unsigned int real_yrs, leap_yr; 111 : : #endif 112 : 0 : unsigned char century = 0; 113 : : 114 : 0 : yrs = time->tm_year; 115 : 0 : mon = time->tm_mon + 1; /* tm_mon starts at zero */ 116 : 0 : day = time->tm_mday; 117 : 0 : hrs = time->tm_hour; 118 : 0 : min = time->tm_min; 119 : 0 : sec = time->tm_sec; 120 : : 121 [ # # ]: 0 : if (yrs > 255) /* They are unsigned */ 122 : : return -EINVAL; 123 : : 124 : 0 : spin_lock_irqsave(&rtc_lock, flags); 125 : : #ifdef CONFIG_MACH_DECSTATION 126 : : real_yrs = yrs; 127 : : leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) || 128 : : !((yrs + 1900) % 400)); 129 : : yrs = 72; 130 : : 131 : : /* 132 : : * We want to keep the year set to 73 until March 133 : : * for non-leap years, so that Feb, 29th is handled 134 : : * correctly. 135 : : */ 136 : : if (!leap_yr && mon < 3) { 137 : : real_yrs--; 138 : : yrs = 73; 139 : : } 140 : : #endif 141 : : 142 : : #ifdef CONFIG_ACPI 143 [ # # ]: 0 : if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && 144 [ # # ]: 0 : acpi_gbl_FADT.century) { 145 : 0 : century = (yrs + 1900) / 100; 146 : 0 : yrs %= 100; 147 : : } 148 : : #endif 149 : : 150 : : /* These limits and adjustments are independent of 151 : : * whether the chip is in binary mode or not. 152 : : */ 153 [ # # ]: 0 : if (yrs > 169) { 154 : 0 : spin_unlock_irqrestore(&rtc_lock, flags); 155 : 0 : return -EINVAL; 156 : : } 157 : : 158 [ # # ]: 0 : if (yrs >= 100) 159 : 0 : yrs -= 100; 160 : : 161 : 0 : if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) 162 : : || RTC_ALWAYS_BCD) { 163 [ # # ]: 0 : sec = bin2bcd(sec); 164 [ # # ]: 0 : min = bin2bcd(min); 165 [ # # ]: 0 : hrs = bin2bcd(hrs); 166 [ # # ]: 0 : day = bin2bcd(day); 167 [ # # ]: 0 : mon = bin2bcd(mon); 168 [ # # ]: 0 : yrs = bin2bcd(yrs); 169 [ # # ]: 0 : century = bin2bcd(century); 170 : : } 171 : : 172 : 0 : save_control = CMOS_READ(RTC_CONTROL); 173 : 0 : CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); 174 : 0 : save_freq_select = CMOS_READ(RTC_FREQ_SELECT); 175 : 0 : CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); 176 : : 177 : : #ifdef CONFIG_MACH_DECSTATION 178 : : CMOS_WRITE(real_yrs, RTC_DEC_YEAR); 179 : : #endif 180 : 0 : CMOS_WRITE(yrs, RTC_YEAR); 181 : 0 : CMOS_WRITE(mon, RTC_MONTH); 182 : 0 : CMOS_WRITE(day, RTC_DAY_OF_MONTH); 183 : 0 : CMOS_WRITE(hrs, RTC_HOURS); 184 : 0 : CMOS_WRITE(min, RTC_MINUTES); 185 : 0 : CMOS_WRITE(sec, RTC_SECONDS); 186 : : #ifdef CONFIG_ACPI 187 [ # # ]: 0 : if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && 188 [ # # ]: 0 : acpi_gbl_FADT.century) 189 : 0 : CMOS_WRITE(century, acpi_gbl_FADT.century); 190 : : #endif 191 : : 192 : 0 : CMOS_WRITE(save_control, RTC_CONTROL); 193 : 0 : CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 194 : : 195 : 0 : spin_unlock_irqrestore(&rtc_lock, flags); 196 : : 197 : 0 : return 0; 198 : : } 199 : : EXPORT_SYMBOL_GPL(mc146818_set_time);