xref: /OK3568_Linux_fs/kernel/drivers/rtc/rtc-fake.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <linux/module.h>
7 #include <linux/rtc.h>
8 #include <linux/time.h>
9 #include <linux/of_platform.h>
10 
11 static struct timespec begtime;
12 static unsigned long time;
13 
timespec_to_ulong(struct timespec * ts)14 static unsigned long timespec_to_ulong(struct timespec *ts)
15 {
16 	return ts->tv_nsec < NSEC_PER_SEC / 2 ? ts->tv_sec : ts->tv_sec + 1;
17 }
18 
get_uptime(struct timespec * ts)19 static void get_uptime(struct timespec *ts)
20 {
21 	getrawmonotonic(ts);
22 }
23 
fake_rtc_read_time(struct device * dev,struct rtc_time * tm)24 static int fake_rtc_read_time(struct device *dev, struct rtc_time *tm)
25 {
26 	struct timespec now, diff;
27 
28 	get_uptime(&now);
29 	diff = timespec_sub(now, begtime);
30 
31 	rtc_time_to_tm(time + timespec_to_ulong(&diff), tm);
32 
33 	return rtc_valid_tm(tm);
34 }
35 
fake_rtc_set_time(struct device * dev,struct rtc_time * tm)36 static int fake_rtc_set_time(struct device *dev, struct rtc_time *tm)
37 {
38 	get_uptime(&begtime);
39 	rtc_tm_to_time(tm, &time);
40 
41 	return 0;
42 }
43 
fake_rtc_alarm_irq_enable(struct device * dev,unsigned int enabled)44 static int fake_rtc_alarm_irq_enable(struct device *dev,
45 					unsigned int enabled)
46 {
47 	return 0;
48 }
49 
fake_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alm)50 static int fake_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
51 {
52 	return 0;
53 }
54 
fake_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alm)55 static int fake_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
56 {
57 	return 0;
58 }
59 
60 static const struct rtc_class_ops fake_rtc_ops = {
61 	.read_time	= fake_rtc_read_time,
62 	.set_time	= fake_rtc_set_time,
63 	.alarm_irq_enable	= fake_rtc_alarm_irq_enable,
64 	.read_alarm		= fake_rtc_read_alarm,
65 	.set_alarm		= fake_rtc_set_alarm,
66 };
67 
fake_rtc_probe(struct platform_device * pdev)68 static int fake_rtc_probe(struct platform_device *pdev)
69 {
70 	struct rtc_device *fake_rtc;
71 	struct rtc_time tm = {
72 		.tm_wday = 1,
73 		.tm_year = 118,
74 		.tm_mon = 0,
75 		.tm_mday = 1,
76 		.tm_hour = 12,
77 		.tm_min = 0,
78 		.tm_sec = 0,
79 	};
80 
81 	get_uptime(&begtime);
82 	fake_rtc_set_time(&pdev->dev, &tm);
83 
84 	device_init_wakeup(&pdev->dev, 1);
85 
86 	fake_rtc = devm_rtc_device_register(&pdev->dev,
87 				pdev->name, &fake_rtc_ops, THIS_MODULE);
88 	if (IS_ERR(fake_rtc))
89 		return PTR_ERR(fake_rtc);
90 
91 	dev_info(&pdev->dev, "loaded; begtime is %lu, time is %lu\n",
92 		 timespec_to_ulong(&begtime), time);
93 
94 	return 0;
95 }
96 
97 static const struct of_device_id rtc_dt_ids[] = {
98 	{ .compatible = "rtc-fake" },
99 	{},
100 };
101 
102 struct platform_driver fake_rtc_driver = {
103 	.driver		= {
104 		.name	= "rtc-fake",
105 		.owner	= THIS_MODULE,
106 		.of_match_table = of_match_ptr(rtc_dt_ids),
107 	},
108 	.probe		= fake_rtc_probe,
109 };
110 
111 module_platform_driver(fake_rtc_driver);
112 
113 MODULE_AUTHOR("jesse.huang@rock-chips.com");
114 MODULE_DESCRIPTION("FAKE RTC driver");
115 MODULE_LICENSE("GPL");
116 
117