Merge tag 'vfio-v6.4-rc1' of https://github.com/awilliam/linux-vfio
[linux-block.git] / arch / x86 / kernel / rtc.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
1da177e4 2/*
fe599f9f 3 * RTC related functions
1da177e4 4 */
8383d821
JSR
5#include <linux/platform_device.h>
6#include <linux/mc146818rtc.h>
69c60c88 7#include <linux/export.h>
1da2e3d6 8#include <linux/pnp.h>
1da177e4 9
cdc7957d 10#include <asm/vsyscall.h>
7bd867df 11#include <asm/x86_init.h>
8383d821 12#include <asm/time.h>
05454c26 13#include <asm/intel-mid.h>
8d152e7a 14#include <asm/setup.h>
1da177e4 15
1122b134 16#ifdef CONFIG_X86_32
1122b134
TG
17/*
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
fc04b2cc 20 * CMOS/RTC registers. See arch/x86/include/asm/mc146818rtc.h for details.
1122b134 21 */
8383d821 22volatile unsigned long cmos_lock;
1122b134 23EXPORT_SYMBOL(cmos_lock);
8383d821 24#endif /* CONFIG_X86_32 */
1122b134
TG
25
26DEFINE_SPINLOCK(rtc_lock);
27EXPORT_SYMBOL(rtc_lock);
28
1da177e4 29/*
e1a6bc7c 30 * In order to set the CMOS clock precisely, mach_set_cmos_time has to be
1da177e4
LT
31 * called 500 ms after the second nowtime has started, because when
32 * nowtime is written into the registers of the CMOS clock, it will
33 * jump to the next second precisely 500 ms later. Check the Motorola
34 * MC146818A or Dallas DS12887 data sheet for details.
1da177e4 35 */
e1a6bc7c 36int mach_set_cmos_time(const struct timespec64 *now)
1da177e4 37{
13cc36d7 38 unsigned long long nowtime = now->tv_sec;
3195ef59 39 struct rtc_time tm;
8383d821 40 int retval = 0;
1da177e4 41
13cc36d7 42 rtc_time64_to_tm(nowtime, &tm);
3195ef59 43 if (!rtc_valid_tm(&tm)) {
463a8630 44 retval = mc146818_set_time(&tm);
3195ef59
PB
45 if (retval)
46 printk(KERN_ERR "%s: RTC write failed with error %d\n",
02f1f217 47 __func__, retval);
1da177e4 48 } else {
3195ef59 49 printk(KERN_ERR
13cc36d7 50 "%s: Invalid RTC value: write of %llx to RTC failed\n",
02f1f217 51 __func__, nowtime);
3195ef59 52 retval = -EINVAL;
1da177e4 53 }
1da177e4
LT
54 return retval;
55}
56
e27c4929 57void mach_get_cmos_time(struct timespec64 *now)
1da177e4 58{
fc04b2cc 59 struct rtc_time tm;
47997d75 60
ba58d102
CY
61 /*
62 * If pm_trace abused the RTC as storage, set the timespec to 0,
63 * which tells the caller that this RTC value is unusable.
64 */
65 if (!pm_trace_rtc_valid()) {
66 now->tv_sec = now->tv_nsec = 0;
67 return;
68 }
69
fc04b2cc
MJ
70 if (mc146818_get_time(&tm)) {
71 pr_err("Unable to read current time from RTC\n");
72 now->tv_sec = now->tv_nsec = 0;
73 return;
41623b06
MM
74 }
75
fc04b2cc 76 now->tv_sec = rtc_tm_to_time64(&tm);
3565184e 77 now->tv_nsec = 0;
1da177e4
LT
78}
79
fe599f9f
TG
80/* Routines for accessing the CMOS RAM/RTC. */
81unsigned char rtc_cmos_read(unsigned char addr)
82{
83 unsigned char val;
84
85 lock_cmos_prefix(addr);
04aaa7ba
DR
86 outb(addr, RTC_PORT(0));
87 val = inb(RTC_PORT(1));
fe599f9f 88 lock_cmos_suffix(addr);
8383d821 89
fe599f9f
TG
90 return val;
91}
92EXPORT_SYMBOL(rtc_cmos_read);
93
94void rtc_cmos_write(unsigned char val, unsigned char addr)
95{
96 lock_cmos_prefix(addr);
04aaa7ba
DR
97 outb(addr, RTC_PORT(0));
98 outb(val, RTC_PORT(1));
fe599f9f
TG
99 lock_cmos_suffix(addr);
100}
101EXPORT_SYMBOL(rtc_cmos_write);
102
e27c4929 103int update_persistent_clock64(struct timespec64 now)
fe599f9f 104{
3565184e 105 return x86_platform.set_wallclock(&now);
fe599f9f
TG
106}
107
108/* not static: needed by APM */
e27c4929 109void read_persistent_clock64(struct timespec64 *ts)
fe599f9f 110{
3565184e 111 x86_platform.get_wallclock(ts);
fe599f9f
TG
112}
113
1da2e3d6
SS
114
115static struct resource rtc_resources[] = {
116 [0] = {
117 .start = RTC_PORT(0),
118 .end = RTC_PORT(1),
119 .flags = IORESOURCE_IO,
120 },
121 [1] = {
122 .start = RTC_IRQ,
123 .end = RTC_IRQ,
124 .flags = IORESOURCE_IRQ,
125 }
126};
127
128static struct platform_device rtc_device = {
129 .name = "rtc_cmos",
130 .id = -1,
131 .resource = rtc_resources,
132 .num_resources = ARRAY_SIZE(rtc_resources),
133};
134
135static __init int add_rtc_cmos(void)
136{
137#ifdef CONFIG_PNP
d505ad1d 138 static const char * const ids[] __initconst =
758a7f7b
BH
139 { "PNP0b00", "PNP0b01", "PNP0b02", };
140 struct pnp_dev *dev;
758a7f7b
BH
141 int i;
142
143 pnp_for_each_dev(dev) {
bd4edba2
HG
144 for (i = 0; i < ARRAY_SIZE(ids); i++) {
145 if (compare_pnp_id(dev->id, ids[i]) != 0)
146 return 0;
758a7f7b
BH
147 }
148 }
149#endif
8d152e7a 150 if (!x86_platform.legacy.rtc)
d8c98a1d
DV
151 return -ENODEV;
152
1da2e3d6 153 platform_device_register(&rtc_device);
758a7f7b
BH
154 dev_info(&rtc_device.dev,
155 "registered platform RTC device (no PNP device found)\n");
8383d821 156
1da2e3d6
SS
157 return 0;
158}
159device_initcall(add_rtc_cmos);