From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Js3nT-00064w-GY for qemu-devel@nongnu.org; Fri, 02 May 2008 18:32:07 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Js3nS-00063Q-8C for qemu-devel@nongnu.org; Fri, 02 May 2008 18:32:06 -0400 Received: from [199.232.76.173] (port=37771 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Js3nR-00063J-W6 for qemu-devel@nongnu.org; Fri, 02 May 2008 18:32:06 -0400 Received: from savannah.gnu.org ([199.232.41.3] helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Js3nR-0004UJ-9p for qemu-devel@nongnu.org; Fri, 02 May 2008 18:32:05 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1Js3nQ-0000YL-6L for qemu-devel@nongnu.org; Fri, 02 May 2008 22:32:04 +0000 Received: from edgar_igl by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1Js3nP-0000Wh-KN for qemu-devel@nongnu.org; Fri, 02 May 2008 22:32:03 +0000 MIME-Version: 1.0 Errors-To: edgar_igl Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: "Edgar E. Iglesias" Message-Id: Date: Fri, 02 May 2008 22:32:03 +0000 Subject: [Qemu-devel] [4301] ETRAX timers: Improve the support for timer1 and let the board-setup choose irq nr. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 4301 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4301 Author: edgar_igl Date: 2008-05-02 22:32:02 +0000 (Fri, 02 May 2008) Log Message: ----------- ETRAX timers: Improve the support for timer1 and let the board-setup choose irq nr. Modified Paths: -------------- trunk/hw/etraxfs_timer.c Modified: trunk/hw/etraxfs_timer.c =================================================================== --- trunk/hw/etraxfs_timer.c 2008-05-02 22:21:55 UTC (rev 4300) +++ trunk/hw/etraxfs_timer.c 2008-05-02 22:32:02 UTC (rev 4301) @@ -48,27 +48,23 @@ QEMUBH *bh; ptimer_state *ptimer; - unsigned int limit; - int scale; - uint32_t mask; struct timeval last; + /* Control registers. */ + uint32_t rw_tmr0_div; + uint32_t r_tmr0_data; + uint32_t rw_tmr0_ctrl; + + uint32_t rw_tmr1_div; + uint32_t r_tmr1_data; + uint32_t rw_tmr1_ctrl; + uint32_t rw_intr_mask; uint32_t rw_ack_intr; uint32_t r_intr; + uint32_t r_masked_intr; }; -/* diff two timevals. Return a single int in us. */ -int diff_timeval_us(struct timeval *a, struct timeval *b) -{ - int diff; - - /* assume these values are signed. */ - diff = (a->tv_sec - b->tv_sec) * 1000 * 1000; - diff += (a->tv_usec - b->tv_usec); - return diff; -} - static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr) { struct fs_timer_t *t = opaque; @@ -93,19 +89,8 @@ D(printf ("R_TMR1_DATA\n")); break; case R_TIME: - { - struct timeval now; - gettimeofday(&now, NULL); - if (!(t->last.tv_sec == 0 - && t->last.tv_usec == 0)) { - r = diff_timeval_us(&now, &t->last); - r *= 1000; /* convert to ns. */ - r++; /* make sure we increase for each call. */ - } - t->last = now; + r = qemu_get_clock(vm_clock) * 10; break; - } - case RW_INTR_MASK: r = t->rw_intr_mask; break; @@ -128,14 +113,16 @@ addr, env->pc); } -static void write_ctrl(struct fs_timer_t *t, uint32_t v) +#define TIMER_SLOWDOWN 4 +static void update_ctrl(struct fs_timer_t *t) { - int op; - int freq; - int freq_hz; + unsigned int op; + unsigned int freq; + unsigned int freq_hz; + unsigned int div; - op = v & 3; - freq = v >> 2; + op = t->rw_tmr0_ctrl & 3; + freq = t->rw_tmr0_ctrl >> 2; freq_hz = 32000000; switch (freq) @@ -153,25 +140,26 @@ break; } - D(printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit)); - t->scale = 0; - if (t->limit > 2048) - { - t->scale = 2048; - ptimer_set_period(t->ptimer, freq_hz / t->scale); - } + D(printf ("freq_hz=%d div=%d\n", freq_hz, t->rw_tmr0_div)); + div = t->rw_tmr0_div * TIMER_SLOWDOWN; + div >>= 15; + freq_hz >>= 15; + ptimer_set_freq(t->ptimer, freq_hz); + ptimer_set_limit(t->ptimer, div, 0); switch (op) { case 0: - D(printf ("limit=%d %d\n", - t->limit, t->limit/t->scale)); - ptimer_set_limit(t->ptimer, t->limit / t->scale, 1); + /* Load. */ + ptimer_set_limit(t->ptimer, div, 1); + ptimer_run(t->ptimer, 1); break; case 1: + /* Hold. */ ptimer_stop(t->ptimer); break; case 2: + /* Run. */ ptimer_run(t->ptimer, 0); break; default: @@ -180,34 +168,44 @@ } } -static void timer_ack_irq(struct fs_timer_t *t) +static void timer_update_irq(struct fs_timer_t *t) { - if (!(t->r_intr & t->mask & t->rw_intr_mask)) + t->r_intr &= ~(t->rw_ack_intr); + t->r_masked_intr = t->r_intr & t->rw_intr_mask; + + D(printf("%s: masked_intr=%x\n", __func__, t->r_masked_intr)); + if (t->r_masked_intr & 1) + qemu_irq_raise(t->irq[0]); + else qemu_irq_lower(t->irq[0]); } +static void timer_hit(struct fs_timer_t *t) +{ + t->r_intr |= 1; + timer_update_irq(t); +} + static void timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { struct fs_timer_t *t = opaque; CPUState *env = t->env; - D(printf ("%s %x %x pc=%x\n", - __func__, addr, value, env->pc)); /* Make addr relative to this instances base. */ addr -= t->base; switch (addr) { case RW_TMR0_DIV: - D(printf ("RW_TMR0_DIV=%x\n", value)); - t->limit = value; + t->rw_tmr0_div = value; break; case RW_TMR0_CTRL: D(printf ("RW_TMR0_CTRL=%x\n", value)); - write_ctrl(t, value); + t->rw_tmr0_ctrl = value; + update_ctrl(t); break; case RW_TMR1_DIV: - D(printf ("RW_TMR1_DIV=%x\n", value)); + t->rw_tmr1_div = value; break; case RW_TMR1_CTRL: D(printf ("RW_TMR1_CTRL=%x\n", value)); @@ -215,13 +213,15 @@ case RW_INTR_MASK: D(printf ("RW_INTR_MASK=%x\n", value)); t->rw_intr_mask = value; + timer_update_irq(t); break; case RW_WD_CTRL: D(printf ("RW_WD_CTRL=%x\n", value)); break; case RW_ACK_INTR: - t->r_intr &= ~value; - timer_ack_irq(t); + t->rw_ack_intr = value; + timer_update_irq(t); + t->rw_ack_intr = 0; break; default: printf ("%s %x %x pc=%x\n", @@ -242,16 +242,6 @@ &timer_writel, }; -static void timer_irq(void *opaque) -{ - struct fs_timer_t *t = opaque; - t->r_intr |= t->mask; - if (t->mask & t->rw_intr_mask) { - D(printf("%s raise\n", __func__)); - qemu_irq_raise(t->irq[0]); - } -} - void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, target_phys_addr_t base) { @@ -262,10 +252,9 @@ if (!t) return; - t->bh = qemu_bh_new(timer_irq, t); + t->bh = qemu_bh_new(timer_hit, t); t->ptimer = ptimer_init(t->bh); - t->irq = irqs + 26; - t->mask = 1; + t->irq = irqs; t->env = env; t->base = base;