1 /* 2 * RTC subsystem, interface functions 3 * 4 * Copyright (C) 2005 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/rtc.h> 15 16 int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm) 17 { 18 int err; 19 struct rtc_device *rtc = to_rtc_device(class_dev); 20 21 err = mutex_lock_interruptible(&rtc->ops_lock); 22 if (err) 23 return -EBUSY; 24 25 if (!rtc->ops) 26 err = -ENODEV; 27 else if (!rtc->ops->read_time) 28 err = -EINVAL; 29 else { 30 memset(tm, 0, sizeof(struct rtc_time)); 31 err = rtc->ops->read_time(class_dev->dev, tm); 32 } 33 34 mutex_unlock(&rtc->ops_lock); 35 return err; 36 } 37 EXPORT_SYMBOL_GPL(rtc_read_time); 38 39 int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm) 40 { 41 int err; 42 struct rtc_device *rtc = to_rtc_device(class_dev); 43 44 err = rtc_valid_tm(tm); 45 if (err != 0) 46 return err; 47 48 err = mutex_lock_interruptible(&rtc->ops_lock); 49 if (err) 50 return -EBUSY; 51 52 if (!rtc->ops) 53 err = -ENODEV; 54 else if (!rtc->ops->set_time) 55 err = -EINVAL; 56 else 57 err = rtc->ops->set_time(class_dev->dev, tm); 58 59 mutex_unlock(&rtc->ops_lock); 60 return err; 61 } 62 EXPORT_SYMBOL_GPL(rtc_set_time); 63 64 int rtc_set_mmss(struct class_device *class_dev, unsigned long secs) 65 { 66 int err; 67 struct rtc_device *rtc = to_rtc_device(class_dev); 68 69 err = mutex_lock_interruptible(&rtc->ops_lock); 70 if (err) 71 return -EBUSY; 72 73 if (!rtc->ops) 74 err = -ENODEV; 75 else if (rtc->ops->set_mmss) 76 err = rtc->ops->set_mmss(class_dev->dev, secs); 77 else if (rtc->ops->read_time && rtc->ops->set_time) { 78 struct rtc_time new, old; 79 80 err = rtc->ops->read_time(class_dev->dev, &old); 81 if (err == 0) { 82 rtc_time_to_tm(secs, &new); 83 84 /* 85 * avoid writing when we're going to change the day of 86 * the month. We will retry in the next minute. This 87 * basically means that if the RTC must not drift 88 * by more than 1 minute in 11 minutes. 89 */ 90 if (!((old.tm_hour == 23 && old.tm_min == 59) || 91 (new.tm_hour == 23 && new.tm_min == 59))) 92 err = rtc->ops->set_time(class_dev->dev, &new); 93 } 94 } 95 else 96 err = -EINVAL; 97 98 mutex_unlock(&rtc->ops_lock); 99 100 return err; 101 } 102 EXPORT_SYMBOL_GPL(rtc_set_mmss); 103 104 int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) 105 { 106 int err; 107 struct rtc_device *rtc = to_rtc_device(class_dev); 108 109 err = mutex_lock_interruptible(&rtc->ops_lock); 110 if (err) 111 return -EBUSY; 112 113 if (rtc->ops == NULL) 114 err = -ENODEV; 115 else if (!rtc->ops->read_alarm) 116 err = -EINVAL; 117 else { 118 memset(alarm, 0, sizeof(struct rtc_wkalrm)); 119 err = rtc->ops->read_alarm(class_dev->dev, alarm); 120 } 121 122 mutex_unlock(&rtc->ops_lock); 123 return err; 124 } 125 EXPORT_SYMBOL_GPL(rtc_read_alarm); 126 127 int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) 128 { 129 int err; 130 struct rtc_device *rtc = to_rtc_device(class_dev); 131 132 err = mutex_lock_interruptible(&rtc->ops_lock); 133 if (err) 134 return -EBUSY; 135 136 if (!rtc->ops) 137 err = -ENODEV; 138 else if (!rtc->ops->set_alarm) 139 err = -EINVAL; 140 else 141 err = rtc->ops->set_alarm(class_dev->dev, alarm); 142 143 mutex_unlock(&rtc->ops_lock); 144 return err; 145 } 146 EXPORT_SYMBOL_GPL(rtc_set_alarm); 147 148 void rtc_update_irq(struct class_device *class_dev, 149 unsigned long num, unsigned long events) 150 { 151 struct rtc_device *rtc = to_rtc_device(class_dev); 152 153 spin_lock(&rtc->irq_lock); 154 rtc->irq_data = (rtc->irq_data + (num << 8)) | events; 155 spin_unlock(&rtc->irq_lock); 156 157 spin_lock(&rtc->irq_task_lock); 158 if (rtc->irq_task) 159 rtc->irq_task->func(rtc->irq_task->private_data); 160 spin_unlock(&rtc->irq_task_lock); 161 162 wake_up_interruptible(&rtc->irq_queue); 163 kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); 164 } 165 EXPORT_SYMBOL_GPL(rtc_update_irq); 166 167 struct class_device *rtc_class_open(char *name) 168 { 169 struct class_device *class_dev = NULL, 170 *class_dev_tmp; 171 172 down(&rtc_class->sem); 173 list_for_each_entry(class_dev_tmp, &rtc_class->children, node) { 174 if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) { 175 class_dev = class_dev_tmp; 176 break; 177 } 178 } 179 180 if (class_dev) { 181 if (!try_module_get(to_rtc_device(class_dev)->owner)) 182 class_dev = NULL; 183 } 184 up(&rtc_class->sem); 185 186 return class_dev; 187 } 188 EXPORT_SYMBOL_GPL(rtc_class_open); 189 190 void rtc_class_close(struct class_device *class_dev) 191 { 192 module_put(to_rtc_device(class_dev)->owner); 193 } 194 EXPORT_SYMBOL_GPL(rtc_class_close); 195 196 int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task) 197 { 198 int retval = -EBUSY; 199 struct rtc_device *rtc = to_rtc_device(class_dev); 200 201 if (task == NULL || task->func == NULL) 202 return -EINVAL; 203 204 spin_lock(&rtc->irq_task_lock); 205 if (rtc->irq_task == NULL) { 206 rtc->irq_task = task; 207 retval = 0; 208 } 209 spin_unlock(&rtc->irq_task_lock); 210 211 return retval; 212 } 213 EXPORT_SYMBOL_GPL(rtc_irq_register); 214 215 void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task) 216 { 217 struct rtc_device *rtc = to_rtc_device(class_dev); 218 219 spin_lock(&rtc->irq_task_lock); 220 if (rtc->irq_task == task) 221 rtc->irq_task = NULL; 222 spin_unlock(&rtc->irq_task_lock); 223 } 224 EXPORT_SYMBOL_GPL(rtc_irq_unregister); 225 226 int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int enabled) 227 { 228 int err = 0; 229 unsigned long flags; 230 struct rtc_device *rtc = to_rtc_device(class_dev); 231 232 if (rtc->ops->irq_set_state == NULL) 233 return -ENXIO; 234 235 spin_lock_irqsave(&rtc->irq_task_lock, flags); 236 if (rtc->irq_task != task) 237 err = -ENXIO; 238 spin_unlock_irqrestore(&rtc->irq_task_lock, flags); 239 240 if (err == 0) 241 err = rtc->ops->irq_set_state(class_dev->dev, enabled); 242 243 return err; 244 } 245 EXPORT_SYMBOL_GPL(rtc_irq_set_state); 246 247 int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq) 248 { 249 int err = 0; 250 unsigned long flags; 251 struct rtc_device *rtc = to_rtc_device(class_dev); 252 253 if (rtc->ops->irq_set_freq == NULL) 254 return -ENXIO; 255 256 spin_lock_irqsave(&rtc->irq_task_lock, flags); 257 if (rtc->irq_task != task) 258 err = -ENXIO; 259 spin_unlock_irqrestore(&rtc->irq_task_lock, flags); 260 261 if (err == 0) { 262 err = rtc->ops->irq_set_freq(class_dev->dev, freq); 263 if (err == 0) 264 rtc->irq_freq = freq; 265 } 266 return err; 267 } 268 EXPORT_SYMBOL_GPL(rtc_irq_set_freq); 269