rtc-proc.c revision a2db8dfce8d94fecae50128d912fec7980687a51
1728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo/*
2728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo * RTC subsystem, proc interface
3728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo *
4728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo * Copyright (C) 2005-06 Tower Technologies
5728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo * Author: Alessandro Zummo <a.zummo@towertech.it>
6728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo *
7728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo * based on arch/arm/common/rtctime.c
8728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo *
9728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo * This program is free software; you can redistribute it and/or modify
10728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo * it under the terms of the GNU General Public License version 2 as
11728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo * published by the Free Software Foundation.
12728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo*/
13728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
14728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo#include <linux/module.h>
15728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo#include <linux/rtc.h>
16728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo#include <linux/proc_fs.h>
17728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo#include <linux/seq_file.h>
18728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
19728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic struct class_device *rtc_dev = NULL;
20728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic DEFINE_MUTEX(rtc_lock);
21728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
22728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic int rtc_proc_show(struct seq_file *seq, void *offset)
23728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo{
24728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	int err;
25728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	struct class_device *class_dev = seq->private;
26ff8371ac9a5a55c956991fed8e5f58640c7a32f3David Brownell	const struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
27728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	struct rtc_wkalrm alrm;
28728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	struct rtc_time tm;
29728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
30728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	err = rtc_read_time(class_dev, &tm);
31728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	if (err == 0) {
32728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		seq_printf(seq,
33728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			"rtc_time\t: %02d:%02d:%02d\n"
34728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			"rtc_date\t: %04d-%02d-%02d\n",
35728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			tm.tm_hour, tm.tm_min, tm.tm_sec,
36728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
37728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	}
38728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
39728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	err = rtc_read_alarm(class_dev, &alrm);
40728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	if (err == 0) {
41728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		seq_printf(seq, "alrm_time\t: ");
42728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		if ((unsigned int)alrm.time.tm_hour <= 24)
43728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "%02d:", alrm.time.tm_hour);
44728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		else
45728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "**:");
46728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		if ((unsigned int)alrm.time.tm_min <= 59)
47728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "%02d:", alrm.time.tm_min);
48728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		else
49728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "**:");
50728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		if ((unsigned int)alrm.time.tm_sec <= 59)
51728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "%02d\n", alrm.time.tm_sec);
52728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		else
53728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "**\n");
54728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
55728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		seq_printf(seq, "alrm_date\t: ");
56728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		if ((unsigned int)alrm.time.tm_year <= 200)
57728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "%04d-", alrm.time.tm_year + 1900);
58728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		else
59728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "****-");
60728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		if ((unsigned int)alrm.time.tm_mon <= 11)
61728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "%02d-", alrm.time.tm_mon + 1);
62728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		else
63728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "**-");
64db621f174d2c017d960089ea8cbc91c0763f1069David Brownell		if (alrm.time.tm_mday && (unsigned int)alrm.time.tm_mday <= 31)
65728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "%02d\n", alrm.time.tm_mday);
66728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		else
67728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			seq_printf(seq, "**\n");
68a2db8dfce8d94fecae50128d912fec7980687a51David Brownell		seq_printf(seq, "alarm_IRQ\t: %s\n",
69728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo				alrm.enabled ? "yes" : "no");
70728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		seq_printf(seq, "alrm_pending\t: %s\n",
71728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo				alrm.pending ? "yes" : "no");
72728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	}
73728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
74adfb4341259f2f89baac2316a8a3660b63c1103bAlessandro Zummo	seq_printf(seq, "24hr\t\t: yes\n");
75adfb4341259f2f89baac2316a8a3660b63c1103bAlessandro Zummo
76728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	if (ops->proc)
77728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		ops->proc(class_dev->dev, seq);
78728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
79728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	return 0;
80728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo}
81728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
82728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic int rtc_proc_open(struct inode *inode, struct file *file)
83728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo{
84728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	struct class_device *class_dev = PDE(inode)->data;
85728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
86728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	if (!try_module_get(THIS_MODULE))
87728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		return -ENODEV;
88728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
89728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	return single_open(file, rtc_proc_show, class_dev);
90728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo}
91728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
92728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic int rtc_proc_release(struct inode *inode, struct file *file)
93728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo{
94728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	int res = single_release(inode, file);
95728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	module_put(THIS_MODULE);
96728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	return res;
97728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo}
98728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
99728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic struct file_operations rtc_proc_fops = {
100728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	.open		= rtc_proc_open,
101728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	.read		= seq_read,
102728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	.llseek		= seq_lseek,
103728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	.release	= rtc_proc_release,
104728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo};
105728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
106728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic int rtc_proc_add_device(struct class_device *class_dev,
107728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo					struct class_interface *class_intf)
108728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo{
109728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	mutex_lock(&rtc_lock);
110728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	if (rtc_dev == NULL) {
111728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		struct proc_dir_entry *ent;
112728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
113728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		rtc_dev = class_dev;
114728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
115728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		ent = create_proc_entry("driver/rtc", 0, NULL);
116728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		if (ent) {
117728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			struct rtc_device *rtc = to_rtc_device(class_dev);
118728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
119728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			ent->proc_fops = &rtc_proc_fops;
120728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			ent->owner = rtc->owner;
121728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			ent->data = class_dev;
122728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
1235a6534e4cf53e16a6ea92f033f89d6575b3d7422David Brownell			dev_dbg(class_dev->dev, "rtc intf: proc\n");
124728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		}
125728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		else
126728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo			rtc_dev = NULL;
127728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	}
128728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	mutex_unlock(&rtc_lock);
129728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
130728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	return 0;
131728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo}
132728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
133728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic void rtc_proc_remove_device(struct class_device *class_dev,
134728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo					struct class_interface *class_intf)
135728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo{
136728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	mutex_lock(&rtc_lock);
137728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	if (rtc_dev == class_dev) {
138728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		remove_proc_entry("driver/rtc", NULL);
139728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo		rtc_dev = NULL;
140728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	}
141728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	mutex_unlock(&rtc_lock);
142728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo}
143728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
144728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic struct class_interface rtc_proc_interface = {
145728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	.add = &rtc_proc_add_device,
146728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	.remove = &rtc_proc_remove_device,
147728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo};
148728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
149728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic int __init rtc_proc_init(void)
150728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo{
151728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	return rtc_interface_register(&rtc_proc_interface);
152728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo}
153728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
154728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummostatic void __exit rtc_proc_exit(void)
155728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo{
156728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo	class_interface_unregister(&rtc_proc_interface);
157728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo}
158728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
159818a8674b0388d90e33a5d1b13946b40dda7032aDavid Brownellsubsys_initcall(rtc_proc_init);
160728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummomodule_exit(rtc_proc_exit);
161728a294787b780130d8eb237518d4cac0afe760cAlessandro Zummo
162728a294787b780130d8eb237518d4cac0afe760cAlessandro ZummoMODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
163728a294787b780130d8eb237518d4cac0afe760cAlessandro ZummoMODULE_DESCRIPTION("RTC class proc interface");
164728a294787b780130d8eb237518d4cac0afe760cAlessandro ZummoMODULE_LICENSE("GPL");
165