linux/arch/alpha/kernel/rtc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  linux/arch/alpha/kernel/rtc.c
   4 *
   5 *  Copyright (C) 1991, 1992, 1995, 1999, 2000  Linus Torvalds
   6 *
   7 * This file contains date handling.
   8 */
   9#include <linux/errno.h>
  10#include <linux/init.h>
  11#include <linux/kernel.h>
  12#include <linux/param.h>
  13#include <linux/string.h>
  14#include <linux/mc146818rtc.h>
  15#include <linux/bcd.h>
  16#include <linux/rtc.h>
  17#include <linux/platform_device.h>
  18
  19#include "proto.h"
  20
  21
  22/*
  23 * Support for the RTC device.
  24 *
  25 * We don't want to use the rtc-cmos driver, because we don't want to support
  26 * alarms, as that would be indistinguishable from timer interrupts.
  27 *
  28 * Further, generic code is really, really tied to a 1900 epoch.  This is
  29 * true in __get_rtc_time as well as the users of struct rtc_time e.g.
  30 * rtc_tm_to_time.  Thankfully all of the other epochs in use are later
  31 * than 1900, and so it's easy to adjust.
  32 */
  33
  34static unsigned long rtc_epoch;
  35
  36static int __init
  37specifiy_epoch(char *str)
  38{
  39        unsigned long epoch = simple_strtoul(str, NULL, 0);
  40        if (epoch < 1900)
  41                printk("Ignoring invalid user specified epoch %lu\n", epoch);
  42        else
  43                rtc_epoch = epoch;
  44        return 1;
  45}
  46__setup("epoch=", specifiy_epoch);
  47
  48static void __init
  49init_rtc_epoch(void)
  50{
  51        int epoch, year, ctrl;
  52
  53        if (rtc_epoch != 0) {
  54                /* The epoch was specified on the command-line.  */
  55                return;
  56        }
  57
  58        /* Detect the epoch in use on this computer.  */
  59        ctrl = CMOS_READ(RTC_CONTROL);
  60        year = CMOS_READ(RTC_YEAR);
  61        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
  62                year = bcd2bin(year);
  63
  64        /* PC-like is standard; used for year >= 70 */
  65        epoch = 1900;
  66        if (year < 20) {
  67                epoch = 2000;
  68        } else if (year >= 20 && year < 48) {
  69                /* NT epoch */
  70                epoch = 1980;
  71        } else if (year >= 48 && year < 70) {
  72                /* Digital UNIX epoch */
  73                epoch = 1952;
  74        }
  75        rtc_epoch = epoch;
  76
  77        printk(KERN_INFO "Using epoch %d for rtc year %d\n", epoch, year);
  78}
  79
  80static int
  81alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
  82{
  83        int ret = mc146818_get_time(tm);
  84
  85        if (ret < 0) {
  86                dev_err_ratelimited(dev, "unable to read current time\n");
  87                return ret;
  88        }
  89
  90        /* Adjust for non-default epochs.  It's easier to depend on the
  91           generic __get_rtc_time and adjust the epoch here than create
  92           a copy of __get_rtc_time with the edits we need.  */
  93        if (rtc_epoch != 1900) {
  94                int year = tm->tm_year;
  95                /* Undo the century adjustment made in __get_rtc_time.  */
  96                if (year >= 100)
  97                        year -= 100;
  98                year += rtc_epoch - 1900;
  99                /* Redo the century adjustment with the epoch in place.  */
 100                if (year <= 69)
 101                        year += 100;
 102                tm->tm_year = year;
 103        }
 104
 105        return 0;
 106}
 107
 108static int
 109alpha_rtc_set_time(struct device *dev, struct rtc_time *tm)
 110{
 111        struct rtc_time xtm;
 112
 113        if (rtc_epoch != 1900) {
 114                xtm = *tm;
 115                xtm.tm_year -= rtc_epoch - 1900;
 116                tm = &xtm;
 117        }
 118
 119        return mc146818_set_time(tm);
 120}
 121
 122static int
 123alpha_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 124{
 125        switch (cmd) {
 126        case RTC_EPOCH_READ:
 127                return put_user(rtc_epoch, (unsigned long __user *)arg);
 128        case RTC_EPOCH_SET:
 129                if (arg < 1900)
 130                        return -EINVAL;
 131                rtc_epoch = arg;
 132                return 0;
 133        default:
 134                return -ENOIOCTLCMD;
 135        }
 136}
 137
 138static const struct rtc_class_ops alpha_rtc_ops = {
 139        .read_time = alpha_rtc_read_time,
 140        .set_time = alpha_rtc_set_time,
 141        .ioctl = alpha_rtc_ioctl,
 142};
 143
 144/*
 145 * Similarly, except do the actual CMOS access on the boot cpu only.
 146 * This requires marshalling the data across an interprocessor call.
 147 */
 148
 149#if defined(CONFIG_SMP) && \
 150    (defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_MARVEL))
 151# define HAVE_REMOTE_RTC 1
 152
 153union remote_data {
 154        struct rtc_time *tm;
 155        long retval;
 156};
 157
 158static void
 159do_remote_read(void *data)
 160{
 161        union remote_data *x = data;
 162        x->retval = alpha_rtc_read_time(NULL, x->tm);
 163}
 164
 165static int
 166remote_read_time(struct device *dev, struct rtc_time *tm)
 167{
 168        union remote_data x;
 169        if (smp_processor_id() != boot_cpuid) {
 170                x.tm = tm;
 171                smp_call_function_single(boot_cpuid, do_remote_read, &x, 1);
 172                return x.retval;
 173        }
 174        return alpha_rtc_read_time(NULL, tm);
 175}
 176
 177static void
 178do_remote_set(void *data)
 179{
 180        union remote_data *x = data;
 181        x->retval = alpha_rtc_set_time(NULL, x->tm);
 182}
 183
 184static int
 185remote_set_time(struct device *dev, struct rtc_time *tm)
 186{
 187        union remote_data x;
 188        if (smp_processor_id() != boot_cpuid) {
 189                x.tm = tm;
 190                smp_call_function_single(boot_cpuid, do_remote_set, &x, 1);
 191                return x.retval;
 192        }
 193        return alpha_rtc_set_time(NULL, tm);
 194}
 195
 196static const struct rtc_class_ops remote_rtc_ops = {
 197        .read_time = remote_read_time,
 198        .set_time = remote_set_time,
 199        .ioctl = alpha_rtc_ioctl,
 200};
 201#endif
 202
 203static int __init
 204alpha_rtc_init(void)
 205{
 206        struct platform_device *pdev;
 207        struct rtc_device *rtc;
 208
 209        init_rtc_epoch();
 210
 211        pdev = platform_device_register_simple("rtc-alpha", -1, NULL, 0);
 212        rtc = devm_rtc_allocate_device(&pdev->dev);
 213        if (IS_ERR(rtc))
 214                return PTR_ERR(rtc);
 215
 216        platform_set_drvdata(pdev, rtc);
 217        rtc->ops = &alpha_rtc_ops;
 218
 219#ifdef HAVE_REMOTE_RTC
 220        if (alpha_mv.rtc_boot_cpu_only)
 221                rtc->ops = &remote_rtc_ops;
 222#endif
 223
 224        return devm_rtc_register_device(rtc);
 225}
 226device_initcall(alpha_rtc_init);
 227