1 // SPDX-License-Identifier: GPL-2.0
3 * An RTC test device/driver
4 * Copyright (C) 2005 Tower Technologies
5 * Author: Alessandro Zummo <a.zummo@towertech.it>
8 #include <linux/module.h>
10 #include <linux/rtc.h>
11 #include <linux/platform_device.h>
13 #define MAX_RTC_TEST 3
15 struct rtc_test_data
{
16 struct rtc_device
*rtc
;
18 struct timer_list alarm
;
22 static struct platform_device
*pdev
[MAX_RTC_TEST
];
24 static int test_rtc_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
26 struct rtc_test_data
*rtd
= dev_get_drvdata(dev
);
29 alarm
= (rtd
->alarm
.expires
- jiffies
) / HZ
;
30 alarm
+= ktime_get_real_seconds() + rtd
->offset
;
32 rtc_time64_to_tm(alarm
, &alrm
->time
);
33 alrm
->enabled
= rtd
->alarm_en
;
38 static int test_rtc_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alrm
)
40 struct rtc_test_data
*rtd
= dev_get_drvdata(dev
);
44 timeout
= rtc_tm_to_time64(&alrm
->time
) - ktime_get_real_seconds();
45 timeout
-= rtd
->offset
;
47 del_timer(&rtd
->alarm
);
49 expires
= jiffies
+ timeout
* HZ
;
50 if (expires
> U32_MAX
)
53 pr_err("ABE: %s +%d %s\n", __FILE__
, __LINE__
, __func__
);
54 rtd
->alarm
.expires
= expires
;
57 add_timer(&rtd
->alarm
);
59 rtd
->alarm_en
= alrm
->enabled
;
64 static int test_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
66 struct rtc_test_data
*rtd
= dev_get_drvdata(dev
);
68 rtc_time64_to_tm(ktime_get_real_seconds() + rtd
->offset
, tm
);
73 static int test_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
75 struct rtc_test_data
*rtd
= dev_get_drvdata(dev
);
77 rtd
->offset
= rtc_tm_to_time64(tm
) - ktime_get_real_seconds();
82 static int test_rtc_alarm_irq_enable(struct device
*dev
, unsigned int enable
)
84 struct rtc_test_data
*rtd
= dev_get_drvdata(dev
);
86 rtd
->alarm_en
= enable
;
88 add_timer(&rtd
->alarm
);
90 del_timer(&rtd
->alarm
);
95 static const struct rtc_class_ops test_rtc_ops_noalm
= {
96 .read_time
= test_rtc_read_time
,
97 .set_time
= test_rtc_set_time
,
98 .alarm_irq_enable
= test_rtc_alarm_irq_enable
,
101 static const struct rtc_class_ops test_rtc_ops
= {
102 .read_time
= test_rtc_read_time
,
103 .set_time
= test_rtc_set_time
,
104 .read_alarm
= test_rtc_read_alarm
,
105 .set_alarm
= test_rtc_set_alarm
,
106 .alarm_irq_enable
= test_rtc_alarm_irq_enable
,
109 static void test_rtc_alarm_handler(struct timer_list
*t
)
111 struct rtc_test_data
*rtd
= from_timer(rtd
, t
, alarm
);
113 rtc_update_irq(rtd
->rtc
, 1, RTC_AF
| RTC_IRQF
);
116 static int test_probe(struct platform_device
*plat_dev
)
118 struct rtc_test_data
*rtd
;
120 rtd
= devm_kzalloc(&plat_dev
->dev
, sizeof(*rtd
), GFP_KERNEL
);
124 platform_set_drvdata(plat_dev
, rtd
);
126 rtd
->rtc
= devm_rtc_allocate_device(&plat_dev
->dev
);
127 if (IS_ERR(rtd
->rtc
))
128 return PTR_ERR(rtd
->rtc
);
130 switch (plat_dev
->id
) {
132 rtd
->rtc
->ops
= &test_rtc_ops_noalm
;
135 rtd
->rtc
->ops
= &test_rtc_ops
;
136 device_init_wakeup(&plat_dev
->dev
, 1);
139 timer_setup(&rtd
->alarm
, test_rtc_alarm_handler
, 0);
140 rtd
->alarm
.expires
= 0;
142 return rtc_register_device(rtd
->rtc
);
145 static struct platform_driver test_driver
= {
152 static int __init
test_init(void)
156 err
= platform_driver_register(&test_driver
);
161 for (i
= 0; i
< MAX_RTC_TEST
; i
++) {
162 pdev
[i
] = platform_device_alloc("rtc-test", i
);
167 for (i
= 0; i
< MAX_RTC_TEST
; i
++) {
168 err
= platform_device_add(pdev
[i
]);
170 goto exit_device_del
;
177 platform_device_del(pdev
[i
- 1]);
180 for (i
= 0; i
< MAX_RTC_TEST
; i
++)
181 platform_device_put(pdev
[i
]);
183 platform_driver_unregister(&test_driver
);
187 static void __exit
test_exit(void)
191 for (i
= 0; i
< MAX_RTC_TEST
; i
++)
192 platform_device_unregister(pdev
[i
]);
194 platform_driver_unregister(&test_driver
);
197 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
198 MODULE_DESCRIPTION("RTC test driver/device");
199 MODULE_LICENSE("GPL v2");
201 module_init(test_init
);
202 module_exit(test_exit
);