qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Antoine Mathys <barsamin@gmail.com>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, paul@codesourcery.com
Subject: [Qemu-devel] [PATCH 4/4] hw/ds1338.c: Handle stuck bits and preserve CH
Date: Sun, 02 Dec 2012 18:22:30 +0100	[thread overview]
Message-ID: <50BB8E56.1050303@gmail.com> (raw)

Preserve the CH bit when updating the time.

Per the datasheet, some bits in the first eight registers must always 
read back as zero. These registers can be written in two ways:
1. By ourselves when we update the registers with the current time.
2. By user request
Even though (1) is not supposed to set these bits it is safer to check 
anyway. In order not to duplicate this logic I thus chose to enforce it 
at read time.
Note that currently we don't preserve what the user sends in (2). We 
will have to once we support stopping the clock (CH bit).

Signed-off-by: Antoine Mathys <barsamin@gmail.com>
---
  hw/ds1338.c |   50 ++++++++++++++++++++++++++++++++++----------------
  1 file changed, 34 insertions(+), 16 deletions(-)

diff --git a/hw/ds1338.c b/hw/ds1338.c
index f3c6bc5..8f85635 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -40,17 +40,17 @@ static const VMStateDescription vmstate_ds1338 = {
      }
  };

-static void capture_current_time(DS1338State *s)
+/* Write TM to the RTC registers. */
+static void write_time(DS1338State *s, const struct tm *tm)
  {
-    /* Capture the current time into the secondary registers
-     * which will be actually read by the data transfer operation.
-     */
-    struct tm now;
-    qemu_get_timedate(&now, s->offset);
-    s->nvram[0] = to_bcd(now.tm_sec);
-    s->nvram[1] = to_bcd(now.tm_min);
+    /* Preserve the CH flag. */
+    s->nvram[0] &= 0x80;
+    s->nvram[0] |= to_bcd(tm->tm_sec);
+
+    s->nvram[1] = to_bcd(tm->tm_min);
+
      if (s->nvram[2] & 0x40) {
-        int tmp = now.tm_hour;
+        int tmp = tm->tm_hour;
          if (tmp == 0) {
              tmp = 24;
          }
@@ -60,12 +60,30 @@ static void capture_current_time(DS1338State *s)
              s->nvram[2] = 0x60 | to_bcd(tmp - 12);
          }
      } else {
-        s->nvram[2] = to_bcd(now.tm_hour);
+        s->nvram[2] = to_bcd(tm->tm_hour);
      }
-    s->nvram[3] = to_bcd(now.tm_wday + 1);
-    s->nvram[4] = to_bcd(now.tm_mday);
-    s->nvram[5] = to_bcd(now.tm_mon + 1);
-    s->nvram[6] = to_bcd(now.tm_year - 100);
+    s->nvram[3] = to_bcd(tm->tm_wday + 1);
+    s->nvram[4] = to_bcd(tm->tm_mday);
+    s->nvram[5] = to_bcd(tm->tm_mon + 1);
+    s->nvram[6] = to_bcd(tm->tm_year - 100);
+}
+
+static void update_read_buffer(DS1338State *s)
+{
+    /* Capture the current time into the secondary registers
+     * which will be actually read by the data transfer operation.
+     */
+    struct tm now;
+    qemu_get_timedate(&now, s->offset);
+    write_time(s, &now);
+
+    /* Ensure specified bits read as zero. */
+    s->nvram[1] &= 0x7F;
+    s->nvram[2] &= 0x7F;
+    s->nvram[3] &= 0x07;
+    s->nvram[4] &= 0x3F;
+    s->nvram[5] &= 0x1F;
+    s->nvram[7] &= 0xB3;
  }

  static void inc_regptr(DS1338State *s)
@@ -76,7 +94,7 @@ static void inc_regptr(DS1338State *s)
       */
      s->ptr = (s->ptr + 1) & (NVRAM_SIZE - 1);
      if (!s->ptr) {
-        capture_current_time(s);
+        update_read_buffer(s);
      }
  }

@@ -91,7 +109,7 @@ static void ds1338_event(I2CSlave *i2c, enum 
i2c_event event)
           * START_SEND, because the guest can't get at that data
           * without going through a START_RECV which would overwrite it.
           */
-        capture_current_time(s);
+        update_read_buffer(s);
          break;
      case I2C_START_SEND:
          s->addr_byte = true;
-- 
1.7.10.4

             reply	other threads:[~2012-12-02 17:22 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-02 17:22 Antoine Mathys [this message]
2012-12-04 18:01 ` [Qemu-devel] [PATCH 4/4] hw/ds1338.c: Handle stuck bits and preserve CH Peter Maydell

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=50BB8E56.1050303@gmail.com \
    --to=barsamin@gmail.com \
    --cc=paul@codesourcery.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.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;
as well as URLs for NNTP newsgroup(s).