From 1353cd9749377dbcc8290dab5c098deec66fb956 Mon Sep 17 00:00:00 2001
From: Kurt Mahan <kmahan@freescale.com>
Date: Thu, 15 May 2008 13:24:58 -0600
Subject: [PATCH] Add RTC RV5C387A driver for MCF547x and MCF548x.

LTIBName: m547x-8x-rtc-rv5c387a
Signed-off-by: Kurt Mahan <kmahan@freescale.com>
Signed-off-by: Shrek Wu <b16972@freescale.com>
---
 drivers/rtc/rtc-rs5c372.c |   67 +++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 62 insertions(+), 5 deletions(-)

--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -15,7 +15,6 @@
 
 #define DRV_VERSION "0.5"
 
-
 /*
  * Ricoh has a family of I2C based RTCs, which differ only slightly from
  * each other.  Differences center on pinout (e.g. how many interrupts,
@@ -60,6 +59,15 @@
 /* to read (style 1) or write registers starting at R */
 #define RS5C_ADDR(R)		(((R) << 4) | 0)
 
+#ifdef CONFIG_M547X_8X
+#define DRV_NAME "rv5c387a"
+/* i2c configuration */
+#define RV5C387_I2C_ADDR 0x32
+static unsigned short normal_i2c[] = {
+	RV5C387_I2C_ADDR, I2C_CLIENT_END
+};
+I2C_CLIENT_INSMOD; /* defines addr_data */
+#endif
 
 enum rtc_type {
 	rtc_undef = 0,
@@ -506,14 +514,14 @@ static int rs5c372_probe(struct i2c_clie
 		err = -ENODEV;
 		goto exit;
 	}
-
-	if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) {
+	rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL);
+	if (!rs5c372) {
 		err = -ENOMEM;
 		goto exit;
 	}
 
 	/* we read registers 0x0f then 0x00-0x0f; skip the first one */
-	rs5c372->regs=&rs5c372->buf[1];
+	rs5c372->regs = &rs5c372->buf[1];
 
 	rs5c372->client = client;
 	i2c_set_clientdata(client, rs5c372);
@@ -605,7 +613,7 @@ static int rs5c372_probe(struct i2c_clie
 			case rtc_rv5c386:	s = "rv5c386"; break;
 			case rtc_rv5c387a:	s = "rv5c387a"; break;
 			default:		s = "chip"; break;
-			}; s;}),
+			}; s; }),
 			rs5c372->time24 ? "24hr" : "am/pm"
 			);
 
@@ -645,12 +653,61 @@ static int rs5c372_remove(struct i2c_cli
 	return 0;
 }
 
+#ifdef CONFIG_M547X_8X
+static int rv5c387_probe(struct i2c_adapter *adapter, int addr, int kind)
+{
+	int rc = 0;
+	struct i2c_client *new_client = NULL;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+		rc = -ENODEV;
+		printk(KERN_DEBUG "%s i2c_check_functionality\n", __FUNCTION__);
+		goto failout;
+	}
+
+	new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (new_client == NULL) {
+		rc = -ENOMEM;
+		printk(KERN_DEBUG "%s kzalloc new_client\n", __FUNCTION__);
+		goto failout;
+	}
+
+	new_client->addr = addr;
+	new_client->adapter = adapter;
+	new_client->driver = &rs5c372_driver;
+	new_client->flags = 0;
+	strcpy(new_client->name, DRV_NAME);
+
+	rc = i2c_attach_client(new_client);
+	if (rc < 0) {
+		printk(KERN_DEBUG "%s i2c_attach_client\n", __FUNCTION__);
+		goto failout;
+	}
+
+	rs5c372_probe(new_client);
+	return 0;
+failout:
+	kfree(new_client);
+	return rc;
+}
+
+static int
+rv5c387_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_probe(adapter, &addr_data, rv5c387_probe);
+}
+#endif
+
 static struct i2c_driver rs5c372_driver = {
 	.driver		= {
 		.name	= "rtc-rs5c372",
 	},
+#ifdef CONFIG_M547X_8X
+	.attach_adapter = &rv5c387_attach_adapter,
+#else
 	.probe		= rs5c372_probe,
 	.remove		= rs5c372_remove,
+#endif
 };
 
 static __init int rs5c372_init(void)