From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Lx3GC-00060L-Df for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:02:56 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Lx3GB-0005zs-Gq for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:02:56 -0400 Received: from [199.232.76.173] (port=33093 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Lx3GB-0005zf-6d for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:02:55 -0400 Received: from flounder.pepperfish.net ([87.237.62.181]:47453) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Lx3GA-0004c9-5U for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:02:54 -0400 Received: from [10.112.102.2] (helo=jennifer.kylikki.org) by flounder.pepperfish.net with esmtps (Exim 4.69 #1 (Debian)) id 1Lx3G8-0004EU-1W for ; Thu, 23 Apr 2009 19:02:52 +0100 Received: from derik.kyllikki.org ([192.168.7.20] helo=derik) by jennifer.kylikki.org with esmtp (Exim 4.63) (envelope-from ) id 1Lx3G8-0006CB-DA for qemu-devel@nongnu.org; Thu, 23 Apr 2009 19:02:52 +0100 Received: from vince by derik with local (Exim 4.69) (envelope-from ) id 1Lx3G8-00041V-Br for qemu-devel@nongnu.org; Thu, 23 Apr 2009 19:02:52 +0100 Date: Thu, 23 Apr 2009 19:02:52 +0100 From: Vincent Sanders Subject: [Qemu-devel] [PATCH 6/16] S3C Timers Message-ID: <20090423180252.GJ4629@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 S3C Timer implementation Signed-off-by: Vincent Sanders --- s3c24xx_timers.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff -urN qemusvnclean/hw/s3c24xx_timers.c qemusvnpatches/hw/s3c24xx_timers.c --- qemusvnclean/hw/s3c24xx_timers.c 1970-01-01 01:00:00.000000000 +0100 +++ qemusvnpatches/hw/s3c24xx_timers.c 2009-04-23 16:03:04.000000000 +0100 @@ -0,0 +1,137 @@ +/* hw/s3c24xx_timers.c + * + * Samsung S3C24XX 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 "qemu-timer.h" + +#include "s3c24xx.h" + +/* + QEMU_TIMER_BASE is ticks per second for the qemu clocks + TCLK1 (assumed input for timer4) is 12 MHz + Thus, period in ticks of timer4 is: + + (timer4_period * QEMU_TIMER_BASE) / TCLK1 +*/ + +/* Timer configuration 0 */ +#define S3C_TIMERS_TCFG0 0 +/* Timer configuration 1 */ +#define S3C_TIMERS_TCFG1 1 +/* Timer control */ +#define S3C_TIMERS_TCON 2 +/* Timer count buffer 0 */ +#define S3C_TIMERS_TCNTB0 3 +/* Timer compare buffer 0 */ +#define S3C_TIMERS_TCMPB0 4 +/* Timer count observation 0 */ +#define S3C_TIMERS_TCNTO0 5 +/* Timer count buffer 1 */ +#define S3C_TIMERS_TCNTB1 6 +/* Timer compare buffer 1 */ +#define S3C_TIMERS_TCMPB1 7 +/* Timer count observation 1 */ +#define S3C_TIMERS_TCNTO1 8 +/* Timer count buffer 2 */ +#define S3C_TIMERS_TCNTB2 9 +/* Timer compare buffer 2 */ +#define S3C_TIMERS_TCMPB2 10 +/* Timer count observation 2 */ +#define S3C_TIMERS_TCNTO2 11 +/* Timer count buffer 3 */ +#define S3C_TIMERS_TCNTB3 12 +/* Timer compare buffer 3 */ +#define S3C_TIMERS_TCMPB3 13 +/* Timer count observation 3 */ +#define S3C_TIMERS_TCNTO3 14 +/* Timer count buffer 4 */ +#define S3C_TIMERS_TCNTB4 15 +/* Timer count observation 4 */ +#define S3C_TIMERS_TCNTO4 16 + +static void +s3c24xx_schedule_timer4(S3CState *soc) +{ + soc->timers_reg[S3C_TIMERS_TCNTB4] = soc->timer4_reload_value; + soc->timer4_last_ticked = qemu_get_clock(vm_clock); + qemu_mod_timer(soc->timer4, + soc->timer4_last_ticked + ((soc->timer4_reload_value * ticks_per_sec) / soc->tclk1)); +} + +static void +s3c24xx_timer4_tick(void *opaque) +{ + S3CState *soc = (S3CState *)opaque; + + qemu_set_irq(soc->irqs[14], 1); + if (soc->timers_reg[S3C_TIMERS_TCON] && (1<<22)) { + s3c24xx_schedule_timer4(soc); + } +} + +static void +s3c24xx_timers_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value) +{ + S3CState *soc = (S3CState *)opaque; + int addr = (addr_ >> 2) & 0x1f; + + soc->timers_reg[addr] = value; + if (addr == S3C_TIMERS_TCON) { + /* If Timer4's manual update is set, copy in the reload value */ + if (value & (1 << 21) ) + soc->timer4_reload_value = soc->timers_reg[S3C_TIMERS_TCNTB4]; + + /* If Timer4's manual update is unset, and the timer is running, start it */ + if (!(value & (1 << 21)) && + value & (1 << 20)) { + s3c24xx_schedule_timer4(soc); + } + } +} + +static uint32_t +s3c24xx_timers_read_f(void *opaque, target_phys_addr_t addr_) +{ + S3CState *soc = (S3CState *)opaque; + int addr = (addr_ >> 2) & 0x1f; + + if (addr == S3C_TIMERS_TCNTO4 ) { + return soc->timer4_reload_value - + (((qemu_get_clock(vm_clock) - soc->timer4_last_ticked) * soc->tclk1) / ticks_per_sec); + } + return soc->timers_reg[addr]; +} + + +static CPUReadMemoryFunc *s3c24xx_timers_read[] = { + &s3c24xx_timers_read_f, + &s3c24xx_timers_read_f, + &s3c24xx_timers_read_f, +}; + +static CPUWriteMemoryFunc *s3c24xx_timers_write[] = { + &s3c24xx_timers_write_f, + &s3c24xx_timers_write_f, + &s3c24xx_timers_write_f, +}; + +void +s3c24xx_timers_init(S3CState *soc, target_phys_addr_t base_addr) +{ + /* Samsung S3C2410X timer registration. + * + * Specifically the PWM timer4. + */ + int tag = cpu_register_io_memory(0, s3c24xx_timers_read, s3c24xx_timers_write, soc); + cpu_register_physical_memory(base_addr, 17 * 4, tag); + + soc->timer4 = qemu_new_timer(vm_clock, s3c24xx_timer4_tick, soc); +} + -- Regards Vincent http://www.kyllikki.org/