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_mmss64(struct device
*dev
, time64_t secs
)
75 struct rtc_test_data
*rtd
= dev_get_drvdata(dev
);
77 rtd
->offset
= secs
- 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_mmss64
= test_rtc_set_mmss64
,
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 .read_alarm
= test_rtc_read_alarm
,
104 .set_alarm
= test_rtc_set_alarm
,
105 .set_mmss64
= test_rtc_set_mmss64
,
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
;
138 timer_setup(&rtd
->alarm
, test_rtc_alarm_handler
, 0);
139 rtd
->alarm
.expires
= 0;
141 return rtc_register_device(rtd
->rtc
);
144 static struct platform_driver test_driver
= {
151 static int __init
test_init(void)
155 if ((err
= platform_driver_register(&test_driver
)))
159 for (i
= 0; i
< MAX_RTC_TEST
; i
++) {
160 pdev
[i
] = platform_device_alloc("rtc-test", i
);
165 for (i
= 0; i
< MAX_RTC_TEST
; i
++) {
166 err
= platform_device_add(pdev
[i
]);
168 goto exit_device_del
;
175 platform_device_del(pdev
[i
- 1]);
178 for (i
= 0; i
< MAX_RTC_TEST
; i
++)
179 platform_device_put(pdev
[i
]);
181 platform_driver_unregister(&test_driver
);
185 static void __exit
test_exit(void)
189 for (i
= 0; i
< MAX_RTC_TEST
; i
++)
190 platform_device_unregister(pdev
[i
]);
192 platform_driver_unregister(&test_driver
);
195 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
196 MODULE_DESCRIPTION("RTC test driver/device");
197 MODULE_LICENSE("GPL v2");
199 module_init(test_init
);
200 module_exit(test_exit
);