/*
 *	Driver for the SGS-Thomson M48T35 Timekeeper RAM chip
 *
 *	Real Time Clock interface for Linux
 *
 *	TODO: Implement periodic interrupts.
 *
 *	Copyright (C) 2000 Silicon Graphics, Inc.
 *	Written by Ulf Carlsson (ulfc@engr.sgi.com)
 *
 *	Based on code written by Paul Gortmaker.
 *
 *	This driver allows use of the real time clock (built into
 *	nearly all computers) from user space. It exports the /dev/rtc
 *	interface supporting various ioctl() and also the /proc/rtc
 *	pseudo-file for status information.
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 *
 */

#define RTC_VERSION		"1.09b"

#include <linux/bcd.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/rtc.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>

#include <asm/m48t35.h>
#include <asm/sn/ioc3.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/sn/klconfig.h>
#include <asm/sn/sn0/ip27.h>
#include <asm/sn/sn0/hub.h>
#include <asm/sn/sn_private.h>

static int rtc_ioctl(struct inode *inode, struct file *file,
		     unsigned int cmd, unsigned long arg);

static int rtc_read_proc(char *page, char **start, off_t off,
                         int count, int *eof, void *data);

static void get_rtc_time(struct rtc_time *rtc_tm);

/*
 *	Bits in rtc_status. (6 bits of room for future expansion)
 */

#define RTC_IS_OPEN		0x01	/* means /dev/rtc is in use	*/
#define RTC_TIMER_ON		0x02	/* missed irq timer active	*/

static unsigned char rtc_status;	/* bitmapped status byte.	*/
static unsigned long rtc_freq;	/* Current periodic IRQ rate	*/
static struct m48t35_rtc *rtc;

/*
 *	If this driver ever becomes modularised, it will be really nice
 *	to make the epoch retain its value across module reload...
 */

static unsigned long epoch = 1970;	/* year corresponding to 0x00	*/

static const unsigned char days_in_mo[] =
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
		     unsigned long arg)
{

	struct rtc_time wtime;

	switch (cmd) {
	case RTC_RD_TIME:	/* Read the time/date from RTC	*/
	{
		get_rtc_time(&wtime);
		break;
	}
	case RTC_SET_TIME:	/* Set the RTC */
	{
		struct rtc_time rtc_tm;
		unsigned char mon, day, hrs, min, sec, leap_yr;
		unsigned int yrs;

		if (!capable(CAP_SYS_TIME))
			return -EACCES;

		if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
				   sizeof(struct rtc_time)))
			return -EFAULT;

		yrs = rtc_tm.tm_year + 1900;
		mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
		day = rtc_tm.tm_mday;
		hrs = rtc_tm.tm_hour;
		min = rtc_tm.tm_min;
		sec = rtc_tm.tm_sec;

		if (yrs < 1970)
			return -EINVAL;

		leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));

		if ((mon > 12) || (day == 0))
			return -EINVAL;

		if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
			return -EINVAL;

		if ((hrs >= 24) || (min >= 60) || (sec >= 60))
			return -EINVAL;

		if ((yrs -= epoch) > 255)    /* They are unsigned */
			return -EINVAL;

		if (yrs > 169)
			return -EINVAL;

		if (yrs >= 100)
			yrs -= 100;

		sec = BIN2BCD(sec);
		min = BIN2BCD(min);
		hrs = BIN2BCD(hrs);
		day = BIN2BCD(day);
		mon = BIN2BCD(mon);
		yrs = BIN2BCD(yrs);

		spin_lock_irq(&rtc_lock);
		rtc->control |= M48T35_RTC_SET;
		rtc->year = yrs;
		rtc->month = mon;
		rtc->date = day;
		rtc->hour = hrs;
		rtc->min = min;
		rtc->sec = sec;
		rtc->control &= ~M48T35_RTC_SET;
		spin_unlock_irq(&rtc_lock);

		return 0;
	}
	default:
		return -EINVAL;
	}
	return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
}

/*
 *	We enforce only one user at a time here with the open/close.
 *	Also clear the previous interrupt data on an open, and clean
 *	up things on a close.
 */

static int rtc_open(struct inode *inode, struct file *file)
{
	spin_lock_irq(&rtc_lock);

	if (rtc_status & RTC_IS_OPEN) {
		spin_unlock_irq(&rtc_lock);
		return -EBUSY;
	}

	rtc_status |= RTC_IS_OPEN;
	spin_unlock_irq(&rtc_lock);

	return 0;
}

static int rtc_release(struct inode *inode, struct file *file)
{
	/*
	 * Turn off all interrupts once the device is no longer
	 * in use, and clear the data.
	 */

	spin_lock_irq(&rtc_lock);
	rtc_status &= ~RTC_IS_OPEN;
	spin_unlock_irq(&rtc_lock);

	return 0;
}

/*
 *	The various file operations we support.
 */

static const struct file_operations rtc_fops = {
	.owner		= THIS_MODULE,
	.ioctl		= rtc_ioctl,
	.open		= rtc_open,
	.release	= rtc_release,
};

static struct miscdevice rtc_dev=
{
	RTC_MINOR,
	"rtc",
	&rtc_fops
};

static int __init rtc_init(void)
{
	rtc = (struct m48t35_rtc *)
	(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + IOC3_BYTEBUS_DEV0);

	printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION);
	if (misc_register(&rtc_dev)) {
		printk(KERN_ERR "rtc: cannot register misc device.\n");
		return -ENODEV;
	}
	if (!create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL)) {
		printk(KERN_ERR "rtc: cannot create /proc/rtc.\n");
		misc_deregister(&rtc_dev);
		return -ENOENT;
	}

	rtc_freq = 1024;

	return 0;
}

static void __exit rtc_exit (void)
{
	/* interrupts and timer disabled at this point by rtc_release */

	remove_proc_entry ("rtc", NULL);
	misc_deregister(&rtc_dev);
}

module_init(rtc_init);
module_exit(rtc_exit);

/*
 *	Info exported via "/proc/rtc".
 */

static int rtc_get_status(char *buf)
{
	char *p;
	struct rtc_time tm;

	/*
	 * Just emulate the standard /proc/rtc
	 */

	p = buf;

	get_rtc_time(&tm);

	/*
	 * There is no way to tell if the luser has the RTC set for local
	 * time or for Universal Standard Time (GMT). Probably local though.
	 */
	p += sprintf(p,
		     "rtc_time\t: %02d:%02d:%02d\n"
		     "rtc_date\t: %04d-%02d-%02d\n"
	 	     "rtc_epoch\t: %04lu\n"
		     "24hr\t\t: yes\n",
		     tm.tm_hour, tm.tm_min, tm.tm_sec,
		     tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);

	return  p - buf;
}

static int rtc_read_proc(char *page, char **start, off_t off,
                                 int count, int *eof, void *data)
{
        int len = rtc_get_status(page);
        if (len <= off+count) *eof = 1;
        *start = page + off;
        len -= off;
        if (len>count) len = count;
        if (len<0) len = 0;
        return len;
}

static void get_rtc_time(struct rtc_time *rtc_tm)
{
	/*
	 * Do we need to wait for the last update to finish?
	 */

	/*
	 * Only the values that we read from the RTC are set. We leave
	 * tm_wday, tm_yday and tm_isdst untouched. Even though the
	 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
	 * by the RTC when initially set to a non-zero value.
	 */
	spin_lock_irq(&rtc_lock);
	rtc->control |= M48T35_RTC_READ;
	rtc_tm->tm_sec = rtc->sec;
	rtc_tm->tm_min = rtc->min;
	rtc_tm->tm_hour = rtc->hour;
	rtc_tm->tm_mday = rtc->date;
	rtc_tm->tm_mon = rtc->month;
	rtc_tm->tm_year = rtc->year;
	rtc->control &= ~M48T35_RTC_READ;
	spin_unlock_irq(&rtc_lock);

	rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec);
	rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min);
	rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour);
	rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday);
	rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon);
	rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year);

	/*
	 * Account for differences between how the RTC uses the values
	 * and how they are defined in a struct rtc_time;
	 */
	if ((rtc_tm->tm_year += (epoch - 1900)) <= 69)
		rtc_tm->tm_year += 100;

	rtc_tm->tm_mon--;
}
