1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020 Intel Corporation
4 * Author: Johannes Berg <johannes@sipsolutions.net>
6 #include <linux/platform_device.h>
7 #include <linux/time-internal.h>
8 #include <linux/suspend.h>
10 #include <linux/rtc.h>
11 #include <kern_util.h>
16 static time64_t uml_rtc_alarm_time
;
17 static bool uml_rtc_alarm_enabled
;
18 static struct rtc_device
*uml_rtc
;
19 static int uml_rtc_irq_fd
, uml_rtc_irq
;
21 #ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
23 static void uml_rtc_time_travel_alarm(struct time_travel_event
*ev
)
25 uml_rtc_send_timetravel_alarm();
28 static struct time_travel_event uml_rtc_alarm_event
= {
29 .fn
= uml_rtc_time_travel_alarm
,
33 static int uml_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
37 /* Use this to get correct time in time-travel mode */
38 read_persistent_clock64(&ts
);
39 rtc_time64_to_tm(timespec64_to_ktime(ts
) / NSEC_PER_SEC
, tm
);
44 static int uml_rtc_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
46 rtc_time64_to_tm(uml_rtc_alarm_time
, &alrm
->time
);
47 alrm
->enabled
= uml_rtc_alarm_enabled
;
52 static int uml_rtc_alarm_irq_enable(struct device
*dev
, unsigned int enable
)
54 unsigned long long secs
;
56 if (!enable
&& !uml_rtc_alarm_enabled
)
59 uml_rtc_alarm_enabled
= enable
;
61 secs
= uml_rtc_alarm_time
- ktime_get_real_seconds();
63 if (time_travel_mode
== TT_MODE_OFF
) {
65 uml_rtc_disable_alarm();
69 /* enable or update */
70 return uml_rtc_enable_alarm(secs
);
72 time_travel_del_event(¨_rtc_alarm_event
);
75 time_travel_add_event_rel(¨_rtc_alarm_event
,
82 static int uml_rtc_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
84 uml_rtc_alarm_irq_enable(dev
, 0);
85 uml_rtc_alarm_time
= rtc_tm_to_time64(&alrm
->time
);
86 uml_rtc_alarm_irq_enable(dev
, alrm
->enabled
);
91 static const struct rtc_class_ops uml_rtc_ops
= {
92 .read_time
= uml_rtc_read_time
,
93 .read_alarm
= uml_rtc_read_alarm
,
94 .alarm_irq_enable
= uml_rtc_alarm_irq_enable
,
95 .set_alarm
= uml_rtc_set_alarm
,
98 static irqreturn_t
uml_rtc_interrupt(int irq
, void *data
)
100 unsigned long long c
= 0;
102 /* alarm triggered, it's now off */
103 uml_rtc_alarm_enabled
= false;
105 os_read_file(uml_rtc_irq_fd
, &c
, sizeof(c
));
109 rtc_update_irq(uml_rtc
, 1, RTC_IRQF
| RTC_AF
);
114 static int uml_rtc_setup(void)
118 err
= uml_rtc_start(time_travel_mode
!= TT_MODE_OFF
);
119 if (WARN(err
< 0, "err = %d\n", err
))
122 uml_rtc_irq_fd
= err
;
124 err
= um_request_irq(UM_IRQ_ALLOC
, uml_rtc_irq_fd
, IRQ_READ
,
125 uml_rtc_interrupt
, 0, "rtc", NULL
);
127 uml_rtc_stop(time_travel_mode
!= TT_MODE_OFF
);
131 irq_set_irq_wake(err
, 1);
137 static void uml_rtc_cleanup(void)
139 um_free_irq(uml_rtc_irq
, NULL
);
140 uml_rtc_stop(time_travel_mode
!= TT_MODE_OFF
);
143 static int uml_rtc_probe(struct platform_device
*pdev
)
147 err
= uml_rtc_setup();
151 uml_rtc
= devm_rtc_allocate_device(&pdev
->dev
);
152 if (IS_ERR(uml_rtc
)) {
153 err
= PTR_ERR(uml_rtc
);
157 uml_rtc
->ops
= ¨_rtc_ops
;
159 device_init_wakeup(&pdev
->dev
, 1);
161 err
= devm_rtc_register_device(uml_rtc
);
171 static void uml_rtc_remove(struct platform_device
*pdev
)
173 device_init_wakeup(&pdev
->dev
, 0);
177 static struct platform_driver uml_rtc_driver
= {
178 .probe
= uml_rtc_probe
,
179 .remove
= uml_rtc_remove
,
185 static int __init
uml_rtc_init(void)
187 struct platform_device
*pdev
;
190 err
= platform_driver_register(¨_rtc_driver
);
194 pdev
= platform_device_alloc("uml-rtc", 0);
200 err
= platform_device_add(pdev
);
206 platform_device_put(pdev
);
207 platform_driver_unregister(¨_rtc_driver
);
210 device_initcall(uml_rtc_init
);