1/* 2 * linux/arch/arm/common/rtctime.c 3 * 4 * Copyright (C) 2003 Deep Blue Solutions Ltd. 5 * Based on sa1100-rtc.c, Nils Faerber, CIH, Nicolas Pitre. 6 * Based on rtc.c by Paul Gortmaker 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12#include <linux/module.h> 13#include <linux/kernel.h> 14#include <linux/time.h> 15#include <linux/rtc.h> 16#include <linux/poll.h> 17#include <linux/proc_fs.h> 18#include <linux/miscdevice.h> 19#include <linux/spinlock.h> 20#include <linux/capability.h> 21#include <linux/device.h> 22#include <linux/mutex.h> 23#include <linux/rtc.h> 24 25#include <asm/rtc.h> 26#include <asm/semaphore.h> 27 28static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); 29static struct fasync_struct *rtc_async_queue; 30 31/* 32 * rtc_lock protects rtc_irq_data 33 */ 34static DEFINE_SPINLOCK(rtc_lock); 35static unsigned long rtc_irq_data; 36 37/* 38 * rtc_sem protects rtc_inuse and rtc_ops 39 */ 40static DEFINE_MUTEX(rtc_mutex); 41static unsigned long rtc_inuse; 42static struct rtc_ops *rtc_ops; 43 44#define rtc_epoch 1900UL 45 46/* 47 * Calculate the next alarm time given the requested alarm time mask 48 * and the current time. 49 */ 50void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm) 51{ 52 unsigned long next_time; 53 unsigned long now_time; 54 55 next->tm_year = now->tm_year; 56 next->tm_mon = now->tm_mon; 57 next->tm_mday = now->tm_mday; 58 next->tm_hour = alrm->tm_hour; 59 next->tm_min = alrm->tm_min; 60 next->tm_sec = alrm->tm_sec; 61 62 rtc_tm_to_time(now, &now_time); 63 rtc_tm_to_time(next, &next_time); 64 65 if (next_time < now_time) { 66 /* Advance one day */ 67 next_time += 60 * 60 * 24; 68 rtc_time_to_tm(next_time, next); 69 } 70} 71EXPORT_SYMBOL(rtc_next_alarm_time); 72 73static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm) 74{ 75 memset(tm, 0, sizeof(struct rtc_time)); 76 return ops->read_time(tm); 77} 78 79static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm) 80{ 81 int ret; 82 83 ret = rtc_valid_tm(tm); 84 if (ret == 0) 85 ret = ops->set_time(tm); 86 87 return ret; 88} 89 90static inline int rtc_arm_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) 91{ 92 int ret = -EINVAL; 93 if (ops->read_alarm) { 94 memset(alrm, 0, sizeof(struct rtc_wkalrm)); 95 ret = ops->read_alarm(alrm); 96 } 97 return ret; 98} 99 100static inline int rtc_arm_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) 101{ 102 int ret = -EINVAL; 103 if (ops->set_alarm) 104 ret = ops->set_alarm(alrm); 105 return ret; 106} 107 108void rtc_update(unsigned long num, unsigned long events) 109{ 110 spin_lock(&rtc_lock); 111 rtc_irq_data = (rtc_irq_data + (num << 8)) | events; 112 spin_unlock(&rtc_lock); 113 114 wake_up_interruptible(&rtc_wait); 115 kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); 116} 117EXPORT_SYMBOL(rtc_update); 118 119 120static ssize_t 121rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) 122{ 123 DECLARE_WAITQUEUE(wait, current); 124 unsigned long data; 125 ssize_t ret; 126 127 if (count < sizeof(unsigned long)) 128 return -EINVAL; 129 130 add_wait_queue(&rtc_wait, &wait); 131 do { 132 __set_current_state(TASK_INTERRUPTIBLE); 133 134 spin_lock_irq(&rtc_lock); 135 data = rtc_irq_data; 136 rtc_irq_data = 0; 137 spin_unlock_irq(&rtc_lock); 138 139 if (data != 0) { 140 ret = 0; 141 break; 142 } 143 if (file->f_flags & O_NONBLOCK) { 144 ret = -EAGAIN; 145 break; 146 } 147 if (signal_pending(current)) { 148 ret = -ERESTARTSYS; 149 break; 150 } 151 schedule(); 152 } while (1); 153 set_current_state(TASK_RUNNING); 154 remove_wait_queue(&rtc_wait, &wait); 155 156 if (ret == 0) { 157 ret = put_user(data, (unsigned long __user *)buf); 158 if (ret == 0) 159 ret = sizeof(unsigned long); 160 } 161 return ret; 162} 163 164static unsigned int rtc_poll(struct file *file, poll_table *wait) 165{ 166 unsigned long data; 167 168 poll_wait(file, &rtc_wait, wait); 169 170 spin_lock_irq(&rtc_lock); 171 data = rtc_irq_data; 172 spin_unlock_irq(&rtc_lock); 173 174 return data != 0 ? POLLIN | POLLRDNORM : 0; 175} 176 177static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 178 unsigned long arg) 179{ 180 struct rtc_ops *ops = file->private_data; 181 struct rtc_time tm; 182 struct rtc_wkalrm alrm; 183 void __user *uarg = (void __user *)arg; 184 int ret = -EINVAL; 185 186 switch (cmd) { 187 case RTC_ALM_READ: 188 ret = rtc_arm_read_alarm(ops, &alrm); 189 if (ret) 190 break; 191 ret = copy_to_user(uarg, &alrm.time, sizeof(tm)); 192 if (ret) 193 ret = -EFAULT; 194 break; 195 196 case RTC_ALM_SET: 197 ret = copy_from_user(&alrm.time, uarg, sizeof(tm)); 198 if (ret) { 199 ret = -EFAULT; 200 break; 201 } 202 alrm.enabled = 0; 203 alrm.pending = 0; 204 alrm.time.tm_mday = -1; 205 alrm.time.tm_mon = -1; 206 alrm.time.tm_year = -1; 207 alrm.time.tm_wday = -1; 208 alrm.time.tm_yday = -1; 209 alrm.time.tm_isdst = -1; 210 ret = rtc_arm_set_alarm(ops, &alrm); 211 break; 212 213 case RTC_RD_TIME: 214 ret = rtc_arm_read_time(ops, &tm); 215 if (ret) 216 break; 217 ret = copy_to_user(uarg, &tm, sizeof(tm)); 218 if (ret) 219 ret = -EFAULT; 220 break; 221 222 case RTC_SET_TIME: 223 if (!capable(CAP_SYS_TIME)) { 224 ret = -EACCES; 225 break; 226 } 227 ret = copy_from_user(&tm, uarg, sizeof(tm)); 228 if (ret) { 229 ret = -EFAULT; 230 break; 231 } 232 ret = rtc_arm_set_time(ops, &tm); 233 break; 234 235 case RTC_EPOCH_SET: 236#ifndef rtc_epoch 237 /* 238 * There were no RTC clocks before 1900. 239 */ 240 if (arg < 1900) { 241 ret = -EINVAL; 242 break; 243 } 244 if (!capable(CAP_SYS_TIME)) { 245 ret = -EACCES; 246 break; 247 } 248 rtc_epoch = arg; 249 ret = 0; 250#endif 251 break; 252 253 case RTC_EPOCH_READ: 254 ret = put_user(rtc_epoch, (unsigned long __user *)uarg); 255 break; 256 257 case RTC_WKALM_SET: 258 ret = copy_from_user(&alrm, uarg, sizeof(alrm)); 259 if (ret) { 260 ret = -EFAULT; 261 break; 262 } 263 ret = rtc_arm_set_alarm(ops, &alrm); 264 break; 265 266 case RTC_WKALM_RD: 267 ret = rtc_arm_read_alarm(ops, &alrm); 268 if (ret) 269 break; 270 ret = copy_to_user(uarg, &alrm, sizeof(alrm)); 271 if (ret) 272 ret = -EFAULT; 273 break; 274 275 default: 276 if (ops->ioctl) 277 ret = ops->ioctl(cmd, arg); 278 break; 279 } 280 return ret; 281} 282 283static int rtc_open(struct inode *inode, struct file *file) 284{ 285 int ret; 286 287 mutex_lock(&rtc_mutex); 288 289 if (rtc_inuse) { 290 ret = -EBUSY; 291 } else if (!rtc_ops || !try_module_get(rtc_ops->owner)) { 292 ret = -ENODEV; 293 } else { 294 file->private_data = rtc_ops; 295 296 ret = rtc_ops->open ? rtc_ops->open() : 0; 297 if (ret == 0) { 298 spin_lock_irq(&rtc_lock); 299 rtc_irq_data = 0; 300 spin_unlock_irq(&rtc_lock); 301 302 rtc_inuse = 1; 303 } 304 } 305 mutex_unlock(&rtc_mutex); 306 307 return ret; 308} 309 310static int rtc_release(struct inode *inode, struct file *file) 311{ 312 struct rtc_ops *ops = file->private_data; 313 314 if (ops->release) 315 ops->release(); 316 317 spin_lock_irq(&rtc_lock); 318 rtc_irq_data = 0; 319 spin_unlock_irq(&rtc_lock); 320 321 module_put(rtc_ops->owner); 322 rtc_inuse = 0; 323 324 return 0; 325} 326 327static int rtc_fasync(int fd, struct file *file, int on) 328{ 329 return fasync_helper(fd, file, on, &rtc_async_queue); 330} 331 332static const struct file_operations rtc_fops = { 333 .owner = THIS_MODULE, 334 .llseek = no_llseek, 335 .read = rtc_read, 336 .poll = rtc_poll, 337 .ioctl = rtc_ioctl, 338 .open = rtc_open, 339 .release = rtc_release, 340 .fasync = rtc_fasync, 341}; 342 343static struct miscdevice rtc_miscdev = { 344 .minor = RTC_MINOR, 345 .name = "rtc", 346 .fops = &rtc_fops, 347}; 348 349 350static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) 351{ 352 struct rtc_ops *ops = data; 353 struct rtc_wkalrm alrm; 354 struct rtc_time tm; 355 char *p = page; 356 357 if (rtc_arm_read_time(ops, &tm) == 0) { 358 p += sprintf(p, 359 "rtc_time\t: %02d:%02d:%02d\n" 360 "rtc_date\t: %04d-%02d-%02d\n" 361 "rtc_epoch\t: %04lu\n", 362 tm.tm_hour, tm.tm_min, tm.tm_sec, 363 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 364 rtc_epoch); 365 } 366 367 if (rtc_arm_read_alarm(ops, &alrm) == 0) { 368 p += sprintf(p, "alrm_time\t: "); 369 if ((unsigned int)alrm.time.tm_hour <= 24) 370 p += sprintf(p, "%02d:", alrm.time.tm_hour); 371 else 372 p += sprintf(p, "**:"); 373 if ((unsigned int)alrm.time.tm_min <= 59) 374 p += sprintf(p, "%02d:", alrm.time.tm_min); 375 else 376 p += sprintf(p, "**:"); 377 if ((unsigned int)alrm.time.tm_sec <= 59) 378 p += sprintf(p, "%02d\n", alrm.time.tm_sec); 379 else 380 p += sprintf(p, "**\n"); 381 382 p += sprintf(p, "alrm_date\t: "); 383 if ((unsigned int)alrm.time.tm_year <= 200) 384 p += sprintf(p, "%04d-", alrm.time.tm_year + 1900); 385 else 386 p += sprintf(p, "****-"); 387 if ((unsigned int)alrm.time.tm_mon <= 11) 388 p += sprintf(p, "%02d-", alrm.time.tm_mon + 1); 389 else 390 p += sprintf(p, "**-"); 391 if ((unsigned int)alrm.time.tm_mday <= 31) 392 p += sprintf(p, "%02d\n", alrm.time.tm_mday); 393 else 394 p += sprintf(p, "**\n"); 395 p += sprintf(p, "alrm_wakeup\t: %s\n", 396 alrm.enabled ? "yes" : "no"); 397 p += sprintf(p, "alrm_pending\t: %s\n", 398 alrm.pending ? "yes" : "no"); 399 } 400 401 if (ops->proc) 402 p += ops->proc(p); 403 404 return p - page; 405} 406 407int register_rtc(struct rtc_ops *ops) 408{ 409 int ret = -EBUSY; 410 411 mutex_lock(&rtc_mutex); 412 if (rtc_ops == NULL) { 413 rtc_ops = ops; 414 415 ret = misc_register(&rtc_miscdev); 416 if (ret == 0) 417 create_proc_read_entry("driver/rtc", 0, NULL, 418 rtc_read_proc, ops); 419 } 420 mutex_unlock(&rtc_mutex); 421 422 return ret; 423} 424EXPORT_SYMBOL(register_rtc); 425 426void unregister_rtc(struct rtc_ops *rtc) 427{ 428 mutex_lock(&rtc_mutex); 429 if (rtc == rtc_ops) { 430 remove_proc_entry("driver/rtc", NULL); 431 misc_deregister(&rtc_miscdev); 432 rtc_ops = NULL; 433 } 434 mutex_unlock(&rtc_mutex); 435} 436EXPORT_SYMBOL(unregister_rtc); 437