diff options
author | Alessandro Zummo <a.zummo@towertech.it> | 2006-03-27 04:16:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-27 11:44:51 -0500 |
commit | a95579cd4b40a4e062e187d931f498145551ee29 (patch) | |
tree | f7c47f1e27210194448d2fe48c32ac8244ee41ac /drivers | |
parent | 1fec7c66ba98fc3a04e15fd14fad6b404e56fc94 (diff) |
[PATCH] RTC subsystem: test device/driver
Interrupts can be generated by
echo "alarm|tick|update" >/sys/class/rtc/rtcX/device/irq
Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rtc/Kconfig | 15 | ||||
-rw-r--r-- | drivers/rtc/Makefile | 1 | ||||
-rw-r--r-- | drivers/rtc/rtc-test.c | 204 |
3 files changed, 220 insertions, 0 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 3de823f2f055..7eb1368d04f6 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -86,4 +86,19 @@ config RTC_DRV_X1205 | |||
86 | This driver can also be built as a module. If so, the module | 86 | This driver can also be built as a module. If so, the module |
87 | will be called rtc-x1205. | 87 | will be called rtc-x1205. |
88 | 88 | ||
89 | config RTC_DRV_TEST | ||
90 | tristate "Test driver/device" | ||
91 | depends on RTC_CLASS | ||
92 | help | ||
93 | If you say yes here you get support for the | ||
94 | RTC test driver. It's a software RTC which can be | ||
95 | used to test the RTC subsystem APIs. It gets | ||
96 | the time from the system clock. | ||
97 | You want this driver only if you are doing development | ||
98 | on the RTC subsystem. Please read the source code | ||
99 | for further details. | ||
100 | |||
101 | This driver can also be built as a module. If so, the module | ||
102 | will be called rtc-test. | ||
103 | |||
89 | endmenu | 104 | endmenu |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index eaf89b22db7a..d5ea0ed81905 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -12,4 +12,5 @@ obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o | |||
12 | obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o | 12 | obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o |
13 | 13 | ||
14 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 14 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
15 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | ||
15 | 16 | ||
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c new file mode 100644 index 000000000000..43d107487820 --- /dev/null +++ b/drivers/rtc/rtc-test.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * An RTC test device/driver | ||
3 | * Copyright (C) 2005 Tower Technologies | ||
4 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/err.h> | ||
13 | #include <linux/rtc.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | static struct platform_device *test0 = NULL, *test1 = NULL; | ||
17 | |||
18 | static int test_rtc_read_alarm(struct device *dev, | ||
19 | struct rtc_wkalrm *alrm) | ||
20 | { | ||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | static int test_rtc_set_alarm(struct device *dev, | ||
25 | struct rtc_wkalrm *alrm) | ||
26 | { | ||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | static int test_rtc_read_time(struct device *dev, | ||
31 | struct rtc_time *tm) | ||
32 | { | ||
33 | rtc_time_to_tm(get_seconds(), tm); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int test_rtc_set_time(struct device *dev, | ||
38 | struct rtc_time *tm) | ||
39 | { | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static int test_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
44 | { | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static int test_rtc_proc(struct device *dev, struct seq_file *seq) | ||
49 | { | ||
50 | struct platform_device *plat_dev = to_platform_device(dev); | ||
51 | |||
52 | seq_printf(seq, "24hr\t\t: yes\n"); | ||
53 | seq_printf(seq, "test\t\t: yes\n"); | ||
54 | seq_printf(seq, "id\t\t: %d\n", plat_dev->id); | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static int test_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
60 | unsigned long arg) | ||
61 | { | ||
62 | /* We do support interrupts, they're generated | ||
63 | * using the sysfs interface. | ||
64 | */ | ||
65 | switch (cmd) { | ||
66 | case RTC_PIE_ON: | ||
67 | case RTC_PIE_OFF: | ||
68 | case RTC_UIE_ON: | ||
69 | case RTC_UIE_OFF: | ||
70 | case RTC_AIE_ON: | ||
71 | case RTC_AIE_OFF: | ||
72 | return 0; | ||
73 | |||
74 | default: | ||
75 | return -EINVAL; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | static struct rtc_class_ops test_rtc_ops = { | ||
80 | .proc = test_rtc_proc, | ||
81 | .read_time = test_rtc_read_time, | ||
82 | .set_time = test_rtc_set_time, | ||
83 | .read_alarm = test_rtc_read_alarm, | ||
84 | .set_alarm = test_rtc_set_alarm, | ||
85 | .set_mmss = test_rtc_set_mmss, | ||
86 | .ioctl = test_rtc_ioctl, | ||
87 | }; | ||
88 | |||
89 | static ssize_t test_irq_show(struct device *dev, | ||
90 | struct device_attribute *attr, char *buf) | ||
91 | { | ||
92 | return sprintf(buf, "%d\n", 42); | ||
93 | } | ||
94 | static ssize_t test_irq_store(struct device *dev, | ||
95 | struct device_attribute *attr, | ||
96 | const char *buf, size_t count) | ||
97 | { | ||
98 | int retval; | ||
99 | struct platform_device *plat_dev = to_platform_device(dev); | ||
100 | struct rtc_device *rtc = platform_get_drvdata(plat_dev); | ||
101 | |||
102 | retval = count; | ||
103 | if (strncmp(buf, "tick", 4) == 0) | ||
104 | rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF); | ||
105 | else if (strncmp(buf, "alarm", 5) == 0) | ||
106 | rtc_update_irq(&rtc->class_dev, 1, RTC_AF | RTC_IRQF); | ||
107 | else if (strncmp(buf, "update", 6) == 0) | ||
108 | rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF); | ||
109 | else | ||
110 | retval = -EINVAL; | ||
111 | |||
112 | return retval; | ||
113 | } | ||
114 | static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store); | ||
115 | |||
116 | static int test_probe(struct platform_device *plat_dev) | ||
117 | { | ||
118 | int err; | ||
119 | struct rtc_device *rtc = rtc_device_register("test", &plat_dev->dev, | ||
120 | &test_rtc_ops, THIS_MODULE); | ||
121 | if (IS_ERR(rtc)) { | ||
122 | err = PTR_ERR(rtc); | ||
123 | dev_err(&plat_dev->dev, | ||
124 | "unable to register the class device\n"); | ||
125 | return err; | ||
126 | } | ||
127 | device_create_file(&plat_dev->dev, &dev_attr_irq); | ||
128 | |||
129 | platform_set_drvdata(plat_dev, rtc); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int __devexit test_remove(struct platform_device *plat_dev) | ||
135 | { | ||
136 | struct rtc_device *rtc = platform_get_drvdata(plat_dev); | ||
137 | |||
138 | rtc_device_unregister(rtc); | ||
139 | device_remove_file(&plat_dev->dev, &dev_attr_irq); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static struct platform_driver test_drv = { | ||
145 | .probe = test_probe, | ||
146 | .remove = __devexit_p(test_remove), | ||
147 | .driver = { | ||
148 | .name = "rtc-test", | ||
149 | .owner = THIS_MODULE, | ||
150 | }, | ||
151 | }; | ||
152 | |||
153 | static int __init test_init(void) | ||
154 | { | ||
155 | int err; | ||
156 | |||
157 | if ((err = platform_driver_register(&test_drv))) | ||
158 | return err; | ||
159 | |||
160 | if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) { | ||
161 | err = -ENOMEM; | ||
162 | goto exit_driver_unregister; | ||
163 | } | ||
164 | |||
165 | if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) { | ||
166 | err = -ENOMEM; | ||
167 | goto exit_free_test0; | ||
168 | } | ||
169 | |||
170 | if ((err = platform_device_add(test0))) | ||
171 | goto exit_free_test1; | ||
172 | |||
173 | if ((err = platform_device_add(test1))) | ||
174 | goto exit_device_unregister; | ||
175 | |||
176 | return 0; | ||
177 | |||
178 | exit_device_unregister: | ||
179 | platform_device_unregister(test0); | ||
180 | |||
181 | exit_free_test1: | ||
182 | platform_device_put(test1); | ||
183 | |||
184 | exit_free_test0: | ||
185 | platform_device_put(test0); | ||
186 | |||
187 | exit_driver_unregister: | ||
188 | platform_driver_unregister(&test_drv); | ||
189 | return err; | ||
190 | } | ||
191 | |||
192 | static void __exit test_exit(void) | ||
193 | { | ||
194 | platform_device_unregister(test0); | ||
195 | platform_device_unregister(test1); | ||
196 | platform_driver_unregister(&test_drv); | ||
197 | } | ||
198 | |||
199 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
200 | MODULE_DESCRIPTION("RTC test driver/device"); | ||
201 | MODULE_LICENSE("GPL"); | ||
202 | |||
203 | module_init(test_init); | ||
204 | module_exit(test_exit); | ||