/*
 * PCF8563 RTC
 *
 * From Phillips' datasheet:
 *
 * The PCF8563 is a CMOS real-time clock/calendar optimized for low power
 * consumption. A programmable clock output, interupt output and voltage
 * low detector are also provided. All address and data are transferred
 * serially via two-line bidirectional I2C-bus. Maximum bus speed is
 * 400 kbits/s. The built-in word address register is incremented
 * automatically after each written or read byte.
 *
 * Copyright (c) 2002-2003, Axis Communications AB
 * All rights reserved.
 *
 * Author: Tobias Anderberg <tobiasa@axis.com>.
 *
 */

#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/bcd.h>

#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/rtc.h>

#include "i2c.h"

#define PCF8563_MAJOR	121	/* Local major number. */
#define DEVICE_NAME	"rtc"	/* Name which is registered in /proc/devices. */
#define PCF8563_NAME	"PCF8563"
#define DRIVER_VERSION	"$Revision: 1.1 $"

/* Two simple wrapper macros, saves a few keystrokes. */
#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)

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

int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
int pcf8563_open(struct inode *, struct file *);
int pcf8563_release(struct inode *, struct file *);

static struct file_operations pcf8563_fops = {
	owner: THIS_MODULE,
	ioctl: pcf8563_ioctl,
	open: pcf8563_open,
	release: pcf8563_release,
};

unsigned char
pcf8563_readreg(int reg)
{
	unsigned char res = rtc_read(reg);

	/* The PCF8563 does not return 0 for unimplemented bits */
	switch (reg) {
		case RTC_SECONDS:
		case RTC_MINUTES:
			res &= 0x7F;
			break;
		case RTC_HOURS:
		case RTC_DAY_OF_MONTH:
			res &= 0x3F;
			break;
		case RTC_WEEKDAY:
			res &= 0x07;
			break;
		case RTC_MONTH:
			res &= 0x1F;
			break;
		case RTC_CONTROL1:
			res &= 0xA8;
			break;
		case RTC_CONTROL2:
			res &= 0x1F;
			break;
		case RTC_CLOCKOUT_FREQ:
		case RTC_TIMER_CONTROL:
			res &= 0x83;
			break;
	}
	return res;
}

void
pcf8563_writereg(int reg, unsigned char val)
{
#ifdef CONFIG_ETRAX_RTC_READONLY
	if (reg == RTC_CONTROL1 || (reg >= RTC_SECONDS && reg <= RTC_YEAR))
		return;
#endif

	rtc_write(reg, val);
}

void
get_rtc_time(struct rtc_time *tm)
{
	tm->tm_sec  = rtc_read(RTC_SECONDS);
	tm->tm_min  = rtc_read(RTC_MINUTES);
	tm->tm_hour = rtc_read(RTC_HOURS);
	tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH);
	tm->tm_wday = rtc_read(RTC_WEEKDAY);
	tm->tm_mon  = rtc_read(RTC_MONTH);
	tm->tm_year = rtc_read(RTC_YEAR);

	if (tm->tm_sec & 0x80)
		printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
		       "information is no longer guaranteed!\n", PCF8563_NAME);

	tm->tm_year  = BCD_TO_BIN(tm->tm_year) + ((tm->tm_mon & 0x80) ? 100 : 0);
	tm->tm_sec  &= 0x7F;
	tm->tm_min  &= 0x7F;
	tm->tm_hour &= 0x3F;
	tm->tm_mday &= 0x3F;
	tm->tm_wday &= 0x07; /* Not coded in BCD. */
	tm->tm_mon  &= 0x1F;

	BCD_TO_BIN(tm->tm_sec);
	BCD_TO_BIN(tm->tm_min);
	BCD_TO_BIN(tm->tm_hour);
	BCD_TO_BIN(tm->tm_mday);
	BCD_TO_BIN(tm->tm_mon);
	tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */
}

int __init
pcf8563_init(void)
{
	/* Initiate the i2c protocol. */
	i2c_init();

	/*
	 * First of all we need to reset the chip. This is done by
	 * clearing control1, control2 and clk freq and resetting
	 * all alarms.
	 */
	if (rtc_write(RTC_CONTROL1, 0x00) < 0)
		goto err;

	if (rtc_write(RTC_CONTROL2, 0x00) < 0)
		goto err;

	if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)
		goto err;

	if (rtc_write(RTC_TIMER_CONTROL, 0x03) < 0)
		goto err;

	/* Reset the alarms. */
	if (rtc_write(RTC_MINUTE_ALARM, 0x80) < 0)
		goto err;

	if (rtc_write(RTC_HOUR_ALARM, 0x80) < 0)
		goto err;

	if (rtc_write(RTC_DAY_ALARM, 0x80) < 0)
		goto err;

	if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0)
		goto err;

	if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
		printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n",
		       PCF8563_NAME, PCF8563_MAJOR);
		return -1;
	}

	printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);

	/* Check for low voltage, and warn about it.. */
	if (rtc_read(RTC_SECONDS) & 0x80)
		printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
		       "information is no longer guaranteed!\n", PCF8563_NAME);

	return 0;

err:
	printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
	return -1;
}

void __exit
pcf8563_exit(void)
{
	if (unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME) < 0) {
		printk(KERN_INFO "%s: Unable to unregister device.\n", PCF8563_NAME);
	}
}

/*
 * ioctl calls for this driver. Why return -ENOTTY upon error? Because
 * POSIX says so!
 */
int
pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
	/* Some sanity checks. */
	if (_IOC_TYPE(cmd) != RTC_MAGIC)
		return -ENOTTY;

	if (_IOC_NR(cmd) > RTC_MAX_IOCTL)
		return -ENOTTY;

	switch (cmd) {
		case RTC_RD_TIME:
		{
			struct rtc_time tm;

			memset(&tm, 0, sizeof (struct rtc_time));
			get_rtc_time(&tm);

			if (copy_to_user((struct rtc_time *) arg, &tm, sizeof tm)) {
				return -EFAULT;
			}

			return 0;
		}

		case RTC_SET_TIME:
		{
#ifdef CONFIG_ETRAX_RTC_READONLY
			return -EPERM;
#else
			int leap;
			int year;
			int century;
			struct rtc_time tm;

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

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

			/* Convert from struct tm to struct rtc_time. */
			tm.tm_year += 1900;
			tm.tm_mon += 1;

			/*
			 * Check if tm.tm_year is a leap year. A year is a leap
			 * year if it is divisible by 4 but not 100, except
			 * that years divisible by 400 _are_ leap years.
			 */
			year = tm.tm_year;
			leap = (tm.tm_mon == 2) && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);

			/* Perform some sanity checks. */
			if ((tm.tm_year < 1970) ||
			    (tm.tm_mon > 12) ||
			    (tm.tm_mday == 0) ||
			    (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
			    (tm.tm_wday >= 7) ||
			    (tm.tm_hour >= 24) ||
			    (tm.tm_min >= 60) ||
			    (tm.tm_sec >= 60))
				return -EINVAL;

			century = (tm.tm_year >= 2000) ? 0x80 : 0;
			tm.tm_year = tm.tm_year % 100;

			BIN_TO_BCD(tm.tm_year);
			BIN_TO_BCD(tm.tm_mday);
			BIN_TO_BCD(tm.tm_hour);
			BIN_TO_BCD(tm.tm_min);
			BIN_TO_BCD(tm.tm_sec);
			tm.tm_mon |= century;

			rtc_write(RTC_YEAR, tm.tm_year);
			rtc_write(RTC_MONTH, tm.tm_mon);
			rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */
			rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
			rtc_write(RTC_HOURS, tm.tm_hour);
			rtc_write(RTC_MINUTES, tm.tm_min);
			rtc_write(RTC_SECONDS, tm.tm_sec);

			return 0;
#endif /* !CONFIG_ETRAX_RTC_READONLY */
		}

		case RTC_VLOW_RD:
		{
			int vl_bit = 0;

			if (rtc_read(RTC_SECONDS) & 0x80) {
				vl_bit = 1;
				printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
				       "date/time information is no longer guaranteed!\n",
				       PCF8563_NAME);
			}
			if (copy_to_user((int *) arg, &vl_bit, sizeof(int)))
				return -EFAULT;

			return 0;
		}

		case RTC_VLOW_SET:
		{
			/* Clear the VL bit in the seconds register */
			int ret = rtc_read(RTC_SECONDS);

			rtc_write(RTC_SECONDS, (ret & 0x7F));

			return 0;
		}

		default:
			return -ENOTTY;
	}

	return 0;
}

int
pcf8563_open(struct inode *inode, struct file *filp)
{
	MOD_INC_USE_COUNT;
	return 0;
}

int
pcf8563_release(struct inode *inode, struct file *filp)
{
	MOD_DEC_USE_COUNT;
	return 0;
}

module_init(pcf8563_init);
module_exit(pcf8563_exit);
