cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rtc.c (5031B)


      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);