linux/include/asm-generic/rtc.h
<<
>>
Prefs
   1/* 
   2 * include/asm-generic/rtc.h
   3 *
   4 * Author: Tom Rini <trini@mvista.com>
   5 *
   6 * Based on:
   7 * drivers/char/rtc.c
   8 *
   9 * Please read the COPYING file for all license details.
  10 */
  11
  12#ifndef __ASM_RTC_H__
  13#define __ASM_RTC_H__
  14
  15#include <linux/mc146818rtc.h>
  16#include <linux/rtc.h>
  17#include <linux/bcd.h>
  18#include <linux/delay.h>
  19#ifdef CONFIG_ACPI
  20#include <linux/acpi.h>
  21#endif
  22
  23#define RTC_PIE 0x40            /* periodic interrupt enable */
  24#define RTC_AIE 0x20            /* alarm interrupt enable */
  25#define RTC_UIE 0x10            /* update-finished interrupt enable */
  26
  27/* some dummy definitions */
  28#define RTC_BATT_BAD 0x100      /* battery bad */
  29#define RTC_SQWE 0x08           /* enable square-wave output */
  30#define RTC_DM_BINARY 0x04      /* all time/date values are BCD if clear */
  31#define RTC_24H 0x02            /* 24 hour mode - else hours bit 7 means pm */
  32#define RTC_DST_EN 0x01         /* auto switch DST - works f. USA only */
  33
  34/*
  35 * Returns true if a clock update is in progress
  36 */
  37static inline unsigned char rtc_is_updating(void)
  38{
  39        unsigned char uip;
  40        unsigned long flags;
  41
  42        spin_lock_irqsave(&rtc_lock, flags);
  43        uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
  44        spin_unlock_irqrestore(&rtc_lock, flags);
  45        return uip;
  46}
  47
  48static inline unsigned int __get_rtc_time(struct rtc_time *time)
  49{
  50        unsigned char ctrl;
  51        unsigned long flags;
  52        unsigned char century = 0;
  53
  54#ifdef CONFIG_MACH_DECSTATION
  55        unsigned int real_year;
  56#endif
  57
  58        /*
  59         * read RTC once any update in progress is done. The update
  60         * can take just over 2ms. We wait 20ms. There is no need to
  61         * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
  62         * If you need to know *exactly* when a second has started, enable
  63         * periodic update complete interrupts, (via ioctl) and then 
  64         * immediately read /dev/rtc which will block until you get the IRQ.
  65         * Once the read clears, read the RTC time (again via ioctl). Easy.
  66         */
  67        if (rtc_is_updating())
  68                mdelay(20);
  69
  70        /*
  71         * Only the values that we read from the RTC are set. We leave
  72         * tm_wday, tm_yday and tm_isdst untouched. Even though the
  73         * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
  74         * by the RTC when initially set to a non-zero value.
  75         */
  76        spin_lock_irqsave(&rtc_lock, flags);
  77        time->tm_sec = CMOS_READ(RTC_SECONDS);
  78        time->tm_min = CMOS_READ(RTC_MINUTES);
  79        time->tm_hour = CMOS_READ(RTC_HOURS);
  80        time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
  81        time->tm_mon = CMOS_READ(RTC_MONTH);
  82        time->tm_year = CMOS_READ(RTC_YEAR);
  83#ifdef CONFIG_MACH_DECSTATION
  84        real_year = CMOS_READ(RTC_DEC_YEAR);
  85#endif
  86#ifdef CONFIG_ACPI
  87        if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
  88            acpi_gbl_FADT.century)
  89                century = CMOS_READ(acpi_gbl_FADT.century);
  90#endif
  91        ctrl = CMOS_READ(RTC_CONTROL);
  92        spin_unlock_irqrestore(&rtc_lock, flags);
  93
  94        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
  95        {
  96                time->tm_sec = bcd2bin(time->tm_sec);
  97                time->tm_min = bcd2bin(time->tm_min);
  98                time->tm_hour = bcd2bin(time->tm_hour);
  99                time->tm_mday = bcd2bin(time->tm_mday);
 100                time->tm_mon = bcd2bin(time->tm_mon);
 101                time->tm_year = bcd2bin(time->tm_year);
 102                century = bcd2bin(century);
 103        }
 104
 105#ifdef CONFIG_MACH_DECSTATION
 106        time->tm_year += real_year - 72;
 107#endif
 108
 109        if (century)
 110                time->tm_year += (century - 19) * 100;
 111
 112        /*
 113         * Account for differences between how the RTC uses the values
 114         * and how they are defined in a struct rtc_time;
 115         */
 116        if (time->tm_year <= 69)
 117                time->tm_year += 100;
 118
 119        time->tm_mon--;
 120
 121        return RTC_24H;
 122}
 123
 124#ifndef get_rtc_time
 125#define get_rtc_time    __get_rtc_time
 126#endif
 127
 128/* Set the current date and time in the real time clock. */
 129static inline int __set_rtc_time(struct rtc_time *time)
 130{
 131        unsigned long flags;
 132        unsigned char mon, day, hrs, min, sec;
 133        unsigned char save_control, save_freq_select;
 134        unsigned int yrs;
 135#ifdef CONFIG_MACH_DECSTATION
 136        unsigned int real_yrs, leap_yr;
 137#endif
 138        unsigned char century = 0;
 139
 140        yrs = time->tm_year;
 141        mon = time->tm_mon + 1;   /* tm_mon starts at zero */
 142        day = time->tm_mday;
 143        hrs = time->tm_hour;
 144        min = time->tm_min;
 145        sec = time->tm_sec;
 146
 147        if (yrs > 255)  /* They are unsigned */
 148                return -EINVAL;
 149
 150        spin_lock_irqsave(&rtc_lock, flags);
 151#ifdef CONFIG_MACH_DECSTATION
 152        real_yrs = yrs;
 153        leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
 154                        !((yrs + 1900) % 400));
 155        yrs = 72;
 156
 157        /*
 158         * We want to keep the year set to 73 until March
 159         * for non-leap years, so that Feb, 29th is handled
 160         * correctly.
 161         */
 162        if (!leap_yr && mon < 3) {
 163                real_yrs--;
 164                yrs = 73;
 165        }
 166#endif
 167
 168#ifdef CONFIG_ACPI
 169        if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
 170            acpi_gbl_FADT.century) {
 171                century = (yrs + 1900) / 100;
 172                yrs %= 100;
 173        }
 174#endif
 175
 176        /* These limits and adjustments are independent of
 177         * whether the chip is in binary mode or not.
 178         */
 179        if (yrs > 169) {
 180                spin_unlock_irqrestore(&rtc_lock, flags);
 181                return -EINVAL;
 182        }
 183
 184        if (yrs >= 100)
 185                yrs -= 100;
 186
 187        if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
 188            || RTC_ALWAYS_BCD) {
 189                sec = bin2bcd(sec);
 190                min = bin2bcd(min);
 191                hrs = bin2bcd(hrs);
 192                day = bin2bcd(day);
 193                mon = bin2bcd(mon);
 194                yrs = bin2bcd(yrs);
 195                century = bin2bcd(century);
 196        }
 197
 198        save_control = CMOS_READ(RTC_CONTROL);
 199        CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
 200        save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
 201        CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
 202
 203#ifdef CONFIG_MACH_DECSTATION
 204        CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
 205#endif
 206        CMOS_WRITE(yrs, RTC_YEAR);
 207        CMOS_WRITE(mon, RTC_MONTH);
 208        CMOS_WRITE(day, RTC_DAY_OF_MONTH);
 209        CMOS_WRITE(hrs, RTC_HOURS);
 210        CMOS_WRITE(min, RTC_MINUTES);
 211        CMOS_WRITE(sec, RTC_SECONDS);
 212#ifdef CONFIG_ACPI
 213        if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
 214            acpi_gbl_FADT.century)
 215                CMOS_WRITE(century, acpi_gbl_FADT.century);
 216#endif
 217
 218        CMOS_WRITE(save_control, RTC_CONTROL);
 219        CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
 220
 221        spin_unlock_irqrestore(&rtc_lock, flags);
 222
 223        return 0;
 224}
 225
 226#ifndef set_rtc_time
 227#define set_rtc_time    __set_rtc_time
 228#endif
 229
 230static inline unsigned int get_rtc_ss(void)
 231{
 232        struct rtc_time h;
 233
 234        get_rtc_time(&h);
 235        return h.tm_sec;
 236}
 237
 238static inline int get_rtc_pll(struct rtc_pll_info *pll)
 239{
 240        return -EINVAL;
 241}
 242static inline int set_rtc_pll(struct rtc_pll_info *pll)
 243{
 244        return -EINVAL;
 245}
 246
 247#endif /* __ASM_RTC_H__ */
 248