]>
Commit | Line | Data |
---|---|---|
728a2947 AZ |
1 | /* |
2 | * RTC subsystem, proc interface | |
3 | * | |
4 | * Copyright (C) 2005-06 Tower Technologies | |
5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | |
6 | * | |
7 | * based on arch/arm/common/rtctime.c | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License version 2 as | |
11 | * published by the Free Software Foundation. | |
12 | */ | |
13 | ||
14 | #include <linux/module.h> | |
15 | #include <linux/rtc.h> | |
16 | #include <linux/proc_fs.h> | |
17 | #include <linux/seq_file.h> | |
18 | ||
ab6a2d70 DB |
19 | #include "rtc-core.h" |
20 | ||
21 | ||
728a2947 AZ |
22 | static struct class_device *rtc_dev = NULL; |
23 | static DEFINE_MUTEX(rtc_lock); | |
24 | ||
25 | static int rtc_proc_show(struct seq_file *seq, void *offset) | |
26 | { | |
27 | int err; | |
ab6a2d70 DB |
28 | struct rtc_device *rtc = seq->private; |
29 | const struct rtc_class_ops *ops = rtc->ops; | |
728a2947 AZ |
30 | struct rtc_wkalrm alrm; |
31 | struct rtc_time tm; | |
32 | ||
ab6a2d70 | 33 | err = rtc_read_time(rtc, &tm); |
728a2947 AZ |
34 | if (err == 0) { |
35 | seq_printf(seq, | |
36 | "rtc_time\t: %02d:%02d:%02d\n" | |
37 | "rtc_date\t: %04d-%02d-%02d\n", | |
38 | tm.tm_hour, tm.tm_min, tm.tm_sec, | |
39 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | |
40 | } | |
41 | ||
ab6a2d70 | 42 | err = rtc_read_alarm(rtc, &alrm); |
728a2947 AZ |
43 | if (err == 0) { |
44 | seq_printf(seq, "alrm_time\t: "); | |
45 | if ((unsigned int)alrm.time.tm_hour <= 24) | |
46 | seq_printf(seq, "%02d:", alrm.time.tm_hour); | |
47 | else | |
48 | seq_printf(seq, "**:"); | |
49 | if ((unsigned int)alrm.time.tm_min <= 59) | |
50 | seq_printf(seq, "%02d:", alrm.time.tm_min); | |
51 | else | |
52 | seq_printf(seq, "**:"); | |
53 | if ((unsigned int)alrm.time.tm_sec <= 59) | |
54 | seq_printf(seq, "%02d\n", alrm.time.tm_sec); | |
55 | else | |
56 | seq_printf(seq, "**\n"); | |
57 | ||
58 | seq_printf(seq, "alrm_date\t: "); | |
59 | if ((unsigned int)alrm.time.tm_year <= 200) | |
60 | seq_printf(seq, "%04d-", alrm.time.tm_year + 1900); | |
61 | else | |
62 | seq_printf(seq, "****-"); | |
63 | if ((unsigned int)alrm.time.tm_mon <= 11) | |
64 | seq_printf(seq, "%02d-", alrm.time.tm_mon + 1); | |
65 | else | |
66 | seq_printf(seq, "**-"); | |
db621f17 | 67 | if (alrm.time.tm_mday && (unsigned int)alrm.time.tm_mday <= 31) |
728a2947 AZ |
68 | seq_printf(seq, "%02d\n", alrm.time.tm_mday); |
69 | else | |
70 | seq_printf(seq, "**\n"); | |
a2db8dfc | 71 | seq_printf(seq, "alarm_IRQ\t: %s\n", |
728a2947 AZ |
72 | alrm.enabled ? "yes" : "no"); |
73 | seq_printf(seq, "alrm_pending\t: %s\n", | |
74 | alrm.pending ? "yes" : "no"); | |
75 | } | |
76 | ||
adfb4341 AZ |
77 | seq_printf(seq, "24hr\t\t: yes\n"); |
78 | ||
728a2947 | 79 | if (ops->proc) |
ab6a2d70 | 80 | ops->proc(rtc->class_dev.dev, seq); |
728a2947 AZ |
81 | |
82 | return 0; | |
83 | } | |
84 | ||
85 | static int rtc_proc_open(struct inode *inode, struct file *file) | |
86 | { | |
ab6a2d70 | 87 | struct rtc_device *rtc = PDE(inode)->data; |
728a2947 AZ |
88 | |
89 | if (!try_module_get(THIS_MODULE)) | |
90 | return -ENODEV; | |
91 | ||
ab6a2d70 | 92 | return single_open(file, rtc_proc_show, rtc); |
728a2947 AZ |
93 | } |
94 | ||
95 | static int rtc_proc_release(struct inode *inode, struct file *file) | |
96 | { | |
97 | int res = single_release(inode, file); | |
98 | module_put(THIS_MODULE); | |
99 | return res; | |
100 | } | |
101 | ||
d54b1fdb | 102 | static const struct file_operations rtc_proc_fops = { |
728a2947 AZ |
103 | .open = rtc_proc_open, |
104 | .read = seq_read, | |
105 | .llseek = seq_lseek, | |
106 | .release = rtc_proc_release, | |
107 | }; | |
108 | ||
109 | static int rtc_proc_add_device(struct class_device *class_dev, | |
110 | struct class_interface *class_intf) | |
111 | { | |
112 | mutex_lock(&rtc_lock); | |
113 | if (rtc_dev == NULL) { | |
114 | struct proc_dir_entry *ent; | |
115 | ||
116 | rtc_dev = class_dev; | |
117 | ||
118 | ent = create_proc_entry("driver/rtc", 0, NULL); | |
119 | if (ent) { | |
120 | struct rtc_device *rtc = to_rtc_device(class_dev); | |
121 | ||
122 | ent->proc_fops = &rtc_proc_fops; | |
123 | ent->owner = rtc->owner; | |
ab6a2d70 | 124 | ent->data = rtc; |
728a2947 | 125 | |
5a6534e4 | 126 | dev_dbg(class_dev->dev, "rtc intf: proc\n"); |
728a2947 AZ |
127 | } |
128 | else | |
129 | rtc_dev = NULL; | |
130 | } | |
131 | mutex_unlock(&rtc_lock); | |
132 | ||
133 | return 0; | |
134 | } | |
135 | ||
136 | static void rtc_proc_remove_device(struct class_device *class_dev, | |
137 | struct class_interface *class_intf) | |
138 | { | |
139 | mutex_lock(&rtc_lock); | |
140 | if (rtc_dev == class_dev) { | |
141 | remove_proc_entry("driver/rtc", NULL); | |
142 | rtc_dev = NULL; | |
143 | } | |
144 | mutex_unlock(&rtc_lock); | |
145 | } | |
146 | ||
147 | static struct class_interface rtc_proc_interface = { | |
148 | .add = &rtc_proc_add_device, | |
149 | .remove = &rtc_proc_remove_device, | |
150 | }; | |
151 | ||
152 | static int __init rtc_proc_init(void) | |
153 | { | |
154 | return rtc_interface_register(&rtc_proc_interface); | |
155 | } | |
156 | ||
157 | static void __exit rtc_proc_exit(void) | |
158 | { | |
159 | class_interface_unregister(&rtc_proc_interface); | |
160 | } | |
161 | ||
818a8674 | 162 | subsys_initcall(rtc_proc_init); |
728a2947 AZ |
163 | module_exit(rtc_proc_exit); |
164 | ||
165 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | |
166 | MODULE_DESCRIPTION("RTC class proc interface"); | |
167 | MODULE_LICENSE("GPL"); |