blob: 348ce016a835c291deeae528fb327ea8f93ffbdb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Thomas Gleixnerfe599f92008-01-30 13:30:26 +01002 * RTC related functions
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 */
Jaswinder Singh Rajput8383d822009-03-21 16:56:37 +05304#include <linux/platform_device.h>
5#include <linux/mc146818rtc.h>
Thomas Gleixner1122b132008-01-30 13:30:27 +01006#include <linux/acpi.h>
Thomas Gleixnerfe599f92008-01-30 13:30:26 +01007#include <linux/bcd.h>
Paul Gortmaker69c60c82011-05-26 12:22:53 -04008#include <linux/export.h>
Stas Sergeev1da2e3d2008-06-12 15:21:54 -07009#include <linux/pnp.h>
Sebastian Andrzej Siewior3bcbaf62011-02-22 21:07:46 +010010#include <linux/of.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011
Ingo Molnarcdc79572008-01-30 13:32:39 +010012#include <asm/vsyscall.h>
Feng Tang7bd867d2009-09-10 10:48:56 +080013#include <asm/x86_init.h>
Jaswinder Singh Rajput8383d822009-03-21 16:56:37 +053014#include <asm/time.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015
Thomas Gleixner1122b132008-01-30 13:30:27 +010016#ifdef CONFIG_X86_32
Thomas Gleixner1122b132008-01-30 13:30:27 +010017/*
18 * This is a special lock that is owned by the CPU and holds the index
19 * register we are working with. It is required for NMI access to the
20 * CMOS/RTC registers. See include/asm-i386/mc146818rtc.h for details.
21 */
Jaswinder Singh Rajput8383d822009-03-21 16:56:37 +053022volatile unsigned long cmos_lock;
Thomas Gleixner1122b132008-01-30 13:30:27 +010023EXPORT_SYMBOL(cmos_lock);
Jaswinder Singh Rajput8383d822009-03-21 16:56:37 +053024#endif /* CONFIG_X86_32 */
Thomas Gleixner1122b132008-01-30 13:30:27 +010025
Andi Kleenb62576a2008-02-09 16:16:58 +010026/* For two digit years assume time is always after that */
27#define CMOS_YEARS_OFFS 2000
28
Thomas Gleixner1122b132008-01-30 13:30:27 +010029DEFINE_SPINLOCK(rtc_lock);
30EXPORT_SYMBOL(rtc_lock);
31
Linus Torvalds1da177e2005-04-16 15:20:36 -070032/*
33 * In order to set the CMOS clock precisely, set_rtc_mmss has to be
34 * called 500 ms after the second nowtime has started, because when
35 * nowtime is written into the registers of the CMOS clock, it will
36 * jump to the next second precisely 500 ms later. Check the Motorola
37 * MC146818A or Dallas DS12887 data sheet for details.
38 *
39 * BUG: This routine does not handle hour overflow properly; it just
40 * sets the minutes. Usually you'll only notice that after reboot!
41 */
Thomas Gleixnerfe599f92008-01-30 13:30:26 +010042int mach_set_rtc_mmss(unsigned long nowtime)
Linus Torvalds1da177e2005-04-16 15:20:36 -070043{
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 int real_seconds, real_minutes, cmos_minutes;
45 unsigned char save_control, save_freq_select;
Matt Fleming47997d72011-09-21 16:08:03 +020046 unsigned long flags;
Jaswinder Singh Rajput8383d822009-03-21 16:56:37 +053047 int retval = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
Matt Fleming47997d72011-09-21 16:08:03 +020049 spin_lock_irqsave(&rtc_lock, flags);
50
Thomas Gleixner1122b132008-01-30 13:30:27 +010051 /* tell the clock it's being set */
52 save_control = CMOS_READ(RTC_CONTROL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
54
Thomas Gleixner1122b132008-01-30 13:30:27 +010055 /* stop and reset prescaler */
56 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
58
59 cmos_minutes = CMOS_READ(RTC_MINUTES);
60 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
Adrian Bunk357c6e62008-10-18 20:28:42 -070061 cmos_minutes = bcd2bin(cmos_minutes);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63 /*
64 * since we're only adjusting minutes and seconds,
65 * don't interfere with hour overflow. This avoids
66 * messing with unknown time zones but requires your
67 * RTC not to be off by more than 15 minutes
68 */
69 real_seconds = nowtime % 60;
70 real_minutes = nowtime / 60;
Thomas Gleixner1122b132008-01-30 13:30:27 +010071 /* correct for half hour time zone */
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
Thomas Gleixner1122b132008-01-30 13:30:27 +010073 real_minutes += 30;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 real_minutes %= 60;
75
76 if (abs(real_minutes - cmos_minutes) < 30) {
77 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
Adrian Bunk357c6e62008-10-18 20:28:42 -070078 real_seconds = bin2bcd(real_seconds);
79 real_minutes = bin2bcd(real_minutes);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 }
Jaswinder Singh Rajput8383d822009-03-21 16:56:37 +053081 CMOS_WRITE(real_seconds, RTC_SECONDS);
82 CMOS_WRITE(real_minutes, RTC_MINUTES);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 } else {
Stephen Hemminger3e5c1242011-01-12 16:59:31 -080084 printk_once(KERN_NOTICE
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 "set_rtc_mmss: can't update from %d to %d\n",
86 cmos_minutes, real_minutes);
87 retval = -1;
88 }
89
90 /* The following flags have to be released exactly in this order,
91 * otherwise the DS12887 (popular MC146818A clone with integrated
92 * battery and quartz) will not reset the oscillator and will not
93 * update precisely 500 ms later. You won't find this mentioned in
94 * the Dallas Semiconductor data sheets, but who believes data
95 * sheets anyway ... -- Markus Kuhn
96 */
97 CMOS_WRITE(save_control, RTC_CONTROL);
98 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
99
Matt Fleming47997d72011-09-21 16:08:03 +0200100 spin_unlock_irqrestore(&rtc_lock, flags);
101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 return retval;
103}
104
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100105unsigned long mach_get_cmos_time(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106{
Andi Kleen068c9222008-02-09 16:16:59 +0100107 unsigned int status, year, mon, day, hour, min, sec, century = 0;
Matt Fleming47997d72011-09-21 16:08:03 +0200108 unsigned long flags;
109
110 spin_lock_irqsave(&rtc_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Thomas Gleixner1122b132008-01-30 13:30:27 +0100112 /*
113 * If UIP is clear, then we have >= 244 microseconds before
114 * RTC registers will be updated. Spec sheet says that this
115 * is the reliable way to read RTC - registers. If UIP is set
116 * then the register access might be invalid.
117 */
118 while ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
119 cpu_relax();
Matt Mackall63732c22006-03-28 01:55:58 -0800120
Thomas Gleixner1122b132008-01-30 13:30:27 +0100121 sec = CMOS_READ(RTC_SECONDS);
122 min = CMOS_READ(RTC_MINUTES);
123 hour = CMOS_READ(RTC_HOURS);
124 day = CMOS_READ(RTC_DAY_OF_MONTH);
125 mon = CMOS_READ(RTC_MONTH);
126 year = CMOS_READ(RTC_YEAR);
127
Andi Kleen45de7072008-02-09 16:17:01 +0100128#ifdef CONFIG_ACPI
Thomas Gleixner1122b132008-01-30 13:30:27 +0100129 if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
130 acpi_gbl_FADT.century)
131 century = CMOS_READ(acpi_gbl_FADT.century);
132#endif
133
Andi Kleen068c9222008-02-09 16:16:59 +0100134 status = CMOS_READ(RTC_CONTROL);
Andi Kleen45de7072008-02-09 16:17:01 +0100135 WARN_ON_ONCE(RTC_ALWAYS_BCD && (status & RTC_DM_BINARY));
Andi Kleen068c9222008-02-09 16:16:59 +0100136
Matt Fleming47997d72011-09-21 16:08:03 +0200137 spin_unlock_irqrestore(&rtc_lock, flags);
138
Andi Kleen068c9222008-02-09 16:16:59 +0100139 if (RTC_ALWAYS_BCD || !(status & RTC_DM_BINARY)) {
Adrian Bunk357c6e62008-10-18 20:28:42 -0700140 sec = bcd2bin(sec);
141 min = bcd2bin(min);
142 hour = bcd2bin(hour);
143 day = bcd2bin(day);
144 mon = bcd2bin(mon);
145 year = bcd2bin(year);
Matt Mackall41623b02006-03-28 01:56:09 -0800146 }
147
Thomas Gleixner1122b132008-01-30 13:30:27 +0100148 if (century) {
Adrian Bunk357c6e62008-10-18 20:28:42 -0700149 century = bcd2bin(century);
Thomas Gleixner1122b132008-01-30 13:30:27 +0100150 year += century * 100;
151 printk(KERN_INFO "Extended CMOS year: %d\n", century * 100);
Andi Kleenb62576a2008-02-09 16:16:58 +0100152 } else
Thomas Gleixner1122b132008-01-30 13:30:27 +0100153 year += CMOS_YEARS_OFFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
155 return mktime(year, mon, day, hour, min, sec);
156}
157
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100158/* Routines for accessing the CMOS RAM/RTC. */
159unsigned char rtc_cmos_read(unsigned char addr)
160{
161 unsigned char val;
162
163 lock_cmos_prefix(addr);
David P. Reed04aaa7b2008-02-17 16:56:39 -0500164 outb(addr, RTC_PORT(0));
165 val = inb(RTC_PORT(1));
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100166 lock_cmos_suffix(addr);
Jaswinder Singh Rajput8383d822009-03-21 16:56:37 +0530167
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100168 return val;
169}
170EXPORT_SYMBOL(rtc_cmos_read);
171
172void rtc_cmos_write(unsigned char val, unsigned char addr)
173{
174 lock_cmos_prefix(addr);
David P. Reed04aaa7b2008-02-17 16:56:39 -0500175 outb(addr, RTC_PORT(0));
176 outb(val, RTC_PORT(1));
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100177 lock_cmos_suffix(addr);
178}
179EXPORT_SYMBOL(rtc_cmos_write);
180
Feng Tang7bd867d2009-09-10 10:48:56 +0800181int update_persistent_clock(struct timespec now)
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100182{
Matt Fleming47997d72011-09-21 16:08:03 +0200183 return x86_platform.set_wallclock(now.tv_sec);
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100184}
185
186/* not static: needed by APM */
Martin Schwidefskyd4f587c2009-08-14 15:47:31 +0200187void read_persistent_clock(struct timespec *ts)
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100188{
Matt Fleming47997d72011-09-21 16:08:03 +0200189 unsigned long retval;
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100190
Feng Tang7bd867d2009-09-10 10:48:56 +0800191 retval = x86_platform.get_wallclock();
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100192
Martin Schwidefskyd4f587c2009-08-14 15:47:31 +0200193 ts->tv_sec = retval;
194 ts->tv_nsec = 0;
Thomas Gleixnerfe599f92008-01-30 13:30:26 +0100195}
196
Ingo Molnar92767af2008-01-30 13:32:40 +0100197unsigned long long native_read_tsc(void)
Ingo Molnarcdc79572008-01-30 13:32:39 +0100198{
Ingo Molnar92767af2008-01-30 13:32:40 +0100199 return __native_read_tsc();
Ingo Molnarcdc79572008-01-30 13:32:39 +0100200}
Ingo Molnar92767af2008-01-30 13:32:40 +0100201EXPORT_SYMBOL(native_read_tsc);
202
Stas Sergeev1da2e3d2008-06-12 15:21:54 -0700203
204static struct resource rtc_resources[] = {
205 [0] = {
206 .start = RTC_PORT(0),
207 .end = RTC_PORT(1),
208 .flags = IORESOURCE_IO,
209 },
210 [1] = {
211 .start = RTC_IRQ,
212 .end = RTC_IRQ,
213 .flags = IORESOURCE_IRQ,
214 }
215};
216
217static struct platform_device rtc_device = {
218 .name = "rtc_cmos",
219 .id = -1,
220 .resource = rtc_resources,
221 .num_resources = ARRAY_SIZE(rtc_resources),
222};
223
224static __init int add_rtc_cmos(void)
225{
226#ifdef CONFIG_PNP
Bjorn Helgaas758a7f72008-10-14 17:01:03 -0600227 static const char *ids[] __initconst =
228 { "PNP0b00", "PNP0b01", "PNP0b02", };
229 struct pnp_dev *dev;
230 struct pnp_id *id;
231 int i;
232
233 pnp_for_each_dev(dev) {
234 for (id = dev->id; id; id = id->next) {
235 for (i = 0; i < ARRAY_SIZE(ids); i++) {
236 if (compare_pnp_id(id, ids[i]) != 0)
237 return 0;
238 }
239 }
240 }
241#endif
Sebastian Andrzej Siewior3bcbaf62011-02-22 21:07:46 +0100242 if (of_have_populated_dt())
243 return 0;
Bjorn Helgaas758a7f72008-10-14 17:01:03 -0600244
Stas Sergeev1da2e3d2008-06-12 15:21:54 -0700245 platform_device_register(&rtc_device);
Bjorn Helgaas758a7f72008-10-14 17:01:03 -0600246 dev_info(&rtc_device.dev,
247 "registered platform RTC device (no PNP device found)\n");
Jaswinder Singh Rajput8383d822009-03-21 16:56:37 +0530248
Stas Sergeev1da2e3d2008-06-12 15:21:54 -0700249 return 0;
250}
251device_initcall(add_rtc_cmos);