Blame view
arch/x86/kernel/rtc.c
6.42 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
fe599f9fb x86: isolate the ... |
2 |
* RTC related functions |
1da177e4c Linux-2.6.12-rc2 |
3 |
*/ |
8383d821e x86: rtc.c cleanup |
4 5 |
#include <linux/platform_device.h> #include <linux/mc146818rtc.h> |
1122b134b x86: share rtc code |
6 |
#include <linux/acpi.h> |
fe599f9fb x86: isolate the ... |
7 |
#include <linux/bcd.h> |
69c60c88e x86: Fix files ex... |
8 |
#include <linux/export.h> |
1da2e3d67 provide rtc_cmos ... |
9 |
#include <linux/pnp.h> |
3bcbaf6e0 rtc: cmos: Add OF... |
10 |
#include <linux/of.h> |
1da177e4c Linux-2.6.12-rc2 |
11 |
|
cdc7957d1 x86: move native_... |
12 |
#include <asm/vsyscall.h> |
7bd867dfb x86: Move get/set... |
13 |
#include <asm/x86_init.h> |
8383d821e x86: rtc.c cleanup |
14 |
#include <asm/time.h> |
35d476996 x86/rtc, mrst: Do... |
15 |
#include <asm/mrst.h> |
1da177e4c Linux-2.6.12-rc2 |
16 |
|
1122b134b x86: share rtc code |
17 |
#ifdef CONFIG_X86_32 |
1122b134b x86: share rtc code |
18 19 20 21 22 |
/* * This is a special lock that is owned by the CPU and holds the index * register we are working with. It is required for NMI access to the * CMOS/RTC registers. See include/asm-i386/mc146818rtc.h for details. */ |
8383d821e x86: rtc.c cleanup |
23 |
volatile unsigned long cmos_lock; |
1122b134b x86: share rtc code |
24 |
EXPORT_SYMBOL(cmos_lock); |
8383d821e x86: rtc.c cleanup |
25 |
#endif /* CONFIG_X86_32 */ |
1122b134b x86: share rtc code |
26 |
|
b62576a2f x86: use year 200... |
27 28 |
/* For two digit years assume time is always after that */ #define CMOS_YEARS_OFFS 2000 |
1122b134b x86: share rtc code |
29 30 |
DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL(rtc_lock); |
1da177e4c Linux-2.6.12-rc2 |
31 32 33 34 35 36 37 38 39 40 |
/* * In order to set the CMOS clock precisely, set_rtc_mmss has to be * called 500 ms after the second nowtime has started, because when * nowtime is written into the registers of the CMOS clock, it will * jump to the next second precisely 500 ms later. Check the Motorola * MC146818A or Dallas DS12887 data sheet for details. * * BUG: This routine does not handle hour overflow properly; it just * sets the minutes. Usually you'll only notice that after reboot! */ |
fe599f9fb x86: isolate the ... |
41 |
int mach_set_rtc_mmss(unsigned long nowtime) |
1da177e4c Linux-2.6.12-rc2 |
42 |
{ |
1da177e4c Linux-2.6.12-rc2 |
43 44 |
int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; |
47997d756 x86/rtc: Don't re... |
45 |
unsigned long flags; |
8383d821e x86: rtc.c cleanup |
46 |
int retval = 0; |
1da177e4c Linux-2.6.12-rc2 |
47 |
|
47997d756 x86/rtc: Don't re... |
48 |
spin_lock_irqsave(&rtc_lock, flags); |
1122b134b x86: share rtc code |
49 50 |
/* tell the clock it's being set */ save_control = CMOS_READ(RTC_CONTROL); |
1da177e4c Linux-2.6.12-rc2 |
51 |
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); |
1122b134b x86: share rtc code |
52 53 |
/* stop and reset prescaler */ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); |
1da177e4c Linux-2.6.12-rc2 |
54 55 56 57 |
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); cmos_minutes = CMOS_READ(RTC_MINUTES); if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) |
357c6e635 rtc: use bcd2bin/... |
58 |
cmos_minutes = bcd2bin(cmos_minutes); |
1da177e4c Linux-2.6.12-rc2 |
59 60 61 62 63 64 65 66 67 |
/* * since we're only adjusting minutes and seconds, * don't interfere with hour overflow. This avoids * messing with unknown time zones but requires your * RTC not to be off by more than 15 minutes */ real_seconds = nowtime % 60; real_minutes = nowtime / 60; |
1122b134b x86: share rtc code |
68 |
/* correct for half hour time zone */ |
1da177e4c Linux-2.6.12-rc2 |
69 |
if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) |
1122b134b x86: share rtc code |
70 |
real_minutes += 30; |
1da177e4c Linux-2.6.12-rc2 |
71 72 73 74 |
real_minutes %= 60; if (abs(real_minutes - cmos_minutes) < 30) { if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
357c6e635 rtc: use bcd2bin/... |
75 76 |
real_seconds = bin2bcd(real_seconds); real_minutes = bin2bcd(real_minutes); |
1da177e4c Linux-2.6.12-rc2 |
77 |
} |
8383d821e x86: rtc.c cleanup |
78 79 |
CMOS_WRITE(real_seconds, RTC_SECONDS); CMOS_WRITE(real_minutes, RTC_MINUTES); |
1da177e4c Linux-2.6.12-rc2 |
80 |
} else { |
3e5c12409 set_rtc_mmss: sho... |
81 |
printk_once(KERN_NOTICE |
1da177e4c Linux-2.6.12-rc2 |
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
"set_rtc_mmss: can't update from %d to %d ", cmos_minutes, real_minutes); retval = -1; } /* The following flags have to be released exactly in this order, * otherwise the DS12887 (popular MC146818A clone with integrated * battery and quartz) will not reset the oscillator and will not * update precisely 500 ms later. You won't find this mentioned in * the Dallas Semiconductor data sheets, but who believes data * sheets anyway ... -- Markus Kuhn */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); |
47997d756 x86/rtc: Don't re... |
97 |
spin_unlock_irqrestore(&rtc_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
98 99 |
return retval; } |
fe599f9fb x86: isolate the ... |
100 |
unsigned long mach_get_cmos_time(void) |
1da177e4c Linux-2.6.12-rc2 |
101 |
{ |
068c9222d x86: add warning ... |
102 |
unsigned int status, year, mon, day, hour, min, sec, century = 0; |
47997d756 x86/rtc: Don't re... |
103 104 105 |
unsigned long flags; spin_lock_irqsave(&rtc_lock, flags); |
1122b134b x86: share rtc code |
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
/* * If UIP is clear, then we have >= 244 microseconds before * RTC registers will be updated. Spec sheet says that this * is the reliable way to read RTC - registers. If UIP is set * then the register access might be invalid. */ while ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) cpu_relax(); sec = CMOS_READ(RTC_SECONDS); min = CMOS_READ(RTC_MINUTES); hour = CMOS_READ(RTC_HOURS); day = CMOS_READ(RTC_DAY_OF_MONTH); mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); |
45de70791 x86: enable ACPI ... |
122 |
#ifdef CONFIG_ACPI |
1122b134b x86: share rtc code |
123 124 125 126 |
if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && acpi_gbl_FADT.century) century = CMOS_READ(acpi_gbl_FADT.century); #endif |
068c9222d x86: add warning ... |
127 |
status = CMOS_READ(RTC_CONTROL); |
45de70791 x86: enable ACPI ... |
128 |
WARN_ON_ONCE(RTC_ALWAYS_BCD && (status & RTC_DM_BINARY)); |
068c9222d x86: add warning ... |
129 |
|
47997d756 x86/rtc: Don't re... |
130 |
spin_unlock_irqrestore(&rtc_lock, flags); |
068c9222d x86: add warning ... |
131 |
if (RTC_ALWAYS_BCD || !(status & RTC_DM_BINARY)) { |
357c6e635 rtc: use bcd2bin/... |
132 133 134 135 136 137 |
sec = bcd2bin(sec); min = bcd2bin(min); hour = bcd2bin(hour); day = bcd2bin(day); mon = bcd2bin(mon); year = bcd2bin(year); |
41623b064 [PATCH] RTC: Fix ... |
138 |
} |
1122b134b x86: share rtc code |
139 |
if (century) { |
357c6e635 rtc: use bcd2bin/... |
140 |
century = bcd2bin(century); |
1122b134b x86: share rtc code |
141 142 143 |
year += century * 100; printk(KERN_INFO "Extended CMOS year: %d ", century * 100); |
b62576a2f x86: use year 200... |
144 |
} else |
1122b134b x86: share rtc code |
145 |
year += CMOS_YEARS_OFFS; |
1da177e4c Linux-2.6.12-rc2 |
146 147 148 |
return mktime(year, mon, day, hour, min, sec); } |
fe599f9fb x86: isolate the ... |
149 150 151 152 153 154 |
/* Routines for accessing the CMOS RAM/RTC. */ unsigned char rtc_cmos_read(unsigned char addr) { unsigned char val; lock_cmos_prefix(addr); |
04aaa7ba0 x86: fix cmos rea... |
155 156 |
outb(addr, RTC_PORT(0)); val = inb(RTC_PORT(1)); |
fe599f9fb x86: isolate the ... |
157 |
lock_cmos_suffix(addr); |
8383d821e x86: rtc.c cleanup |
158 |
|
fe599f9fb x86: isolate the ... |
159 160 161 162 163 164 165 |
return val; } EXPORT_SYMBOL(rtc_cmos_read); void rtc_cmos_write(unsigned char val, unsigned char addr) { lock_cmos_prefix(addr); |
04aaa7ba0 x86: fix cmos rea... |
166 167 |
outb(addr, RTC_PORT(0)); outb(val, RTC_PORT(1)); |
fe599f9fb x86: isolate the ... |
168 169 170 |
lock_cmos_suffix(addr); } EXPORT_SYMBOL(rtc_cmos_write); |
7bd867dfb x86: Move get/set... |
171 |
int update_persistent_clock(struct timespec now) |
fe599f9fb x86: isolate the ... |
172 |
{ |
47997d756 x86/rtc: Don't re... |
173 |
return x86_platform.set_wallclock(now.tv_sec); |
fe599f9fb x86: isolate the ... |
174 175 176 |
} /* not static: needed by APM */ |
d4f587c67 timekeeping: Incr... |
177 |
void read_persistent_clock(struct timespec *ts) |
fe599f9fb x86: isolate the ... |
178 |
{ |
47997d756 x86/rtc: Don't re... |
179 |
unsigned long retval; |
fe599f9fb x86: isolate the ... |
180 |
|
7bd867dfb x86: Move get/set... |
181 |
retval = x86_platform.get_wallclock(); |
fe599f9fb x86: isolate the ... |
182 |
|
d4f587c67 timekeeping: Incr... |
183 184 |
ts->tv_sec = retval; ts->tv_nsec = 0; |
fe599f9fb x86: isolate the ... |
185 |
} |
92767af0e x86: fix sched_cl... |
186 |
unsigned long long native_read_tsc(void) |
cdc7957d1 x86: move native_... |
187 |
{ |
92767af0e x86: fix sched_cl... |
188 |
return __native_read_tsc(); |
cdc7957d1 x86: move native_... |
189 |
} |
92767af0e x86: fix sched_cl... |
190 |
EXPORT_SYMBOL(native_read_tsc); |
1da2e3d67 provide rtc_cmos ... |
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
static struct resource rtc_resources[] = { [0] = { .start = RTC_PORT(0), .end = RTC_PORT(1), .flags = IORESOURCE_IO, }, [1] = { .start = RTC_IRQ, .end = RTC_IRQ, .flags = IORESOURCE_IRQ, } }; static struct platform_device rtc_device = { .name = "rtc_cmos", .id = -1, .resource = rtc_resources, .num_resources = ARRAY_SIZE(rtc_resources), }; static __init int add_rtc_cmos(void) { #ifdef CONFIG_PNP |
758a7f7bb x86: register a p... |
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
static const char *ids[] __initconst = { "PNP0b00", "PNP0b01", "PNP0b02", }; struct pnp_dev *dev; struct pnp_id *id; int i; pnp_for_each_dev(dev) { for (id = dev->id; id; id = id->next) { for (i = 0; i < ARRAY_SIZE(ids); i++) { if (compare_pnp_id(id, ids[i]) != 0) return 0; } } } #endif |
3bcbaf6e0 rtc: cmos: Add OF... |
230 231 |
if (of_have_populated_dt()) return 0; |
758a7f7bb x86: register a p... |
232 |
|
35d476996 x86/rtc, mrst: Do... |
233 234 235 |
/* Intel MID platforms don't have ioport rtc */ if (mrst_identify_cpu()) return -ENODEV; |
1da2e3d67 provide rtc_cmos ... |
236 |
platform_device_register(&rtc_device); |
758a7f7bb x86: register a p... |
237 238 239 |
dev_info(&rtc_device.dev, "registered platform RTC device (no PNP device found) "); |
8383d821e x86: rtc.c cleanup |
240 |
|
1da2e3d67 provide rtc_cmos ... |
241 242 243 |
return 0; } device_initcall(add_rtc_cmos); |