1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/rtc.h>
15#include <linux/log2.h>
16
17int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
18{
19 int err;
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(rtc->dev.parent, tm);
32 }
33
34 mutex_unlock(&rtc->ops_lock);
35 return err;
36}
37EXPORT_SYMBOL_GPL(rtc_read_time);
38
39int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
40{
41 int err;
42
43 err = rtc_valid_tm(tm);
44 if (err != 0)
45 return err;
46
47 err = mutex_lock_interruptible(&rtc->ops_lock);
48 if (err)
49 return -EBUSY;
50
51 if (!rtc->ops)
52 err = -ENODEV;
53 else if (!rtc->ops->set_time)
54 err = -EINVAL;
55 else
56 err = rtc->ops->set_time(rtc->dev.parent, tm);
57
58 mutex_unlock(&rtc->ops_lock);
59 return err;
60}
61EXPORT_SYMBOL_GPL(rtc_set_time);
62
63int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
64{
65 int err;
66
67 err = mutex_lock_interruptible(&rtc->ops_lock);
68 if (err)
69 return -EBUSY;
70
71 if (!rtc->ops)
72 err = -ENODEV;
73 else if (rtc->ops->set_mmss)
74 err = rtc->ops->set_mmss(rtc->dev.parent, secs);
75 else if (rtc->ops->read_time && rtc->ops->set_time) {
76 struct rtc_time new, old;
77
78 err = rtc->ops->read_time(rtc->dev.parent, &old);
79 if (err == 0) {
80 rtc_time_to_tm(secs, &new);
81
82
83
84
85
86
87
88 if (!((old.tm_hour == 23 && old.tm_min == 59) ||
89 (new.tm_hour == 23 && new.tm_min == 59)))
90 err = rtc->ops->set_time(rtc->dev.parent,
91 &new);
92 }
93 }
94 else
95 err = -EINVAL;
96
97 mutex_unlock(&rtc->ops_lock);
98
99 return err;
100}
101EXPORT_SYMBOL_GPL(rtc_set_mmss);
102
103static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
104{
105 int err;
106
107 err = mutex_lock_interruptible(&rtc->ops_lock);
108 if (err)
109 return -EBUSY;
110
111 if (rtc->ops == NULL)
112 err = -ENODEV;
113 else if (!rtc->ops->read_alarm)
114 err = -EINVAL;
115 else {
116 memset(alarm, 0, sizeof(struct rtc_wkalrm));
117 err = rtc->ops->read_alarm(rtc->dev.parent, alarm);
118 }
119
120 mutex_unlock(&rtc->ops_lock);
121 return err;
122}
123
124int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
125{
126 int err;
127 struct rtc_time before, now;
128 int first_time = 1;
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 err = rtc_read_time(rtc, &before);
163 if (err < 0)
164 return err;
165 do {
166 if (!first_time)
167 memcpy(&before, &now, sizeof(struct rtc_time));
168 first_time = 0;
169
170
171 err = rtc_read_alarm_internal(rtc, alarm);
172 if (err)
173 return err;
174 if (!alarm->enabled)
175 return 0;
176
177
178 err = rtc_read_time(rtc, &now);
179 if (err < 0)
180 return err;
181
182
183 } while ( before.tm_min != now.tm_min
184 || before.tm_hour != now.tm_hour
185 || before.tm_mon != now.tm_mon
186 || before.tm_year != now.tm_year
187 || before.tm_isdst != now.tm_isdst);
188
189
190 if (alarm->time.tm_sec == -1)
191 alarm->time.tm_sec = now.tm_sec;
192 if (alarm->time.tm_min == -1)
193 alarm->time.tm_min = now.tm_min;
194 if (alarm->time.tm_hour == -1)
195 alarm->time.tm_hour = now.tm_hour;
196 if (alarm->time.tm_mday == -1)
197 alarm->time.tm_mday = now.tm_mday;
198 if (alarm->time.tm_mon == -1)
199 alarm->time.tm_mon = now.tm_mon;
200 if (alarm->time.tm_year == -1)
201 alarm->time.tm_year = now.tm_year;
202 return 0;
203}
204EXPORT_SYMBOL_GPL(rtc_read_alarm);
205
206int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
207{
208 int err;
209
210 err = rtc_valid_tm(&alarm->time);
211 if (err != 0)
212 return err;
213
214 err = mutex_lock_interruptible(&rtc->ops_lock);
215 if (err)
216 return -EBUSY;
217
218 if (!rtc->ops)
219 err = -ENODEV;
220 else if (!rtc->ops->set_alarm)
221 err = -EINVAL;
222 else
223 err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
224
225 mutex_unlock(&rtc->ops_lock);
226 return err;
227}
228EXPORT_SYMBOL_GPL(rtc_set_alarm);
229
230
231
232
233
234
235
236
237void rtc_update_irq(struct rtc_device *rtc,
238 unsigned long num, unsigned long events)
239{
240 spin_lock(&rtc->irq_lock);
241 rtc->irq_data = (rtc->irq_data + (num << 8)) | events;
242 spin_unlock(&rtc->irq_lock);
243
244 spin_lock(&rtc->irq_task_lock);
245 if (rtc->irq_task)
246 rtc->irq_task->func(rtc->irq_task->private_data);
247 spin_unlock(&rtc->irq_task_lock);
248
249 wake_up_interruptible(&rtc->irq_queue);
250 kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
251}
252EXPORT_SYMBOL_GPL(rtc_update_irq);
253
254struct rtc_device *rtc_class_open(char *name)
255{
256 struct device *dev;
257 struct rtc_device *rtc = NULL;
258
259 down(&rtc_class->sem);
260 list_for_each_entry(dev, &rtc_class->devices, node) {
261 if (strncmp(dev->bus_id, name, BUS_ID_SIZE) == 0) {
262 dev = get_device(dev);
263 if (dev)
264 rtc = to_rtc_device(dev);
265 break;
266 }
267 }
268
269 if (rtc) {
270 if (!try_module_get(rtc->owner)) {
271 put_device(dev);
272 rtc = NULL;
273 }
274 }
275 up(&rtc_class->sem);
276
277 return rtc;
278}
279EXPORT_SYMBOL_GPL(rtc_class_open);
280
281void rtc_class_close(struct rtc_device *rtc)
282{
283 module_put(rtc->owner);
284 put_device(&rtc->dev);
285}
286EXPORT_SYMBOL_GPL(rtc_class_close);
287
288int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
289{
290 int retval = -EBUSY;
291
292 if (task == NULL || task->func == NULL)
293 return -EINVAL;
294
295
296 if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags))
297 return -EBUSY;
298
299 spin_lock_irq(&rtc->irq_task_lock);
300 if (rtc->irq_task == NULL) {
301 rtc->irq_task = task;
302 retval = 0;
303 }
304 spin_unlock_irq(&rtc->irq_task_lock);
305
306 clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
307
308 return retval;
309}
310EXPORT_SYMBOL_GPL(rtc_irq_register);
311
312void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
313{
314 spin_lock_irq(&rtc->irq_task_lock);
315 if (rtc->irq_task == task)
316 rtc->irq_task = NULL;
317 spin_unlock_irq(&rtc->irq_task_lock);
318}
319EXPORT_SYMBOL_GPL(rtc_irq_unregister);
320
321
322
323
324
325
326
327
328
329
330
331int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
332{
333 int err = 0;
334 unsigned long flags;
335
336 if (rtc->ops->irq_set_state == NULL)
337 return -ENXIO;
338
339 spin_lock_irqsave(&rtc->irq_task_lock, flags);
340 if (rtc->irq_task != NULL && task == NULL)
341 err = -EBUSY;
342 if (rtc->irq_task != task)
343 err = -EACCES;
344 spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
345
346 if (err == 0)
347 err = rtc->ops->irq_set_state(rtc->dev.parent, enabled);
348
349 return err;
350}
351EXPORT_SYMBOL_GPL(rtc_irq_set_state);
352
353
354
355
356
357
358
359
360
361
362
363int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
364{
365 int err = 0;
366 unsigned long flags;
367
368 if (rtc->ops->irq_set_freq == NULL)
369 return -ENXIO;
370
371 if (!is_power_of_2(freq))
372 return -EINVAL;
373
374 spin_lock_irqsave(&rtc->irq_task_lock, flags);
375 if (rtc->irq_task != NULL && task == NULL)
376 err = -EBUSY;
377 if (rtc->irq_task != task)
378 err = -EACCES;
379 spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
380
381 if (err == 0) {
382 err = rtc->ops->irq_set_freq(rtc->dev.parent, freq);
383 if (err == 0)
384 rtc->irq_freq = freq;
385 }
386 return err;
387}
388EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
389