From patchwork Sun Dec 2 17:22:30 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antoine Mathys X-Patchwork-Id: 203234 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9CD912C007D for ; Mon, 3 Dec 2012 04:22:44 +1100 (EST) Received: from localhost ([::1]:59375 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TfDFa-0004X4-QF for incoming@patchwork.ozlabs.org; Sun, 02 Dec 2012 12:22:42 -0500 Received: from eggs.gnu.org ([208.118.235.92]:33924) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TfDFT-0004Wx-Vo for qemu-devel@nongnu.org; Sun, 02 Dec 2012 12:22:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TfDFS-00025i-R1 for qemu-devel@nongnu.org; Sun, 02 Dec 2012 12:22:35 -0500 Received: from mail-bk0-f45.google.com ([209.85.214.45]:59526) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TfDFS-00025b-JX for qemu-devel@nongnu.org; Sun, 02 Dec 2012 12:22:34 -0500 Received: by mail-bk0-f45.google.com with SMTP id jk13so680924bkc.4 for ; Sun, 02 Dec 2012 09:22:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:cc:subject :content-type:content-transfer-encoding; bh=mTskePx+5bIwnbBjniLZbyG5rB7ey/yFqiCT7vB10sA=; b=NZV9ZHWuJOC+H/tZVhWrTCgNiTfcuZYOKOcNdrdFN2xRHQdij7gN/zGwBHWts9W5ef FDAMmXe0oZLK2t5ZhUawG1R2srZ2X8kflDrHtRYj0sGvd5TQqRIg58x0P1fvvD2Or5tj eRFoFaB8QtDKdflM7zT5ijtd1BZv8hRBsgucWs0JiKYQ1lIrKsSSF0+KmCS4bQMgx7AV JO6XkdJqRlYJl0yq+1HZc/Q8X0yqvwJh96UVILDrcxpnTSzP+hLcLwS1pEFWrKotRSxL iMgV90zDROPZaODtXZ7PJ3jgX1jHErUurnxwErQr6UL4Cow6sdyCnfu8M5yv1UJtcRTF ynYQ== Received: by 10.204.8.18 with SMTP id f18mr2228532bkf.82.1354468953775; Sun, 02 Dec 2012 09:22:33 -0800 (PST) Received: from [192.168.1.33] (adsl-89-217-2-169.adslplus.ch. [89.217.2.169]) by mx.google.com with ESMTPS id l17sm5743752bkw.12.2012.12.02.09.22.31 (version=SSLv3 cipher=OTHER); Sun, 02 Dec 2012 09:22:32 -0800 (PST) Message-ID: <50BB8E56.1050303@gmail.com> Date: Sun, 02 Dec 2012 18:22:30 +0100 From: Antoine Mathys User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/17.0 Thunderbird/17.0 MIME-Version: 1.0 To: qemu-devel@nongnu.org X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.214.45 Cc: peter.maydell@linaro.org, paul@codesourcery.com Subject: [Qemu-devel] [PATCH 4/4] hw/ds1338.c: Handle stuck bits and preserve CH X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- hw/ds1338.c | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) s->addr_byte = true; 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: