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