linux/arch/alpha/kernel/rtc.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/alpha/kernel/rtc.c
   3 *
   4 *  Copyright (C) 1991, 1992, 1995, 1999, 2000  Linus Torvalds
   5 *
   6 * This file contains date handling.
   7 */
   8#include <linux/errno.h>
   9#include <linux/init.h>
  10#include <linux/kernel.h>
  11#include <linux/param.h>
  12#include <linux/string.h>
  13#include <linux/mc146818rtc.h>
  14#include <linux/bcd.h>
  15#include <linux/rtc.h>
  16#include <linux/platform_device.h>
  17
  18#include <asm/rtc.h>
  19
  20#include "proto.h"
  21
  22
  23/*
  24 * Support for the RTC device.
  25 *
  26 * We don't want to use the rtc-cmos driver, because we don't want to support
  27 * alarms, as that would be indistinguishable from timer interrupts.
  28 *
  29 * Further, generic code is really, really tied to a 1900 epoch.  This is
  30 * true in __get_rtc_time as well as the users of struct rtc_time e.g.
  31 * rtc_tm_to_time.  Thankfully all of the other epochs in use are later
  32 * than 1900, and so it's easy to adjust.
  33 */
  34
  35static unsigned long rtc_epoch;
  36
  37static int __init
  38specifiy_epoch(char *str)
  39{
  40        unsigned long epoch = simple_strtoul(str, NULL, 0);
  41        if (epoch < 1900)
  42                printk("Ignoring invalid user specified epoch %lu\n", epoch);
  43        else
  44                rtc_epoch = epoch;
  45        return 1;
  46}
  47__setup("epoch=", specifiy_epoch);
  48
  49static void __init
  50init_rtc_epoch(void)
  51{
  52        int epoch, year, ctrl;
  53
  54        if (rtc_epoch != 0) {
  55                /* The epoch was specified on the command-line.  */
  56                return;
  57        }
  58
  59        /* Detect the epoch in use on this computer.  */
  60        ctrl = CMOS_READ(RTC_CONTROL);
  61        year = CMOS_READ(RTC_YEAR);
  62        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
  63                year = bcd2bin(year);
  64
  65        /* PC-like is standard; used for year >= 70 */
  66        epoch = 1900;
  67        if (year < 20) {
  68                epoch = 2000;
  69        } else if (year >= 20 && year < 48) {
  70                /* NT epoch */
  71                epoch = 1980;
  72        } else if (year >= 48 && year < 70) {
  73                /* Digital UNIX epoch */
  74                epoch = 1952;
  75        }
  76        rtc_epoch = epoch;
  77
  78        printk(KERN_INFO "Using epoch %d for rtc year %d\n", epoch, year);
  79}
  80
  81static int
  82alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
  83{
  84        __get_rtc_time(tm);
  85
  86        /* Adjust for non-default epochs.  It's easier to depend on the
  87           generic __get_rtc_time and adjust the epoch here than create
  88           a copy of __get_rtc_time with the edits we need.  */
  89        if (rtc_epoch != 1900) {
  90                int year = tm->tm_year;
  91                /* Undo the century adjustment made in __get_rtc_time.  */
  92                if (year >= 100)
  93                        year -= 100;
  94                year += rtc_epoch - 1900;
  95                /* Redo the century adjustment with the epoch in place.  */
  96                if (year <= 69)
  97                        year += 100;
  98                tm->tm_year = year;
  99        }
 100
 101        return rtc_valid_tm(tm);
 102}
 103
 104static int
 105alpha_rtc_set_time(struct device *dev, struct rtc_time *tm)
 106{
 107        struct rtc_time xtm;
 108
 109        if (rtc_epoch != 1900) {
 110                xtm = *tm;
 111                xtm.tm_year -= rtc_epoch - 1900;
 112                tm = &xtm;
 113        }
 114
 115        return __set_rtc_time(tm);
 116}
 117
 118static int
 119alpha_rtc_set_mmss(struct device *dev, time64_t nowtime)
 120{
 121        int retval = 0;
 122        int real_seconds, real_minutes, cmos_minutes;
 123        unsigned char save_control, save_freq_select;
 124
 125        /* Note: This code only updates minutes and seconds.  Comments
 126           indicate this was to avoid messing with unknown time zones,
 127           and with the epoch nonsense described above.  In order for
 128           this to work, the existing clock cannot be off by more than
 129           15 minutes.
 130
 131           ??? This choice is may be out of date.  The x86 port does
 132           not have problems with timezones, and the epoch processing has
 133           now been fixed in alpha_set_rtc_time.
 134
 135           In either case, one can always force a full rtc update with
 136           the userland hwclock program, so surely 15 minute accuracy
 137           is no real burden.  */
 138
 139        /* In order to set the CMOS clock precisely, we have to be called
 140           500 ms after the second nowtime has started, because when
 141           nowtime is written into the registers of the CMOS clock, it will
 142           jump to the next second precisely 500 ms later. Check the Motorola
 143           MC146818A or Dallas DS12887 data sheet for details.  */
 144
 145        /* irq are locally disabled here */
 146        spin_lock(&rtc_lock);
 147        /* Tell the clock it's being set */
 148        save_control = CMOS_READ(RTC_CONTROL);
 149        CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
 150
 151        /* Stop and reset prescaler */
 152        save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
 153        CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
 154
 155        cmos_minutes = CMOS_READ(RTC_MINUTES);
 156        if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
 157                cmos_minutes = bcd2bin(cmos_minutes);
 158
 159        real_seconds = nowtime % 60;
 160        real_minutes = nowtime / 60;
 161        if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) {
 162                /* correct for half hour time zone */
 163                real_minutes += 30;
 164        }
 165        real_minutes %= 60;
 166
 167        if (abs(real_minutes - cmos_minutes) < 30) {
 168                if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
 169                        real_seconds = bin2bcd(real_seconds);
 170                        real_minutes = bin2bcd(real_minutes);
 171                }
 172                CMOS_WRITE(real_seconds,RTC_SECONDS);
 173                CMOS_WRITE(real_minutes,RTC_MINUTES);
 174        } else {
 175                printk_once(KERN_NOTICE
 176                            "set_rtc_mmss: can't update from %d to %d\n",
 177                            cmos_minutes, real_minutes);
 178                retval = -1;
 179        }
 180
 181        /* The following flags have to be released exactly in this order,
 182         * otherwise the DS12887 (popular MC146818A clone with integrated
 183         * battery and quartz) will not reset the oscillator and will not
 184         * update precisely 500 ms later. You won't find this mentioned in
 185         * the Dallas Semiconductor data sheets, but who believes data
 186         * sheets anyway ...                           -- Markus Kuhn
 187         */
 188        CMOS_WRITE(save_control, RTC_CONTROL);
 189        CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
 190        spin_unlock(&rtc_lock);
 191
 192        return retval;
 193}
 194
 195static int
 196alpha_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 197{
 198        switch (cmd) {
 199        case RTC_EPOCH_READ:
 200                return put_user(rtc_epoch, (unsigned long __user *)arg);
 201        case RTC_EPOCH_SET:
 202                if (arg < 1900)
 203                        return -EINVAL;
 204                rtc_epoch = arg;
 205                return 0;
 206        default:
 207                return -ENOIOCTLCMD;
 208        }
 209}
 210
 211static const struct rtc_class_ops alpha_rtc_ops = {
 212        .read_time = alpha_rtc_read_time,
 213        .set_time = alpha_rtc_set_time,
 214        .set_mmss64 = alpha_rtc_set_mmss,
 215        .ioctl = alpha_rtc_ioctl,
 216};
 217
 218/*
 219 * Similarly, except do the actual CMOS access on the boot cpu only.
 220 * This requires marshalling the data across an interprocessor call.
 221 */
 222
 223#if defined(CONFIG_SMP) && \
 224    (defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_MARVEL))
 225# define HAVE_REMOTE_RTC 1
 226
 227union remote_data {
 228        struct rtc_time *tm;
 229        unsigned long now;
 230        long retval;
 231};
 232
 233static void
 234do_remote_read(void *data)
 235{
 236        union remote_data *x = data;
 237        x->retval = alpha_rtc_read_time(NULL, x->tm);
 238}
 239
 240static int
 241remote_read_time(struct device *dev, struct rtc_time *tm)
 242{
 243        union remote_data x;
 244        if (smp_processor_id() != boot_cpuid) {
 245                x.tm = tm;
 246                smp_call_function_single(boot_cpuid, do_remote_read, &x, 1);
 247                return x.retval;
 248        }
 249        return alpha_rtc_read_time(NULL, tm);
 250}
 251
 252static void
 253do_remote_set(void *data)
 254{
 255        union remote_data *x = data;
 256        x->retval = alpha_rtc_set_time(NULL, x->tm);
 257}
 258
 259static int
 260remote_set_time(struct device *dev, struct rtc_time *tm)
 261{
 262        union remote_data x;
 263        if (smp_processor_id() != boot_cpuid) {
 264                x.tm = tm;
 265                smp_call_function_single(boot_cpuid, do_remote_set, &x, 1);
 266                return x.retval;
 267        }
 268        return alpha_rtc_set_time(NULL, tm);
 269}
 270
 271static void
 272do_remote_mmss(void *data)
 273{
 274        union remote_data *x = data;
 275        x->retval = alpha_rtc_set_mmss(NULL, x->now);
 276}
 277
 278static int
 279remote_set_mmss(struct device *dev, time64_t now)
 280{
 281        union remote_data x;
 282        if (smp_processor_id() != boot_cpuid) {
 283                x.now = now;
 284                smp_call_function_single(boot_cpuid, do_remote_mmss, &x, 1);
 285                return x.retval;
 286        }
 287        return alpha_rtc_set_mmss(NULL, now);
 288}
 289
 290static const struct rtc_class_ops remote_rtc_ops = {
 291        .read_time = remote_read_time,
 292        .set_time = remote_set_time,
 293        .set_mmss64 = remote_set_mmss,
 294        .ioctl = alpha_rtc_ioctl,
 295};
 296#endif
 297
 298static int __init
 299alpha_rtc_init(void)
 300{
 301        const struct rtc_class_ops *ops;
 302        struct platform_device *pdev;
 303        struct rtc_device *rtc;
 304        const char *name;
 305
 306        init_rtc_epoch();
 307        name = "rtc-alpha";
 308        ops = &alpha_rtc_ops;
 309
 310#ifdef HAVE_REMOTE_RTC
 311        if (alpha_mv.rtc_boot_cpu_only)
 312                ops = &remote_rtc_ops;
 313#endif
 314
 315        pdev = platform_device_register_simple(name, -1, NULL, 0);
 316        rtc = devm_rtc_device_register(&pdev->dev, name, ops, THIS_MODULE);
 317        if (IS_ERR(rtc))
 318                return PTR_ERR(rtc);
 319
 320        platform_set_drvdata(pdev, rtc);
 321        return 0;
 322}
 323device_initcall(alpha_rtc_init);
 324