interface.c 15.3 KB
Newer Older
A
Alessandro Zummo 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * RTC subsystem, interface functions
 *
 * Copyright (C) 2005 Tower Technologies
 * Author: Alessandro Zummo <a.zummo@towertech.it>
 *
 * based on arch/arm/common/rtctime.c
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

#include <linux/rtc.h>
15
#include <linux/sched.h>
16
#include <linux/log2.h>
17
#include <linux/workqueue.h>
A
Alessandro Zummo 已提交
18

19
static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
A
Alessandro Zummo 已提交
20 21 22 23 24 25 26 27
{
	int err;
	if (!rtc->ops)
		err = -ENODEV;
	else if (!rtc->ops->read_time)
		err = -EINVAL;
	else {
		memset(tm, 0, sizeof(struct rtc_time));
28
		err = rtc->ops->read_time(rtc->dev.parent, tm);
A
Alessandro Zummo 已提交
29
	}
30 31 32 33 34 35
	return err;
}

int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
{
	int err;
A
Alessandro Zummo 已提交
36

37 38 39 40 41
	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
		return err;

	err = __rtc_read_time(rtc, tm);
A
Alessandro Zummo 已提交
42 43 44 45 46
	mutex_unlock(&rtc->ops_lock);
	return err;
}
EXPORT_SYMBOL_GPL(rtc_read_time);

47
int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
A
Alessandro Zummo 已提交
48 49 50 51 52 53 54 55 56
{
	int err;

	err = rtc_valid_tm(tm);
	if (err != 0)
		return err;

	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
57
		return err;
A
Alessandro Zummo 已提交
58 59 60

	if (!rtc->ops)
		err = -ENODEV;
61
	else if (rtc->ops->set_time)
62
		err = rtc->ops->set_time(rtc->dev.parent, tm);
63 64 65 66 67 68 69
	else if (rtc->ops->set_mmss) {
		unsigned long secs;
		err = rtc_tm_to_time(tm, &secs);
		if (err == 0)
			err = rtc->ops->set_mmss(rtc->dev.parent, secs);
	} else
		err = -EINVAL;
A
Alessandro Zummo 已提交
70 71 72 73 74 75

	mutex_unlock(&rtc->ops_lock);
	return err;
}
EXPORT_SYMBOL_GPL(rtc_set_time);

76
int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
A
Alessandro Zummo 已提交
77 78 79 80 81
{
	int err;

	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
82
		return err;
A
Alessandro Zummo 已提交
83 84 85 86

	if (!rtc->ops)
		err = -ENODEV;
	else if (rtc->ops->set_mmss)
87
		err = rtc->ops->set_mmss(rtc->dev.parent, secs);
A
Alessandro Zummo 已提交
88 89 90
	else if (rtc->ops->read_time && rtc->ops->set_time) {
		struct rtc_time new, old;

91
		err = rtc->ops->read_time(rtc->dev.parent, &old);
A
Alessandro Zummo 已提交
92 93 94 95 96 97 98 99 100 101 102
		if (err == 0) {
			rtc_time_to_tm(secs, &new);

			/*
			 * avoid writing when we're going to change the day of
			 * the month. We will retry in the next minute. This
			 * basically means that if the RTC must not drift
			 * by more than 1 minute in 11 minutes.
			 */
			if (!((old.tm_hour == 23 && old.tm_min == 59) ||
				(new.tm_hour == 23 && new.tm_min == 59)))
103
				err = rtc->ops->set_time(rtc->dev.parent,
104
						&new);
A
Alessandro Zummo 已提交
105 106 107 108 109 110 111 112 113 114 115
		}
	}
	else
		err = -EINVAL;

	mutex_unlock(&rtc->ops_lock);

	return err;
}
EXPORT_SYMBOL_GPL(rtc_set_mmss);

116
int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
A
Alessandro Zummo 已提交
117 118 119 120 121
{
	int err;

	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
122
		return err;
123 124 125
	alarm->enabled = rtc->aie_timer.enabled;
	if (alarm->enabled)
		alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires);
A
Alessandro Zummo 已提交
126
	mutex_unlock(&rtc->ops_lock);
127 128

	return 0;
A
Alessandro Zummo 已提交
129
}
130
EXPORT_SYMBOL_GPL(rtc_read_alarm);
131

132
int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
133
{
134 135
	struct rtc_time tm;
	long now, scheduled;
136 137
	int err;

138 139
	err = rtc_valid_tm(&alarm->time);
	if (err)
140
		return err;
141
	rtc_tm_to_time(&alarm->time, &scheduled);
142

143 144 145 146 147 148 149 150 151 152
	/* Make sure we're not setting alarms in the past */
	err = __rtc_read_time(rtc, &tm);
	rtc_tm_to_time(&tm, &now);
	if (scheduled <= now)
		return -ETIME;
	/*
	 * XXX - We just checked to make sure the alarm time is not
	 * in the past, but there is still a race window where if
	 * the is alarm set for the next second and the second ticks
	 * over right here, before we set the alarm.
153 154
	 */

155 156 157 158 159 160 161 162
	if (!rtc->ops)
		err = -ENODEV;
	else if (!rtc->ops->set_alarm)
		err = -EINVAL;
	else
		err = rtc->ops->set_alarm(rtc->dev.parent, alarm);

	return err;
163
}
A
Alessandro Zummo 已提交
164

165
int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
A
Alessandro Zummo 已提交
166 167 168
{
	int err;

169 170 171 172
	err = rtc_valid_tm(&alarm->time);
	if (err != 0)
		return err;

A
Alessandro Zummo 已提交
173 174
	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
175
		return err;
176
	if (rtc->aie_timer.enabled) {
T
Thomas Gleixner 已提交
177
		rtc_timer_remove(rtc, &rtc->aie_timer);
178 179 180 181 182 183
		rtc->aie_timer.enabled = 0;
	}
	rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
	rtc->aie_timer.period = ktime_set(0, 0);
	if (alarm->enabled) {
		rtc->aie_timer.enabled = 1;
T
Thomas Gleixner 已提交
184
		rtc_timer_enqueue(rtc, &rtc->aie_timer);
185
	}
A
Alessandro Zummo 已提交
186
	mutex_unlock(&rtc->ops_lock);
187
	return 0;
A
Alessandro Zummo 已提交
188 189 190
}
EXPORT_SYMBOL_GPL(rtc_set_alarm);

191 192 193 194 195 196
int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
{
	int err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
		return err;

197 198 199
	if (rtc->aie_timer.enabled != enabled) {
		if (enabled) {
			rtc->aie_timer.enabled = 1;
T
Thomas Gleixner 已提交
200
			rtc_timer_enqueue(rtc, &rtc->aie_timer);
201
		} else {
T
Thomas Gleixner 已提交
202
			rtc_timer_remove(rtc, &rtc->aie_timer);
203 204 205 206
			rtc->aie_timer.enabled = 0;
		}
	}

207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
	if (!rtc->ops)
		err = -ENODEV;
	else if (!rtc->ops->alarm_irq_enable)
		err = -EINVAL;
	else
		err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled);

	mutex_unlock(&rtc->ops_lock);
	return err;
}
EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);

int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
{
	int err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
		return err;

225 226 227 228 229 230 231 232 233 234 235 236 237 238
	/* make sure we're changing state */
	if (rtc->uie_rtctimer.enabled == enabled)
		goto out;

	if (enabled) {
		struct rtc_time tm;
		ktime_t now, onesec;

		__rtc_read_time(rtc, &tm);
		onesec = ktime_set(1, 0);
		now = rtc_tm_to_ktime(tm);
		rtc->uie_rtctimer.node.expires = ktime_add(now, onesec);
		rtc->uie_rtctimer.period = ktime_set(1, 0);
		rtc->uie_rtctimer.enabled = 1;
T
Thomas Gleixner 已提交
239
		rtc_timer_enqueue(rtc, &rtc->uie_rtctimer);
240
	} else {
T
Thomas Gleixner 已提交
241
		rtc_timer_remove(rtc, &rtc->uie_rtctimer);
242
		rtc->uie_rtctimer.enabled = 0;
243 244
	}

245
out:
246 247
	mutex_unlock(&rtc->ops_lock);
	return err;
248

249 250 251
}
EXPORT_SYMBOL_GPL(rtc_update_irq_enable);

252

253
/**
254 255 256 257 258 259 260
 * rtc_handle_legacy_irq - AIE, UIE and PIE event hook
 * @rtc: pointer to the rtc device
 *
 * This function is called when an AIE, UIE or PIE mode interrupt
 * has occured (or been emulated).
 *
 * Triggers the registered irq_task function callback.
261
 */
262
static void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode)
A
Alessandro Zummo 已提交
263
{
264 265
	unsigned long flags;

266
	/* mark one irq of the appropriate mode */
267
	spin_lock_irqsave(&rtc->irq_lock, flags);
268
	rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode);
269
	spin_unlock_irqrestore(&rtc->irq_lock, flags);
A
Alessandro Zummo 已提交
270

271
	/* call the task func */
272
	spin_lock_irqsave(&rtc->irq_task_lock, flags);
A
Alessandro Zummo 已提交
273 274
	if (rtc->irq_task)
		rtc->irq_task->func(rtc->irq_task->private_data);
275
	spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
A
Alessandro Zummo 已提交
276 277 278 279

	wake_up_interruptible(&rtc->irq_queue);
	kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
}
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342


/**
 * rtc_aie_update_irq - AIE mode rtctimer hook
 * @private: pointer to the rtc_device
 *
 * This functions is called when the aie_timer expires.
 */
void rtc_aie_update_irq(void *private)
{
	struct rtc_device *rtc = (struct rtc_device *)private;
	rtc_handle_legacy_irq(rtc, 1, RTC_AF);
}


/**
 * rtc_uie_update_irq - UIE mode rtctimer hook
 * @private: pointer to the rtc_device
 *
 * This functions is called when the uie_timer expires.
 */
void rtc_uie_update_irq(void *private)
{
	struct rtc_device *rtc = (struct rtc_device *)private;
	rtc_handle_legacy_irq(rtc, 1,  RTC_UF);
}


/**
 * rtc_pie_update_irq - PIE mode hrtimer hook
 * @timer: pointer to the pie mode hrtimer
 *
 * This function is used to emulate PIE mode interrupts
 * using an hrtimer. This function is called when the periodic
 * hrtimer expires.
 */
enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer)
{
	struct rtc_device *rtc;
	ktime_t period;
	int count;
	rtc = container_of(timer, struct rtc_device, pie_timer);

	period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
	count = hrtimer_forward_now(timer, period);

	rtc_handle_legacy_irq(rtc, count, RTC_PF);

	return HRTIMER_RESTART;
}

/**
 * rtc_update_irq - Triggered when a RTC interrupt occurs.
 * @rtc: the rtc device
 * @num: how many irqs are being reported (usually one)
 * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
 * Context: any
 */
void rtc_update_irq(struct rtc_device *rtc,
		unsigned long num, unsigned long events)
{
	schedule_work(&rtc->irqwork);
}
A
Alessandro Zummo 已提交
343 344
EXPORT_SYMBOL_GPL(rtc_update_irq);

D
Dave Young 已提交
345 346 347 348
static int __rtc_match(struct device *dev, void *data)
{
	char *name = (char *)data;

349
	if (strcmp(dev_name(dev), name) == 0)
D
Dave Young 已提交
350 351 352 353
		return 1;
	return 0;
}

354
struct rtc_device *rtc_class_open(char *name)
A
Alessandro Zummo 已提交
355
{
356
	struct device *dev;
357
	struct rtc_device *rtc = NULL;
A
Alessandro Zummo 已提交
358

359
	dev = class_find_device(rtc_class, NULL, name, __rtc_match);
D
Dave Young 已提交
360 361
	if (dev)
		rtc = to_rtc_device(dev);
A
Alessandro Zummo 已提交
362

363 364
	if (rtc) {
		if (!try_module_get(rtc->owner)) {
365
			put_device(dev);
366 367
			rtc = NULL;
		}
A
Alessandro Zummo 已提交
368 369
	}

370
	return rtc;
A
Alessandro Zummo 已提交
371 372 373
}
EXPORT_SYMBOL_GPL(rtc_class_open);

374
void rtc_class_close(struct rtc_device *rtc)
A
Alessandro Zummo 已提交
375
{
376
	module_put(rtc->owner);
377
	put_device(&rtc->dev);
A
Alessandro Zummo 已提交
378 379 380
}
EXPORT_SYMBOL_GPL(rtc_class_close);

381
int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
A
Alessandro Zummo 已提交
382 383 384 385 386 387
{
	int retval = -EBUSY;

	if (task == NULL || task->func == NULL)
		return -EINVAL;

A
Alessandro Zummo 已提交
388
	/* Cannot register while the char dev is in use */
389
	if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags))
A
Alessandro Zummo 已提交
390 391
		return -EBUSY;

392
	spin_lock_irq(&rtc->irq_task_lock);
A
Alessandro Zummo 已提交
393 394 395 396
	if (rtc->irq_task == NULL) {
		rtc->irq_task = task;
		retval = 0;
	}
397
	spin_unlock_irq(&rtc->irq_task_lock);
A
Alessandro Zummo 已提交
398

399
	clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
A
Alessandro Zummo 已提交
400

A
Alessandro Zummo 已提交
401 402 403 404
	return retval;
}
EXPORT_SYMBOL_GPL(rtc_irq_register);

405
void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
A
Alessandro Zummo 已提交
406
{
407
	spin_lock_irq(&rtc->irq_task_lock);
A
Alessandro Zummo 已提交
408 409
	if (rtc->irq_task == task)
		rtc->irq_task = NULL;
410
	spin_unlock_irq(&rtc->irq_task_lock);
A
Alessandro Zummo 已提交
411 412 413
}
EXPORT_SYMBOL_GPL(rtc_irq_unregister);

414 415 416 417 418 419 420 421 422 423
/**
 * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs
 * @rtc: the rtc device
 * @task: currently registered with rtc_irq_register()
 * @enabled: true to enable periodic IRQs
 * Context: any
 *
 * Note that rtc_irq_set_freq() should previously have been used to
 * specify the desired frequency of periodic IRQ task->func() callbacks.
 */
424
int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
A
Alessandro Zummo 已提交
425 426 427 428 429
{
	int err = 0;
	unsigned long flags;

	spin_lock_irqsave(&rtc->irq_task_lock, flags);
A
Alessandro Zummo 已提交
430 431
	if (rtc->irq_task != NULL && task == NULL)
		err = -EBUSY;
A
Alessandro Zummo 已提交
432
	if (rtc->irq_task != task)
A
Alessandro Zummo 已提交
433
		err = -EACCES;
A
Alessandro Zummo 已提交
434

435 436 437 438 439 440 441 442
	if (enabled) {
		ktime_t period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
		hrtimer_start(&rtc->pie_timer, period, HRTIMER_MODE_REL);
	} else {
		hrtimer_cancel(&rtc->pie_timer);
	}
	rtc->pie_enabled = enabled;
	spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
A
Alessandro Zummo 已提交
443 444 445 446 447

	return err;
}
EXPORT_SYMBOL_GPL(rtc_irq_set_state);

448 449 450 451 452 453 454 455 456 457
/**
 * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
 * @rtc: the rtc device
 * @task: currently registered with rtc_irq_register()
 * @freq: positive frequency with which task->func() will be called
 * Context: any
 *
 * Note that rtc_irq_set_state() is used to enable or disable the
 * periodic IRQs.
 */
458
int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
A
Alessandro Zummo 已提交
459
{
460
	int err = 0;
A
Alessandro Zummo 已提交
461 462 463
	unsigned long flags;

	spin_lock_irqsave(&rtc->irq_task_lock, flags);
A
Alessandro Zummo 已提交
464 465
	if (rtc->irq_task != NULL && task == NULL)
		err = -EBUSY;
A
Alessandro Zummo 已提交
466
	if (rtc->irq_task != task)
A
Alessandro Zummo 已提交
467
		err = -EACCES;
A
Alessandro Zummo 已提交
468
	if (err == 0) {
469 470 471 472 473 474 475 476
		rtc->irq_freq = freq;
		if (rtc->pie_enabled) {
			ktime_t period;
			hrtimer_cancel(&rtc->pie_timer);
			period = ktime_set(0, NSEC_PER_SEC/rtc->irq_freq);
			hrtimer_start(&rtc->pie_timer, period,
					HRTIMER_MODE_REL);
		}
A
Alessandro Zummo 已提交
477
	}
478
	spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
A
Alessandro Zummo 已提交
479 480
	return err;
}
481
EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
482 483

/**
T
Thomas Gleixner 已提交
484
 * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue
485 486 487 488 489 490 491 492
 * @rtc rtc device
 * @timer timer being added.
 *
 * Enqueues a timer onto the rtc devices timerqueue and sets
 * the next alarm event appropriately.
 *
 * Must hold ops_lock for proper serialization of timerqueue
 */
T
Thomas Gleixner 已提交
493
void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
494 495 496 497 498 499 500 501 502 503 504 505 506 507
{
	timerqueue_add(&rtc->timerqueue, &timer->node);
	if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) {
		struct rtc_wkalrm alarm;
		int err;
		alarm.time = rtc_ktime_to_tm(timer->node.expires);
		alarm.enabled = 1;
		err = __rtc_set_alarm(rtc, &alarm);
		if (err == -ETIME)
			schedule_work(&rtc->irqwork);
	}
}

/**
T
Thomas Gleixner 已提交
508
 * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue
509 510 511 512 513 514 515 516
 * @rtc rtc device
 * @timer timer being removed.
 *
 * Removes a timer onto the rtc devices timerqueue and sets
 * the next alarm event appropriately.
 *
 * Must hold ops_lock for proper serialization of timerqueue
 */
T
Thomas Gleixner 已提交
517
void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
{
	struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
	timerqueue_del(&rtc->timerqueue, &timer->node);

	if (next == &timer->node) {
		struct rtc_wkalrm alarm;
		int err;
		next = timerqueue_getnext(&rtc->timerqueue);
		if (!next)
			return;
		alarm.time = rtc_ktime_to_tm(next->expires);
		alarm.enabled = 1;
		err = __rtc_set_alarm(rtc, &alarm);
		if (err == -ETIME)
			schedule_work(&rtc->irqwork);
	}
}

/**
T
Thomas Gleixner 已提交
537
 * rtc_timer_do_work - Expires rtc timers
538 539 540 541 542 543 544 545
 * @rtc rtc device
 * @timer timer being removed.
 *
 * Expires rtc timers. Reprograms next alarm event if needed.
 * Called via worktask.
 *
 * Serializes access to timerqueue via ops_lock mutex
 */
T
Thomas Gleixner 已提交
546
void rtc_timer_do_work(struct work_struct *work)
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
{
	struct rtc_timer *timer;
	struct timerqueue_node *next;
	ktime_t now;
	struct rtc_time tm;

	struct rtc_device *rtc =
		container_of(work, struct rtc_device, irqwork);

	mutex_lock(&rtc->ops_lock);
again:
	__rtc_read_time(rtc, &tm);
	now = rtc_tm_to_ktime(tm);
	while ((next = timerqueue_getnext(&rtc->timerqueue))) {
		if (next->expires.tv64 > now.tv64)
			break;

		/* expire timer */
		timer = container_of(next, struct rtc_timer, node);
		timerqueue_del(&rtc->timerqueue, &timer->node);
		timer->enabled = 0;
		if (timer->task.func)
			timer->task.func(timer->task.private_data);

		/* Re-add/fwd periodic timers */
		if (ktime_to_ns(timer->period)) {
			timer->node.expires = ktime_add(timer->node.expires,
							timer->period);
			timer->enabled = 1;
			timerqueue_add(&rtc->timerqueue, &timer->node);
		}
	}

	/* Set next alarm */
	if (next) {
		struct rtc_wkalrm alarm;
		int err;
		alarm.time = rtc_ktime_to_tm(next->expires);
		alarm.enabled = 1;
		err = __rtc_set_alarm(rtc, &alarm);
		if (err == -ETIME)
			goto again;
	}

	mutex_unlock(&rtc->ops_lock);
}


T
Thomas Gleixner 已提交
595
/* rtc_timer_init - Initializes an rtc_timer
596 597 598 599 600 601
 * @timer: timer to be intiialized
 * @f: function pointer to be called when timer fires
 * @data: private data passed to function pointer
 *
 * Kernel interface to initializing an rtc_timer.
 */
T
Thomas Gleixner 已提交
602
void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data)
603 604 605 606 607 608 609
{
	timerqueue_init(&timer->node);
	timer->enabled = 0;
	timer->task.func = f;
	timer->task.private_data = data;
}

T
Thomas Gleixner 已提交
610
/* rtc_timer_start - Sets an rtc_timer to fire in the future
611 612 613 614 615 616 617
 * @ rtc: rtc device to be used
 * @ timer: timer being set
 * @ expires: time at which to expire the timer
 * @ period: period that the timer will recur
 *
 * Kernel interface to set an rtc_timer
 */
T
Thomas Gleixner 已提交
618
int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer,
619 620 621 622 623
			ktime_t expires, ktime_t period)
{
	int ret = 0;
	mutex_lock(&rtc->ops_lock);
	if (timer->enabled)
T
Thomas Gleixner 已提交
624
		rtc_timer_remove(rtc, timer);
625 626 627 628 629

	timer->node.expires = expires;
	timer->period = period;

	timer->enabled = 1;
T
Thomas Gleixner 已提交
630
	rtc_timer_enqueue(rtc, timer);
631 632 633 634 635

	mutex_unlock(&rtc->ops_lock);
	return ret;
}

T
Thomas Gleixner 已提交
636
/* rtc_timer_cancel - Stops an rtc_timer
637 638 639 640 641
 * @ rtc: rtc device to be used
 * @ timer: timer being set
 *
 * Kernel interface to cancel an rtc_timer
 */
T
Thomas Gleixner 已提交
642
int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer)
643 644 645 646
{
	int ret = 0;
	mutex_lock(&rtc->ops_lock);
	if (timer->enabled)
T
Thomas Gleixner 已提交
647
		rtc_timer_remove(rtc, timer);
648 649 650 651 652 653
	timer->enabled = 0;
	mutex_unlock(&rtc->ops_lock);
	return ret;
}