1/*
2 * PCF8563 RTC
3 *
4 * From Phillips' datasheet:
5 *
6 * The PCF8563 is a CMOS real-time clock/calendar optimized for low power
7 * consumption. A programmable clock output, interupt output and voltage
8 * low detector are also provided. All address and data are transferred
9 * serially via two-line bidirectional I2C-bus. Maximum bus speed is
10 * 400 kbits/s. The built-in word address register is incremented
11 * automatically after each written or read bute.
12 *
13 * Copyright (c) 2002, Axis Communications AB
14 * All rights reserved.
15 *
16 * Author: Tobias Anderberg <tobiasa@axis.com>.
17 *
18 * $Id: pcf8563.c,v 1.1.1.1 2008/10/15 03:26:01 james26_jang Exp $
19 */
20
21#include <linux/config.h>
22#include <linux/version.h>
23#include <linux/module.h>
24#include <linux/kernel.h>
25#include <linux/types.h>
26#include <linux/sched.h>
27#include <linux/init.h>
28#include <linux/fs.h>
29#include <linux/ioctl.h>
30#include <linux/delay.h>
31
32#include <asm/uaccess.h>
33#include <asm/system.h>
34#include <asm/io.h>
35#include <asm/svinto.h>
36#include <asm/rtc.h>
37#include "i2c.h"
38
39#define PCF8563_MAJOR 121		/* Local major number. */
40#define DEVICE_NAME "rtc"		/* Name which is registered in /proc/devices. */
41#define PCF8563_NAME "PCF8563"
42#define DRIVER_VERSION "$Rev$"
43
44/* Two simple wrapper macros, saves a few keystrokes. */
45#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
46#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
47
48static const unsigned char days_in_month[] =
49	{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
50
51int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
52int pcf8563_open(struct inode *, struct file *);
53int pcf8563_release(struct inode *, struct file *);
54
55static struct file_operations pcf8563_fops = {
56	owner: THIS_MODULE,
57	ioctl: pcf8563_ioctl,
58	open: pcf8563_open,
59	release: pcf8563_release,
60};
61
62void
63get_rtc_time(struct rtc_time *tm)
64{
65	unsigned long flags;
66
67	tm->tm_sec = rtc_read(RTC_SECONDS);
68	tm->tm_min = rtc_read(RTC_MINUTES);
69	tm->tm_hour = rtc_read(RTC_HOURS);
70	tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH);
71	tm->tm_mon = rtc_read(RTC_MONTH);
72	tm->tm_year = rtc_read(RTC_YEAR);
73
74	if (tm->tm_sec & 0x80)
75		printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME);
76
77        tm->tm_year = BCD_TO_BIN(tm->tm_year) + ((tm->tm_mon & 0x80) ? 100 : 0);
78	tm->tm_sec &= 0x7f;
79	tm->tm_min &= 0x7f;
80	tm->tm_hour &= 0x3f;
81	tm->tm_mday &= 0x3f;
82	tm->tm_mon &= 0x1f;
83
84	BCD_TO_BIN(tm->tm_sec);
85	BCD_TO_BIN(tm->tm_min);
86	BCD_TO_BIN(tm->tm_hour);
87	BCD_TO_BIN(tm->tm_mday);
88	BCD_TO_BIN(tm->tm_mon);
89	tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */
90}
91
92int __init
93pcf8563_init(void)
94{
95	unsigned char ret;
96        struct rtc_time tm;
97
98	/*
99	 * First of all we need to reset the chip. This is done by
100	 * clearing control1, control2 and clk freq, clear the
101	 * Voltage Low bit, and resetting all alarms.
102	 */
103	if (rtc_write(RTC_CONTROL1, 0x00) < 0)
104		goto err;
105
106	if (rtc_write(RTC_CONTROL2, 0x00) < 0)
107		goto err;
108
109	if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)
110		goto err;
111
112	/* Clear the VL bit in the seconds register. */
113	ret = rtc_read(RTC_SECONDS);
114
115	if (rtc_write(RTC_SECONDS, (ret & 0x7f)) < 0)
116		goto err;
117
118	/* Reset the alarms. */
119	if (rtc_write(RTC_MINUTE_ALARM, 0x00) < 0)
120		goto err;
121
122	if (rtc_write(RTC_HOUR_ALARM, 0x00) < 0)
123		goto err;
124
125	if (rtc_write(RTC_DAY_ALARM, 0x00) < 0)
126		goto err;
127
128	if (rtc_write(RTC_WEEKDAY_ALARM, 0x00) < 0)
129		goto err;
130
131	if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
132		printk(KERN_INFO "%s: Unable to get major numer %d for RTC device.\n",
133		       PCF8563_NAME, PCF8563_MAJOR);
134		return -1;
135	}
136
137	printk(KERN_INFO "%s Real-Time Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
138
139	/* Check for low voltage, and warn about it.. */
140	if (rtc_read(RTC_SECONDS) & 0x80)
141		printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME);
142
143	return 0;
144
145err:
146	printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
147	return -1;
148}
149
150void __exit
151pcf8563_exit(void)
152{
153	if (unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME) < 0) {
154		printk(KERN_INFO "%s: Unable to unregister device.\n", PCF8563_NAME);
155	}
156}
157
158/*
159 * ioctl calls for this driver. Why return -ENOTTY upon error? Because
160 * POSIX says so!
161 */
162int
163pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
164{
165	/* Some sanity checks. */
166	if (_IOC_TYPE(cmd) != PCF8563_MAGIC)
167		return -ENOTTY;
168
169	if (_IOC_NR(cmd) > RTC_MAX_IOCTL)
170		return -ENOTTY;
171
172	switch (cmd) {
173		case RTC_RD_TIME:
174			{
175				struct rtc_time tm;
176
177				get_rtc_time(&tm);
178
179				if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) {
180					return -EFAULT;
181				}
182
183				return 0;
184			}
185			break;
186		case RTC_SET_TIME:
187			{
188				int leap;
189				int century;
190				unsigned long flags;
191				struct rtc_time tm;
192
193				if (!capable(CAP_SYS_TIME))
194					return -EPERM;
195
196				if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(struct rtc_time)))
197					return -EFAULT;
198
199				/* Convert from struct tm to struct rtc_time. */
200				tm.tm_year += 1900;
201				tm.tm_mon += 1;
202
203				leap = ((tm.tm_mon == 2) && ((tm.tm_year % 4) == 0)) ? 1 : 0;
204
205				/* Perform some sanity checks. */
206				if ((tm.tm_year < 1970) ||
207				    (tm.tm_mon > 12) ||
208				    (tm.tm_mday == 0) ||
209				    (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
210				    (tm.tm_hour >= 24) ||
211				    (tm.tm_min >= 60) ||
212				    (tm.tm_sec >= 60))
213					return -EINVAL;
214
215				century = (tm.tm_year >= 2000) ? 0x80 : 0;
216				tm.tm_year = tm.tm_year % 100;
217
218				BIN_TO_BCD(tm.tm_year);
219				BIN_TO_BCD(tm.tm_mday);
220				BIN_TO_BCD(tm.tm_hour);
221				BIN_TO_BCD(tm.tm_min);
222				BIN_TO_BCD(tm.tm_sec);
223				tm.tm_mon |= century;
224
225				rtc_write(RTC_YEAR, tm.tm_year);
226				rtc_write(RTC_MONTH, tm.tm_mon);
227				rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
228				rtc_write(RTC_HOURS, tm.tm_hour);
229				rtc_write(RTC_MINUTES, tm.tm_min);
230				rtc_write(RTC_SECONDS, tm.tm_sec);
231
232				return 0;
233			}
234			break;
235		default:
236				return -ENOTTY;
237	}
238
239	return 0;
240}
241
242int
243pcf8563_open(struct inode *inode, struct file *filp)
244{
245	MOD_INC_USE_COUNT;
246	return 0;
247}
248
249int
250pcf8563_release(struct inode *inode, struct file *filp)
251{
252	MOD_DEC_USE_COUNT;
253	return 0;
254}
255
256EXPORT_NO_SYMBOLS;
257module_init(pcf8563_init);
258module_exit(pcf8563_exit);
259