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