linux/drivers/rtc/interface.c
<<
>>
Prefs
   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#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                         * avoid writing when we're going to change the day of
  84                         * the month. We will retry in the next minute. This
  85                         * basically means that if the RTC must not drift
  86                         * by more than 1 minute in 11 minutes.
  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        /* The lower level RTC driver may not be capable of filling
 131         * in all fields of the rtc_time struct (eg. rtc-cmos),
 132         * and so might instead return -1 in some fields.
 133         * We deal with that here by grabbing a current RTC timestamp
 134         * and using values from that for any missing (-1) values.
 135         *
 136         * But this can be racey, because some fields of the RTC timestamp
 137         * may have wrapped in the interval since we read the RTC alarm,
 138         * which would lead to us inserting inconsistent values in place
 139         * of the -1 fields.
 140         *
 141         * Reading the alarm and timestamp in the reverse sequence
 142         * would have the same race condition, and not solve the issue.
 143         *
 144         * So, we must first read the RTC timestamp,
 145         * then read the RTC alarm value,
 146         * and then read a second RTC timestamp.
 147         *
 148         * If any fields of the second timestamp have changed
 149         * when compared with the first timestamp, then we know
 150         * our timestamp may be inconsistent with that used by
 151         * the low-level rtc_read_alarm_internal() function.
 152         *
 153         * So, when the two timestamps disagree, we just loop and do
 154         * the process again to get a fully consistent set of values.
 155         *
 156         * This could all instead be done in the lower level driver,
 157         * but since more than one lower level RTC implementation needs it,
 158         * then it's probably best best to do it here instead of there..
 159         */
 160
 161        /* Get the "before" timestamp */
 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                /* get the RTC alarm values, which may be incomplete */
 171                err = rtc_read_alarm_internal(rtc, alarm);
 172                if (err)
 173                        return err;
 174                if (!alarm->enabled)
 175                        return 0;
 176
 177                /* get the "after" timestamp, to detect wrapped fields */
 178                err = rtc_read_time(rtc, &now);
 179                if (err < 0)
 180                        return err;
 181
 182                /* note that tm_sec is a "don't care" value here: */
 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        /* Fill in any missing alarm fields using the timestamp */
 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 * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
 232 * @rtc: the rtc device
 233 * @num: how many irqs are being reported (usually one)
 234 * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
 235 * Context: in_interrupt(), irqs blocked
 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        /* Cannot register while the char dev is in use */
 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 * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs
 323 * @rtc: the rtc device
 324 * @task: currently registered with rtc_irq_register()
 325 * @enabled: true to enable periodic IRQs
 326 * Context: any
 327 *
 328 * Note that rtc_irq_set_freq() should previously have been used to
 329 * specify the desired frequency of periodic IRQ task->func() callbacks.
 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 * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
 355 * @rtc: the rtc device
 356 * @task: currently registered with rtc_irq_register()
 357 * @freq: positive frequency with which task->func() will be called
 358 * Context: any
 359 *
 360 * Note that rtc_irq_set_state() is used to enable or disable the
 361 * periodic IRQs.
 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