From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:49693) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R9QqZ-0001G1-UJ for qemu-devel@nongnu.org; Thu, 29 Sep 2011 20:21:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R9QqX-0004Xz-Pe for qemu-devel@nongnu.org; Thu, 29 Sep 2011 20:20:59 -0400 Received: from lemon.ertos.nicta.com.au ([203.143.174.143]:41516 helo=lemon.ken.nicta.com.au) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R9QqX-0004Xt-3d for qemu-devel@nongnu.org; Thu, 29 Sep 2011 20:20:57 -0400 Date: Fri, 30 Sep 2011 10:20:36 +1000 Message-ID: From: Peter Chubb In-Reply-To: References: MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH] [ARM] Fix sp804 dual-timer List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Peter Maydell Cc: davidm@ok-labs.com, Peter Chubb , qemu-devel@nongnu.org, philipo@ok-labs.com, Paul Brook Thanks Peter! Here's a reworked patch. =46rom 7af8e24d6cbd9170a206b6aaac164e3934312b7c Mon Sep 17 00:00:00 2001 From: David Mirabito Date: Fri, 24 Jul 2009 11:43:14 +1000 Subject: [PATCH 53/57] Fix sp804 read/write for second timer. Properly implement the dual-timer read/write for the sp804 dual timer modul= e. Based on ARM specs at http://infocenter.arm.com/help/index.jsp?topic=3D/com.arm.doc.ddi0271d/inde= x.html Signed-off-by: Peter Chubb Signed-off-by: David Mirabito Signed-off-by: Hans Jang --- hw/arm_timer.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++----= ----- 1 file changed, 54 insertions(+), 9 deletions(-) Index: qemu-working/hw/arm_timer.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- qemu-working.orig/hw/arm_timer.c 2011-09-29 12:40:24.657526348 +1000 +++ qemu-working/hw/arm_timer.c 2011-09-30 10:15:00.724397699 +1000 @@ -163,64 +163,108 @@ static arm_timer_state *arm_timer_init(u s->freq =3D freq; s->control =3D TIMER_CTRL_IE; =20 bh =3D qemu_bh_new(arm_timer_tick, s); s->timer =3D ptimer_init(bh); vmstate_register(NULL, -1, &vmstate_arm_timer, s); return s; } =20 /* ARM PrimeCell SP804 dual timer module. - Docs for this device don't seem to be publicly available. This - implementation is based on guesswork, the linux kernel sources and the - Integrator/CP timer modules. */ + * Docs at + * http://infocenter.arm.com/help/index.jsp?topic=3D/com.arm.doc.ddi0271d/= index.html +*/ =20 typedef struct { SysBusDevice busdev; MemoryRegion iomem; arm_timer_state *timer[2]; int level[2]; qemu_irq irq; } sp804_state; =20 +/* + * sp804_id should be: + * union { + * struct { + * uint32_t PartNumber:12; =3D=3D 0x804 + * uint32_t DesignerID:8; =3D=3D 'A' + * uint32_t Revision:4; =3D=3D 1 + * uint32_t Configurations:6; =3D=3D 0 + * }; + * uint8_t bytes[4]; + * }; + * but that gets into too many byte-ordering and packing issues. + */ +static const uint8_t sp804_id[] =3D {0x04, 0x18, 0x14, 0}; +static const uint8_t sp804_PrimeCellID[] =3D {0xB1, 0x05, 0xF0, 0x0D}; + /* Merge the IRQs from the two component devices. */ static void sp804_set_irq(void *opaque, int irq, int level) { sp804_state *s =3D (sp804_state *)opaque; =20 s->level[irq] =3D level; qemu_set_irq(s->irq, s->level[0] || s->level[1]); } =20 static uint64_t sp804_read(void *opaque, target_phys_addr_t offset, unsigned size) { sp804_state *s =3D (sp804_state *)opaque; =20 - /* ??? Don't know the PrimeCell ID for this device. */ if (offset < 0x20) { return arm_timer_read(s->timer[0], offset); - } else { + } + if (offset < 0x40) { return arm_timer_read(s->timer[1], offset - 0x20); } + + /* + * Ids are packed into a word, then accessed one byte per word. + */ + /* TimerPeriphID */ + if (offset >=3D 0xfe0 && offset <=3D 0xfec) + return sp804_id[(offset - 0xfe0) >> 2]; + /* PrimeCellID */ + if (offset >=3D 0xff0 && offset <=3D 0xffc) + return sp804_PrimeCellID[(offset - 0xff0) >> 2] + + switch(offset){ + /* Integration Test control registers, which we won't support */ + case 0xf00: /* TimerITCR */ + case 0xf04: /* TimerITOP (strictly write only but..) */ + return 0; + + } + + hw_error("sp804_read: Bad offset %x\n", (int)offset); + return 0; } =20 static void sp804_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { sp804_state *s =3D (sp804_state *)opaque; =20 if (offset < 0x20) { arm_timer_write(s->timer[0], offset, value); - } else { + return; + } + + if (offset < 0x40) { arm_timer_write(s->timer[1], offset - 0x20, value); - } + return; + } + + /* Technically we could be writing to the Test Registers, but not like= ly */ + hw_error("sp804_write: Bad offset %x\n", (int)offset); } =20 static const MemoryRegionOps sp804_ops =3D { .read =3D sp804_read, .write =3D sp804_write, .endianness =3D DEVICE_NATIVE_ENDIAN, }; =20 static const VMStateDescription vmstate_sp804 =3D { .name =3D "sp804", @@ -262,36 +306,37 @@ typedef struct { } icp_pit_state; =20 static uint64_t icp_pit_read(void *opaque, target_phys_addr_t offset, unsigned size) { icp_pit_state *s =3D (icp_pit_state *)opaque; int n; =20 /* ??? Don't know the PrimeCell ID for this device. */ n =3D offset >> 8; + if (n > 3) { - hw_error("sp804_read: Bad timer %d\n", n); + hw_error("icp_pit_read: Bad timer %d\n", n); } =20 return arm_timer_read(s->timer[n], offset & 0xff); } =20 static void icp_pit_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { icp_pit_state *s =3D (icp_pit_state *)opaque; int n; =20 n =3D offset >> 8; if (n > 3) { - hw_error("sp804_write: Bad timer %d\n", n); + hw_error("icp_pit_write: Bad timer %d\n", n); } =20 arm_timer_write(s->timer[n], offset & 0xff, value); } =20 static const MemoryRegionOps icp_pit_ops =3D { .read =3D icp_pit_read, .write =3D icp_pit_write, .endianness =3D DEVICE_NATIVE_ENDIAN, }; -- Dr Peter Chubb http://www.gelato.unsw.edu.au peterc AT gelato.unsw.edu.au http://www.ertos.nicta.com.au ERTOS within National ICT Australia