All of lore.kernel.org
 help / color / mirror / Atom feed
* [lm-sensors] [PATCH] x1205 fix osc on startup
@ 2005-12-13 20:47 Alessandro Zummo
  0 siblings, 0 replies; only message in thread
From: Alessandro Zummo @ 2005-12-13 20:47 UTC (permalink / raw)
  To: lm-sensors


Content-Disposition: inline; filename=i2c-x1205-fix-osc.patch

When the battery fails, the x1205 will refuse to run the oscillator
unless something is written to its date/time register.

On platforms where this driver is actually used (NSLU2), along with
a class based RTC core, the time is updated via /dev/rtc 
using the hwclock utility.

hwclock will wait for a seconds increment before writing the new
date/time and that's why this patch is required for it to work.

Requires i2c-x1205-cleanup.patch

Signed-off-by: Alessandro Zummo <a.zummo at towertech.it>
---
 drivers/i2c/chips/x1205.c |  116 ++++++++++++++++++++++++++++++----------------
 1 file changed, 76 insertions(+), 40 deletions(-)

--- linux-nslu2.orig/drivers/i2c/chips/x1205.c	2005-12-12 18:59:07.000000000 +0100
+++ linux-nslu2/drivers/i2c/chips/x1205.c	2005-12-13 21:31:32.000000000 +0100
@@ -22,9 +22,9 @@
 #include <linux/string.h>
 #include <linux/bcd.h>
 #include <linux/rtc.h>
+#include <linux/delay.h>
 
-
-#define DRV_VERSION "1.0.0"
+#define DRV_VERSION "1.0.1"
 
 /* Addresses to scan: none. This chip is located at
  * 0x6f and uses a two bytes register addressing.
@@ -141,35 +141,19 @@ static int x1205_validate_tm(struct rtc_
  * Epoch is initialized as 2000. Time is set to UTC.
  */
 static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
-				u8 reg_base)
+				unsigned char reg_base)
 {
 	unsigned char dt_addr[2] = { 0, reg_base };
-	static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
 
-	unsigned char buf[8], sr;
+	unsigned char buf[8];
 
 	struct i2c_msg msgs[] = {
-		{ client->addr, 0, 2, sr_addr },	/* setup read ptr */
-		{ client->addr, I2C_M_RD, 1, &sr }, 	/* read status */
 		{ client->addr, 0, 2, dt_addr },	/* setup read ptr */
 		{ client->addr, I2C_M_RD, 8, buf },	/* read date */
 	};
 
-	/* read status register */
-	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
-		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
-		return -EIO;
-	}
-
-	/* check for battery failure */
-	if (sr & X1205_SR_RTCF) {
-		dev_warn(&client->dev,
-			"Clock had a power failure, you must set the date.\n");
-		return -EINVAL;
-	}
-
 	/* read date registers */
-	if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
+	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
 		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
 		return -EIO;
 	}
@@ -199,11 +183,28 @@ static int x1205_get_datetime(struct i2c
 	return 0;
 }
 
+static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
+{
+	static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
+
+	struct i2c_msg msgs[] = {
+		{ client->addr, 0, 2, sr_addr },	/* setup read ptr */
+		{ client->addr, I2C_M_RD, 1, sr },	/* read status */
+	};
+
+	/* read status register */
+	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
 				int datetoo, u8 reg_base)
 {
-	int i, err, xfer;
-
+	int i, xfer;
 	unsigned char buf[8];
 
 	static const unsigned char wel[3] = { 0, X1205_REG_SR,
@@ -214,15 +215,10 @@ static int x1205_set_datetime(struct i2c
 
 	static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
 
-	/* check if all values in the tm struct are correct */
-	if ((err = x1205_validate_tm(tm)) < 0)
-		return err;
-
-	dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
-		"mday=%d, mon=%d, year=%d, wday=%d\n",
+	dev_dbg(&client->dev,
+		"%s: secs=%d, mins=%d, hours=%d\n",
 		__FUNCTION__,
-		tm->tm_sec, tm->tm_min, tm->tm_hour,
-		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+		tm->tm_sec, tm->tm_min, tm->tm_hour);
 
 	buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
 	buf[CCR_MIN] = BIN2BCD(tm->tm_min);
@@ -232,6 +228,11 @@ static int x1205_set_datetime(struct i2c
 
 	/* should we also set the date? */
 	if (datetoo) {
+		dev_dbg(&client->dev,
+			"%s: mday=%d, mon=%d, year=%d, wday=%d\n",
+			__FUNCTION__,
+			tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
 		buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
 
 		/* month, 0 - 11 */
@@ -280,6 +281,22 @@ static int x1205_set_datetime(struct i2c
 	return 0;
 }
 
+static int x1205_fix_osc(struct i2c_client *client)
+{
+	int err;
+	struct rtc_time tm;
+
+	tm.tm_hour = 0;
+	tm.tm_min = 0;
+	tm.tm_sec = 0;
+
+	if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0)
+		dev_err(&client->dev,
+			"unable to restart the clock\n");
+
+	return err;
+}
+
 static int x1205_get_dtrim(struct i2c_client *client, int *trim)
 {
 	unsigned char dtr;
@@ -352,14 +369,17 @@ static int x1205_hctosys(struct i2c_clie
 
 	struct rtc_time tm;
 	struct timespec tv;
+	unsigned char sr;
 
+	if ((err = x1205_get_status(client, &sr)) < 0)
+		return err;
 
-	err = x1205_get_datetime(client, &tm, X1205_CCR_BASE);
-	if (err) {
-		dev_err(&client->dev,
-			"Unable to set the system clock\n");
+	/* Don't set if we had a power failure */
+	if (sr & X1205_SR_RTCF)
+		return -EINVAL;
+
+	if ((err = x1205_get_datetime(client, &tm, X1205_CCR_BASE)) < 0)
 		return err;
-	}
 
 	/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
 	 * whether it stores the most close value or the value with partial
@@ -506,9 +526,9 @@ static int x1205_attach(struct i2c_adapt
 
 static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
 {
-	struct i2c_client *client;
-
 	int err = 0;
+	unsigned char sr;
+	struct i2c_client *client;
 
 	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
 
@@ -543,9 +563,25 @@ static int x1205_probe(struct i2c_adapte
 
 	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
+	/* Check for power failures and eventualy enable the osc */
+	if ((err = x1205_get_status(client, &sr)) = 0) {
+		if (sr & X1205_SR_RTCF) {
+			dev_err(&client->dev,
+				"power failure detected, "
+				"please set the clock\n");
+			udelay(50);
+			x1205_fix_osc(client);
+		}
+	}
+	else
+		dev_err(&client->dev, "couldn't read status\n");
+
 	/* If requested, set the system time */
-	if (hctosys)
-		x1205_hctosys(client);
+	if (hctosys) {
+		if ((err = x1205_hctosys(client)) < 0)
+			dev_err(&client->dev,
+				"unable to set the system clock\n");
+	}
 
 	return 0;
 


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-12-13 20:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-12-13 20:47 [lm-sensors] [PATCH] x1205 fix osc on startup Alessandro Zummo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.