public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] RTC subsystem
@ 2006-03-31 10:04 Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 01/10] RTC subsystem, DS1672 oscillator handling Alessandro Zummo
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm

 RTC subsystem. 

 - general cleanup of white spaces and error messages
 - new NEC VR41XX driver
 - fixed some sysfs error codes
 - oscillator handling in ds1672
--

 Best regards,

 Alessandro Zummo,
  Tower Technologies - Turin, Italy

  http://www.towertech.it

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/10] RTC subsystem, DS1672 oscillator handling
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 02/10] RTC subsystem, DS1672 cleanup Alessandro Zummo
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm, Kumar Gala

[-- Attachment #1: rtc-subsys-ds1672-fix-osc.patch --]
[-- Type: text/plain, Size: 3706 bytes --]

From: Kumar Gala <galak@kernel.crashing.org>

* Always enable the oscillator when we set the time
* If the oscillator is disable when we probe the RTC report back a warning
  to the user
* Added sysfs attribute to represent the state of the oscillator

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>

---
commit 3acc1a4629e70bce7493b5463f3c785379ae8b6b
tree 34463406603ac788697d8d228a2caf2c0ea40b3a
parent 329b10bb0feacb7fb9a41389313ff0a51ae56f2a
author Kumar Gala <galak@kernel.crashing.org> Tue, 28 Mar 2006 16:53:43 -0600
committer Kumar Gala <galak@kernel.crashing.org> Tue, 28 Mar 2006 16:53:43 -0600

 drivers/rtc/rtc-ds1672.c |   61 ++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 58 insertions(+), 3 deletions(-)

--- linux-rtc.orig/drivers/rtc/rtc-ds1672.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-ds1672.c	2006-03-29 02:16:01.000000000 +0200
@@ -23,6 +23,7 @@ I2C_CLIENT_INSMOD;
 
 #define DS1672_REG_CNT_BASE	0
 #define DS1672_REG_CONTROL	4
+#define DS1672_REG_CONTROL_EOSC	0x80
 #define DS1672_REG_TRICKLE	5
 
 
@@ -72,16 +73,17 @@ static int ds1672_get_datetime(struct i2
 static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
 {
 	int xfer;
-	unsigned char buf[5];
+	unsigned char buf[6];
 
 	buf[0] = DS1672_REG_CNT_BASE;
 	buf[1] = secs & 0x000000FF;
 	buf[2] = (secs & 0x0000FF00) >> 8;
 	buf[3] = (secs & 0x00FF0000) >> 16;
 	buf[4] = (secs & 0xFF000000) >> 24;
+	buf[5] = 0;	/* set control reg to enable counting */
 
-	xfer = i2c_master_send(client, buf, 5);
-	if (xfer != 5) {
+	xfer = i2c_master_send(client, buf, 6);
+	if (xfer != 6) {
 		dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer);
 		return -EIO;
 	}
@@ -120,6 +122,44 @@ static int ds1672_rtc_set_mmss(struct de
 	return ds1672_set_mmss(to_i2c_client(dev), secs);
 }
 
+static int ds1672_get_control(struct i2c_client *client, u8 *status)
+{
+	unsigned char addr = DS1672_REG_CONTROL;
+
+	struct i2c_msg msgs[] = {
+		{ client->addr, 0, 1, &addr },		/* setup read ptr */
+		{ client->addr, I2C_M_RD, 1, status },	/* read control */
+	};
+
+	/* read control register */
+	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	char *state = "enabled";
+	u8 control;
+	int err;
+
+	err = ds1672_get_control(client, &control);
+	if (err)
+		return err;
+
+	if (control & DS1672_REG_CONTROL_EOSC)
+		state = "disabled";
+
+	return sprintf(buf, "%s\n", state);
+}
+
+static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
+
 static struct rtc_class_ops ds1672_rtc_ops = {
 	.read_time	= ds1672_rtc_read_time,
 	.set_time	= ds1672_rtc_set_time,
@@ -162,6 +202,7 @@ static struct i2c_driver ds1672_driver =
 static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
 {
 	int err = 0;
+	u8 control;
 	struct i2c_client *client;
 	struct rtc_device *rtc;
 
@@ -202,6 +243,20 @@ static int ds1672_probe(struct i2c_adapt
 
 	i2c_set_clientdata(client, rtc);
 
+	/* read control register */
+	err = ds1672_get_control(client, &control);
+	if (err) {
+		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+		goto exit_detach;
+	}
+
+	if (control & DS1672_REG_CONTROL_EOSC)
+		dev_warn(&client->dev, "Oscillator not enabled. "
+					"Set time to enable.\n");
+
+	/* Register sysfs hooks */
+	device_create_file(&client->dev, &dev_attr_control);
+
 	return 0;
 
 exit_detach:

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 02/10] RTC subsystem, DS1672 cleanup
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 01/10] RTC subsystem, DS1672 oscillator handling Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 03/10] RTC subsystem, X1205 sysfs cleanup Alessandro Zummo
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm, Kumar Gala

[-- Attachment #1: rtc-subsys-ds1672-tidy.patch --]
[-- Type: text/plain, Size: 3561 bytes --]

 - removed a duplicate error message
 - bumped driver version
 - removed some debugging messages in excess
 - refined the formatting
 - adjusted copyright notice


Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Cc: Kumar Gala <galak@kernel.crashing.org>

---
 drivers/rtc/rtc-ds1672.c |   29 ++++++++++-------------------
 1 file changed, 10 insertions(+), 19 deletions(-)

--- linux-rtc.orig/drivers/rtc/rtc-ds1672.c	2006-03-29 02:16:01.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-ds1672.c	2006-03-29 02:29:43.000000000 +0200
@@ -1,6 +1,8 @@
 /*
  * An rtc/i2c driver for the Dallas DS1672
- * Copyright 2005 Alessandro Zummo
+ * Copyright 2005-06 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,7 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/rtc.h>
 
-#define DRV_VERSION "0.2"
+#define DRV_VERSION "0.3"
 
 /* Addresses to scan: none. This chip cannot be detected. */
 static unsigned short normal_i2c[] = { I2C_CLIENT_END };
@@ -23,9 +25,9 @@ I2C_CLIENT_INSMOD;
 
 #define DS1672_REG_CNT_BASE	0
 #define DS1672_REG_CONTROL	4
-#define DS1672_REG_CONTROL_EOSC	0x80
 #define DS1672_REG_TRICKLE	5
 
+#define DS1672_REG_CONTROL_EOSC	0x80
 
 /* Prototypes */
 static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind);
@@ -54,8 +56,7 @@ static int ds1672_get_datetime(struct i2
 
 	dev_dbg(&client->dev,
 		"%s: raw read data - counters=%02x,%02x,%02x,%02x\n"
-		__FUNCTION__,
-		buf[0], buf[1], buf[2], buf[3]);
+		__FUNCTION__, buf[0], buf[1], buf[2], buf[3]);
 
 	time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
 
@@ -63,8 +64,7 @@ static int ds1672_get_datetime(struct i2
 
 	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
 		"mday=%d, mon=%d, year=%d, wday=%d\n",
-		__FUNCTION__,
-		tm->tm_sec, tm->tm_min, tm->tm_hour,
+		__FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour,
 		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
 	return 0;
@@ -144,7 +144,6 @@ static int ds1672_get_control(struct i2c
 static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	char *state = "enabled";
 	u8 control;
 	int err;
 
@@ -152,12 +151,9 @@ static ssize_t show_control(struct devic
 	if (err)
 		return err;
 
-	if (control & DS1672_REG_CONTROL_EOSC)
-		state = "disabled";
-
-	return sprintf(buf, "%s\n", state);
+	return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC)
+					? "disabled" : "enabled");
 }
-
 static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
 
 static struct rtc_class_ops ds1672_rtc_ops = {
@@ -168,7 +164,6 @@ static struct rtc_class_ops ds1672_rtc_o
 
 static int ds1672_attach(struct i2c_adapter *adapter)
 {
-	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 	return i2c_probe(adapter, &addr_data, ds1672_probe);
 }
 
@@ -177,8 +172,6 @@ static int ds1672_detach(struct i2c_clie
 	int err;
 	struct rtc_device *rtc = i2c_get_clientdata(client);
 
-	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
  	if (rtc)
 		rtc_device_unregister(rtc);
 
@@ -245,10 +238,8 @@ static int ds1672_probe(struct i2c_adapt
 
 	/* read control register */
 	err = ds1672_get_control(client, &control);
-	if (err) {
-		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+	if (err)
 		goto exit_detach;
-	}
 
 	if (control & DS1672_REG_CONTROL_EOSC)
 		dev_warn(&client->dev, "Oscillator not enabled. "

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 03/10] RTC subsystem, X1205 sysfs cleanup
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 01/10] RTC subsystem, DS1672 oscillator handling Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 02/10] RTC subsystem, DS1672 cleanup Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 04/10] RTC subsystem, whitespaces and error messages cleanup Alessandro Zummo
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm

[-- Attachment #1: rtc-subsys-x1205-fix-sysfs.patch --]
[-- Type: text/plain, Size: 1604 bytes --]

 fixed sysfs show() return code

Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>

---
 drivers/rtc/rtc-x1205.c |   22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

--- linux-rtc.orig/drivers/rtc/rtc-x1205.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-x1205.c	2006-03-29 02:33:57.000000000 +0200
@@ -19,7 +19,7 @@
 #include <linux/rtc.h>
 #include <linux/delay.h>
 
-#define DRV_VERSION "1.0.6"
+#define DRV_VERSION "1.0.7"
 
 /* Addresses to scan: none. This chip is located at
  * 0x6f and uses a two bytes register addressing.
@@ -473,24 +473,26 @@ static struct rtc_class_ops x1205_rtc_op
 static ssize_t x1205_sysfs_show_atrim(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	int atrim;
+	int err, atrim;
 
-	if (x1205_get_atrim(to_i2c_client(dev), &atrim) == 0)
-		return sprintf(buf, "%d.%02d pF\n",
-			atrim / 1000, atrim % 1000);
-	return 0;
+	err = x1205_get_atrim(to_i2c_client(dev), &atrim);
+	if (err)
+		return err;
+
+	return sprintf(buf, "%d.%02d pF\n", atrim / 1000, atrim % 1000);
 }
 static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL);
 
 static ssize_t x1205_sysfs_show_dtrim(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	int dtrim;
+	int err, dtrim;
 
-	if (x1205_get_dtrim(to_i2c_client(dev), &dtrim) == 0)
-		return sprintf(buf, "%d ppm\n", dtrim);
+	err = x1205_get_dtrim(to_i2c_client(dev), &dtrim);
+	if (err)
+		return err;
 
-	return 0;
+	return sprintf(buf, "%d ppm\n", dtrim);
 }
 static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL);
 

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 04/10] RTC subsystem, whitespaces and error messages cleanup
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
                   ` (2 preceding siblings ...)
  2006-03-31 10:04 ` [PATCH 03/10] RTC subsystem, X1205 sysfs cleanup Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 05/10] RTC subsystem, fix proc output Alessandro Zummo
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm

[-- Attachment #1: rtc-subsys-tidy.patch --]
[-- Type: text/plain, Size: 2355 bytes --]

 - fixed whitespaces
 - removed some debugging in excess

Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>

---
 drivers/rtc/rtc-m48t86.c  |    2 +-
 drivers/rtc/rtc-pcf8563.c |    2 --
 drivers/rtc/rtc-rs5c372.c |    3 ---
 drivers/rtc/rtc-x1205.c   |    3 ---
 4 files changed, 1 insertion(+), 9 deletions(-)

--- linux-rtc.orig/drivers/rtc/rtc-x1205.c	2006-03-29 02:33:58.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-x1205.c	2006-03-29 03:12:07.000000000 +0200
@@ -498,7 +498,6 @@ static DEVICE_ATTR(dtrim, S_IRUGO, x1205
 
 static int x1205_attach(struct i2c_adapter *adapter)
 {
-	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 	return i2c_probe(adapter, &addr_data, x1205_probe);
 }
 
@@ -587,8 +586,6 @@ static int x1205_detach(struct i2c_clien
 	int err;
 	struct rtc_device *rtc = i2c_get_clientdata(client);
 
-	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
  	if (rtc)
 		rtc_device_unregister(rtc);
 
--- linux-rtc.orig/drivers/rtc/rtc-rs5c372.c	2006-03-29 02:47:17.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-rs5c372.c	2006-03-29 03:12:07.000000000 +0200
@@ -193,7 +193,6 @@ static DEVICE_ATTR(osc, S_IRUGO, rs5c372
 
 static int rs5c372_attach(struct i2c_adapter *adapter)
 {
-	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 	return i2c_probe(adapter, &addr_data, rs5c372_probe);
 }
 
@@ -260,8 +259,6 @@ static int rs5c372_detach(struct i2c_cli
 	int err;
 	struct rtc_device *rtc = i2c_get_clientdata(client);
 
-	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
 	if (rtc)
 		rtc_device_unregister(rtc);
 
--- linux-rtc.orig/drivers/rtc/rtc-pcf8563.c	2006-03-29 02:47:17.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-pcf8563.c	2006-03-29 03:12:07.000000000 +0200
@@ -321,8 +321,6 @@ static int pcf8563_detach(struct i2c_cli
 	int err;
 	struct rtc_device *rtc = i2c_get_clientdata(client);
 
-	dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
 	if (rtc)
 		rtc_device_unregister(rtc);
 
--- linux-rtc.orig/drivers/rtc/rtc-m48t86.c	2006-03-29 02:47:17.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-m48t86.c	2006-03-29 03:12:07.000000000 +0200
@@ -23,7 +23,7 @@
 #define M48T86_REG_SECALRM	0x01
 #define M48T86_REG_MIN		0x02
 #define M48T86_REG_MINALRM	0x03
-#define M48T86_REG_HOUR	0x04
+#define M48T86_REG_HOUR		0x04
 #define M48T86_REG_HOURALRM	0x05
 #define M48T86_REG_DOW		0x06 /* 1 = sunday */
 #define M48T86_REG_DOM		0x07

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 05/10] RTC subsystem, fix proc output
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
                   ` (3 preceding siblings ...)
  2006-03-31 10:04 ` [PATCH 04/10] RTC subsystem, whitespaces and error messages cleanup Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 06/10] RTC subsystem, RS5C372 sysfs fix Alessandro Zummo
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm, Lennert Buytenhek

[-- Attachment #1: rtc-subsys-fix-proc-24hr.patch --]
[-- Type: text/plain, Size: 3690 bytes --]

 Moved the "24hr: yes" proc output from drivers to rtc
 proc code. This is required because the time value
 in the proc output is always in 24hr mode regardless
 of the driver.

Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>

---
 drivers/rtc/rtc-ep93xx.c  |    1 -
 drivers/rtc/rtc-m48t86.c  |    3 ---
 drivers/rtc/rtc-pcf8563.c |    7 -------
 drivers/rtc/rtc-proc.c    |    2 ++
 drivers/rtc/rtc-rs5c372.c |    5 ++---
 drivers/rtc/rtc-test.c    |    1 -
 drivers/rtc/rtc-x1205.c   |    2 --
 7 files changed, 4 insertions(+), 17 deletions(-)

--- linux-rtc.orig/drivers/rtc/rtc-ep93xx.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-ep93xx.c	2006-03-29 02:40:12.000000000 +0200
@@ -67,7 +67,6 @@ static int ep93xx_rtc_proc(struct device
 
 	ep93xx_get_swcomp(dev, &preload, &delete);
 
-	seq_printf(seq, "24hr\t\t: yes\n");
 	seq_printf(seq, "preload\t\t: %d\n", preload);
 	seq_printf(seq, "delete\t\t: %d\n", delete);
 
--- linux-rtc.orig/drivers/rtc/rtc-pcf8563.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-pcf8563.c	2006-03-29 02:40:27.000000000 +0200
@@ -227,14 +227,7 @@ static int pcf8563_rtc_set_time(struct d
 	return pcf8563_set_datetime(to_i2c_client(dev), tm);
 }
 
-static int pcf8563_rtc_proc(struct device *dev, struct seq_file *seq)
-{
-	seq_printf(seq, "24hr\t\t: yes\n");
-	return 0;
-}
-
 static struct rtc_class_ops pcf8563_rtc_ops = {
-	.proc		= pcf8563_rtc_proc,
 	.read_time	= pcf8563_rtc_read_time,
 	.set_time	= pcf8563_rtc_set_time,
 };
--- linux-rtc.orig/drivers/rtc/rtc-proc.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-proc.c	2006-03-29 02:39:56.000000000 +0200
@@ -71,6 +71,8 @@ static int rtc_proc_show(struct seq_file
 				alrm.pending ? "yes" : "no");
 	}
 
+	seq_printf(seq, "24hr\t\t: yes\n");
+
 	if (ops->proc)
 		ops->proc(class_dev->dev, seq);
 
--- linux-rtc.orig/drivers/rtc/rtc-rs5c372.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-rs5c372.c	2006-03-29 02:46:57.000000000 +0200
@@ -151,9 +151,8 @@ static int rs5c372_rtc_proc(struct devic
 {
 	int err, osc, trim;
 
-	seq_printf(seq, "24hr\t\t: yes\n");
-
-	if ((err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim)) == 0) {
+	err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim);
+	if (err == 0) {
 		seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000);
 		seq_printf(seq, "trim\t: %d\n", trim);
 	}
--- linux-rtc.orig/drivers/rtc/rtc-x1205.c	2006-03-29 02:38:39.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-x1205.c	2006-03-29 02:39:46.000000000 +0200
@@ -451,8 +451,6 @@ static int x1205_rtc_proc(struct device 
 {
 	int err, dtrim, atrim;
 
-	seq_printf(seq, "24hr\t\t: yes\n");
-
 	if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0)
 		seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim);
 
--- linux-rtc.orig/drivers/rtc/rtc-m48t86.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-m48t86.c	2006-03-29 02:42:37.000000000 +0200
@@ -127,9 +127,6 @@ static int m48t86_rtc_proc(struct device
 
 	reg = ops->readb(M48T86_REG_B);
 
-	seq_printf(seq, "24hr\t\t: %s\n",
-		 (reg & M48T86_REG_B_H24) ? "yes" : "no");
-
 	seq_printf(seq, "mode\t\t: %s\n",
 		 (reg & M48T86_REG_B_DM) ? "binary" : "bcd");
 
--- linux-rtc.orig/drivers/rtc/rtc-test.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-test.c	2006-03-29 02:42:54.000000000 +0200
@@ -49,7 +49,6 @@ static int test_rtc_proc(struct device *
 {
 	struct platform_device *plat_dev = to_platform_device(dev);
 
-	seq_printf(seq, "24hr\t\t: yes\n");
 	seq_printf(seq, "test\t\t: yes\n");
 	seq_printf(seq, "id\t\t: %d\n", plat_dev->id);
 

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 06/10] RTC subsystem, RS5C372 sysfs fix
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
                   ` (4 preceding siblings ...)
  2006-03-31 10:04 ` [PATCH 05/10] RTC subsystem, fix proc output Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 07/10] RTC subsystem, compact error messages Alessandro Zummo
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm

[-- Attachment #1: rtc-subsys-rs5c372-fix-sysfs.patch --]
[-- Type: text/plain, Size: 1372 bytes --]

 fixed sysfs show() return code

Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>

---
 drivers/rtc/rtc-rs5c372.c |   18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

--- linux-rtc.orig/drivers/rtc/rtc-rs5c372.c	2006-03-29 02:41:04.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-rs5c372.c	2006-03-29 02:46:40.000000000 +0200
@@ -169,24 +169,26 @@ static struct rtc_class_ops rs5c372_rtc_
 static ssize_t rs5c372_sysfs_show_trim(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	int trim;
+	int err, trim;
 
-	if (rs5c372_get_trim(to_i2c_client(dev), NULL, &trim) == 0)
-		return sprintf(buf, "0x%2x\n", trim);
+	err = rs5c372_get_trim(to_i2c_client(dev), NULL, &trim);
+	if (err)
+		return err;
 
-	return 0;
+	return sprintf(buf, "0x%2x\n", trim);
 }
 static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL);
 
 static ssize_t rs5c372_sysfs_show_osc(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	int osc;
+	int err, osc;
 
-	if (rs5c372_get_trim(to_i2c_client(dev), &osc, NULL) == 0)
-		return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000);
+	err = rs5c372_get_trim(to_i2c_client(dev), &osc, NULL);
+	if (err)
+		return err;
 
-	return 0;
+	return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000);
 }
 static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL);
 

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 07/10] RTC subsystem, compact error messages
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
                   ` (5 preceding siblings ...)
  2006-03-31 10:04 ` [PATCH 06/10] RTC subsystem, RS5C372 sysfs fix Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
  2006-03-31 10:04 ` [PATCH 08/10] RTC subsystem, SA1100 cleanup Alessandro Zummo
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm, Lennert Buytenhek

[-- Attachment #1: rtc-subsys-compact-err-message.patch --]
[-- Type: text/plain, Size: 3979 bytes --]

 - move registration error message from drivers
 to core.

Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>

---
 drivers/rtc/class.c       |    2 ++
 drivers/rtc/rtc-ds1672.c  |    2 --
 drivers/rtc/rtc-ep93xx.c  |    1 -
 drivers/rtc/rtc-m48t86.c  |    4 +---
 drivers/rtc/rtc-pcf8563.c |    2 --
 drivers/rtc/rtc-rs5c372.c |    2 --
 drivers/rtc/rtc-sa1100.c  |    1 -
 drivers/rtc/rtc-test.c    |    2 --
 drivers/rtc/rtc-x1205.c   |    2 --
 9 files changed, 3 insertions(+), 15 deletions(-)

--- linux-rtc.orig/drivers/rtc/class.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/class.c	2006-03-29 02:55:47.000000000 +0200
@@ -96,6 +96,8 @@ exit_idr:
 	idr_remove(&rtc_idr, id);
 
 exit:
+	dev_err(dev, "rtc core: unable to register %s, err = %d\n",
+			name, err);
 	return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(rtc_device_register);
--- linux-rtc.orig/drivers/rtc/rtc-x1205.c	2006-03-29 02:50:57.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-x1205.c	2006-03-29 02:53:01.000000000 +0200
@@ -544,8 +544,6 @@ static int x1205_probe(struct i2c_adapte
 
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&client->dev,
-			"unable to register the class device\n");
 		goto exit_detach;
 	}
 
--- linux-rtc.orig/drivers/rtc/rtc-ds1672.c	2006-03-29 02:29:43.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-ds1672.c	2006-03-29 02:57:10.000000000 +0200
@@ -229,8 +229,6 @@ static int ds1672_probe(struct i2c_adapt
 
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&client->dev,
-			"unable to register the class device\n");
 		goto exit_detach;
 	}
 
--- linux-rtc.orig/drivers/rtc/rtc-m48t86.c	2006-03-29 02:50:57.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-m48t86.c	2006-03-29 02:56:48.000000000 +0200
@@ -151,10 +151,8 @@ static int __devinit m48t86_rtc_probe(st
 	struct rtc_device *rtc = rtc_device_register("m48t86",
 				&dev->dev, &m48t86_rtc_ops, THIS_MODULE);
 
-	if (IS_ERR(rtc)) {
-		dev_err(&dev->dev, "unable to register\n");
+	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
-	}
 
 	platform_set_drvdata(dev, rtc);
 
--- linux-rtc.orig/drivers/rtc/rtc-pcf8563.c	2006-03-29 02:50:57.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-pcf8563.c	2006-03-29 02:57:01.000000000 +0200
@@ -290,8 +290,6 @@ static int pcf8563_probe(struct i2c_adap
 
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&client->dev,
-			"unable to register the class device\n");
 		goto exit_detach;
 	}
 
--- linux-rtc.orig/drivers/rtc/rtc-test.c	2006-03-29 02:50:57.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-test.c	2006-03-29 02:56:29.000000000 +0200
@@ -119,8 +119,6 @@ static int test_probe(struct platform_de
 						&test_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&plat_dev->dev,
-			"unable to register the class device\n");
 		return err;
 	}
 	device_create_file(&plat_dev->dev, &dev_attr_irq);
--- linux-rtc.orig/drivers/rtc/rtc-ep93xx.c	2006-03-29 02:50:57.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-ep93xx.c	2006-03-29 02:58:03.000000000 +0200
@@ -109,7 +109,6 @@ static int __devinit ep93xx_rtc_probe(st
 				&dev->dev, &ep93xx_rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rtc)) {
-		dev_err(&dev->dev, "unable to register\n");
 		return PTR_ERR(rtc);
 	}
 
--- linux-rtc.orig/drivers/rtc/rtc-sa1100.c	2006-03-29 02:14:50.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-sa1100.c	2006-03-29 02:57:38.000000000 +0200
@@ -341,7 +341,6 @@ static int sa1100_rtc_probe(struct platf
 				THIS_MODULE);
 
 	if (IS_ERR(rtc)) {
-		dev_err(&pdev->dev, "Unable to register the RTC device\n");
 		return PTR_ERR(rtc);
 	}
 
--- linux-rtc.orig/drivers/rtc/rtc-rs5c372.c	2006-03-29 02:50:58.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-rs5c372.c	2006-03-29 02:59:15.000000000 +0200
@@ -233,8 +233,6 @@ static int rs5c372_probe(struct i2c_adap
 
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		dev_err(&client->dev,
-			"unable to register the class device\n");
 		goto exit_detach;
 	}
 

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 08/10] RTC subsystem, SA1100 cleanup
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
                   ` (6 preceding siblings ...)
  2006-03-31 10:04 ` [PATCH 07/10] RTC subsystem, compact error messages Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
  2006-04-02 18:43   ` Pavel Machek
  2006-03-31 10:04 ` [PATCH 09/10] RTC subsystem, VR41XX driver Alessandro Zummo
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm, Richard Purdie

[-- Attachment #1: rtc-subsys-sa1100-tidy.patch --]
[-- Type: text/plain, Size: 1953 bytes --]

 - converted printks to dev_xxx
 - removed messages in excess

Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Cc: Richard Purdie <rpurdie@rpsys.net>
---
 drivers/rtc/rtc-sa1100.c |   13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

--- linux-rtc.orig/drivers/rtc/rtc-sa1100.c	2006-03-29 03:15:58.000000000 +0200
+++ linux-rtc/drivers/rtc/rtc-sa1100.c	2006-03-29 03:15:58.000000000 +0200
@@ -160,19 +160,19 @@ static int sa1100_rtc_open(struct device
 	ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT,
 				"rtc 1Hz", dev);
 	if (ret) {
-		printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz);
+		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
 		goto fail_ui;
 	}
 	ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT,
 				"rtc Alrm", dev);
 	if (ret) {
-		printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm);
+		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
 		goto fail_ai;
 	}
 	ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT,
 				"rtc timer", dev);
 	if (ret) {
-		printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1);
+		dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
 		goto fail_pi;
 	}
 	return 0;
@@ -332,7 +332,7 @@ static int sa1100_rtc_probe(struct platf
 	 */
 	if (RTTR == 0) {
 		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-		printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n");
+		dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
 		/* The current RTC value probably doesn't make sense either */
 		RCNR = 0;
 	}
@@ -340,14 +340,11 @@ static int sa1100_rtc_probe(struct platf
 	rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
 				THIS_MODULE);
 
-	if (IS_ERR(rtc)) {
+	if (IS_ERR(rtc))
 		return PTR_ERR(rtc);
-	}
 
 	platform_set_drvdata(pdev, rtc);
 
-	dev_info(&pdev->dev, "SA11xx/PXA2xx RTC Registered\n");
-
 	return 0;
 }
 

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 09/10] RTC subsystem, VR41XX driver
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
                   ` (7 preceding siblings ...)
  2006-03-31 10:04 ` [PATCH 08/10] RTC subsystem, SA1100 cleanup Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
  2006-04-01 23:20   ` Andrew Morton
  2006-03-31 10:04 ` [PATCH 10/10] RTC subsystem, VR41XX cleanup Alessandro Zummo
       [not found] ` <Pine.LNX.4.63.0605030826290.1846@pcgl.dsa-ac.de>
  10 siblings, 1 reply; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm, Yoichi Yuasa

[-- Attachment #1: rtc-subsys-drv-vr41xx.patch --]
[-- Type: text/plain, Size: 31323 bytes --]

From: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>

Hi,

This patch updates VR4100 series RTC driver.

* This driver supports new RTC subsystem.
* Simple set time/read time test worked fine.

Yoichi

Signed-off-by: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>

diff -pruN -X dontdiff mm2-orig/drivers/char/Kconfig mm2/drivers/char/Kconfig
--- mm2-orig/drivers/char/Kconfig	2006-03-31 12:54:47.327851500 +0900
+++ mm2/drivers/char/Kconfig	2006-03-29 11:47:27.440976000 +0900
@@ -788,10 +788,6 @@ config S3C2410_RTC
 	  Samsung S3C2410. This can provide periodic interrupt rates
 	  from 1Hz to 64Hz for user programs, and wakeup from Alarm.
 
-config RTC_VR41XX
-	tristate "NEC VR4100 series Real Time Clock Support"
-	depends on CPU_VR41XX
-
 config COBALT_LCD
 	bool "Support for Cobalt LCD"
 	depends on MIPS_COBALT
diff -pruN -X dontdiff mm2-orig/drivers/char/Makefile mm2/drivers/char/Makefile
--- mm2-orig/drivers/char/Makefile	2006-03-31 12:54:47.327851500 +0900
+++ mm2/drivers/char/Makefile	2006-03-29 11:48:15.283966000 +0900
@@ -65,7 +65,6 @@ obj-$(CONFIG_SGI_DS1286)	+= ds1286.o
 obj-$(CONFIG_SGI_IP27_RTC)	+= ip27-rtc.o
 obj-$(CONFIG_DS1302)		+= ds1302.o
 obj-$(CONFIG_S3C2410_RTC)	+= s3c2410-rtc.o
-obj-$(CONFIG_RTC_VR41XX)	+= vr41xx_rtc.o
 ifeq ($(CONFIG_GENERIC_NVRAM),y)
   obj-$(CONFIG_NVRAM)	+= generic_nvram.o
 else
diff -pruN -X dontdiff mm2-orig/drivers/char/vr41xx_rtc.c mm2/drivers/char/vr41xx_rtc.c
--- mm2-orig/drivers/char/vr41xx_rtc.c	2006-03-31 12:54:51.296099500 +0900
+++ mm2/drivers/char/vr41xx_rtc.c	1970-01-01 09:00:00.000000000 +0900
@@ -1,717 +0,0 @@
-/*
- *  Driver for NEC VR4100 series  Real Time Clock unit.
- *
- *  Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
- *
- *  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.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/platform_device.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/mc146818rtc.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/rtc.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-
-#include <asm/div64.h>
-#include <asm/io.h>
-#include <asm/time.h>
-#include <asm/uaccess.h>
-#include <asm/vr41xx/vr41xx.h>
-
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
-MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
-MODULE_LICENSE("GPL");
-
-#define RTC1_TYPE1_START	0x0b0000c0UL
-#define RTC1_TYPE1_END		0x0b0000dfUL
-#define RTC2_TYPE1_START	0x0b0001c0UL
-#define RTC2_TYPE1_END		0x0b0001dfUL
-
-#define RTC1_TYPE2_START	0x0f000100UL
-#define RTC1_TYPE2_END		0x0f00011fUL
-#define RTC2_TYPE2_START	0x0f000120UL
-#define RTC2_TYPE2_END		0x0f00013fUL
-
-#define RTC1_SIZE		0x20
-#define RTC2_SIZE		0x20
-
-/* RTC 1 registers */
-#define ETIMELREG		0x00
-#define ETIMEMREG		0x02
-#define ETIMEHREG		0x04
-/* RFU */
-#define ECMPLREG		0x08
-#define ECMPMREG		0x0a
-#define ECMPHREG		0x0c
-/* RFU */
-#define RTCL1LREG		0x10
-#define RTCL1HREG		0x12
-#define RTCL1CNTLREG		0x14
-#define RTCL1CNTHREG		0x16
-#define RTCL2LREG		0x18
-#define RTCL2HREG		0x1a
-#define RTCL2CNTLREG		0x1c
-#define RTCL2CNTHREG		0x1e
-
-/* RTC 2 registers */
-#define TCLKLREG		0x00
-#define TCLKHREG		0x02
-#define TCLKCNTLREG		0x04
-#define TCLKCNTHREG		0x06
-/* RFU */
-#define RTCINTREG		0x1e
- #define TCLOCK_INT		0x08
- #define RTCLONG2_INT		0x04
- #define RTCLONG1_INT		0x02
- #define ELAPSEDTIME_INT	0x01
-
-#define RTC_FREQUENCY		32768
-#define MAX_PERIODIC_RATE	6553
-#define MAX_USER_PERIODIC_RATE	64
-
-static void __iomem *rtc1_base;
-static void __iomem *rtc2_base;
-
-#define rtc1_read(offset)		readw(rtc1_base + (offset))
-#define rtc1_write(offset, value)	writew((value), rtc1_base + (offset))
-
-#define rtc2_read(offset)		readw(rtc2_base + (offset))
-#define rtc2_write(offset, value)	writew((value), rtc2_base + (offset))
-
-static unsigned long epoch = 1970;	/* Jan 1 1970 00:00:00 */
-
-static spinlock_t rtc_task_lock;
-static wait_queue_head_t rtc_wait;
-static unsigned long rtc_irq_data;
-static struct fasync_struct *rtc_async_queue;
-static rtc_task_t *rtc_callback;
-static char rtc_name[] = "RTC";
-static unsigned long periodic_frequency;
-static unsigned long periodic_count;
-
-typedef enum {
-	RTC_RELEASE,
-	RTC_OPEN,
-} rtc_status_t;
-
-static rtc_status_t rtc_status;
-
-typedef enum {
-	FUNCTION_RTC_IOCTL,
-	FUNCTION_RTC_CONTROL,
-} rtc_callfrom_t;
-
-struct resource rtc_resource[2] = {
-	{	.name	= rtc_name,
-		.flags	= IORESOURCE_MEM,	},
-	{	.name	= rtc_name,
-		.flags	= IORESOURCE_MEM,	},
-};
-
-static inline unsigned long read_elapsed_second(void)
-{
-	unsigned long first_low, first_mid, first_high;
-	unsigned long second_low, second_mid, second_high;
-
-	do {
-		first_low = rtc1_read(ETIMELREG);
-		first_mid = rtc1_read(ETIMEMREG);
-		first_high = rtc1_read(ETIMEHREG);
-		second_low = rtc1_read(ETIMELREG);
-		second_mid = rtc1_read(ETIMEMREG);
-		second_high = rtc1_read(ETIMEHREG);
-	} while (first_low != second_low || first_mid != second_mid ||
-	         first_high != second_high);
-
-	return (first_high << 17) | (first_mid << 1) | (first_low >> 15);
-}
-
-static inline void write_elapsed_second(unsigned long sec)
-{
-	spin_lock_irq(&rtc_lock);
-
-	rtc1_write(ETIMELREG, (uint16_t)(sec << 15));
-	rtc1_write(ETIMEMREG, (uint16_t)(sec >> 1));
-	rtc1_write(ETIMEHREG, (uint16_t)(sec >> 17));
-
-	spin_unlock_irq(&rtc_lock);
-}
-
-static void set_alarm(struct rtc_time *time)
-{
-	unsigned long alarm_sec;
-
-	alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
-	                   time->tm_hour, time->tm_min, time->tm_sec);
-
-	spin_lock_irq(&rtc_lock);
-
-	rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
-	rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
-	rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
-
-	spin_unlock_irq(&rtc_lock);
-}
-
-static void read_alarm(struct rtc_time *time)
-{
-	unsigned long low, mid, high;
-
-	spin_lock_irq(&rtc_lock);
-
-	low = rtc1_read(ECMPLREG);
-	mid = rtc1_read(ECMPMREG);
-	high = rtc1_read(ECMPHREG);
-
-	spin_unlock_irq(&rtc_lock);
-
-	to_tm((high << 17) | (mid << 1) | (low >> 15), time);
-	time->tm_year -= 1900;
-}
-
-static void read_time(struct rtc_time *time)
-{
-	unsigned long epoch_sec, elapsed_sec;
-
-	epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
-	elapsed_sec = read_elapsed_second();
-
-	to_tm(epoch_sec + elapsed_sec, time);
-	time->tm_year -= 1900;
-}
-
-static void set_time(struct rtc_time *time)
-{
-	unsigned long epoch_sec, current_sec;
-
-	epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
-	current_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
-	                     time->tm_hour, time->tm_min, time->tm_sec);
-
-	write_elapsed_second(current_sec - epoch_sec);
-}
-
-static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long irq_data;
-	int retval = 0;
-
-	if (count != sizeof(unsigned int) && count != sizeof(unsigned long))
-		return -EINVAL;
-
-	add_wait_queue(&rtc_wait, &wait);
-
-	do {
-		__set_current_state(TASK_INTERRUPTIBLE);
-
-		spin_lock_irq(&rtc_lock);
-		irq_data = rtc_irq_data;
-		rtc_irq_data = 0;
-		spin_unlock_irq(&rtc_lock);
-
-		if (irq_data != 0)
-			break;
-
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EAGAIN;
-			break;
-		}
-
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-	} while (1);
-
-	if (retval == 0) {
-		if (count == sizeof(unsigned int)) {
-			retval = put_user(irq_data, (unsigned int __user *)buf);
-			if (retval == 0)
-				retval = sizeof(unsigned int);
-		} else {
-			retval = put_user(irq_data, (unsigned long __user *)buf);
-			if (retval == 0)
-				retval = sizeof(unsigned long);
-		}
-
-	}
-
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&rtc_wait, &wait);
-
-	return retval;
-}
-
-static unsigned int rtc_poll(struct file *file, struct poll_table_struct *table)
-{
-	poll_wait(file, &rtc_wait, table);
-
-	if (rtc_irq_data != 0)
-		return POLLIN | POLLRDNORM;
-
-	return 0;
-}
-
-static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from)
-{
-	struct rtc_time time;
-	unsigned long count;
-
-	switch (cmd) {
-	case RTC_AIE_ON:
-		enable_irq(ELAPSEDTIME_IRQ);
-		break;
-	case RTC_AIE_OFF:
-		disable_irq(ELAPSEDTIME_IRQ);
-		break;
-	case RTC_PIE_ON:
-		enable_irq(RTCLONG1_IRQ);
-		break;
-	case RTC_PIE_OFF:
-		disable_irq(RTCLONG1_IRQ);
-		break;
-	case RTC_ALM_SET:
-		if (copy_from_user(&time, (struct rtc_time __user *)arg,
-		                   sizeof(struct rtc_time)))
-			return -EFAULT;
-
-		set_alarm(&time);
-		break;
-	case RTC_ALM_READ:
-		memset(&time, 0, sizeof(struct rtc_time));
-		read_alarm(&time);
-		break;
-	case RTC_RD_TIME:
-		memset(&time, 0, sizeof(struct rtc_time));
-		read_time(&time);
-		if (copy_to_user((void __user *)arg, &time, sizeof(struct rtc_time)))
-			return -EFAULT;
-		break;
-	case RTC_SET_TIME:
-		if (capable(CAP_SYS_TIME) == 0)
-			return -EACCES;
-
-		if (copy_from_user(&time, (struct rtc_time __user *)arg,
-		                   sizeof(struct rtc_time)))
-			return -EFAULT;
-
-		set_time(&time);
-		break;
-	case RTC_IRQP_READ:
-		return put_user(periodic_frequency, (unsigned long __user *)arg);
-		break;
-	case RTC_IRQP_SET:
-		if (arg > MAX_PERIODIC_RATE)
-			return -EINVAL;
-
-		if (from == FUNCTION_RTC_IOCTL && arg > MAX_USER_PERIODIC_RATE &&
-		    capable(CAP_SYS_RESOURCE) == 0)
-			return -EACCES;
-
-		periodic_frequency = arg;
-
-		count = RTC_FREQUENCY;
-		do_div(count, arg);
-
-		periodic_count = count;
-
-		spin_lock_irq(&rtc_lock);
-
-		rtc1_write(RTCL1LREG, count);
-		rtc1_write(RTCL1HREG, count >> 16);
-
-		spin_unlock_irq(&rtc_lock);
-		break;
-	case RTC_EPOCH_READ:
-		return put_user(epoch, (unsigned long __user *)arg);
-	case RTC_EPOCH_SET:
-		/* Doesn't support before 1900 */
-		if (arg < 1900)
-			return -EINVAL;
-
-		if (capable(CAP_SYS_TIME) == 0)
-			return -EACCES;
-
-		epoch = arg;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-                     unsigned long arg)
-{
-	return rtc_do_ioctl(cmd, arg, FUNCTION_RTC_IOCTL);
-}
-
-static int rtc_open(struct inode *inode, struct file *file)
-{
-	spin_lock_irq(&rtc_lock);
-
-	if (rtc_status == RTC_OPEN) {
-		spin_unlock_irq(&rtc_lock);
-		return -EBUSY;
-	}
-
-	rtc_status = RTC_OPEN;
-	rtc_irq_data = 0;
-
-	spin_unlock_irq(&rtc_lock);
-
-	return 0;
-}
-
-static int rtc_release(struct inode *inode, struct file *file)
-{
-	if (file->f_flags & FASYNC)
-		(void)fasync_helper(-1, file, 0, &rtc_async_queue);
-
-	spin_lock_irq(&rtc_lock);
-
-	rtc1_write(ECMPLREG, 0);
-	rtc1_write(ECMPMREG, 0);
-	rtc1_write(ECMPHREG, 0);
-	rtc1_write(RTCL1LREG, 0);
-	rtc1_write(RTCL1HREG, 0);
-
-	rtc_status = RTC_RELEASE;
-
-	spin_unlock_irq(&rtc_lock);
-
-	disable_irq(ELAPSEDTIME_IRQ);
-	disable_irq(RTCLONG1_IRQ);
-
-	return 0;
-}
-
-static int rtc_fasync(int fd, struct file *file, int on)
-{
-	return fasync_helper(fd, file, on, &rtc_async_queue);
-}
-
-static struct file_operations rtc_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= rtc_read,
-	.poll		= rtc_poll,
-	.ioctl		= rtc_ioctl,
-	.open		= rtc_open,
-	.release	= rtc_release,
-	.fasync		= rtc_fasync,
-};
-
-static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	spin_lock(&rtc_lock);
-	rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
-
-	rtc_irq_data += 0x100;
-	rtc_irq_data &= ~0xff;
-	rtc_irq_data |= RTC_AF;
-	spin_unlock(&rtc_lock);
-
-	spin_lock(&rtc_lock);
-	if (rtc_callback)
-		rtc_callback->func(rtc_callback->private_data);
-	spin_unlock(&rtc_lock);
-
-	wake_up_interruptible(&rtc_wait);
-
-	kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long count = periodic_count;
-
-	spin_lock(&rtc_lock);
-	rtc2_write(RTCINTREG, RTCLONG1_INT);
-
-	rtc1_write(RTCL1LREG, count);
-	rtc1_write(RTCL1HREG, count >> 16);
-
-	rtc_irq_data += 0x100;
-	rtc_irq_data &= ~0xff;
-	rtc_irq_data |= RTC_PF;
-	spin_unlock(&rtc_lock);
-
-	spin_lock(&rtc_task_lock);
-	if (rtc_callback)
-		rtc_callback->func(rtc_callback->private_data);
-	spin_unlock(&rtc_task_lock);
-
-	wake_up_interruptible(&rtc_wait);
-
-	kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
-
-	return IRQ_HANDLED;
-}
-
-int rtc_register(rtc_task_t *task)
-{
-	if (task == NULL || task->func == NULL)
-		return -EINVAL;
-
-	spin_lock_irq(&rtc_lock);
-	if (rtc_status == RTC_OPEN) {
-		spin_unlock_irq(&rtc_lock);
-		return -EBUSY;
-	}
-
-	spin_lock(&rtc_task_lock);
-	if (rtc_callback != NULL) {
-		spin_unlock(&rtc_task_lock);
-		spin_unlock_irq(&rtc_task_lock);
-		return -EBUSY;
-	}
-
-	rtc_callback = task;
-	spin_unlock(&rtc_task_lock);
-
-	rtc_status = RTC_OPEN;
-
-	spin_unlock_irq(&rtc_lock);
-
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(rtc_register);
-
-int rtc_unregister(rtc_task_t *task)
-{
-	spin_lock_irq(&rtc_task_lock);
-	if (task == NULL || rtc_callback != task) {
-		spin_unlock_irq(&rtc_task_lock);
-		return -ENXIO;
-	}
-
-	spin_lock(&rtc_lock);
-
-	rtc1_write(ECMPLREG, 0);
-	rtc1_write(ECMPMREG, 0);
-	rtc1_write(ECMPHREG, 0);
-	rtc1_write(RTCL1LREG, 0);
-	rtc1_write(RTCL1HREG, 0);
-
-	rtc_status = RTC_RELEASE;
-
-	spin_unlock(&rtc_lock);
-
-	rtc_callback = NULL;
-
-	spin_unlock_irq(&rtc_task_lock);
-
-	disable_irq(ELAPSEDTIME_IRQ);
-	disable_irq(RTCLONG1_IRQ);
-
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(rtc_unregister);
-
-int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
-{
-	int retval = 0;
-
-	spin_lock_irq(&rtc_task_lock);
-
-	if (rtc_callback != task)
-		retval = -ENXIO;
-	else
-		rtc_do_ioctl(cmd, arg, FUNCTION_RTC_CONTROL);
-
-	spin_unlock_irq(&rtc_task_lock);
-
-	return retval;
-}
-
-EXPORT_SYMBOL_GPL(rtc_control);
-
-static struct miscdevice rtc_miscdevice = {
-	.minor	= RTC_MINOR,
-	.name	= rtc_name,
-	.fops	= &rtc_fops,
-};
-
-static int __devinit rtc_probe(struct platform_device *pdev)
-{
-	unsigned int irq;
-	int retval;
-
-	if (pdev->num_resources != 2)
-		return -EBUSY;
-
-	rtc1_base = ioremap(pdev->resource[0].start, RTC1_SIZE);
-	if (rtc1_base == NULL)
-		return -EBUSY;
-
-	rtc2_base = ioremap(pdev->resource[1].start, RTC2_SIZE);
-	if (rtc2_base == NULL) {
-		iounmap(rtc1_base);
-		rtc1_base = NULL;
-		return -EBUSY;
-	}
-
-	retval = misc_register(&rtc_miscdevice);
-	if (retval < 0) {
-		iounmap(rtc1_base);
-		iounmap(rtc2_base);
-		rtc1_base = NULL;
-		rtc2_base = NULL;
-		return retval;
-	}
-
-	spin_lock_irq(&rtc_lock);
-
-	rtc1_write(ECMPLREG, 0);
-	rtc1_write(ECMPMREG, 0);
-	rtc1_write(ECMPHREG, 0);
-	rtc1_write(RTCL1LREG, 0);
-	rtc1_write(RTCL1HREG, 0);
-
-	rtc_status = RTC_RELEASE;
-	rtc_irq_data = 0;
-
-	spin_unlock_irq(&rtc_lock);
-
-	init_waitqueue_head(&rtc_wait);
-
-	irq = ELAPSEDTIME_IRQ;
-	retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT,
-	                     "elapsed_time", NULL);
-	if (retval == 0) {
-		irq = RTCLONG1_IRQ;
-		retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT,
-		                     "rtclong1", NULL);
-	}
-
-	if (retval < 0) {
-		printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
-		if (irq == RTCLONG1_IRQ)
-			free_irq(ELAPSEDTIME_IRQ, NULL);
-		iounmap(rtc1_base);
-		iounmap(rtc2_base);
-		rtc1_base = NULL;
-		rtc2_base = NULL;
-		return retval;
-	}
-
-	disable_irq(ELAPSEDTIME_IRQ);
-	disable_irq(RTCLONG1_IRQ);
-
-	spin_lock_init(&rtc_task_lock);
-
-	printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
-
-	return 0;
-}
-
-static int __devexit rtc_remove(struct platform_device *dev)
-{
-	int retval;
-
-	retval = misc_deregister(&rtc_miscdevice);
-	if (retval < 0)
-		return retval;
-
-	free_irq(ELAPSEDTIME_IRQ, NULL);
-	free_irq(RTCLONG1_IRQ, NULL);
-	if (rtc1_base != NULL)
-		iounmap(rtc1_base);
-	if (rtc2_base != NULL)
-		iounmap(rtc2_base);
-
-	return 0;
-}
-
-static struct platform_device *rtc_platform_device;
-
-static struct platform_driver rtc_device_driver = {
-	.probe		= rtc_probe,
-	.remove		= __devexit_p(rtc_remove),
-	.driver		= {
-		.name	= rtc_name,
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init vr41xx_rtc_init(void)
-{
-	int retval;
-
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		rtc_resource[0].start = RTC1_TYPE1_START;
-		rtc_resource[0].end = RTC1_TYPE1_END;
-		rtc_resource[1].start = RTC2_TYPE1_START;
-		rtc_resource[1].end = RTC2_TYPE1_END;
-		break;
-	case CPU_VR4122:
-	case CPU_VR4131:
-	case CPU_VR4133:
-		rtc_resource[0].start = RTC1_TYPE2_START;
-		rtc_resource[0].end = RTC1_TYPE2_END;
-		rtc_resource[1].start = RTC2_TYPE2_START;
-		rtc_resource[1].end = RTC2_TYPE2_END;
-		break;
-	default:
-		return -ENODEV;
-		break;
-	}
-
-	rtc_platform_device = platform_device_alloc("RTC", -1);
-	if (!rtc_platform_device)
-		return -ENOMEM;
-
-	retval = platform_device_add_resources(rtc_platform_device,
-				rtc_resource, ARRAY_SIZE(rtc_resource));
-
-	if (retval == 0)
-		retval = platform_device_add(rtc_platform_device);
-
-	if (retval < 0) {
-		platform_device_put(rtc_platform_device);
-		return retval;
-	}
-
-	retval = platform_driver_register(&rtc_device_driver);
-	if (retval < 0)
-		platform_device_unregister(rtc_platform_device);
-
-	return retval;
-}
-
-static void __exit vr41xx_rtc_exit(void)
-{
-	platform_driver_unregister(&rtc_device_driver);
-	platform_device_unregister(rtc_platform_device);
-}
-
-module_init(vr41xx_rtc_init);
-module_exit(vr41xx_rtc_exit);
diff -pruN -X dontdiff mm2-orig/drivers/rtc/Kconfig mm2/drivers/rtc/Kconfig
--- mm2-orig/drivers/rtc/Kconfig	2006-03-31 12:55:36.858947000 +0900
+++ mm2/drivers/rtc/Kconfig	2006-03-29 11:52:56.725555000 +0900
@@ -147,6 +147,10 @@ config RTC_DRV_SA1100
 	  To compile this driver as a module, choose M here: the
 	  module will be called rtc-sa1100.
 
+config RTC_DRV_VR41XX
+	tristate "NEC VR4100 series RTC"
+	depends on RTC_CLASS && CPU_VR41XX
+
 config RTC_DRV_TEST
 	tristate "Test driver/device"
 	depends on RTC_CLASS
diff -pruN -X dontdiff mm2-orig/drivers/rtc/Makefile mm2/drivers/rtc/Makefile
--- mm2-orig/drivers/rtc/Makefile	2006-03-31 12:55:36.858947000 +0900
+++ mm2/drivers/rtc/Makefile	2006-03-29 11:49:17.499854250 +0900
@@ -19,3 +19,4 @@ obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5
 obj-$(CONFIG_RTC_DRV_M48T86)	+= rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_SA1100)	+= rtc-sa1100.o
+obj-$(CONFIG_RTC_DRV_VR41XX)	+= rtc-vr41xx.o
diff -pruN -X dontdiff mm2-orig/drivers/rtc/rtc-vr41xx.c mm2/drivers/rtc/rtc-vr41xx.c
--- mm2-orig/drivers/rtc/rtc-vr41xx.c	1970-01-01 09:00:00.000000000 +0900
+++ mm2/drivers/rtc/rtc-vr41xx.c	2006-03-31 15:35:06.909395500 +0900
@@ -0,0 +1,471 @@
+/*
+ *  Driver for NEC VR4100 series Real Time Clock unit.
+ *
+ *  Copyright (C) 2003-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/div64.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
+MODULE_LICENSE("GPL");
+
+#define RTC1_TYPE1_START	0x0b0000c0UL
+#define RTC1_TYPE1_END		0x0b0000dfUL
+#define RTC2_TYPE1_START	0x0b0001c0UL
+#define RTC2_TYPE1_END		0x0b0001dfUL
+
+#define RTC1_TYPE2_START	0x0f000100UL
+#define RTC1_TYPE2_END		0x0f00011fUL
+#define RTC2_TYPE2_START	0x0f000120UL
+#define RTC2_TYPE2_END		0x0f00013fUL
+
+#define RTC1_SIZE		0x20
+#define RTC2_SIZE		0x20
+
+/* RTC 1 registers */
+#define ETIMELREG		0x00
+#define ETIMEMREG		0x02
+#define ETIMEHREG		0x04
+/* RFU */
+#define ECMPLREG		0x08
+#define ECMPMREG		0x0a
+#define ECMPHREG		0x0c
+/* RFU */
+#define RTCL1LREG		0x10
+#define RTCL1HREG		0x12
+#define RTCL1CNTLREG		0x14
+#define RTCL1CNTHREG		0x16
+#define RTCL2LREG		0x18
+#define RTCL2HREG		0x1a
+#define RTCL2CNTLREG		0x1c
+#define RTCL2CNTHREG		0x1e
+
+/* RTC 2 registers */
+#define TCLKLREG		0x00
+#define TCLKHREG		0x02
+#define TCLKCNTLREG		0x04
+#define TCLKCNTHREG		0x06
+/* RFU */
+#define RTCINTREG		0x1e
+ #define TCLOCK_INT		0x08
+ #define RTCLONG2_INT		0x04
+ #define RTCLONG1_INT		0x02
+ #define ELAPSEDTIME_INT	0x01
+
+#define RTC_FREQUENCY		32768
+#define MAX_PERIODIC_RATE	6553
+#define MAX_USER_PERIODIC_RATE	64
+
+static void __iomem *rtc1_base;
+static void __iomem *rtc2_base;
+
+#define rtc1_read(offset)		readw(rtc1_base + (offset))
+#define rtc1_write(offset, value)	writew((value), rtc1_base + (offset))
+
+#define rtc2_read(offset)		readw(rtc2_base + (offset))
+#define rtc2_write(offset, value)	writew((value), rtc2_base + (offset))
+
+static unsigned long epoch = 1970;	/* Jan 1 1970 00:00:00 */
+
+static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+static char rtc_name[] = "RTC";
+static unsigned long periodic_frequency;
+static unsigned long periodic_count;
+
+struct resource rtc_resource[2] = {
+	{	.name	= rtc_name,
+		.flags	= IORESOURCE_MEM,	},
+	{	.name	= rtc_name,
+		.flags	= IORESOURCE_MEM,	},
+};
+
+static inline unsigned long read_elapsed_second(void)
+{
+
+	unsigned long first_low, first_mid, first_high;
+
+	unsigned long second_low, second_mid, second_high;
+
+	do {
+		first_low = rtc1_read(ETIMELREG);
+		first_mid = rtc1_read(ETIMEMREG);
+		first_high = rtc1_read(ETIMEHREG);
+		second_low = rtc1_read(ETIMELREG);
+		second_mid = rtc1_read(ETIMEMREG);
+		second_high = rtc1_read(ETIMEHREG);
+	} while (first_low != second_low || first_mid != second_mid ||
+	         first_high != second_high);
+
+	return (first_high << 17) | (first_mid << 1) | (first_low >> 15);
+}
+
+static inline void write_elapsed_second(unsigned long sec)
+{
+	spin_lock_irq(&rtc_lock);
+
+	rtc1_write(ETIMELREG, (uint16_t)(sec << 15));
+	rtc1_write(ETIMEMREG, (uint16_t)(sec >> 1));
+	rtc1_write(ETIMEHREG, (uint16_t)(sec >> 17));
+
+	spin_unlock_irq(&rtc_lock);
+}
+
+static void vr41xx_rtc_release(struct device *dev)
+{
+
+	spin_lock_irq(&rtc_lock);
+
+	rtc1_write(ECMPLREG, 0);
+	rtc1_write(ECMPMREG, 0);
+	rtc1_write(ECMPHREG, 0);
+	rtc1_write(RTCL1LREG, 0);
+	rtc1_write(RTCL1HREG, 0);
+
+	spin_unlock_irq(&rtc_lock);
+
+	disable_irq(ELAPSEDTIME_IRQ);
+	disable_irq(RTCLONG1_IRQ);
+}
+
+static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
+{
+	unsigned long epoch_sec, elapsed_sec;
+
+	epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
+	elapsed_sec = read_elapsed_second();
+
+	rtc_time_to_tm(epoch_sec + elapsed_sec, time);
+
+	return 0;
+}
+
+static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
+{
+	unsigned long epoch_sec, current_sec;
+
+	epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
+	current_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+	                     time->tm_hour, time->tm_min, time->tm_sec);
+
+	write_elapsed_second(current_sec - epoch_sec);
+
+	return 0;
+}
+
+static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+	unsigned long low, mid, high;
+	struct rtc_time *time = &wkalrm->time;
+
+	spin_lock_irq(&rtc_lock);
+
+	low = rtc1_read(ECMPLREG);
+	mid = rtc1_read(ECMPMREG);
+	high = rtc1_read(ECMPHREG);
+
+	spin_unlock_irq(&rtc_lock);
+
+	rtc_time_to_tm((high << 17) | (mid << 1) | (low >> 15), time);
+
+	return 0;
+}
+
+static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+	unsigned long alarm_sec;
+	struct rtc_time *time = &wkalrm->time;
+
+	alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+	                   time->tm_hour, time->tm_min, time->tm_sec);
+
+	spin_lock_irq(&rtc_lock);
+
+	rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
+	rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
+	rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
+
+	spin_unlock_irq(&rtc_lock);
+
+	return 0;
+}
+
+static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	unsigned long count;
+
+	switch (cmd) {
+	case RTC_AIE_ON:
+		enable_irq(ELAPSEDTIME_IRQ);
+		break;
+	case RTC_AIE_OFF:
+		disable_irq(ELAPSEDTIME_IRQ);
+		break;
+	case RTC_PIE_ON:
+		enable_irq(RTCLONG1_IRQ);
+		break;
+	case RTC_PIE_OFF:
+		disable_irq(RTCLONG1_IRQ);
+		break;
+	case RTC_IRQP_READ:
+		return put_user(periodic_frequency, (unsigned long __user *)arg);
+		break;
+	case RTC_IRQP_SET:
+		if (arg > MAX_PERIODIC_RATE)
+			return -EINVAL;
+
+		if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0)
+			return -EACCES;
+
+		periodic_frequency = arg;
+
+		count = RTC_FREQUENCY;
+		do_div(count, arg);
+
+		periodic_count = count;
+
+		spin_lock_irq(&rtc_lock);
+
+		rtc1_write(RTCL1LREG, count);
+		rtc1_write(RTCL1HREG, count >> 16);
+
+		spin_unlock_irq(&rtc_lock);
+		break;
+	case RTC_EPOCH_READ:
+		return put_user(epoch, (unsigned long __user *)arg);
+	case RTC_EPOCH_SET:
+		/* Doesn't support before 1900 */
+		if (arg < 1900)
+			return -EINVAL;
+
+		if (capable(CAP_SYS_TIME) == 0)
+			return -EACCES;
+
+		epoch = arg;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct platform_device *pdev = (struct platform_device *)dev_id;
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+	rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
+
+	rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct platform_device *pdev = (struct platform_device *)dev_id;
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
+	unsigned long count = periodic_count;
+
+	rtc2_write(RTCINTREG, RTCLONG1_INT);
+
+	rtc1_write(RTCL1LREG, count);
+	rtc1_write(RTCL1HREG, count >> 16);
+
+	rtc_update_irq(&rtc->class_dev, 1, RTC_PF);
+
+	return IRQ_HANDLED;
+}
+
+static struct rtc_class_ops vr41xx_rtc_ops = {
+	.release	= vr41xx_rtc_release,
+	.ioctl		= vr41xx_rtc_ioctl,
+	.read_time	= vr41xx_rtc_read_time,
+	.set_time	= vr41xx_rtc_set_time,
+	.read_alarm	= vr41xx_rtc_read_alarm,
+	.set_alarm	= vr41xx_rtc_set_alarm,
+};
+
+static int __devinit rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	unsigned int irq;
+	int retval;
+
+	if (pdev->num_resources != 2)
+		return -EBUSY;
+
+	rtc1_base = ioremap(pdev->resource[0].start, RTC1_SIZE);
+	if (rtc1_base == NULL)
+		return -EBUSY;
+
+	rtc2_base = ioremap(pdev->resource[1].start, RTC2_SIZE);
+	if (rtc2_base == NULL) {
+		iounmap(rtc1_base);
+		rtc1_base = NULL;
+		return -EBUSY;
+	}
+
+	rtc = rtc_device_register(rtc_name, &pdev->dev, &vr41xx_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		iounmap(rtc1_base);
+		iounmap(rtc2_base);
+		rtc1_base = NULL;
+		rtc2_base = NULL;
+		return PTR_ERR(rtc);
+	}
+
+	spin_lock_irq(&rtc_lock);
+
+	rtc1_write(ECMPLREG, 0);
+	rtc1_write(ECMPMREG, 0);
+	rtc1_write(ECMPHREG, 0);
+	rtc1_write(RTCL1LREG, 0);
+	rtc1_write(RTCL1HREG, 0);
+
+	spin_unlock_irq(&rtc_lock);
+
+	irq = ELAPSEDTIME_IRQ;
+	retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT,
+	                     "elapsed_time", pdev);
+	if (retval == 0) {
+		irq = RTCLONG1_IRQ;
+		retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT,
+		                     "rtclong1", pdev);
+	}
+
+	if (retval < 0) {
+		printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
+		rtc_device_unregister(rtc);
+		if (irq == RTCLONG1_IRQ)
+			free_irq(ELAPSEDTIME_IRQ, NULL);
+		iounmap(rtc1_base);
+		iounmap(rtc2_base);
+		rtc1_base = NULL;
+		rtc2_base = NULL;
+		return retval;
+	}
+
+	platform_set_drvdata(pdev, rtc);
+
+	disable_irq(ELAPSEDTIME_IRQ);
+	disable_irq(RTCLONG1_IRQ);
+
+	printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
+
+	return 0;
+}
+
+static int __devexit rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+
+	rtc = platform_get_drvdata(pdev);
+	if (rtc != NULL)
+		rtc_device_unregister(rtc);
+
+	platform_set_drvdata(pdev, NULL);
+
+	free_irq(ELAPSEDTIME_IRQ, NULL);
+	free_irq(RTCLONG1_IRQ, NULL);
+	if (rtc1_base != NULL)
+		iounmap(rtc1_base);
+	if (rtc2_base != NULL)
+		iounmap(rtc2_base);
+
+	return 0;
+}
+
+static struct platform_device *rtc_platform_device;
+
+static struct platform_driver rtc_platform_driver = {
+	.probe		= rtc_probe,
+	.remove		= __devexit_p(rtc_remove),
+	.driver		= {
+		.name	= rtc_name,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init vr41xx_rtc_init(void)
+{
+	int retval;
+
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		rtc_resource[0].start = RTC1_TYPE1_START;
+		rtc_resource[0].end = RTC1_TYPE1_END;
+		rtc_resource[1].start = RTC2_TYPE1_START;
+		rtc_resource[1].end = RTC2_TYPE1_END;
+		break;
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133:
+		rtc_resource[0].start = RTC1_TYPE2_START;
+		rtc_resource[0].end = RTC1_TYPE2_END;
+		rtc_resource[1].start = RTC2_TYPE2_START;
+		rtc_resource[1].end = RTC2_TYPE2_END;
+		break;
+	default:
+		return -ENODEV;
+		break;
+	}
+
+	rtc_platform_device = platform_device_alloc("RTC", -1);
+	if (rtc_platform_device == NULL)
+		return -ENOMEM;
+
+	retval = platform_device_add_resources(rtc_platform_device,
+				rtc_resource, ARRAY_SIZE(rtc_resource));
+
+	if (retval == 0)
+		retval = platform_device_add(rtc_platform_device);
+
+	if (retval < 0) {
+		platform_device_put(rtc_platform_device);
+		return retval;
+	}
+
+	retval = platform_driver_register(&rtc_platform_driver);
+	if (retval < 0)
+		platform_device_unregister(rtc_platform_device);
+
+	return retval;
+}
+
+static void __exit vr41xx_rtc_exit(void)
+{
+	platform_driver_unregister(&rtc_platform_driver);
+	platform_device_unregister(rtc_platform_device);
+}
+
+module_init(vr41xx_rtc_init);
+module_exit(vr41xx_rtc_exit);

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 10/10] RTC subsystem, VR41XX cleanup
  2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
                   ` (8 preceding siblings ...)
  2006-03-31 10:04 ` [PATCH 09/10] RTC subsystem, VR41XX driver Alessandro Zummo
@ 2006-03-31 10:04 ` Alessandro Zummo
       [not found] ` <Pine.LNX.4.63.0605030826290.1846@pcgl.dsa-ac.de>
  10 siblings, 0 replies; 14+ messages in thread
From: Alessandro Zummo @ 2006-03-31 10:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, akpm, Yoichi Yuasa

[-- Attachment #1: rtc-subsys-drv-vr41xx-kconfig.patch --]
[-- Type: text/plain, Size: 852 bytes --]

 Cleaned up kconfig entry for the rtc-vr41xx.

Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
CC: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
---
 drivers/rtc/Kconfig |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

--- linux-rtc.orig/drivers/rtc/Kconfig	2006-03-31 11:39:15.000000000 +0200
+++ linux-rtc/drivers/rtc/Kconfig	2006-03-31 11:49:09.000000000 +0200
@@ -148,8 +148,14 @@ config RTC_DRV_SA1100
 	  module will be called rtc-sa1100.
 
 config RTC_DRV_VR41XX
-	tristate "NEC VR4100 series RTC"
+	tristate "NEC VR41XX"
 	depends on RTC_CLASS && CPU_VR41XX
+	help
+	  If you say Y here you will get access to the real time clock
+	  built into your NEC VR41XX CPU.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rtc-vr41xx.
 
 config RTC_DRV_TEST
 	tristate "Test driver/device"

--

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 09/10] RTC subsystem, VR41XX driver
  2006-03-31 10:04 ` [PATCH 09/10] RTC subsystem, VR41XX driver Alessandro Zummo
@ 2006-04-01 23:20   ` Andrew Morton
  0 siblings, 0 replies; 14+ messages in thread
From: Andrew Morton @ 2006-04-01 23:20 UTC (permalink / raw)
  To: Alessandro Zummo; +Cc: linux-kernel, akpm, yoichi_yuasa

Alessandro Zummo <a.zummo@towertech.it> wrote:
>
> This patch updates VR4100 series RTC driver.

It also renames the driver's .c file.  This makes it quite hard for
reviewers to see what was changed.

When you have patches which move large amounts of code around, please make
sure that the patch does *only* that.  Functional changes should happen in
later patches.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 08/10] RTC subsystem, SA1100 cleanup
  2006-03-31 10:04 ` [PATCH 08/10] RTC subsystem, SA1100 cleanup Alessandro Zummo
@ 2006-04-02 18:43   ` Pavel Machek
  0 siblings, 0 replies; 14+ messages in thread
From: Pavel Machek @ 2006-04-02 18:43 UTC (permalink / raw)
  To: Alessandro Zummo; +Cc: linux-kernel, akpm, akpm, Richard Purdie

On Pá 31-03-06 12:04:31, Alessandro Zummo wrote:
>  - converted printks to dev_xxx
>  - removed messages in excess
> 
> Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
> Cc: Richard Purdie <rpurdie@rpsys.net>

Looks good to me.
						Pavel
-- 
Picture of sleeping (Linux) penguin wanted...

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: drivers/acorn/char/pcf8583.[hc] vs. RTC subsystem
       [not found]               ` <20060503132301.52a75dcd@inspiron>
@ 2006-05-05 18:43                 ` Guennadi Liakhovetski
  0 siblings, 0 replies; 14+ messages in thread
From: Guennadi Liakhovetski @ 2006-05-05 18:43 UTC (permalink / raw)
  To: Alessandro Zummo; +Cc: Russell King, akpm, linux-kernel

On Thu, 4 May 2006, Guennadi Liakhovetski wrote:

> On Wed, 3 May 2006, Russell King wrote:
> 
> > I doubt we could switch - we need to read the year from the memory part
> > and that's specific to Acorn machines.  The PCF8583 has a 2 bit year
> > counter which is totally useless, so Acorn machines keep track of the
> > year in the CMOS part of the chip.
> 
> The driver I've submitted does exactly this. It is a CMOS built into the pcf,
> so, why not just use it for that?
> 
> > Hence to _correctly_ interpret the time and date from the clock, you
> > _have_ to have this special knowledge built in to the driver.  That
> > won't be suitable for other setups, so I don't see how you could
> > sanely combine the drivers and keep the functionality.
> 
> Why do you think it is unsuitable for others?

Russell, as you haven't replied, I take it as an agreement with this 
patch, leaving the original driver under drivers/acorn so far alone.

On Wed, 3 May 2006, Alessandro Zummo wrote:

> On Wed, 3 May 2006 12:49:16 +0200 (CEST)
> Guennadi Liakhovetski <gl@dsa-ac.de> wrote:
> > 
> > Ok, the patch is attached (sorry, this my pine is still not configured 
> > properly for inlining, if it is a problem, will resend from home), so the 
> > interested parties can already review it, but I would still wait for 
> > Russell's opinion, I am not quite excited by the idea of having 2 drivers 
> > for pcf8583 in the kernel:-)
> 
>  ok.  here is my
> 
> Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
> 
>  when you feel ready, you can send it to Andrew Morton
>  for inclusion in -mm.

The unmodified patch is below. Andrew, please, apply.

Thanks
Guennadi
---
Guennadi Liakhovetski

Signed-off-by: G. Liakhovetski <gl@dsa-ac.de>

diff -u /dev/null b/drivers/rtc/rtc-pcf8583.c
--- /dev/null	2004-06-30 21:04:37.000000000
+++ b/drivers/rtc/rtc-pcf8583.c	2006-05-03 12:31:03.147332245
@@ -0,0 +1,394 @@
+/*
+ *  drivers/rtc/rtc-pcf8583.c
+ *
+ *  Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Driver for PCF8583 RTC & RAM chip
+ *
+ *  Converted to the generic RTC susbsystem by G. Liakhovetski (2006)
+ */
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/mc146818rtc.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/bcd.h>
+
+struct rtc_mem {
+	unsigned int	loc;
+	unsigned int	nr;
+	unsigned char	*data;
+};
+
+struct pcf8583 {
+	struct i2c_client client;
+	struct rtc_device *rtc;
+	unsigned char ctrl;
+};
+
+#define CTRL_STOP	0x80
+#define CTRL_HOLD	0x40
+#define CTRL_32KHZ	0x00
+#define CTRL_MASK	0x08
+#define CTRL_ALARMEN	0x04
+#define CTRL_ALARM	0x02
+#define CTRL_TIMER	0x01
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Module parameters */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver pcf8583_driver;
+
+#define get_ctrl(x)    ((struct pcf8583 *)i2c_get_clientdata(x))->ctrl
+#define set_ctrl(x, v) get_ctrl(x) = v
+
+#define CMOS_YEAR	(64 + 128)
+#define CMOS_CHECKSUM	(63)
+
+static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt)
+{
+	unsigned char buf[8], addr[1] = { 1 };
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = 6,
+			.buf = buf,
+		}
+	};
+	int ret;
+
+	memset(buf, 0, sizeof(buf));
+
+	ret = i2c_transfer(client->adapter, msgs, 2);
+	if (ret == 2) {
+		dt->tm_year = buf[4] >> 6;
+		dt->tm_wday = buf[5] >> 5;
+
+		buf[4] &= 0x3f;
+		buf[5] &= 0x1f;
+
+		dt->tm_sec = BCD_TO_BIN(buf[1]);
+		dt->tm_min = BCD_TO_BIN(buf[2]);
+		dt->tm_hour = BCD_TO_BIN(buf[3]);
+		dt->tm_mday = BCD_TO_BIN(buf[4]);
+		dt->tm_mon = BCD_TO_BIN(buf[5]);
+	}
+
+	return ret == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
+{
+	unsigned char buf[8];
+	int ret, len = 6;
+
+	buf[0] = 0;
+	buf[1] = get_ctrl(client) | 0x80;
+	buf[2] = 0;
+	buf[3] = BIN_TO_BCD(dt->tm_sec);
+	buf[4] = BIN_TO_BCD(dt->tm_min);
+	buf[5] = BIN_TO_BCD(dt->tm_hour);
+
+	if (datetoo) {
+		len = 8;
+		buf[6] = BIN_TO_BCD(dt->tm_mday) | (dt->tm_year << 6);
+		buf[7] = BIN_TO_BCD(dt->tm_mon)  | (dt->tm_wday << 5);
+	}
+
+	ret = i2c_master_send(client, (char *)buf, len);
+	if (ret != len)
+		return -EIO;
+
+	buf[1] = get_ctrl(client);
+	ret = i2c_master_send(client, (char *)buf, 2);
+
+	return ret == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+	*ctrl = get_ctrl(client);
+	return 0;
+}
+
+static int pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+	unsigned char buf[2];
+
+	buf[0] = 0;
+	buf[1] = *ctrl;
+	set_ctrl(client, *ctrl);
+
+	return i2c_master_send(client, (char *)buf, 2);
+}
+
+static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+	unsigned char addr[1];
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = mem->nr,
+			.buf = mem->data,
+		}
+	};
+
+	if (mem->loc < 8)
+		return -EINVAL;
+
+	addr[0] = mem->loc;
+
+	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+	unsigned char addr[1];
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_NOSTART,
+			.len = mem->nr,
+			.buf = mem->data,
+		}
+	};
+
+	if (mem->loc < 8)
+		return -EINVAL;
+
+	addr[0] = mem->loc;
+
+	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned char ctrl, year[2];
+	struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year };
+	int real_year, year_offset, err;
+
+	/*
+	 * Ensure that the RTC is running.
+	 */
+	pcf8583_get_ctrl(client, &ctrl);
+	if (ctrl & (CTRL_STOP | CTRL_HOLD)) {
+		unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD);
+
+		printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n",
+		       ctrl, new_ctrl);
+
+		if ((err = pcf8583_set_ctrl(client, &new_ctrl)) < 0)
+			return err;
+	}
+
+	if (pcf8583_get_datetime(client, tm) ||
+	    pcf8583_read_mem(client, &mem))
+		return -EIO;
+
+	real_year = year[0];
+
+	/*
+	 * The RTC year holds the LSB two bits of the current
+	 * year, which should reflect the LSB two bits of the
+	 * CMOS copy of the year.  Any difference indicates
+	 * that we have to correct the CMOS version.
+	 */
+	year_offset = tm->tm_year - (real_year & 3);
+	if (year_offset < 0)
+		/*
+		 * RTC year wrapped.  Adjust it appropriately.
+		 */
+		year_offset += 4;
+
+	tm->tm_year = real_year + year_offset + year[1] * 100;
+
+	return 0;
+}
+
+static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned char year[2], chk;
+	struct rtc_mem cmos_year  = { CMOS_YEAR, sizeof(year), year };
+	struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
+	int ret;
+
+	/*
+	 * The RTC's own 2-bit year must reflect the least
+	 * significant two bits of the CMOS year.
+	 */
+
+	ret = pcf8583_set_datetime(client, tm, 1);
+	if (ret)
+		return ret;
+
+	ret = pcf8583_read_mem(client, &cmos_check);
+	if (ret)
+		return ret;
+
+	ret = pcf8583_read_mem(client, &cmos_year);
+	if (ret)
+		return ret;
+
+	chk -= year[1] + year[0];
+
+	year[1] = tm->tm_year / 100;
+	year[0] = tm->tm_year % 100;
+
+	chk += year[1] + year[0];
+
+	ret = pcf8583_write_mem(client, &cmos_year);
+
+	if (ret)
+		return ret;
+
+	ret = pcf8583_write_mem(client, &cmos_check);
+
+	return ret;
+}
+
+static struct rtc_class_ops pcf8583_rtc_ops = {
+	.read_time	= pcf8583_rtc_read_time,
+	.set_time	= pcf8583_rtc_set_time,
+};
+
+static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind);
+
+static int pcf8583_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, pcf8583_probe);
+}
+
+static int pcf8583_detach(struct i2c_client *client)
+{
+	int err;
+	struct pcf8583 *pcf = i2c_get_clientdata(client);
+	struct rtc_device *rtc = pcf->rtc;
+
+	if (rtc)
+		rtc_device_unregister(rtc);
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(pcf);
+	return 0;
+}
+
+static struct i2c_driver pcf8583_driver = {
+	.driver = {
+		.name	= "pcf8583",
+	},
+	.id		= I2C_DRIVERID_PCF8583,
+	.attach_adapter	= pcf8583_attach,
+	.detach_client	= pcf8583_detach,
+};
+
+static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct pcf8583 *pcf;
+	struct i2c_client *client;
+	struct rtc_device *rtc;
+	unsigned char buf[1], ad[1] = { 0 };
+	int err;
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = addr,
+			.flags = 0,
+			.len = 1,
+			.buf = ad,
+		}, {
+			.addr = addr,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = buf,
+		}
+	};
+
+	pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
+	if (!pcf)
+		return -ENOMEM;
+
+	client = &pcf->client;
+
+	client->addr		= addr;
+	client->adapter	= adap;
+	client->driver	= &pcf8583_driver;
+
+	strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE);
+
+	if (i2c_transfer(client->adapter, msgs, 2) != 2) {
+		err = -EIO;
+		goto exit_kfree;
+	}
+
+	err = i2c_attach_client(client);
+
+	if (err)
+		goto exit_kfree;
+
+	rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev,
+				  &pcf8583_rtc_ops, THIS_MODULE);
+
+	if (IS_ERR(rtc)) {
+		err = PTR_ERR(rtc);
+		goto exit_detach;
+	}
+
+	pcf->rtc = rtc;
+	i2c_set_clientdata(client, pcf);
+	set_ctrl(client, buf[0]);
+
+	return 0;
+
+exit_detach:
+	i2c_detach_client(client);
+
+exit_kfree:
+	kfree(pcf);
+
+	return err;
+}
+
+static __init int pcf8583_init(void)
+{
+	return i2c_add_driver(&pcf8583_driver);
+}
+
+static __exit void pcf8583_exit(void)
+{
+	i2c_del_driver(&pcf8583_driver);
+}
+
+module_init(pcf8583_init);
+module_exit(pcf8583_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("PCF8583 I2C RTC driver");
+MODULE_LICENSE("GPL");
diff -u a/drivers/rtc/Makefile b/drivers/rtc/Makefile
--- a/drivers/rtc/Makefile	2006-04-28 15:28:20.000000000
+++ b/drivers/rtc/Makefile	2006-05-02 15:06:47.000000000
@@ -15,6 +15,7 @@
 obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o
 obj-$(CONFIG_RTC_DRV_DS1672)	+= rtc-ds1672.o
 obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o
+obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
 obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o
 obj-$(CONFIG_RTC_DRV_M48T86)	+= rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
diff -u a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
--- a/drivers/rtc/Kconfig	2006-04-28 15:28:20.000000000
+++ b/drivers/rtc/Kconfig	2006-05-03 12:34:21.593469115
@@ -107,6 +107,16 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-pcf8563.
 
+config RTC_DRV_PCF8583
+	tristate "Philips PCF8583"
+	depends on RTC_CLASS && I2C
+	help
+	  If you say yes here you get support for the
+	  Philips PCF8583 RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-pcf8583.
+
 config RTC_DRV_RS5C372
 	tristate "Ricoh RS5C372A/B"
 	depends on RTC_CLASS && I2C

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2006-05-05 18:43 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-03-31 10:04 [PATCH 00/10] RTC subsystem Alessandro Zummo
2006-03-31 10:04 ` [PATCH 01/10] RTC subsystem, DS1672 oscillator handling Alessandro Zummo
2006-03-31 10:04 ` [PATCH 02/10] RTC subsystem, DS1672 cleanup Alessandro Zummo
2006-03-31 10:04 ` [PATCH 03/10] RTC subsystem, X1205 sysfs cleanup Alessandro Zummo
2006-03-31 10:04 ` [PATCH 04/10] RTC subsystem, whitespaces and error messages cleanup Alessandro Zummo
2006-03-31 10:04 ` [PATCH 05/10] RTC subsystem, fix proc output Alessandro Zummo
2006-03-31 10:04 ` [PATCH 06/10] RTC subsystem, RS5C372 sysfs fix Alessandro Zummo
2006-03-31 10:04 ` [PATCH 07/10] RTC subsystem, compact error messages Alessandro Zummo
2006-03-31 10:04 ` [PATCH 08/10] RTC subsystem, SA1100 cleanup Alessandro Zummo
2006-04-02 18:43   ` Pavel Machek
2006-03-31 10:04 ` [PATCH 09/10] RTC subsystem, VR41XX driver Alessandro Zummo
2006-04-01 23:20   ` Andrew Morton
2006-03-31 10:04 ` [PATCH 10/10] RTC subsystem, VR41XX cleanup Alessandro Zummo
     [not found] ` <Pine.LNX.4.63.0605030826290.1846@pcgl.dsa-ac.de>
     [not found]   ` <20060503105816.65f309f8@inspiron>
     [not found]     ` <Pine.LNX.4.63.0605031120570.1846@pcgl.dsa-ac.de>
     [not found]       ` <20060503121354.61bf3558@inspiron>
     [not found]         ` <Pine.LNX.4.63.0605031223350.1846@pcgl.dsa-ac.de>
     [not found]           ` <20060503122555.5337523f@inspiron>
     [not found]             ` <Pine.LNX.4.63.0605031242020.1846@pcgl.dsa-ac.de>
     [not found]               ` <20060503132301.52a75dcd@inspiron>
2006-05-05 18:43                 ` drivers/acorn/char/pcf8583.[hc] vs. RTC subsystem Guennadi Liakhovetski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox