aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sbus/char/rtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sbus/char/rtc.c')
-rw-r--r--drivers/sbus/char/rtc.c109
1 files changed, 102 insertions, 7 deletions
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
index bf3273eb1c8b..9b988baf0b51 100644
--- a/drivers/sbus/char/rtc.c
+++ b/drivers/sbus/char/rtc.c
@@ -28,10 +28,46 @@
28 28
29static int rtc_busy = 0; 29static int rtc_busy = 0;
30 30
31/* This is the structure layout used by drivers/char/rtc.c, we
32 * support that driver's ioctls so that things are less messy in
33 * userspace.
34 */
35struct rtc_time_generic {
36 int tm_sec;
37 int tm_min;
38 int tm_hour;
39 int tm_mday;
40 int tm_mon;
41 int tm_year;
42 int tm_wday;
43 int tm_yday;
44 int tm_isdst;
45};
46#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */
47#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */
48#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
49#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */
50#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */
51#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */
52#define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */
53#define RTC_WIE_OFF _IO('p', 0x10) /* ... off */
54#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time_generic) /* Read RTC time */
55#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time_generic) /* Set RTC time */
56#define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */
57#define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */
58#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */
59#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */
60#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
61#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
62#define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/
63#define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/
64#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
65#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */
66
31/* Retrieve the current date and time from the real time clock. */ 67/* Retrieve the current date and time from the real time clock. */
32static void get_rtc_time(struct rtc_time *t) 68static void get_rtc_time(struct rtc_time *t)
33{ 69{
34 void * __iomem regs = mstk48t02_regs; 70 void __iomem *regs = mstk48t02_regs;
35 u8 tmp; 71 u8 tmp;
36 72
37 spin_lock_irq(&mostek_lock); 73 spin_lock_irq(&mostek_lock);
@@ -58,7 +94,7 @@ static void get_rtc_time(struct rtc_time *t)
58/* Set the current date and time inthe real time clock. */ 94/* Set the current date and time inthe real time clock. */
59void set_rtc_time(struct rtc_time *t) 95void set_rtc_time(struct rtc_time *t)
60{ 96{
61 void * __iomem regs = mstk48t02_regs; 97 void __iomem *regs = mstk48t02_regs;
62 u8 tmp; 98 u8 tmp;
63 99
64 spin_lock_irq(&mostek_lock); 100 spin_lock_irq(&mostek_lock);
@@ -82,29 +118,87 @@ void set_rtc_time(struct rtc_time *t)
82 spin_unlock_irq(&mostek_lock); 118 spin_unlock_irq(&mostek_lock);
83} 119}
84 120
121static int put_rtc_time_generic(void __user *argp, struct rtc_time *tm)
122{
123 struct rtc_time_generic __user *utm = argp;
124
125 if (__put_user(tm->sec, &utm->tm_sec) ||
126 __put_user(tm->min, &utm->tm_min) ||
127 __put_user(tm->hour, &utm->tm_hour) ||
128 __put_user(tm->dom, &utm->tm_mday) ||
129 __put_user(tm->month, &utm->tm_mon) ||
130 __put_user(tm->year, &utm->tm_year) ||
131 __put_user(tm->dow, &utm->tm_wday) ||
132 __put_user(0, &utm->tm_yday) ||
133 __put_user(0, &utm->tm_isdst))
134 return -EFAULT;
135
136 return 0;
137}
138
139static int get_rtc_time_generic(struct rtc_time *tm, void __user *argp)
140{
141 struct rtc_time_generic __user *utm = argp;
142
143 if (__get_user(tm->sec, &utm->tm_sec) ||
144 __get_user(tm->min, &utm->tm_min) ||
145 __get_user(tm->hour, &utm->tm_hour) ||
146 __get_user(tm->dom, &utm->tm_mday) ||
147 __get_user(tm->month, &utm->tm_mon) ||
148 __get_user(tm->year, &utm->tm_year) ||
149 __get_user(tm->dow, &utm->tm_wday))
150 return -EFAULT;
151
152 return 0;
153}
154
85static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 155static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
86 unsigned long arg) 156 unsigned long arg)
87{ 157{
88 struct rtc_time rtc_tm; 158 struct rtc_time rtc_tm;
89 void __user *argp = (void __user *)arg; 159 void __user *argp = (void __user *)arg;
90 160
91 switch (cmd) 161 switch (cmd) {
92 { 162 /* No interrupt support, return an error
163 * compatible with drivers/char/rtc.c
164 */
165 case RTC_AIE_OFF:
166 case RTC_AIE_ON:
167 case RTC_PIE_OFF:
168 case RTC_PIE_ON:
169 case RTC_UIE_OFF:
170 case RTC_UIE_ON:
171 case RTC_IRQP_READ:
172 case RTC_IRQP_SET:
173 case RTC_EPOCH_SET:
174 case RTC_EPOCH_READ:
175 return -EINVAL;
176
93 case RTCGET: 177 case RTCGET:
178 case RTC_RD_TIME:
94 memset(&rtc_tm, 0, sizeof(struct rtc_time)); 179 memset(&rtc_tm, 0, sizeof(struct rtc_time));
95 get_rtc_time(&rtc_tm); 180 get_rtc_time(&rtc_tm);
96 181
97 if (copy_to_user(argp, &rtc_tm, sizeof(struct rtc_time))) 182 if (cmd == RTCGET) {
183 if (copy_to_user(argp, &rtc_tm,
184 sizeof(struct rtc_time)))
185 return -EFAULT;
186 } else if (put_rtc_time_generic(argp, &rtc_tm))
98 return -EFAULT; 187 return -EFAULT;
99 188
100 return 0; 189 return 0;
101 190
102 191
103 case RTCSET: 192 case RTCSET:
193 case RTC_SET_TIME:
104 if (!capable(CAP_SYS_TIME)) 194 if (!capable(CAP_SYS_TIME))
105 return -EPERM; 195 return -EPERM;
106 196
107 if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time))) 197 if (cmd == RTCSET) {
198 if (copy_from_user(&rtc_tm, argp,
199 sizeof(struct rtc_time)))
200 return -EFAULT;
201 } else if (get_rtc_time_generic(&rtc_tm, argp))
108 return -EFAULT; 202 return -EFAULT;
109 203
110 set_rtc_time(&rtc_tm); 204 set_rtc_time(&rtc_tm);
@@ -156,7 +250,7 @@ static int __init rtc_sun_init(void)
156 /* It is possible we are being driven by some other RTC chip 250 /* It is possible we are being driven by some other RTC chip
157 * and thus another RTC driver is handling things. 251 * and thus another RTC driver is handling things.
158 */ 252 */
159 if (mstk48t02_regs == 0) 253 if (!mstk48t02_regs)
160 return -ENODEV; 254 return -ENODEV;
161 255
162 error = misc_register(&rtc_dev); 256 error = misc_register(&rtc_dev);
@@ -164,6 +258,7 @@ static int __init rtc_sun_init(void)
164 printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n"); 258 printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n");
165 return error; 259 return error;
166 } 260 }
261 printk("rtc_sun_init: Registered Mostek RTC driver.\n");
167 262
168 return 0; 263 return 0;
169} 264}