1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * Copyright (C) 2020 Intel Corporation
4   * Author: Johannes Berg <johannes@sipsolutions.net>
5   */
6  #include <linux/platform_device.h>
7  #include <linux/time-internal.h>
8  #include <linux/suspend.h>
9  #include <linux/err.h>
10  #include <linux/rtc.h>
11  #include <kern_util.h>
12  #include <irq_kern.h>
13  #include <os.h>
14  #include "rtc.h"
15  
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;
20  
21  #ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
22  
uml_rtc_time_travel_alarm(struct time_travel_event * ev)23  static void uml_rtc_time_travel_alarm(struct time_travel_event *ev)
24  {
25  	uml_rtc_send_timetravel_alarm();
26  }
27  
28  static struct time_travel_event uml_rtc_alarm_event = {
29  	.fn = uml_rtc_time_travel_alarm,
30  };
31  #endif
32  
uml_rtc_read_time(struct device * dev,struct rtc_time * tm)33  static int uml_rtc_read_time(struct device *dev, struct rtc_time *tm)
34  {
35  	struct timespec64 ts;
36  
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);
40  
41  	return 0;
42  }
43  
uml_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alrm)44  static int uml_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
45  {
46  	rtc_time64_to_tm(uml_rtc_alarm_time, &alrm->time);
47  	alrm->enabled = uml_rtc_alarm_enabled;
48  
49  	return 0;
50  }
51  
uml_rtc_alarm_irq_enable(struct device * dev,unsigned int enable)52  static int uml_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
53  {
54  	unsigned long long secs;
55  
56  	if (!enable && !uml_rtc_alarm_enabled)
57  		return 0;
58  
59  	uml_rtc_alarm_enabled = enable;
60  
61  	secs = uml_rtc_alarm_time - ktime_get_real_seconds();
62  
63  	if (time_travel_mode == TT_MODE_OFF) {
64  		if (!enable) {
65  			uml_rtc_disable_alarm();
66  			return 0;
67  		}
68  
69  		/* enable or update */
70  		return uml_rtc_enable_alarm(secs);
71  	} else {
72  		time_travel_del_event(&uml_rtc_alarm_event);
73  
74  		if (enable)
75  			time_travel_add_event_rel(&uml_rtc_alarm_event,
76  						  secs * NSEC_PER_SEC);
77  	}
78  
79  	return 0;
80  }
81  
uml_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alrm)82  static int uml_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
83  {
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);
87  
88  	return 0;
89  }
90  
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,
96  };
97  
uml_rtc_interrupt(int irq,void * data)98  static irqreturn_t uml_rtc_interrupt(int irq, void *data)
99  {
100  	unsigned long long c = 0;
101  
102  	/* alarm triggered, it's now off */
103  	uml_rtc_alarm_enabled = false;
104  
105  	os_read_file(uml_rtc_irq_fd, &c, sizeof(c));
106  	WARN_ON(c == 0);
107  
108  	pm_system_wakeup();
109  	rtc_update_irq(uml_rtc, 1, RTC_IRQF | RTC_AF);
110  
111  	return IRQ_HANDLED;
112  }
113  
uml_rtc_setup(void)114  static int uml_rtc_setup(void)
115  {
116  	int err;
117  
118  	err = uml_rtc_start(time_travel_mode != TT_MODE_OFF);
119  	if (WARN(err < 0, "err = %d\n", err))
120  		return err;
121  
122  	uml_rtc_irq_fd = err;
123  
124  	err = um_request_irq(UM_IRQ_ALLOC, uml_rtc_irq_fd, IRQ_READ,
125  			     uml_rtc_interrupt, 0, "rtc", NULL);
126  	if (err < 0) {
127  		uml_rtc_stop(time_travel_mode != TT_MODE_OFF);
128  		return err;
129  	}
130  
131  	irq_set_irq_wake(err, 1);
132  
133  	uml_rtc_irq = err;
134  	return 0;
135  }
136  
uml_rtc_cleanup(void)137  static void uml_rtc_cleanup(void)
138  {
139  	um_free_irq(uml_rtc_irq, NULL);
140  	uml_rtc_stop(time_travel_mode != TT_MODE_OFF);
141  }
142  
uml_rtc_probe(struct platform_device * pdev)143  static int uml_rtc_probe(struct platform_device *pdev)
144  {
145  	int err;
146  
147  	err = uml_rtc_setup();
148  	if (err)
149  		return err;
150  
151  	uml_rtc = devm_rtc_allocate_device(&pdev->dev);
152  	if (IS_ERR(uml_rtc)) {
153  		err = PTR_ERR(uml_rtc);
154  		goto cleanup;
155  	}
156  
157  	uml_rtc->ops = &uml_rtc_ops;
158  
159  	device_init_wakeup(&pdev->dev, 1);
160  
161  	err = devm_rtc_register_device(uml_rtc);
162  	if (err)
163  		goto cleanup;
164  
165  	return 0;
166  cleanup:
167  	uml_rtc_cleanup();
168  	return err;
169  }
170  
uml_rtc_remove(struct platform_device * pdev)171  static int uml_rtc_remove(struct platform_device *pdev)
172  {
173  	device_init_wakeup(&pdev->dev, 0);
174  	uml_rtc_cleanup();
175  	return 0;
176  }
177  
178  static struct platform_driver uml_rtc_driver = {
179  	.probe = uml_rtc_probe,
180  	.remove = uml_rtc_remove,
181  	.driver = {
182  		.name = "uml-rtc",
183  	},
184  };
185  
uml_rtc_init(void)186  static int __init uml_rtc_init(void)
187  {
188  	struct platform_device *pdev;
189  	int err;
190  
191  	err = platform_driver_register(&uml_rtc_driver);
192  	if (err)
193  		return err;
194  
195  	pdev = platform_device_alloc("uml-rtc", 0);
196  	if (!pdev) {
197  		err = -ENOMEM;
198  		goto unregister;
199  	}
200  
201  	err = platform_device_add(pdev);
202  	if (err)
203  		goto unregister;
204  	return 0;
205  
206  unregister:
207  	platform_device_put(pdev);
208  	platform_driver_unregister(&uml_rtc_driver);
209  	return err;
210  }
211  device_initcall(uml_rtc_init);
212