From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Lx3HT-0006TJ-3j for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:04:15 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Lx3HS-0006SY-6k for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:04:14 -0400 Received: from [199.232.76.173] (port=59425 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Lx3HS-0006SR-09 for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:04:14 -0400 Received: from flounder.pepperfish.net ([87.237.62.181]:46922) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Lx3HR-0004p3-5M for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:04:13 -0400 Received: from [10.112.102.2] (helo=jennifer.kylikki.org) by flounder.pepperfish.net with esmtps (Exim 4.69 #1 (Debian)) id 1Lx3HO-0004KH-UX for ; Thu, 23 Apr 2009 19:04:11 +0100 Received: from derik.kyllikki.org ([192.168.7.20] helo=derik) by jennifer.kylikki.org with esmtp (Exim 4.63) (envelope-from ) id 1Lx3HP-0006CF-Au for qemu-devel@nongnu.org; Thu, 23 Apr 2009 19:04:11 +0100 Received: from vince by derik with local (Exim 4.69) (envelope-from ) id 1Lx3HP-00041j-8r for qemu-devel@nongnu.org; Thu, 23 Apr 2009 19:04:11 +0100 Date: Thu, 23 Apr 2009 19:04:11 +0100 From: Vincent Sanders Subject: [Qemu-devel] [PATCH 8/16] S3C Real Time Clock Message-ID: <20090423180411.GK4629@derik> References: <20090423171503.GC4629@derik> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20090423171503.GC4629@derik> List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Real Time clock Signed-off-by: Vincent Sanders --- s3c24xx_rtc.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff -urN qemusvnclean/hw/s3c24xx_rtc.c qemusvnpatches/hw/s3c24xx_rtc.c --- qemusvnclean/hw/s3c24xx_rtc.c 1970-01-01 01:00:00.000000000 +0100 +++ qemusvnpatches/hw/s3c24xx_rtc.c 2009-04-23 17:07:07.000000000 +0100 @@ -0,0 +1,123 @@ +/* hw/s3c24xx_rtc.c + * + * Samsung S3C24XX RTC emulation + * + * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders + * + * This file is under the terms of the GNU General Public + * License Version 2 + */ + +#include "hw.h" + +#include "s3c24xx.h" + + +/* RTC Control RW Byte */ +#define S3C_REG_RTCCON 0 +/* Tick time count RW Byte */ +#define S3C_REG_TICNT 1 +/* RTC Alarm Control RW Byte */ +#define S3C_REG_RTCALM 4 +/* Alarm second */ +#define S3C_REG_ALMSEC 5 +/* Alarm minute */ +#define S3C_REG_ALMMIN 6 +/* Alarm hour */ +#define S3C_REG_ALMHOUR 7 +/* Alarm day */ +#define S3C_REG_ALMDATE 8 +/* Alarm month */ +#define S3C_REG_ALMMON 9 +/* Alarm year */ +#define S3C_REG_ALMYEAR 10 +/* RTC Round Reset */ +#define S3C_REG_RTCRST 11 +/* BCD Second */ +#define S3C_REG_BCDSEC 12 +/* BCD Minute */ +#define S3C_REG_BCDMIN 13 +/* BCD Hour */ +#define S3C_REG_BCDHOUR 14 +/* BCD Day */ +#define S3C_REG_BCDDATE 15 +/* BCD Day of week */ +#define S3C_REG_BCDDAY 16 +/* BCD Month */ +#define S3C_REG_BCDMON 17 +/* BCD Year */ +#define S3C_REG_BCDYEAR 18 + +static inline int to_bcd(int a) +{ + return ((a/10)<<4) | (a%10); +} + +static void update_time(S3CState *soc) +{ + time_t ti; + struct tm *tm; + /* update the RTC registers from system time */ + time(&ti); + tm = gmtime(&ti); + soc->rtc_reg[S3C_REG_BCDSEC] = to_bcd(tm->tm_sec); + soc->rtc_reg[S3C_REG_BCDMIN] = to_bcd(tm->tm_min); + soc->rtc_reg[S3C_REG_BCDHOUR] = to_bcd(tm->tm_hour); + soc->rtc_reg[S3C_REG_BCDDATE] = to_bcd(tm->tm_mday); + soc->rtc_reg[S3C_REG_BCDDAY] = to_bcd(tm->tm_wday + 1); + soc->rtc_reg[S3C_REG_BCDMON] = to_bcd(tm->tm_mon + 1); + soc->rtc_reg[S3C_REG_BCDYEAR] = to_bcd(tm->tm_year - 100); +} + +static void +s3c24xx_rtc_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value) +{ + S3CState *soc = (S3CState *)opaque; + int addr = (addr_ - 0x40) >> 2; + if (addr < 0 || addr > 18) + addr = 18; + + soc->rtc_reg[addr] = value; +} + +static uint32_t +s3c24xx_rtc_read_f(void *opaque, target_phys_addr_t addr_) +{ + S3CState *soc = (S3CState *)opaque; + int addr = (addr_ - 0x40) >> 2; + + if (addr < 0 || addr > 18) + addr = 18; + + update_time(soc); + + return soc->rtc_reg[addr]; +} + +static CPUReadMemoryFunc *s3c24xx_rtc_read[] = { + &s3c24xx_rtc_read_f, + &s3c24xx_rtc_read_f, + &s3c24xx_rtc_read_f, +}; + +static CPUWriteMemoryFunc *s3c24xx_rtc_write[] = { + &s3c24xx_rtc_write_f, + &s3c24xx_rtc_write_f, + &s3c24xx_rtc_write_f, +}; + + +void +s3c24xx_rtc_init(S3CState *soc, target_phys_addr_t base_addr) +{ + int tag; + tag = cpu_register_io_memory(0, s3c24xx_rtc_read, s3c24xx_rtc_write, soc); + + /* there are only 19 real registers but they start at offset 0x40 into the + * range so we have 35 registers mapped + */ + cpu_register_physical_memory(base_addr, 35 * 4, tag); + + /* set the RTC so it appears active */ + soc->rtc_reg[S3C_REG_RTCCON] = 1; +} -- Regards Vincent http://www.kyllikki.org/