linux-old/drivers/char/ds1286.c
<<
>>
Prefs
   1/*
   2 * DS1286 Real Time Clock interface for Linux
   3 *
   4 * Copyright (C) 1998, 1999, 2000 Ralf Baechle
   5 *
   6 * Based on code written by Paul Gortmaker.
   7 *
   8 * This driver allows use of the real time clock (built into nearly all
   9 * computers) from user space. It exports the /dev/rtc interface supporting
  10 * various ioctl() and also the /proc/rtc pseudo-file for status
  11 * information.
  12 *
  13 * The ioctls can be used to set the interrupt behaviour and generation rate
  14 * from the RTC via IRQ 8. Then the /dev/rtc interface can be used to make
  15 * use of these timer interrupts, be they interval or alarm based.
  16 *
  17 * The /dev/rtc interface will block on reads until an interrupt has been
  18 * received. If a RTC interrupt has already happened, it will output an
  19 * unsigned long and then block. The output value contains the interrupt
  20 * status in the low byte and the number of interrupts since the last read
  21 * in the remaining high bytes. The /dev/rtc interface can also be used with
  22 * the select(2) call.
  23 *
  24 * This program is free software; you can redistribute it and/or modify it
  25 * under the terms of the GNU General Public License as published by the
  26 * Free Software Foundation; either version 2 of the License, or (at your
  27 * option) any later version.
  28 */
  29#include <linux/types.h>
  30#include <linux/errno.h>
  31#include <linux/miscdevice.h>
  32#include <linux/slab.h>
  33#include <linux/ioport.h>
  34#include <linux/fcntl.h>
  35#include <linux/init.h>
  36#include <linux/poll.h>
  37#include <linux/rtc.h>
  38#include <linux/spinlock.h>
  39
  40#include <asm/ds1286.h>
  41#include <asm/io.h>
  42#include <asm/uaccess.h>
  43#include <asm/system.h>
  44
  45#define DS1286_VERSION          "1.0"
  46
  47/*
  48 *      We sponge a minor off of the misc major. No need slurping
  49 *      up another valuable major dev number for this. If you add
  50 *      an ioctl, make sure you don't conflict with SPARC's RTC
  51 *      ioctls.
  52 */
  53
  54static DECLARE_WAIT_QUEUE_HEAD(ds1286_wait);
  55
  56static ssize_t ds1286_read(struct file *file, char *buf,
  57                        size_t count, loff_t *ppos);
  58
  59static int ds1286_ioctl(struct inode *inode, struct file *file,
  60                        unsigned int cmd, unsigned long arg);
  61
  62static unsigned int ds1286_poll(struct file *file, poll_table *wait);
  63
  64void ds1286_get_alm_time (struct rtc_time *alm_tm);
  65void ds1286_get_time(struct rtc_time *rtc_tm);
  66int ds1286_set_time(struct rtc_time *rtc_tm);
  67
  68void set_rtc_irq_bit(unsigned char bit);
  69void clear_rtc_irq_bit(unsigned char bit);
  70
  71static inline unsigned char ds1286_is_updating(void);
  72
  73static spinlock_t ds1286_lock = SPIN_LOCK_UNLOCKED;
  74
  75/*
  76 *      Bits in rtc_status. (7 bits of room for future expansion)
  77 */
  78
  79#define RTC_IS_OPEN             0x01    /* means /dev/rtc is in use     */
  80#define RTC_TIMER_ON            0x02    /* missed irq timer active      */
  81
  82unsigned char ds1286_status;            /* bitmapped status byte.       */
  83unsigned long ds1286_freq;              /* Current periodic IRQ rate    */
  84
  85unsigned char days_in_mo[] =
  86{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  87
  88/*
  89 *      Now all the various file operations that we export.
  90 */
  91
  92static ssize_t ds1286_read(struct file *file, char *buf,
  93                           size_t count, loff_t *ppos)
  94{
  95        return -EIO;
  96}
  97
  98static int ds1286_ioctl(struct inode *inode, struct file *file,
  99                        unsigned int cmd, unsigned long arg)
 100{
 101
 102        struct rtc_time wtime;
 103
 104        switch (cmd) {
 105        case RTC_AIE_OFF:       /* Mask alarm int. enab. bit    */
 106        {
 107                unsigned int flags;
 108                unsigned char val;
 109
 110                if (!capable(CAP_SYS_TIME))
 111                        return -EACCES;
 112
 113                spin_lock_irqsave(&ds1286_lock, flags);
 114                val = CMOS_READ(RTC_CMD);
 115                val |=  RTC_TDM;
 116                CMOS_WRITE(val, RTC_CMD);
 117                spin_unlock_irqrestore(&ds1286_lock, flags);
 118
 119                return 0;
 120        }
 121        case RTC_AIE_ON:        /* Allow alarm interrupts.      */
 122        {
 123                unsigned int flags;
 124                unsigned char val;
 125
 126                if (!capable(CAP_SYS_TIME))
 127                        return -EACCES;
 128
 129                spin_lock_irqsave(&ds1286_lock, flags);
 130                val = CMOS_READ(RTC_CMD);
 131                val &=  ~RTC_TDM;
 132                CMOS_WRITE(val, RTC_CMD);
 133                spin_unlock_irqrestore(&ds1286_lock, flags);
 134
 135                return 0;
 136        }
 137        case RTC_WIE_OFF:       /* Mask watchdog int. enab. bit */
 138        {
 139                unsigned int flags;
 140                unsigned char val;
 141
 142                if (!capable(CAP_SYS_TIME))
 143                        return -EACCES;
 144
 145                spin_lock_irqsave(&ds1286_lock, flags);
 146                val = CMOS_READ(RTC_CMD);
 147                val |= RTC_WAM;
 148                CMOS_WRITE(val, RTC_CMD);
 149                spin_unlock_irqrestore(&ds1286_lock, flags);
 150
 151                return 0;
 152        }
 153        case RTC_WIE_ON:        /* Allow watchdog interrupts.   */
 154        {
 155                unsigned int flags;
 156                unsigned char val;
 157
 158                if (!capable(CAP_SYS_TIME))
 159                        return -EACCES;
 160
 161                spin_lock_irqsave(&ds1286_lock, flags);
 162                val = CMOS_READ(RTC_CMD);
 163                val &= ~RTC_WAM;
 164                CMOS_WRITE(val, RTC_CMD);
 165                spin_unlock_irqrestore(&ds1286_lock, flags);
 166
 167                return 0;
 168        }
 169        case RTC_ALM_READ:      /* Read the present alarm time */
 170        {
 171                /*
 172                 * This returns a struct rtc_time. Reading >= 0xc0
 173                 * means "don't care" or "match all". Only the tm_hour,
 174                 * tm_min, and tm_sec values are filled in.
 175                 */
 176                memset(&wtime, 0, sizeof(struct rtc_time));
 177                ds1286_get_alm_time(&wtime);
 178                break;
 179        }
 180        case RTC_ALM_SET:       /* Store a time into the alarm */
 181        {
 182                /*
 183                 * This expects a struct rtc_time. Writing 0xff means
 184                 * "don't care" or "match all". Only the tm_hour,
 185                 * tm_min and tm_sec are used.
 186                 */
 187                unsigned char hrs, min, sec;
 188                struct rtc_time alm_tm;
 189
 190                if (!capable(CAP_SYS_TIME))
 191                        return -EACCES;
 192
 193                if (copy_from_user(&alm_tm, (struct rtc_time*)arg,
 194                                   sizeof(struct rtc_time)))
 195                        return -EFAULT;
 196
 197                hrs = alm_tm.tm_hour;
 198                min = alm_tm.tm_min;
 199
 200                if (hrs >= 24)
 201                        hrs = 0xff;
 202
 203                if (min >= 60)
 204                        min = 0xff;
 205
 206                BIN_TO_BCD(sec);
 207                BIN_TO_BCD(min);
 208                BIN_TO_BCD(hrs);
 209
 210                spin_lock(&ds1286_lock);
 211                CMOS_WRITE(hrs, RTC_HOURS_ALARM);
 212                CMOS_WRITE(min, RTC_MINUTES_ALARM);
 213                spin_unlock(&ds1286_lock);
 214
 215                return 0;
 216        }
 217        case RTC_RD_TIME:       /* Read the time/date from RTC  */
 218        {
 219                memset(&wtime, 0, sizeof(struct rtc_time));
 220                ds1286_get_time(&wtime);
 221                break;
 222        }
 223        case RTC_SET_TIME:      /* Set the RTC */
 224        {
 225                struct rtc_time rtc_tm;
 226
 227                if (!capable(CAP_SYS_TIME))
 228                        return -EACCES;
 229
 230                if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
 231                                   sizeof(struct rtc_time)))
 232                        return -EFAULT;
 233
 234                return ds1286_set_time(&rtc_tm);
 235        }
 236        default:
 237                return -EINVAL;
 238        }
 239        return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
 240}
 241
 242/*
 243 *      We enforce only one user at a time here with the open/close.
 244 *      Also clear the previous interrupt data on an open, and clean
 245 *      up things on a close.
 246 */
 247
 248static int ds1286_open(struct inode *inode, struct file *file)
 249{
 250        spin_lock_irq(&ds1286_lock);
 251
 252        if (ds1286_status & RTC_IS_OPEN)
 253                goto out_busy;
 254
 255        ds1286_status |= RTC_IS_OPEN;
 256
 257        spin_lock_irq(&ds1286_lock);
 258        return 0;
 259
 260out_busy:
 261        spin_lock_irq(&ds1286_lock);
 262        return -EBUSY;
 263}
 264
 265static int ds1286_release(struct inode *inode, struct file *file)
 266{
 267        ds1286_status &= ~RTC_IS_OPEN;
 268
 269        return 0;
 270}
 271
 272static unsigned int ds1286_poll(struct file *file, poll_table *wait)
 273{
 274        poll_wait(file, &ds1286_wait, wait);
 275
 276        return 0;
 277}
 278
 279/*
 280 *      The various file operations we support.
 281 */
 282
 283static struct file_operations ds1286_fops = {
 284        .llseek         = no_llseek,
 285        .read           = ds1286_read,
 286        .poll           = ds1286_poll,
 287        .ioctl          = ds1286_ioctl,
 288        .open           = ds1286_open,
 289        .release        = ds1286_release,
 290};
 291
 292static struct miscdevice ds1286_dev=
 293{
 294        .minor  = RTC_MINOR,
 295        .name   = "rtc",
 296        .fops   = &ds1286_fops,
 297};
 298
 299int __init ds1286_init(void)
 300{
 301        printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION);
 302        return misc_register(&ds1286_dev);
 303}
 304
 305static char *days[] = {
 306        "***", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 307};
 308
 309/*
 310 *      Info exported via "/proc/rtc".
 311 */
 312int get_ds1286_status(char *buf)
 313{
 314        char *p, *s;
 315        struct rtc_time tm;
 316        unsigned char hundredth, month, cmd, amode;
 317
 318        p = buf;
 319
 320        ds1286_get_time(&tm);
 321        hundredth = CMOS_READ(RTC_HUNDREDTH_SECOND);
 322        BCD_TO_BIN(hundredth);
 323
 324        p += sprintf(p,
 325                     "rtc_time\t: %02d:%02d:%02d.%02d\n"
 326                     "rtc_date\t: %04d-%02d-%02d\n",
 327                     tm.tm_hour, tm.tm_min, tm.tm_sec, hundredth,
 328                     tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
 329
 330        /*
 331         * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will
 332         * match any value for that particular field. Values that are
 333         * greater than a valid time, but less than 0xc0 shouldn't appear.
 334         */
 335        ds1286_get_alm_time(&tm);
 336        p += sprintf(p, "alarm\t\t: %s ", days[tm.tm_wday]);
 337        if (tm.tm_hour <= 24)
 338                p += sprintf(p, "%02d:", tm.tm_hour);
 339        else
 340                p += sprintf(p, "**:");
 341
 342        if (tm.tm_min <= 59)
 343                p += sprintf(p, "%02d\n", tm.tm_min);
 344        else
 345                p += sprintf(p, "**\n");
 346
 347        month = CMOS_READ(RTC_MONTH);
 348        p += sprintf(p,
 349                     "oscillator\t: %s\n"
 350                     "square_wave\t: %s\n",
 351                     (month & RTC_EOSC) ? "disabled" : "enabled",
 352                     (month & RTC_ESQW) ? "disabled" : "enabled");
 353
 354        amode = ((CMOS_READ(RTC_MINUTES_ALARM) & 0x80) >> 5) |
 355                ((CMOS_READ(RTC_HOURS_ALARM) & 0x80) >> 6) |
 356                ((CMOS_READ(RTC_DAY_ALARM) & 0x80) >> 7);
 357        if (amode == 7)      s = "each minute";
 358        else if (amode == 3) s = "minutes match";
 359        else if (amode == 1) s = "hours and minutes match";
 360        else if (amode == 0) s = "days, hours and minutes match";
 361        else                 s = "invalid";
 362        p += sprintf(p, "alarm_mode\t: %s\n", s);
 363
 364        cmd = CMOS_READ(RTC_CMD);
 365        p += sprintf(p,
 366                     "alarm_enable\t: %s\n"
 367                     "wdog_alarm\t: %s\n"
 368                     "alarm_mask\t: %s\n"
 369                     "wdog_alarm_mask\t: %s\n"
 370                     "interrupt_mode\t: %s\n"
 371                     "INTB_mode\t: %s_active\n"
 372                     "interrupt_pins\t: %s\n",
 373                     (cmd & RTC_TDF) ? "yes" : "no",
 374                     (cmd & RTC_WAF) ? "yes" : "no",
 375                     (cmd & RTC_TDM) ? "disabled" : "enabled",
 376                     (cmd & RTC_WAM) ? "disabled" : "enabled",
 377                     (cmd & RTC_PU_LVL) ? "pulse" : "level",
 378                     (cmd & RTC_IBH_LO) ? "low" : "high",
 379                     (cmd & RTC_IPSW) ? "unswapped" : "swapped");
 380
 381        return  p - buf;
 382}
 383
 384/*
 385 * Returns true if a clock update is in progress
 386 */
 387static inline unsigned char ds1286_is_updating(void)
 388{
 389        return CMOS_READ(RTC_CMD) & RTC_TE;
 390}
 391
 392
 393void ds1286_get_time(struct rtc_time *rtc_tm)
 394{
 395        unsigned char save_control;
 396        unsigned int flags;
 397        unsigned long uip_watchdog = jiffies;
 398
 399        /*
 400         * read RTC once any update in progress is done. The update
 401         * can take just over 2ms. We wait 10 to 20ms. There is no need to
 402         * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
 403         * If you need to know *exactly* when a second has started, enable
 404         * periodic update complete interrupts, (via ioctl) and then
 405         * immediately read /dev/rtc which will block until you get the IRQ.
 406         * Once the read clears, read the RTC time (again via ioctl). Easy.
 407         */
 408
 409        if (ds1286_is_updating() != 0)
 410                while (jiffies - uip_watchdog < 2*HZ/100)
 411                        barrier();
 412
 413        /*
 414         * Only the values that we read from the RTC are set. We leave
 415         * tm_wday, tm_yday and tm_isdst untouched. Even though the
 416         * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
 417         * by the RTC when initially set to a non-zero value.
 418         */
 419        spin_lock_irqsave(&ds1286_lock, flags);
 420        save_control = CMOS_READ(RTC_CMD);
 421        CMOS_WRITE((save_control|RTC_TE), RTC_CMD);
 422
 423        rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
 424        rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
 425        rtc_tm->tm_hour = CMOS_READ(RTC_HOURS) & 0x3f;
 426        rtc_tm->tm_mday = CMOS_READ(RTC_DATE);
 427        rtc_tm->tm_mon = CMOS_READ(RTC_MONTH) & 0x1f;
 428        rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
 429
 430        CMOS_WRITE(save_control, RTC_CMD);
 431        spin_unlock_irqrestore(&ds1286_lock, flags);
 432
 433        BCD_TO_BIN(rtc_tm->tm_sec);
 434        BCD_TO_BIN(rtc_tm->tm_min);
 435        BCD_TO_BIN(rtc_tm->tm_hour);
 436        BCD_TO_BIN(rtc_tm->tm_mday);
 437        BCD_TO_BIN(rtc_tm->tm_mon);
 438        BCD_TO_BIN(rtc_tm->tm_year);
 439
 440        /*
 441         * Account for differences between how the RTC uses the values
 442         * and how they are defined in a struct rtc_time;
 443         */
 444        if (rtc_tm->tm_year < 45)
 445                rtc_tm->tm_year += 30;
 446        if ((rtc_tm->tm_year += 40) < 70)
 447                rtc_tm->tm_year += 100;
 448
 449        rtc_tm->tm_mon--;
 450}
 451
 452int ds1286_set_time(struct rtc_time *rtc_tm)
 453{
 454        unsigned char mon, day, hrs, min, sec, leap_yr;
 455        unsigned char save_control;
 456        unsigned int yrs, flags;
 457
 458
 459        yrs = rtc_tm->tm_year + 1900;
 460        mon = rtc_tm->tm_mon + 1;   /* tm_mon starts at zero */
 461        day = rtc_tm->tm_mday;
 462        hrs = rtc_tm->tm_hour;
 463        min = rtc_tm->tm_min;
 464        sec = rtc_tm->tm_sec;
 465
 466        if (yrs < 1970)
 467                return -EINVAL;
 468
 469        leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
 470
 471        if ((mon > 12) || (day == 0))
 472                return -EINVAL;
 473
 474        if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
 475                return -EINVAL;
 476
 477        if ((hrs >= 24) || (min >= 60) || (sec >= 60))
 478                return -EINVAL;
 479
 480        if ((yrs -= 1940) > 255)    /* They are unsigned */
 481                return -EINVAL;
 482
 483        if (yrs >= 100)
 484                yrs -= 100;
 485
 486        BIN_TO_BCD(sec);
 487        BIN_TO_BCD(min);
 488        BIN_TO_BCD(hrs);
 489        BIN_TO_BCD(day);
 490        BIN_TO_BCD(mon);
 491        BIN_TO_BCD(yrs);
 492
 493        spin_lock_irqsave(&ds1286_lock, flags);
 494        save_control = CMOS_READ(RTC_CMD);
 495        CMOS_WRITE((save_control|RTC_TE), RTC_CMD);
 496
 497        CMOS_WRITE(yrs, RTC_YEAR);
 498        CMOS_WRITE(mon, RTC_MONTH);
 499        CMOS_WRITE(day, RTC_DATE);
 500        CMOS_WRITE(hrs, RTC_HOURS);
 501        CMOS_WRITE(min, RTC_MINUTES);
 502        CMOS_WRITE(sec, RTC_SECONDS);
 503        CMOS_WRITE(0, RTC_HUNDREDTH_SECOND);
 504
 505        CMOS_WRITE(save_control, RTC_CMD);
 506        spin_unlock_irqrestore(&ds1286_lock, flags);
 507
 508        return 0;
 509}
 510
 511void ds1286_get_alm_time(struct rtc_time *alm_tm)
 512{
 513        unsigned char cmd;
 514        unsigned int flags;
 515
 516        /*
 517         * Only the values that we read from the RTC are set. That
 518         * means only tm_wday, tm_hour, tm_min.
 519         */
 520        spin_lock_irqsave(&ds1286_lock, flags);
 521        alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM) & 0x7f;
 522        alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM)  & 0x1f;
 523        alm_tm->tm_wday = CMOS_READ(RTC_DAY_ALARM)    & 0x07;
 524        cmd = CMOS_READ(RTC_CMD);
 525        spin_unlock_irqrestore(&ds1286_lock, flags);
 526
 527        BCD_TO_BIN(alm_tm->tm_min);
 528        BCD_TO_BIN(alm_tm->tm_hour);
 529        alm_tm->tm_sec = 0;
 530}
 531
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.