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