mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Nate Case <ncase@xes-inc.com>
To: David Brownell <dbrownell@users.sourceforge.net>
Cc: linux-kernel@vger.kernel.org, Nate Case <ncase@xes-inc.com>
Subject: [PATCH] rtc-ds1307: Reset bogus register values on m41t00
Date: Wed, 29 Oct 2008 12:29:37 -0500	[thread overview]
Message-ID: <1225301377-9092-1-git-send-email-ncase@xes-inc.com> (raw)

On the M41T00, registers are in a random state if the Vbat power
was lost before the driver probes it (regardless of whether or
not the oscillator is still running).  In this case, give all
registers valid values so that the bogus values don't cause it to
error out and skip the device.

Signed-off-by: Nate Case <ncase@xes-inc.com>
---
 drivers/rtc/rtc-ds1307.c |   61 +++++++++++++++++++++++++++++++++++----------
 1 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 162330b..aec17bb 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -198,6 +198,29 @@ static irqreturn_t ds1307_irq(int irq, void *dev_id)
 
 /*----------------------------------------------------------------------*/
 
+static int ds1307_regs_valid(struct ds1307 *ds1307)
+{
+	int tmp, valid = 1;
+
+	tmp = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f);
+	if (tmp > 60)
+		valid = 0;
+
+	tmp = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+	if (tmp > 60)
+		valid = 0;
+
+	tmp = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+	if (tmp == 0 || tmp > 31)
+		valid = 0;
+
+	tmp = bcd2bin(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
+	if (tmp == 0 || tmp > 12)
+		valid = 0;
+
+	return valid;
+}
+
 static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 {
 	struct ds1307	*ds1307 = dev_get_drvdata(dev);
@@ -571,6 +594,7 @@ static int __devinit ds1307_probe(struct i2c_client *client,
 	const struct chip_desc	*chip = &chips[id->driver_data];
 	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
 	int			want_irq = false;
+	int			already_reset = false;
 
 	if (!i2c_check_functionality(adapter,
 			I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
@@ -663,6 +687,28 @@ read_rtc:
 	switch (ds1307->type) {
 	case ds_1307:
 	case m41t00:
+		/*
+		 * Registers can be in random state if the Vbat power
+		 * was lost, and sometimes this will happen even with
+		 * the oscillator running.  Give all registers valid
+		 * values so that the bogus values don't cause it to
+		 * error out later on.
+		 */
+		if (!ds1307_regs_valid(ds1307)) {
+			if (already_reset)
+				goto exit_bad;
+			i2c_smbus_write_byte_data(client, DS1307_REG_YEAR, 1);
+			i2c_smbus_write_byte_data(client, DS1307_REG_MONTH, 1);
+			i2c_smbus_write_byte_data(client, DS1307_REG_MDAY, 1);
+			i2c_smbus_write_byte_data(client, DS1307_REG_WDAY, 1);
+			i2c_smbus_write_byte_data(client, DS1307_REG_HOUR, 0);
+			i2c_smbus_write_byte_data(client, DS1307_REG_MIN, 0);
+			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 1);
+			dev_warn(&client->dev, "reset bogus registers\n");
+			already_reset = true;
+			goto read_rtc;
+		}
+
 		/* clock halted?  turn it on, so clock can tick. */
 		if (tmp & DS1307_BIT_CH) {
 			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
@@ -707,20 +753,7 @@ read_rtc:
 		break;
 	}
 
-	tmp = ds1307->regs[DS1307_REG_SECS];
-	tmp = bcd2bin(tmp & 0x7f);
-	if (tmp > 60)
-		goto exit_bad;
-	tmp = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
-	if (tmp > 60)
-		goto exit_bad;
-
-	tmp = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
-	if (tmp == 0 || tmp > 31)
-		goto exit_bad;
-
-	tmp = bcd2bin(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
-	if (tmp == 0 || tmp > 12)
+	if (!ds1307_regs_valid(ds1307))
 		goto exit_bad;
 
 	tmp = ds1307->regs[DS1307_REG_HOUR];
-- 
1.6.0.2


             reply	other threads:[~2008-10-29 18:32 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-10-29 17:29 Nate Case [this message]
2008-10-30  8:16 ` David Brownell
2008-10-30 15:05   ` Nate Case
2008-10-30 17:06     ` David Brownell
2008-10-30 20:31       ` Nate Case
2008-10-30 21:34         ` Nate Case
2008-10-30 22:11           ` David Brownell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1225301377-9092-1-git-send-email-ncase@xes-inc.com \
    --to=ncase@xes-inc.com \
    --cc=dbrownell@users.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®