// SPDX-License-Identifier: GPL-2.0
/*
 *  linux/arch/alpha/kernel/rtc.c
 *
 *  Copyright (C) 1991, 1992, 1995, 1999, 2000  Linus Torvalds
 *
 * This file contains date handling.
 */
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mc146818rtc.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>

#include "proto.h"


/*
 * Support for the RTC device.
 *
 * We don't want to use the rtc-cmos driver, because we don't want to support
 * alarms, as that would be indistinguishable from timer interrupts.
 *
 * Further, generic code is really, really tied to a 1900 epoch.  This is
 * true in __get_rtc_time as well as the users of struct rtc_time e.g.
 * rtc_tm_to_time.  Thankfully all of the other epochs in use are later
 * than 1900, and so it's easy to adjust.
 */

static unsigned long rtc_epoch;

static int __init
specifiy_epoch(char *str)
{
	unsigned long epoch = simple_strtoul(str, NULL, 0);
	if (epoch < 1900)
		printk("Ignoring invalid user specified epoch %lu\n", epoch);
	else
		rtc_epoch = epoch;
	return 1;
}
__setup("epoch=", specifiy_epoch);

static void __init
init_rtc_epoch(void)
{
	int epoch, year, ctrl;

	if (rtc_epoch != 0) {
		/* The epoch was specified on the command-line.  */
		return;
	}

	/* Detect the epoch in use on this computer.  */
	ctrl = CMOS_READ(RTC_CONTROL);
	year = CMOS_READ(RTC_YEAR);
	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
		year = bcd2bin(year);

	/* PC-like is standard; used for year >= 70 */
	epoch = 1900;
	if (year < 20) {
		epoch = 2000;
	} else if (year >= 20 && year < 48) {
		/* NT epoch */
		epoch = 1980;
	} else if (year >= 48 && year < 70) {
		/* Digital UNIX epoch */
		epoch = 1952;
	}
	rtc_epoch = epoch;

	printk(KERN_INFO "Using epoch %d for rtc year %d\n", epoch, year);
}

static int
alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	int ret = mc146818_get_time(tm, 10);

	if (ret < 0) {
		dev_err_ratelimited(dev, "unable to read current time\n");
		return ret;
	}

	/* Adjust for non-default epochs.  It's easier to depend on the
	   generic __get_rtc_time and adjust the epoch here than create
	   a copy of __get_rtc_time with the edits we need.  */
	if (rtc_epoch != 1900) {
		int year = tm->tm_year;
		/* Undo the century adjustment made in __get_rtc_time.  */
		if (year >= 100)
			year -= 100;
		year += rtc_epoch - 1900;
		/* Redo the century adjustment with the epoch in place.  */
		if (year <= 69)
			year += 100;
		tm->tm_year = year;
	}

	return 0;
}

static int
alpha_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct rtc_time xtm;

	if (rtc_epoch != 1900) {
		xtm = *tm;
		xtm.tm_year -= rtc_epoch - 1900;
		tm = &xtm;
	}

	return mc146818_set_time(tm);
}

static int
alpha_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
	switch (cmd) {
	case RTC_EPOCH_READ:
		return put_user(rtc_epoch, (unsigned long __user *)arg);
	case RTC_EPOCH_SET:
		if (arg < 1900)
			return -EINVAL;
		rtc_epoch = arg;
		return 0;
	default:
		return -ENOIOCTLCMD;
	}
}

static const struct rtc_class_ops alpha_rtc_ops = {
	.read_time = alpha_rtc_read_time,
	.set_time = alpha_rtc_set_time,
	.ioctl = alpha_rtc_ioctl,
};

/*
 * Similarly, except do the actual CMOS access on the boot cpu only.  The
 * access polls for the RTC update cycle and takes rtc_lock, so run it in a
 * worker on that cpu rather than from an interprocessor interrupt.
 */

#if defined(CONFIG_SMP) && \
    (defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_MARVEL))
# define HAVE_REMOTE_RTC 1

static long
do_remote_read(void *data)
{
	return alpha_rtc_read_time(NULL, data);
}

static int
remote_read_time(struct device *dev, struct rtc_time *tm)
{
	if (smp_processor_id() != boot_cpuid)
		return work_on_cpu(boot_cpuid, do_remote_read, tm);
	return alpha_rtc_read_time(NULL, tm);
}

static long
do_remote_set(void *data)
{
	return alpha_rtc_set_time(NULL, data);
}

static int
remote_set_time(struct device *dev, struct rtc_time *tm)
{
	if (smp_processor_id() != boot_cpuid)
		return work_on_cpu(boot_cpuid, do_remote_set, tm);
	return alpha_rtc_set_time(NULL, tm);
}

static const struct rtc_class_ops remote_rtc_ops = {
	.read_time = remote_read_time,
	.set_time = remote_set_time,
	.ioctl = alpha_rtc_ioctl,
};
#endif

static int __init
alpha_rtc_init(void)
{
	struct platform_device *pdev;
	struct rtc_device *rtc;

	init_rtc_epoch();

	pdev = platform_device_register_simple("rtc-alpha", -1, NULL, 0);
	rtc = devm_rtc_allocate_device(&pdev->dev);
	if (IS_ERR(rtc))
		return PTR_ERR(rtc);

	platform_set_drvdata(pdev, rtc);
	rtc->ops = &alpha_rtc_ops;

#ifdef HAVE_REMOTE_RTC
	if (alpha_mv.rtc_boot_cpu_only)
		rtc->ops = &remote_rtc_ops;
#endif

	return devm_rtc_register_device(rtc);
}
device_initcall(alpha_rtc_init);
