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 rtd
->alarm
.expires
= expires
;
56 add_timer(&rtd
->alarm
);
58 rtd
->alarm_en
= alrm
->enabled
;
63 static int test_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
65 struct rtc_test_data
*rtd
= dev_get_drvdata(dev
);
67 rtc_time64_to_tm(ktime_get_real_seconds() + rtd
->offset
, tm
);
72 static int test_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
74 struct rtc_test_data
*rtd
= dev_get_drvdata(dev
);
76 rtd
->offset
= rtc_tm_to_time64(tm
) - ktime_get_real_seconds();
81 static int test_rtc_alarm_irq_enable(struct device
*dev
, unsigned int enable
)
83 struct rtc_test_data
*rtd
= dev_get_drvdata(dev
);
85 rtd
->alarm_en
= enable
;
87 add_timer(&rtd
->alarm
);
89 del_timer(&rtd
->alarm
);
94 static const struct rtc_class_ops test_rtc_ops_noalm
= {
95 .read_time
= test_rtc_read_time
,
96 .set_time
= test_rtc_set_time
,
97 .alarm_irq_enable
= test_rtc_alarm_irq_enable
,
100 static const struct rtc_class_ops test_rtc_ops
= {
101 .read_time
= test_rtc_read_time
,
102 .set_time
= test_rtc_set_time
,
103 .read_alarm
= test_rtc_read_alarm
,
104 .set_alarm
= test_rtc_set_alarm
,
105 .alarm_irq_enable
= test_rtc_alarm_irq_enable
,
108 static void test_rtc_alarm_handler(struct timer_list
*t
)
110 struct rtc_test_data
*rtd
= from_timer(rtd
, t
, alarm
);
112 rtc_update_irq(rtd
->rtc
, 1, RTC_AF
| RTC_IRQF
);
115 static int test_probe(struct platform_device
*plat_dev
)
117 struct rtc_test_data
*rtd
;
119 rtd
= devm_kzalloc(&plat_dev
->dev
, sizeof(*rtd
), GFP_KERNEL
);
123 platform_set_drvdata(plat_dev
, rtd
);
125 rtd
->rtc
= devm_rtc_allocate_device(&plat_dev
->dev
);
126 if (IS_ERR(rtd
->rtc
))
127 return PTR_ERR(rtd
->rtc
);
129 switch (plat_dev
->id
) {
131 rtd
->rtc
->ops
= &test_rtc_ops_noalm
;
134 rtd
->rtc
->ops
= &test_rtc_ops
;
135 device_init_wakeup(&plat_dev
->dev
, 1);
138 timer_setup(&rtd
->alarm
, test_rtc_alarm_handler
, 0);
139 rtd
->alarm
.expires
= 0;
141 return devm_rtc_register_device(rtd
->rtc
);
144 static struct platform_driver test_driver
= {
151 static int __init
test_init(void)
155 err
= platform_driver_register(&test_driver
);
160 for (i
= 0; i
< MAX_RTC_TEST
; i
++) {
161 pdev
[i
] = platform_device_alloc("rtc-test", i
);
166 for (i
= 0; i
< MAX_RTC_TEST
; i
++) {
167 err
= platform_device_add(pdev
[i
]);
169 goto exit_device_del
;
176 platform_device_del(pdev
[i
- 1]);
179 for (i
= 0; i
< MAX_RTC_TEST
; i
++)
180 platform_device_put(pdev
[i
]);
182 platform_driver_unregister(&test_driver
);
186 static void __exit
test_exit(void)
190 for (i
= 0; i
< MAX_RTC_TEST
; i
++)
191 platform_device_unregister(pdev
[i
]);
193 platform_driver_unregister(&test_driver
);
196 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
197 MODULE_DESCRIPTION("RTC test driver/device");
198 MODULE_LICENSE("GPL v2");
200 module_init(test_init
);
201 module_exit(test_exit
);