Patchwork Subject: [PATCH] rtc-m41t80: Check stored time validitiy during device probe.

login
register
mail settings
Submitter Richard Retanubun
Date Aug. 13, 2010, 8:35 p.m.
Message ID <4C65AC8A.1070505@RuggedCom.com>
Download mbox | patch
Permalink /patch/61709/
State New
Headers show

Comments

Richard Retanubun - Aug. 13, 2010, 8:35 p.m.
From 57e07fc70021602ea02c0842817ba1a4e06c0ee7 Mon Sep 17 00:00:00 2001
From: Richard Retanubun <RichardRetanubun@RuggedCom.com>
Date: Fri, 13 Aug 2010 14:45:16 -0400
Subject: [PATCH] rtc-m41t80: Check stored time validitiy during device probe.

When the battery is gone on rtc-m41t80, data integrity is always
in question. Check the validity of the returned date time.

In addition, if the time is found to be invalid during device probe,
initialize the date time to a sane default value.
---
The checking validity during reads are already mainlined with
commit b485fe5ea1008db02abff9ef15be4f31b52df4f7
My change simply adds a typecast to remove compiler warning for
m41t80_rtc_read_alarm

The valid time check during device probe is what I am proposing,
what the default time should be is probably up for debate
I made it a #def to make it easy to customize.

  drivers/rtc/rtc-m41t80.c |   49 +++++++++++++++++++++++++++++++++++++--------
  1 files changed, 40 insertions(+), 9 deletions(-)

--
1.7.1

Patch

diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 60fe266..9ac82b1 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -66,6 +66,8 @@ 
  #define M41T80_FEATURE_WD	(1 << 3)	/* Extra watchdog resolution */
  #define M41T80_FEATURE_SQ_ALT	(1 << 4)	/* RSx bits are in reg 4 */

+#define M41T80_DEFAULT_TIME	1262304000	/* 2010-01-01 00:00:00 UTC */
+
  #define DRV_VERSION "0.05"

  static const struct i2c_device_id m41t80_id[] = {
@@ -121,7 +123,7 @@  static int m41t80_get_datetime(struct i2c_client *client,

  	/* assume 20YY not 19YY, and ignore the Century Bit */
  	tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100;
-	return 0;
+	return rtc_valid_tm(tm);
  }

  /* Sets the given date and time to the real time clock. */
@@ -364,7 +366,7 @@  static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
  	t->time.tm_isdst = -1;
  	t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE);
  	t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF);
-	return 0;
+	return rtc_valid_tm((struct rtc_time *)t);
  }

  static struct rtc_class_ops m41t80_rtc_ops = {
@@ -806,21 +808,50 @@  static int m41t80_probe(struct i2c_client *client,

  	if (rc & M41T80_ALHOUR_HT) {
  		if (clientdata->features & M41T80_FEATURE_HT) {
-			m41t80_get_datetime(client, &tm);
  			dev_info(&client->dev, "HT bit was set!\n");
-			dev_info(&client->dev,
-				 "Power Down at "
-				 "%04i-%02i-%02i %02i:%02i:%02i\n",
-				 tm.tm_year + 1900,
-				 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
-				 tm.tm_min, tm.tm_sec);
+
+			/* Show power down time only if it is valid */
+			if (m41t80_get_datetime(client, &tm) == 0) {
+				dev_info(&client->dev,
+					"Power Down at "
+					"%04i-%02i-%02i %02i:%02i:%02i\n",
+					tm.tm_year + 1900,
+					tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+					tm.tm_min, tm.tm_sec);
+			}
  		}
+		/* Clear the HT bit */
  		if (i2c_smbus_write_byte_data(client,
  					      M41T80_REG_ALARM_HOUR,
  					      rc & ~M41T80_ALHOUR_HT) < 0)
  			goto ht_err;
  	}

+	/*
+	 * check if RTC time is valid, if it is not valid, set it to known
+	 * default. The check is done here to make sure HT bit is
+	 * already checked and cleared before time is set.
+	 */
+	if (m41t80_get_datetime(client, &tm) != 0) {
+		dev_err(&client->dev,
+			"Invalid date %04i-%02i-%02i %02i:%02i:%02i\n",
+			tm.tm_year + 1900,
+			tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+			tm.tm_min, tm.tm_sec);
+
+		rtc_time_to_tm(M41T80_DEFAULT_TIME, &tm);
+
+		dev_err(&client->dev,
+			"Date defaulted to %04i-%02i-%02i %02i:%02i:%02i\n",
+			tm.tm_year + 1900,
+			tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
+			tm.tm_min, tm.tm_sec);
+
+		if (m41t80_set_datetime(client, &tm) != 0) {
+			goto exit;
+		}
+	}
+
  	/* Make sure ST (stop) bit is cleared */
  	rc = i2c_smbus_read_byte_data(client, M41T80_REG_SEC);
  	if (rc < 0)