[Qemu-devel] [Bug 1324724] Re: make install fails if running strip
The libexec case doesn't actually work, which is why IO switched to a separate variable. One of the reasons I said the patch is probably wrong. I suspect we need something like $(STRIP) $(addprefix $(DESTDIR)/$(BINDIR), $(notdir ${TOOLS))) And I didn't see the problem on x86_64, only on armhf. I think x86_64 doesn't need the fsdev helper. -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1324724 Title: make install fails if running strip Status in QEMU: New Bug description: I do: ./configure --target-list=arm-softmmu make sudo make install and see: install -d -m 0755 "/usr/local/bin" libtool --quiet --mode=install install -c -m 0755 qemu-ga qemu-nbd qemu-img qemu-io fsdev/virtfs-proxy-helper "/usr/local/bin" strip "/usr/local/bin/qemu-ga" "/usr/local/bin/qemu-nbd" "/usr/local/bin/qemu-img" "/usr/local/bin/qemu-io" "/usr/local/bin/fsdev/virtfs-proxy-helper" strip: '/usr/local/bin/fsdev/virtfs-proxy-helper': No such file Makefile:379: recipe for target 'install' failed make: *** [install] Error 1 Host is Odroid-XU running Debian Jessie. Source is at d7d3d6092cb7edc75dc49fb90c86dd5425ab4805 Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-peter' libtool version 2.4.2-1.7 armhf To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1324724/+subscriptions
[Qemu-devel] [Bug 1324727] [NEW] qemu-system-arm segfaults without KVM on ARM
Public bug reported: I'm running on Odroid-XU, Debian Jessie armhf qemu built from today's head d7d3d6092cb7edc75dc49fb90c86dd5425ab4805 sudo qemu-system-arm -M vexpress-a15 -drive if=none,file=arm.img,cache=writeback,id=foo -device virtio-blk-device,drive=foo -netdev user,id=user.0 -device virtio-net-device,netdev=user.0 -nographic -append 'root=/dev/vda rw console=ttyAMA0 rootwait' -kernel /usr/src/build/arm/linux-guest/arch/arm/boot/zImage -dtb a15x2.dtb audio: Could not init `oss' audio driver Uncompressing Linux... done, booting the kernel. Segmentation fault If I run under GDB, the linux guest instance panics or hangs -- the behaviour is variable run to run. If I do: sudo qemu-system-arm --enable-kvm -M vexpress-a15 -drive if=none,file=arm.img,cache=writeback,id=foo -device virtio-blk-device,drive=foo -netdev user,id=user.0 -device virtio-net-device,netdev=user.0 -nographic -append 'root=/dev/vda rw console=ttyAMA0 rootwait' -kernel /usr/src/build/arm/linux-guest/arch/arm/boot/zImage -dtb a15x2.dtb then the guest boots as expected. I tried to get a backtrace by allowinghte SEGV to dump core, and using gdb to inspect it: Core was generated by `qemu-system-arm -M vexpress-a15 -drive if=none,file=arm.img,cache=writeback,id='. Program terminated with signal 11, Segmentation fault. #0 0xb53399c0 in ?? () (gdb) bt #0 0xb53399c0 in ?? () Cannot access memory at address 0x28 #1 0x0016d87e in cpu_tb_exec ( tb_ptr=0xc786fe90 , cpu=0x24450d8) at /mnt/qemu/cpu-exec.c:67 #2 cpu_arm_exec (env=) at /mnt/qemu/cpu-exec.c:642 #3 0x in ?? () ** Affects: qemu Importance: Undecided Status: New -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1324727 Title: qemu-system-arm segfaults without KVM on ARM Status in QEMU: New Bug description: I'm running on Odroid-XU, Debian Jessie armhf qemu built from today's head d7d3d6092cb7edc75dc49fb90c86dd5425ab4805 sudo qemu-system-arm -M vexpress-a15 -drive if=none,file=arm.img,cache=writeback,id=foo -device virtio-blk-device,drive=foo -netdev user,id=user.0 -device virtio-net-device,netdev=user.0 -nographic -append 'root=/dev/vda rw console=ttyAMA0 rootwait' -kernel /usr/src/build/arm/linux-guest/arch/arm/boot/zImage -dtb a15x2.dtb audio: Could not init `oss' audio driver Uncompressing Linux... done, booting the kernel. Segmentation fault If I run under GDB, the linux guest instance panics or hangs -- the behaviour is variable run to run. If I do: sudo qemu-system-arm --enable-kvm -M vexpress-a15 -drive if=none,file=arm.img,cache=writeback,id=foo -device virtio-blk-device,drive=foo -netdev user,id=user.0 -device virtio-net-device,netdev=user.0 -nographic -append 'root=/dev/vda rw console=ttyAMA0 rootwait' -kernel /usr/src/build/arm/linux-guest/arch/arm/boot/zImage -dtb a15x2.dtb then the guest boots as expected. I tried to get a backtrace by allowinghte SEGV to dump core, and using gdb to inspect it: Core was generated by `qemu-system-arm -M vexpress-a15 -drive if=none,file=arm.img,cache=writeback,id='. Program terminated with signal 11, Segmentation fault. #0 0xb53399c0 in ?? () (gdb) bt #0 0xb53399c0 in ?? () Cannot access memory at address 0x28 #1 0x0016d87e in cpu_tb_exec ( tb_ptr=0xc786fe90 , cpu=0x24450d8) at /mnt/qemu/cpu-exec.c:67 #2 cpu_arm_exec (env=) at /mnt/qemu/cpu-exec.c:642 #3 0x in ?? () To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1324727/+subscriptions
[Qemu-devel] [Bug 1324724] [NEW] make install fails on arm host
Public bug reported: I do: ./configure --target-list=arm-softmmu make sudo make install and see: install -d -m 0755 "/usr/local/bin" libtool --quiet --mode=install install -c -m 0755 qemu-ga qemu-nbd qemu-img qemu-io fsdev/virtfs-proxy-helper "/usr/local/bin" strip "/usr/local/bin/qemu-ga" "/usr/local/bin/qemu-nbd" "/usr/local/bin/qemu-img" "/usr/local/bin/qemu-io" "/usr/local/bin/fsdev/virtfs-proxy-helper" strip: '/usr/local/bin/fsdev/virtfs-proxy-helper': No such file Makefile:379: recipe for target 'install' failed make: *** [install] Error 1 Host is Odroid-XU running Debian Jessie. Source is at d7d3d6092cb7edc75dc49fb90c86dd5425ab4805 Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-peter' libtool version 2.4.2-1.7 armhf ** Affects: qemu Importance: Undecided Status: New ** Patch added: "Probably wrong fix." https://bugs.launchpad.net/bugs/1324724/+attachment/4122442/+files/fix.patch -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1324724 Title: make install fails on arm host Status in QEMU: New Bug description: I do: ./configure --target-list=arm-softmmu make sudo make install and see: install -d -m 0755 "/usr/local/bin" libtool --quiet --mode=install install -c -m 0755 qemu-ga qemu-nbd qemu-img qemu-io fsdev/virtfs-proxy-helper "/usr/local/bin" strip "/usr/local/bin/qemu-ga" "/usr/local/bin/qemu-nbd" "/usr/local/bin/qemu-img" "/usr/local/bin/qemu-io" "/usr/local/bin/fsdev/virtfs-proxy-helper" strip: '/usr/local/bin/fsdev/virtfs-proxy-helper': No such file Makefile:379: recipe for target 'install' failed make: *** [install] Error 1 Host is Odroid-XU running Debian Jessie. Source is at d7d3d6092cb7edc75dc49fb90c86dd5425ab4805 Merge remote-tracking branch 'remotes/afaerber/tags/qom-devices-for-peter' libtool version 2.4.2-1.7 armhf To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1324724/+subscriptions
Re: [Qemu-devel] [Bug 1273944] Re: multiboot header has 0 in mem_upper field
>>>>> "Peter" == Peter Chubb writes: This change fixes it. > diff --git a/exec.c b/exec.c > index 2435d9e..b387d28 100644 > --- a/exec.c > +++ b/exec.c > @@ -1070,7 +1070,7 @@ static void *file_ram_alloc(RAMBlock *block, > } > > /* MAP_POPULATE silently ignores failures */ > -for (i = 0; i < (memory/hpagesize); i++) { > +for (i = 0; i < (memory/hpagesize)-1; i++) { > memset(area + (hpagesize*i), 0, 1); > } I don't know why this fixes the issue. Hence, no signed-off-by line, etc. My guess is that the memset zeros something it shouldn't off the end of the array (but that doesn't make sense to me!) Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [Bug 1273944] Re: multiboot header has 0 in mem_upper field
This change fixes it. diff --git a/exec.c b/exec.c index 2435d9e..b387d28 100644 --- a/exec.c +++ b/exec.c @@ -1070,7 +1070,7 @@ static void *file_ram_alloc(RAMBlock *block, } /* MAP_POPULATE silently ignores failures */ -for (i = 0; i < (memory/hpagesize); i++) { +for (i = 0; i < (memory/hpagesize)-1; i++) { memset(area + (hpagesize*i), 0, 1); } peterc@Diprotodon:/usr/src/qemu/tests/m -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1273944 Title: multiboot header has 0 in mem_upper field Status in QEMU: New Bug description: When booting a multiboot image,. mem_upper is now always zero. To test, build qemu from current git head, then do cd tests/multiboot ./run_test.sh You will see the test fail. In each case mem_upper is 0k. git-bisect says the bad commit is 0169c511554cb0014a00290b0d3d26c31a49818f in qemu.git To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1273944/+subscriptions
[Qemu-devel] [Bug 1273944] [NEW] multiboot header has 0 in mem_upper field
Public bug reported: When booting a multiboot image,. mem_upper is now always zero. To test, build qemu from current git head, then do cd tests/multiboot ./run_test.sh You will see the test fail. In each case mem_upper is 0k. git-bisect says the bad commit is 0169c511554cb0014a00290b0d3d26c31a49818f in qemu.git ** Affects: qemu Importance: Undecided Status: New -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1273944 Title: multiboot header has 0 in mem_upper field Status in QEMU: New Bug description: When booting a multiboot image,. mem_upper is now always zero. To test, build qemu from current git head, then do cd tests/multiboot ./run_test.sh You will see the test fail. In each case mem_upper is 0k. git-bisect says the bad commit is 0169c511554cb0014a00290b0d3d26c31a49818f in qemu.git To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1273944/+subscriptions
[Qemu-devel] [Patch] Fix typo in qom/object.h
There's been a cut-and-paste error, it looks like, in the documentation in qom/object.h. Signed-off-by: Peter Chubb --- include/qom/object.h |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: qemu/include/qom/object.h === --- qemu.orig/include/qom/object.h 2013-08-06 09:59:30.064467951 +1000 +++ qemu/include/qom/object.h 2013-08-07 12:29:46.678911807 +1000 @@ -249,7 +249,7 @@ typedef struct InterfaceInfo InterfaceIn * MyClass parent_class; * * MyDoSomething parent_do_something; - * } MyClass; + * } DerivedClass; * * static void derived_do_something(MyState *obj) * { -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [Patch] ARM: Add an L2 cache controller to KZM
OK, this is what I've come up with. Dunno whether it's right or not -- the object model is decoupled from the memory model, so there's no straightforward way to override just a few of the registers. At this stage this is just for comment, as I don't really have that much of a clue about how the object/class hierarchy is meant to work. --- hw/arm/kzm.c |3 + hw/misc/arm_l2x0.c | 129 ++--- 2 files changed, 96 insertions(+), 36 deletions(-) Index: qemu/hw/arm/kzm.c === --- qemu.orig/hw/arm/kzm.c 2013-08-07 11:21:48.864692846 +1000 +++ qemu/hw/arm/kzm.c 2013-08-07 11:22:40.292983604 +1000 @@ -33,6 +33,7 @@ * 0x1fffc000-0x1fff RAM EMULATED * 0x2000-0x2fff Reserved IGNORED * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x3000-0x3fff L2 Cache Controller PARTIALLY EMULATED * 0x43f0 IO_AREA0 * 0x43f9 UART1 EMULATED * 0x43f94000 UART2 EMULATED @@ -134,6 +135,8 @@ static void kzm_init(QEMUMachineInitArgs DEVICE_NATIVE_ENDIAN); } +sysbus_create_varargs("imx_l2cc", 0x3000, NULL); + kzm_binfo.ram_size = ram_size; kzm_binfo.kernel_filename = kernel_filename; kzm_binfo.kernel_cmdline = kernel_cmdline; Index: qemu/hw/misc/arm_l2x0.c === --- qemu.orig/hw/misc/arm_l2x0.c2013-08-07 11:21:48.864692846 +1000 +++ qemu/hw/misc/arm_l2x0.c 2013-08-07 11:21:48.860692824 +1000 @@ -21,7 +21,9 @@ #include "hw/sysbus.h" /* L2C-310 r3p2 */ -#define CACHE_ID 0x41c8 +#define PL310_CACHE_ID 0x41c8 +/* L2CC from Freescale */ +#define IMX_PL2CC_CACHE_ID 0xD541 #define TYPE_ARM_L2X0 "l2x0" #define ARM_L2X0(obj) OBJECT_CHECK(L2x0State, (obj), TYPE_ARM_L2X0) @@ -30,6 +32,7 @@ typedef struct L2x0State { SysBusDevice parent_obj; MemoryRegion iomem; +uint32_t cache_id; uint32_t cache_type; uint32_t ctrl; uint32_t aux_ctrl; @@ -66,7 +69,7 @@ static uint64_t l2x0_priv_read(void *opa } switch (offset) { case 0: -return CACHE_ID; +return s->cache_id; case 0x4: /* aux_ctrl values affect cache_type values */ cache_data = (s->aux_ctrl & (7 << 17)) >> 15; @@ -78,23 +81,25 @@ static uint64_t l2x0_priv_read(void *opa return s->aux_ctrl; case 0x108: return s->tag_ctrl; -case 0x10C: -return s->data_ctrl; -case 0xC00: -return s->filter_start; -case 0xC04: -return s->filter_end; case 0xF40: return 0; -case 0xF60: -return 0; -case 0xF80: -return 0; -default: -qemu_log_mask(LOG_GUEST_ERROR, - "l2x0_priv_read: Bad offset %x\n", (int)offset); -break; } +if (s->cache_id == PL310_CACHE_ID) { +switch (offset) { +case 0x10C: +return s->data_ctrl; +case 0xC00: +return s->filter_start; +case 0xC04: +return s->filter_end; +case 0xF60: +return 0; +case 0xF80: +return 0; +} +} +qemu_log_mask(LOG_GUEST_ERROR, + "l2x0_priv_read: Bad offset %x\n", (int)offset); return 0; } @@ -107,6 +112,7 @@ static void l2x0_priv_write(void *opaque /* ignore */ return; } + switch (offset) { case 0x100: s->ctrl = value & 1; @@ -114,29 +120,32 @@ static void l2x0_priv_write(void *opaque case 0x104: s->aux_ctrl = value; break; -case 0x108: -s->tag_ctrl = value; -break; -case 0x10C: -s->data_ctrl = value; -break; -case 0xC00: -s->filter_start = value; -break; -case 0xC04: -s->filter_end = value; -break; case 0xF40: return; -case 0xF60: -return; -case 0xF80: -return; -default: -qemu_log_mask(LOG_GUEST_ERROR, - "l2x0_priv_write: Bad offset %x\n", (int)offset); -break; } + +if (s->cache_id == PL310_CACHE_ID) { +switch (offset) { +case 0x108: +s->tag_ctrl = value; +break; +case 0x10C: +s->data_ctrl = value; +break; +case 0xC00: +s->filter_start = value; +break; +case 0xC04: +s->filter_end = value; +break; +case 0xF60: +return; +case 0xF80: +return; +} +} +qemu_log_mask(LOG_GUEST_ERROR, + "l2x0_priv_write: Bad offset %x\n", (int)offset); } static void l2x0_priv_reset(DeviceState *dev) @@ -184,16 +193,64 @@ static void l2x0_class_init(Object
Re: [Qemu-devel] [Patch] ARM: Add an L2 cache controller to KZM
>>>>> "Andreas" == Andreas Färber writes: Andreas> Peter Ch., if you know the exact differences, why don't you Andreas> just derive an imx-l2cc type (or so) derived from ARM's type, Andreas> overriding the values mentioned above? Sounds trivial to me. For what it's worth, here's a diff between the arm_l2x0.c implementation and a working imx_l2cc.c implementation. Most of the diffs are name change; but there are substantive differences to the initial values, and to which registers are supported. This makes the State variable smaller. So it's a bit more than just overriding a few constants. --- arm_l2x0.c 2013-08-06 09:59:30.008468028 +1000 +++ imx-l2cc-indep.c2013-08-06 10:49:38.021514073 +1000 @@ -1,7 +1,10 @@ /* - * ARM dummy L210, L220, PL310 cache controller. + * IMX dummy level 2 cache controller * - * Copyright (c) 2010-2012 Calxeda + * Copyright (c) 2013 NICTA Peter Chubb + * + * Based on the PL210 implementation in arm_l2x0.c + * Differences: different Cache ID and aux control register values. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -20,46 +23,40 @@ #include "hw/sysbus.h" -/* L2C-310 r3p2 */ -#define CACHE_ID 0x41c8 -#define TYPE_ARM_L2X0 "l2x0" -#define ARM_L2X0(obj) OBJECT_CHECK(L2x0State, (obj), TYPE_ARM_L2X0) +#define CACHE_ID 0xd541 +#define CACHE_TYPE_DEFAULT 0x1C100100 + +#define TYPE_IMX_L2CC "imx_l2cc" +#define IMX_L2CC(obj) OBJECT_CHECK(L2ccState, (obj), TYPE_IMX_L2CC) -typedef struct L2x0State { +typedef struct L2ccState { SysBusDevice parent_obj; MemoryRegion iomem; uint32_t cache_type; uint32_t ctrl; uint32_t aux_ctrl; -uint32_t data_ctrl; -uint32_t tag_ctrl; -uint32_t filter_start; -uint32_t filter_end; -} L2x0State; +} L2ccState; -static const VMStateDescription vmstate_l2x0 = { -.name = "l2x0", +static const VMStateDescription vmstate_l2cc = { +.name = "imx_l2cc", .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { -VMSTATE_UINT32(ctrl, L2x0State), -VMSTATE_UINT32(aux_ctrl, L2x0State), -VMSTATE_UINT32(data_ctrl, L2x0State), -VMSTATE_UINT32(tag_ctrl, L2x0State), -VMSTATE_UINT32(filter_start, L2x0State), -VMSTATE_UINT32(filter_end, L2x0State), +VMSTATE_UINT32(ctrl, L2ccState), +VMSTATE_UINT32(cache_type, L2ccState), +VMSTATE_UINT32(aux_ctrl, L2ccState), VMSTATE_END_OF_LIST() } }; -static uint64_t l2x0_priv_read(void *opaque, hwaddr offset, +static uint64_t l2cc_priv_read(void *opaque, hwaddr offset, unsigned size) { uint32_t cache_data; -L2x0State *s = (L2x0State *)opaque; +L2ccState *s = (L2ccState *)opaque; offset &= 0xfff; if (offset >= 0x730 && offset < 0x800) { return 0; /* cache ops complete */ @@ -76,32 +73,20 @@ return s->ctrl; case 0x104: return s->aux_ctrl; -case 0x108: -return s->tag_ctrl; -case 0x10C: -return s->data_ctrl; -case 0xC00: -return s->filter_start; -case 0xC04: -return s->filter_end; case 0xF40: return 0; -case 0xF60: -return 0; -case 0xF80: -return 0; default: qemu_log_mask(LOG_GUEST_ERROR, - "l2x0_priv_read: Bad offset %x\n", (int)offset); + "l2cc_priv_read: Bad offset %x\n", (int)offset); break; } return 0; } -static void l2x0_priv_write(void *opaque, hwaddr offset, +static void l2cc_priv_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { -L2x0State *s = (L2x0State *)opaque; +L2ccState *s = (L2ccState *)opaque; offset &= 0xfff; if (offset >= 0x730 && offset < 0x800) { /* ignore */ @@ -114,86 +99,61 @@ case 0x104: s->aux_ctrl = value; break; -case 0x108: -s->tag_ctrl = value; -break; -case 0x10C: -s->data_ctrl = value; -break; -case 0xC00: -s->filter_start = value; -break; -case 0xC04: -s->filter_end = value; -break; case 0xF40: return; -case 0xF60: -return; -case 0xF80: -return; default: qemu_log_mask(LOG_GUEST_ERROR, - "l2x0_priv_write: Bad offset %x\n", (int)offset); + "l2cc_priv_write: Bad offset %x\n", (int)offset); break; } } -static void l2x0_priv_reset(DeviceState *dev) +static void l2cc_priv_reset(DeviceState *dev) { -L2x0State *s = ARM_L2X0(dev); +L2ccState *s = IMX_L2CC(dev
Re: [Qemu-devel] [Patch] ARM: Add an L2 cache controller to KZM
>>>>> "Peter" == Peter Maydell writes: Peter> On 5 August 2013 02:21, Peter Chubb Peter> wrote: >> Reads to unassigned memory now return non-zero (since patch >> 9b8c69243585). This breaks guests runnong on i.MX31 that use the >> cache controller --- they poll forever waiting for the L2CC cache >> invalidate regsiter to be zero. Peter> That commit claims it was just restoring the previous Peter> behaviour, so it shouldn't break guests, surely? The behaviour was introduced in 2008 in commit e18231a3 --- The KZM port only went in last year and assumed the then-current behaviour. Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [Patch] ARM: Simplify and fix imx_epit implementation.
When imx_epit.c was last refactored, a common usecase (comparison register zero) broke. This patch fixes that, and simplifies the code yet more. It also fixes a major thinko in the reset path --- the wrong bits in the control register were being cleared. Signed-off-by: Peter Chubb Reviewed-by: Jean-Christophe DUBOIS --- hw/timer/imx_epit.c | 94 +++- 1 file changed, 36 insertions(+), 58 deletions(-) Index: qemu/hw/timer/imx_epit.c === --- qemu.orig/hw/timer/imx_epit.c 2013-08-02 14:07:06.598276595 +1000 +++ qemu/hw/timer/imx_epit.c2013-08-02 14:31:28.494031219 +1000 @@ -43,7 +43,7 @@ static char const *imx_epit_reg_name(uin } # define DPRINTF(fmt, args...) \ - do { printf("%s: " fmt , __func__, ##args); } while (0) +do { fprintf(stderr, "%s: " fmt , __func__, ##args); } while (0) #else # define DPRINTF(fmt, args...) do {} while (0) #endif @@ -152,7 +152,7 @@ static void imx_epit_reset(DeviceState * /* * Soft reset doesn't touch some bits; hard reset clears them */ -s->cr &= ~(CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN); +s->cr &= (CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN); s->sr = 0; s->lr = TIMER_MAX; s->cmp = 0; @@ -167,7 +167,7 @@ static void imx_epit_reset(DeviceState * ptimer_set_limit(s->timer_reload, TIMER_MAX, 1); if (s->freq && (s->cr & CR_EN)) { /* if the timer is still enabled, restart it */ -ptimer_run(s->timer_reload, 1); +ptimer_run(s->timer_reload, 0); } } @@ -218,17 +218,17 @@ static uint64_t imx_epit_read(void *opaq static void imx_epit_reload_compare_timer(IMXEPITState *s) { -if ((s->cr & CR_OCIEN) && s->cmp) { -/* if the compare feature is on */ +if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) { +/* if the compare feature is on and timers are running */ uint32_t tmp = imx_epit_update_count(s); +uint64_t next; if (tmp > s->cmp) { -/* reinit the cmp timer if required */ -ptimer_set_count(s->timer_cmp, tmp - s->cmp); -if ((s->cr & CR_EN)) { -/* Restart the cmp timer if required */ -ptimer_run(s->timer_cmp, 0); -} +/* It'll fire in this round of the timer */ +next = tmp - s->cmp; +} else { /* catch it next time around */ +next = tmp - s->cmp + ((s->cr & CR_RLD) ? TIMER_MAX : s->lr); } +ptimer_set_count(s->timer_cmp, next); } } @@ -237,11 +237,14 @@ static void imx_epit_write(void *opaque, { IMXEPITState *s = IMX_EPIT(opaque); uint32_t reg = offset >> 2; +uint64_t oldcr; DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(reg), (uint32_t)value); switch (reg) { case 0: /* CR */ + +oldcr = s->cr; s->cr = value & 0x03ff; if (s->cr & CR_SWR) { /* handle the reset */ @@ -250,22 +253,35 @@ static void imx_epit_write(void *opaque, imx_epit_set_freq(s); } -if (s->freq && (s->cr & CR_EN)) { +if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) { if (s->cr & CR_ENMOD) { if (s->cr & CR_RLD) { ptimer_set_limit(s->timer_reload, s->lr, 1); +ptimer_set_limit(s->timer_cmp, s->lr, 1); } else { ptimer_set_limit(s->timer_reload, TIMER_MAX, 1); +ptimer_set_limit(s->timer_cmp, TIMER_MAX, 1); } } imx_epit_reload_compare_timer(s); - -ptimer_run(s->timer_reload, 1); -} else { +ptimer_run(s->timer_reload, 0); +if (s->cr & CR_OCIEN) { +ptimer_run(s->timer_cmp, 0); +} else { +ptimer_stop(s->timer_cmp); +} +} else if (!(s->cr & CR_EN)) { /* stop both timers */ ptimer_stop(s->timer_reload); ptimer_stop(s->timer_cmp); +} else if (s->cr & CR_OCIEN) { +if (!(oldcr & CR_OCIEN)) { +imx_epit_reload_compare_timer(s); +ptimer_run(s->timer_cmp, 0); +} +} else { +ptimer_stop(s->timer_cmp); } break; @@ -284,13 +300,13 @@ static void imx_epit_write(void *opaque, /* Also set the limit if the LRD bit is set */ /* If IOVW bit is set then set the timer value */ ptimer_set_limit(s->timer_reload
[Qemu-devel] [Patch] ARM: Add an L2 cache controller to KZM
Reads to unassigned memory now return non-zero (since patch 9b8c69243585). This breaks guests runnong on i.MX31 that use the cache controller --- they poll forever waiting for the L2CC cache invalidate regsiter to be zero. This patch adds in an L2 cache controller. It's not quite right --- it reuses the PL2x0 implementation that is already in QEMU. The differences however are minor --- a different ID, a different initial value for the aux control register (because Freescale have used some of the reserved bits), and the pl2x0 implements registers that are not present in the Freescale cache controller. Signed-off-by: Peter Chubb diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c index bd6c05c..018fc81 100644 --- a/hw/arm/kzm.c +++ b/hw/arm/kzm.c @@ -33,6 +33,7 @@ * 0x1fffc000-0x1fff RAM EMULATED * 0x2000-0x2fff Reserved IGNORED * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x3000-0x3fff L2 Cache Controller PARTIALLY EMULATED * 0x43f0 IO_AREA0 * 0x43f9 UART1 EMULATED * 0x43f94000 UART2 EMULATED @@ -134,6 +135,15 @@ static void kzm_init(QEMUMachineInitArgs *args) DEVICE_NATIVE_ENDIAN); } +/* + * The i.MX L2CC is almost the same as the PL210 + * except for a different ID (the implementor bits are different) + * and the `reserved' bits in the auxilliary control register + * are implemented. The l2x0 qemu implementation is for a superset + * of the PL210. + */ +sysbus_create_varargs("l2x0", 0x3000, NULL); + kzm_binfo.ram_size = ram_size; kzm_binfo.kernel_filename = kernel_filename; kzm_binfo.kernel_cmdline = kernel_cmdline; -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH qom-next for-1.6 06/14] imx_ccm: QOM cast cleanup
>>>>> "Andreas" == Andreas Färber writes: Andreas> Signed-off-by: Andreas Färber --- Acked-by: Peter Chubb -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH qom-next for-1.6 07/15] imx_avic: QOM cast cleanup
>>>>> "Andreas" == Andreas Färber writes: Andreas> Signed-off-by: Andreas Färber --- Acked-by: Peter Chubb -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH] i.MX31: Fix PRCS bit test
>>>>> "Stefan" == Stefan Weil writes: Stefan> cppcheck detected a condition which was always false. Stefan> According to the MCIMX31 Reference Manual, the PRCS bits have Stefan> to be 01 to select the Frequency Pre-Multiplier (FPM). PRCS Stefan> uses bits 1 and 2, so we have to test for 2. Good catch. I hate hard coded constants, they're so easy to get wrong! Stefan> Signed-off-by: Stefan Weil Signed-off-by: Peter Chubb -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [PATCH] [ARM] Fix rfe instruction
The rfe instruction has been broken since patch 5a839c0d54fac9db0516904db873a4fe01f50f4b because of a typo. Signed-off-by: Peter Chubb diff --git a/target-arm/translate.c b/target-arm/translate.c index e5a2e4c..29e8f27 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -6798,7 +6798,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) tcg_gen_qemu_ld32u(tmp, addr, 0); tcg_gen_addi_i32(addr, addr, 4); tmp2 = tcg_temp_new_i32(); -tcg_gen_qemu_ld32u(tmp, addr, 0); +tcg_gen_qemu_ld32u(tmp2, addr, 0); if (insn & (1 << 21)) { /* Base writeback. */ switch (i) { -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH v2 2/2] i.MX: unify all function and variale name convention in GPT
> > -static char const *imx_timerg_reg_name(uint32_t reg) > +static char const *imx_timer_gpt_reg_name(uint32_t reg) You could just use imc_gpt_xxx in line with the imx_epit_xxx naming from your other patch series. Otherwise this looks good. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH] i.MX: implement a more complete version of the GPT timer.
>>>>> "Jean-Christophe" == Jean-Christophe DUBOIS writes: Jean-Christophe> * implement compare 1 2 and 3 registers * Unify Jean-Christophe> function and type naming * use dynamic cast whenever Jean-Christophe> possible * simplify Debug printf. * use new style Jean-Christophe> device intialization. Can you split this patch into two patches: one that just does the changes to support the comparison registers, and one that adapts to the newstyle device initialisation and has the cosmetic renamings and code reorganisaiton, please? I'd much rather review them separately, and keep functional and non-functional changes separate. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH] i.MX: Improve EPIT timer code.
Hi Jean, Thanks for this. Most of it appears cosmetic and an improvement. Comments in-line below. > > /* > * Update interrupt status > */ > -static void imx_timerp_update(IMXTimerPState *s) > +static void imx_timer_epit_update(IMXTimerEPITState *s) > { > -if (s->sr && (s->cr & CR_OCIEN)) { > +if (s->sr && (s->cr & CR_OCIEN) && (s->cr & CR_EN)) { Why not if (s->sr && (s->cr & (CR_OCIEN|CR_EN) == (CR_OCIEN|CR_EN))) > qemu_irq_raise(s->irq); > } else { > qemu_irq_lower(s->irq); > } > } > > -static void set_timerp_freq(IMXTimerPState *s) > +static void imx_timer_epit_set_freq(IMXTimerEPITState *s) > { > unsigned clksrc; > unsigned prescaler; > -uint32_t freq; getting rid of this variable means a pointer dereference every time below. That's OK at some optimisation levels and for some compilers as they'll cache the variable. But I prefer making this explicit so less competent compilers can avoid the pointer dereference. > > clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2); > prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12); > > -freq = imx_clock_frequency(s->ccm, imx_timerp_clocks[clksrc]) / > prescaler; > +s->freq = imx_clock_frequency(s->ccm, > + imx_timer_epit_clocks[clksrc]) / prescaler; > > -s->freq = freq; > DPRINTF("Setting ptimer frequency to %u\n", freq); And here it's inconsistent --- s/freq/s->freq/ and as you've renamed, maybe s/ptimer/epit/ The rest looks OK. I'm not that keen on the longer names, though. Maybe s/timer_epit/epit/ throughout. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH v2] i.MX: implement a more correct version of EPIT timer.
>>>>> "Jean-Christophe" == Jean-Christophe DUBOIS writes: Jean-Christophe> This patch is providing a complete version of the Jean-Christophe> EPIT timer. Note, however that the GPT timer in the Jean-Christophe> same file is still not complete. Looks good. You can add my Reviewed-by: Peter Chubb line. Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [PATCH v2] target-arm: Reinsert SRS missing return statement.
Since patch 81465888c5306cd94abb9847e560796fd13d3c2f target-arm: factor out handling of SRS instruction the SRS instruction has not worked in QEMU. The problem is a missing return directive that was removed in the refactoring, so after decoding the instruction, qemu would do all the generic stuff that it should do for most instructions -- but not SRS. Signed-off-by: Peter Chubb --- target-arm/translate.c |1 + 1 file changed, 1 insertion(+) diff --git a/target-arm/translate.c b/target-arm/translate.c index 35a21be..a1b7b8c 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -6762,6 +6762,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) } ARCH(6); gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21)); +return; } else if ((insn & 0x0e50ffe0) == 0x08100a00) { /* rfe */ int32_t offset; -- 1.7.10.4 -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH] target-arm: Reinsert SRS missing return statements.
>>>>> "Peter" == Peter Maydell writes: Peter> On 15 April 2013 05:50, Peter Chubb Peter> wrote: >> >> >> Since patch 81465888c5306cd94abb9847e560796fd13d3c2f target-arm: >> factor out handling of SRS instruction the SRS instruction has not >> worked in QEMU. >> >> The problem is a return directive that was removed in the >> refactoring, so after decoding the instruction, qemu would fall >> through to do stuff that it should not have done. Peter> Nice catch for the ARM decoder, but not needed for thumb2 I Peter> think? It was there in the code that was removed. I didn't analyse too deeply, as nothing we do uses the thumb version. Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [PATCH] target-arm: Reinsert SRS missing return statements.
Since patch 81465888c5306cd94abb9847e560796fd13d3c2f target-arm: factor out handling of SRS instruction the SRS instruction has not worked in QEMU. The problem is a return directive that was removed in the refactoring, so after decoding the instruction, qemu would fall through to do stuff that it should not have done. Signed-off-by: Peter Chubb diff --git a/target-arm/translate.c b/target-arm/translate.c index 35a21be..c870246 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -6762,6 +6762,7 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) } ARCH(6); gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21)); +return; } else if ((insn & 0x0e50ffe0) == 0x08100a00) { /* rfe */ int32_t offset; @@ -8209,6 +8210,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw /* srs */ gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2, insn & (1 << 21)); +return; } } else { int i, loaded_base = 0; -- 1.7.10.4 Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH] i.MX: implement a more correct version of EPIT timer.
> This patch is providing a complete version of the EPIT timer. > Note, however that the GPT timer in the same file is still not > complete. Thanks! Comments in=line below. > @@ -411,7 +441,7 @@ static int imx_timerg_init(SysBusDevice *dev) > #define CR_SWR (1 << 16) > #define CR_IOVW (1 << 17) > #define CR_DBGEN(1 << 18) > -#define CR_EPIT (1 << 19) > +#define CR_WAITEN (1 << 19) > In the docs this bit is called EPIT. Its function is to enable the timer in wait-mode. So is conformance with the docs or the description of the function more important? If you *do* rename it, there should be a comment to say it's EPIT in the i.mx31 documentation. >-static void set_timerp_freq(IMXTimerPState *s) >+static void imx_reload_compare_timer(IMXTimerPState *s) > { >-int clksrc; >-unsigned prescaler; >-uint32_t freq; >- >-clksrc = (s->cr & CR_CLKSRC_MASK) >> CR_CLKSRC_SHIFT; >-prescaler = 1 + ((s->cr >> CR_PRESCALE_SHIFT) & CR_PRESCALE_MASK); >-freq = imx_clock_frequency(s->ccm, imx_timerp_clocks[clksrc]) / prescaler; >- >-s->freq = freq; >-DPRINTF("Setting ptimer frequency to %u\n", freq); >- >-if (freq) { >-ptimer_set_freq(s->timer, freq); >+if ((s->cr & CR_OCIEN) && s->cmp) { >+/* it the compare feature is on */] s/it/if/ +uint32_t tmp = imx_timerp_update_counts(s); +if (tmp > s->cmp) { +/* reinit the cmp timer if required */ +ptimer_set_count(s->timer_cmp, tmp - s->cmp); +if ((s->cr & CR_EN)) { +/* Restart the cmp timer if required */ +ptimer_run(s->timer_cmp, 0); +} +} } } >@@ -526,40 +599,63 @@ static void imx_timerp_write(void *opaque, hwaddr offset, > > switch (offset >> 2) { > case 0: /* CR */ >-if (value & CR_SWR) { >+s->cr = value & 0x03ff; >+if (s->cr & CR_SWR) { >+/* handle the reset */ > imx_timerp_reset(&s->busdev.qdev); >-value &= ~CR_SWR; >+} else { >+set_timerp_freq(s); > } >-s->cr = value & 0x03ff; >-set_timerp_freq(s); >+value &= s->cr; You're letting the reset function clear the SWR. It's unclear to me from the docs whether when the SWR bit is set, assignment to other fields in the CR happens before or after the reset. I punted on `after' (because it seemted to work), this changes to `before'. The reset looks good --- you seem to understand the ptimer interface better than I did when I updated this code. Peter c -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH] hw/imx_avic.c: Avoid format error when target_phys_addr_t is 64 bits
>>>>> "Peter" == Peter Maydell writes: Peter> Add a missing cast to avoid gcc complaining about format string Peter> errors when printing an expression based on a Peter> target_phys_addr_t. Peter> Signed-off-by: Peter Maydell Reviewed-by: Peter Chubb -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [Patch V10 3/5] i.MX31: Timers
Implement the timers on the Freescale i.MX31 SoC. This is not a complete implementation, but gives enough for Linux to boot and run. In particular external triggers, which are not useful under QEMU, are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- hw/arm/Makefile.objs |2 hw/imx.h |8 hw/imx_timer.c | 689 +++ 3 files changed, 698 insertions(+), 1 deletion(-) create mode 100644 hw/imx_timer.c Index: qemu-working/hw/arm/Makefile.objs === --- qemu-working.orig/hw/arm/Makefile.objs 2012-06-20 09:14:01.040588473 +1000 +++ qemu-working/hw/arm/Makefile.objs 2012-06-20 09:14:01.796592451 +1000 @@ -34,7 +34,7 @@ obj-y += framebuffer.o obj-y += vexpress.o obj-y += strongarm.o obj-y += collie.o -obj-y += imx_serial.o imx_ccm.o +obj-y += imx_serial.o imx_ccm.o imx_timer.o obj-y += pl041.o lm4549.o obj-$(CONFIG_FDT) += ../device_tree.o Index: qemu-working/hw/imx.h === --- qemu-working.orig/hw/imx.h 2012-06-20 09:14:01.040588473 +1000 +++ qemu-working/hw/imx.h 2012-06-20 09:14:01.796592451 +1000 @@ -23,4 +23,12 @@ typedef enum { uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock); +void imx_timerp_create(const target_phys_addr_t addr, + qemu_irq irq, + DeviceState *ccm); +void imx_timerg_create(const target_phys_addr_t addr, + qemu_irq irq, + DeviceState *ccm); + + #endif /* IMX_H */ Index: qemu-working/hw/imx_timer.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_timer.c 2012-06-20 09:14:01.800592472 +1000 @@ -0,0 +1,689 @@ +/* + * IMX31 Timer + * + * Copyright (c) 2008 OK Labs + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * Updated by Peter Chubb + * + * This code is licenced under GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + */ + +#include "hw.h" +#include "qemu-timer.h" +#include "ptimer.h" +#include "sysbus.h" +#include "imx.h" + +//#define DEBUG_TIMER 1 +#ifdef DEBUG_TIMER +# define DPRINTF(fmt, args...) \ + do { printf("imx_timer: " fmt , ##args); } while (0) +#else +# define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_timer: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * GPT : General purpose timer + * + * This timer counts up continuously while it is enabled, resetting itself + * to 0 when it reaches TIMER_MAX (in freerun mode) or when it + * reaches the value of ocr1 (in periodic mode). WE simulate this using a + * QEMU ptimer counting down from ocr1 and reloading from ocr1 in + * periodic mode, or counting from ocr1 to zero, then TIMER_MAX - ocr1. + * waiting_rov is set when counting from TIMER_MAX. + * + * In the real hardware, there are three comparison registers that can + * trigger interrupts, and compare channel 1 can be used to + * force-reset the timer. However, this is a `bare-bones' + * implementation: only what Linux 3.x uses has been implemented + * (free-running timer from 0 to OCR1 or TIMER_MAX) . + */ + + +#define TIMER_MAX 0XUL + +/* Control register. Not all of these bits have any effect (yet) */ +#define GPT_CR_EN (1 << 0) /* GPT Enable */ +#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */ +#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ +#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ +#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ +#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ +#define GPT_CR_CLKSRC_SHIFT (6) +#define GPT_CR_CLKSRC_MASK (0x7) + +#define GPT_CR_FRR(1 << 9) /* Freerun or Restart */ +#define GPT_CR_SWR(1 << 15) /* Software Reset */ +#define GPT_CR_IM1(3 << 16) /* Input capture channel 1 mode (2 bits) */ +#define GPT_CR_IM2(3 << 18) /* Input capture channel 2 mode (2 bits) */ +#define GPT_CR_OM1(7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ +#define GPT_CR_OM2(7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ +#define GPT_CR_OM3(7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ +#define GPT_CR_FO1(1 << 29) /* Force Output Compare Channel 1 */ +#define GPT_CR_FO2(1 << 30) /* Force Output Compare Channel 2 */ +#define GPT_CR_FO3(1
[Qemu-devel] [Patch V10 4/5] i.MX31: Interrupt Controller
Implement the Freescale i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.x Vectors are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- hw/arm/Makefile.objs |2 hw/imx_avic.c| 408 +++ 2 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 hw/imx_avic.c Index: qemu-working/hw/arm/Makefile.objs === --- qemu-working.orig/hw/arm/Makefile.objs 2012-06-20 09:14:02.140594261 +1000 +++ qemu-working/hw/arm/Makefile.objs 2012-06-20 09:14:02.892598215 +1000 @@ -34,7 +34,7 @@ obj-y += framebuffer.o obj-y += vexpress.o obj-y += strongarm.o obj-y += collie.o -obj-y += imx_serial.o imx_ccm.o imx_timer.o +obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o obj-y += pl041.o lm4549.o obj-$(CONFIG_FDT) += ../device_tree.o Index: qemu-working/hw/imx_avic.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_avic.c 2012-06-20 09:14:02.896598236 +1000 @@ -0,0 +1,408 @@ +/* + * i.MX31 Vectored Interrupt Controller + * + * Note this is NOT the PL192 provided by ARM, but + * a custom implementation by Freescale. + * + * Copyright (c) 2008 OKL + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * + * This code is licenced under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * TODO: implement vectors. + */ + +#include "hw.h" +#include "sysbus.h" +#include "host-utils.h" + +#define DEBUG_INT 1 +#undef DEBUG_INT /* comment out for debugging */ + +#ifdef DEBUG_INT +#define DPRINTF(fmt, args...) \ +do { printf("imx_avic: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +#define IMX_AVIC_NUM_IRQS 64 + +/* Interrupt Control Bits */ +#define ABFLAG (1<<25) +#define ABFEN (1<<24) +#define NIDIS (1<<22) /* Normal Interrupt disable */ +#define FIDIS (1<<21) /* Fast interrupt disable */ +#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ +#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ +#define NM(1<<18) /* Normal interrupt mode */ + + +#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) +#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +uint64_t pending; +uint64_t enabled; +uint64_t is_fiq; +uint32_t intcntl; +uint32_t intmask; +qemu_irq irq; +qemu_irq fiq; +uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ +} IMXAVICState; + +static const VMStateDescription vmstate_imx_avic = { +.name = "imx-avic", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT64(pending, IMXAVICState), +VMSTATE_UINT64(enabled, IMXAVICState), +VMSTATE_UINT64(is_fiq, IMXAVICState), +VMSTATE_UINT32(intcntl, IMXAVICState), +VMSTATE_UINT32(intmask, IMXAVICState), +VMSTATE_UINT32_ARRAY(prio, IMXAVICState, PRIO_WORDS), +VMSTATE_END_OF_LIST() +}, +}; + + + +static inline int imx_avic_prio(IMXAVICState *s, int irq) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +return 0xf & (s->prio[word] >> part); +} + +static inline void imx_avic_set_prio(IMXAVICState *s, int irq, int prio) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +uint32_t mask = ~(0xf << part); +s->prio[word] &= mask; +s->prio[word] |= prio << part; +} + +/* Update interrupts. */ +static void imx_avic_update(IMXAVICState *s) +{ +int i; +uint64_t new = s->pending & s->enabled; +uint64_t flags; + +flags = new & s->is_fiq; +qemu_set_irq(s->fiq, !!flags); + +flags = new & ~s->is_fiq; +if (!flags || (s->intmask == 0x1f)) { +qemu_set_irq(s->irq, !!flags); +return; +} + +/* + * Take interrupt if there's a pending interrupt with + * priority higher than the value of intmask + */ +for (i = 0; i < IMX_AVIC_NUM_IRQS; i++) { +if (flags & (1UL << i)) { +if (imx_avic_prio(s, i) > s->intmask) { +qemu_set_irq(s->irq, 1); +retu
[Qemu-devel] [Patch V10 1/5] i.MX: UART support
Implement the Freescale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the Freescale i.MX series. This patch gives only a `bare-bones' implementation, enough to run Linux or OKL4, but that's about it. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- hw/arm/Makefile.objs |1 hw/imx.h | 16 + hw/imx_serial.c | 467 +++ 3 files changed, 484 insertions(+) create mode 100644 hw/imx_serial.c Index: qemu-working/hw/arm/Makefile.objs === --- qemu-working.orig/hw/arm/Makefile.objs 2012-06-20 09:13:58.432574739 +1000 +++ qemu-working/hw/arm/Makefile.objs 2012-06-20 09:13:59.636581087 +1000 @@ -34,6 +34,7 @@ obj-y += framebuffer.o obj-y += vexpress.o obj-y += strongarm.o obj-y += collie.o +obj-y += imx_serial.o obj-y += pl041.o lm4549.o obj-$(CONFIG_FDT) += ../device_tree.o Index: qemu-working/hw/imx.h === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx.h 2012-06-20 09:13:59.636581087 +1000 @@ -0,0 +1,16 @@ +/* + * i.MX31 emulation + * + * Copyright (C) 2012 Peter Chubb + * NICTA + * + * This code is released under the GPL, version 2.0 or later + * See the file `../COPYING' for details. + */ + +#ifndef IMX_H +#define IMX_H + +void imx_serial_create(int uart, const target_phys_addr_t addr, qemu_irq irq); + +#endif /* IMX_H */ Index: qemu-working/hw/imx_serial.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_serial.c2012-06-20 09:13:59.636581087 +1000 @@ -0,0 +1,467 @@ +/* + * IMX31 UARTS + * + * Copyright (c) 2008 OKL + * Originally Written by Hans Jiang + * Copyright (c) 2011 NICTA Pty Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * This is a `bare-bones' implementation of the IMX series serial ports. + * TODO: + * -- implement FIFOs. The real hardware has 32 word transmit + * and receive FIFOs; we currently use a 1-char buffer + * -- implement DMA + * -- implement BAUD-rate and modem lines, for when the backend + * is a real serial device. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "qemu-char.h" +#include "imx.h" + +//#define DEBUG_SERIAL 1 +#ifdef DEBUG_SERIAL +#define DPRINTF(fmt, args...) \ +do { printf("imx_serial: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +//#define DEBUG_IMPLEMENTATION 1 +#ifdef DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +int32_t readbuff; + +uint32_t usr1; +uint32_t usr2; +uint32_t ucr1; +uint32_t ucr2; +uint32_t uts1; + +/* + * The registers below are implemented just so that the + * guest OS sees what it has written + */ +uint32_t onems; +uint32_t ufcr; +uint32_t ubmr; +uint32_t ubrc; +uint32_t ucr3; + +qemu_irq irq; +CharDriverState *chr; +} IMXSerialState; + +static const VMStateDescription vmstate_imx_serial = { +.name = "imx-serial", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_INT32(readbuff, IMXSerialState), +VMSTATE_UINT32(usr1, IMXSerialState), +VMSTATE_UINT32(usr2, IMXSerialState), +VMSTATE_UINT32(ucr1, IMXSerialState), +VMSTATE_UINT32(uts1, IMXSerialState), +VMSTATE_UINT32(onems, IMXSerialState), +VMSTATE_UINT32(ufcr, IMXSerialState), +VMSTATE_UINT32(ubmr, IMXSerialState), +VMSTATE_UINT32(ubrc, IMXSerialState), +VMSTATE_UINT32(ucr3, IMXSerialState), +VMSTATE_END_OF_LIST() +}, +}; + + +#define URXD_CHARRDY(1<<15) /* character read is valid */ +#define URXD_ERR(1<<14) /* Character has error */ +#define URXD_BRK(1<<11) /* Break received */ + +#define USR1_PARTYER(1<<15) /* Parity Error */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Tx ready */ +#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */ +#define USR1_ESCF (1<<11) /* Escape sequence interrupt */ +#define USR1_FRAMERR(1<<10) /* Framing error */ +
[Qemu-devel] [Patch V10 2/5] i.MX31: Clock Control Module
For Linux to be able to work out how fast its clocks are going, so that timer ticks come approximately at the right time, it needs to be able to query the clock control module (CCM). This is the start of a CCM implementation. It currently knows only about the MCU, HSP and IPG clocks --- i.e., the ones used to feed the periodic and general purpose timers. Signed-off-by: Peter Chubb --- hw/arm/Makefile.objs |2 hw/imx.h | 10 + hw/imx_ccm.c | 321 +++ 3 files changed, 332 insertions(+), 1 deletion(-) Index: qemu-working/hw/arm/Makefile.objs === --- qemu-working.orig/hw/arm/Makefile.objs 2012-06-20 09:13:59.968582831 +1000 +++ qemu-working/hw/arm/Makefile.objs 2012-06-20 09:14:00.692586643 +1000 @@ -34,7 +34,7 @@ obj-y += framebuffer.o obj-y += vexpress.o obj-y += strongarm.o obj-y += collie.o -obj-y += imx_serial.o +obj-y += imx_serial.o imx_ccm.o obj-y += pl041.o lm4549.o obj-$(CONFIG_FDT) += ../device_tree.o Index: qemu-working/hw/imx.h === --- qemu-working.orig/hw/imx.h 2012-06-20 09:13:59.968582831 +1000 +++ qemu-working/hw/imx.h 2012-06-20 09:14:00.696586665 +1000 @@ -13,4 +13,14 @@ void imx_serial_create(int uart, const target_phys_addr_t addr, qemu_irq irq); +typedef enum { +NOCLK, +MCU, +HSP, +IPG, +CLK_32k +} IMXClk; + +uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock); + #endif /* IMX_H */ Index: qemu-working/hw/imx_ccm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_ccm.c 2012-06-20 09:14:00.696586665 +1000 @@ -0,0 +1,321 @@ +/* + * IMX31 Clock Control Module + * + * Copyright (C) 2012 NICTA + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * To get the timer frequencies right, we need to emulate at least part of + * the CCM. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "imx.h" + +#define CKIH_FREQ 2600 /* 26MHz crystal input */ +#define CKIL_FREQ32768 /* nominal 32khz clock */ + + +//#define DEBUG_CCM 1 +#ifdef DEBUG_CCM +#define DPRINTF(fmt, args...) \ +do { printf("imx_ccm: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +static int imx_ccm_post_load(void *opaque, int version_id); + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; + +uint32_t ccmr; +uint32_t pdr0; +uint32_t pdr1; +uint32_t mpctl; +uint32_t spctl; +uint32_t cgr[3]; +uint32_t pmcr0; +uint32_t pmcr1; + +/* Frequencies precalculated on register changes */ +uint32_t pll_refclk_freq; +uint32_t mcu_clk_freq; +uint32_t hsp_clk_freq; +uint32_t ipg_clk_freq; +} IMXCCMState; + +static const VMStateDescription vmstate_imx_ccm = { +.name = "imx-ccm", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(ccmr, IMXCCMState), +VMSTATE_UINT32(pdr0, IMXCCMState), +VMSTATE_UINT32(pdr1, IMXCCMState), +VMSTATE_UINT32(mpctl, IMXCCMState), +VMSTATE_UINT32(spctl, IMXCCMState), +VMSTATE_UINT32_ARRAY(cgr, IMXCCMState, 3), +VMSTATE_UINT32(pmcr0, IMXCCMState), +VMSTATE_UINT32(pmcr1, IMXCCMState), +VMSTATE_UINT32(pll_refclk_freq, IMXCCMState), +}, +.post_load = imx_ccm_post_load, +}; + +/* CCMR */ +#define CCMR_FPME (1<<0) +#define CCMR_MPE (1<<3) +#define CCMR_MDS (1<<7) +#define CCMR_FPMF (1<<26) +#define CCMR_PRCS (3<<1) + +/* PDR0 */ +#define PDR0_MCU_PODF_SHIFT (0) +#define PDR0_MCU_PODF_MASK (0x7) +#define PDR0_MAX_PODF_SHIFT (3) +#define PDR0_MAX_PODF_MASK (0x7) +#define PDR0_IPG_PODF_SHIFT (6) +#define PDR0_IPG_PODF_MASK (0x3) +#define PDR0_NFC_PODF_SHIFT (8) +#define PDR0_NFC_PODF_MASK (0x7) +#define PDR0_HSP_PODF_SHIFT (11) +#define PDR0_HSP_PODF_MASK (0x7) +#define PDR0_PER_PODF_SHIFT (16) +#define PDR0_PER_PODF_MASK (0x1f) +#define PDR0_CSI_PODF_SHIFT (23) +#define PDR0_CSI_PODF_MASK (0x1ff) + +#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \ + & PDR0_##name##_PODF_MASK) +#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \ + PDR0_##name##_PODF_SHIFT) +/* PLL control registers */ +#define PD(v) (((v) >> 26) & 0xf) +#define MFD(v) (((v) >> 16) & 0x3ff) +#define MFI(v) (((v) >> 10) & 0xf); +#define MFN(v) ((v) & 0x3ff) + +#define PLL_PD(x) (((x) & 0xf) << 26) +#define PLL_MFD(x) (((x) & 0x3ff) <
[Qemu-devel] [Patch V10 5/5] i.MX31: KZM-ARM11-01 evaluation board
Board support for Kyoto Micro's KZM-ARM11-01, an evaluation board built around the Freescale i.MX31. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- MAINTAINERS |6 + hw/arm/Makefile.objs |1 hw/kzm.c | 154 +++ 3 files changed, 161 insertions(+) create mode 100644 hw/kzm.c Index: qemu-working/MAINTAINERS === --- qemu-working.orig/MAINTAINERS 2012-06-20 09:31:58.311046949 +1000 +++ qemu-working/MAINTAINERS2012-06-20 09:33:32.927501381 +1000 @@ -207,6 +207,12 @@ M: qemu-devel@nongnu.org S: Orphan F: hw/gumstix.c +i.MX31 +M: Peter Chubb +S: Odd fixes +F: hw/imx* +F: hw/kzm.c + Integrator CP M: Paul Brook M: Peter Maydell Index: qemu-working/hw/arm/Makefile.objs === --- qemu-working.orig/hw/arm/Makefile.objs 2012-06-20 09:32:12.659116627 +1000 +++ qemu-working/hw/arm/Makefile.objs 2012-06-20 09:32:15.847132070 +1000 @@ -35,6 +35,7 @@ obj-y += vexpress.o obj-y += strongarm.o obj-y += collie.o obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o +obj-y += kzm.o obj-y += pl041.o lm4549.o obj-$(CONFIG_FDT) += ../device_tree.o Index: qemu-working/hw/kzm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/kzm.c 2012-06-20 09:32:15.851132090 +1000 @@ -0,0 +1,154 @@ +/* + * KZM Board System emulation. + * + * Copyright (c) 2008 OKL and 2011 NICTA + * Written by Hans at OK-Labs + * Updated by Peter Chubb. + * + * This code is licenced under the GPL, version 2 or later. + * See the file `COPYING' in the top level directory. + * + * It (partially) emulates a Kyoto Microcomputer + * KZM-ARM11-01 evaluation board, with a Freescale + * i.MX31 SoC + */ + +#include "sysbus.h" +#include "exec-memory.h" +#include "hw.h" +#include "arm-misc.h" +#include "devices.h" +#include "net.h" +#include "sysemu.h" +#include "boards.h" +#include "pc.h" /* for the FPGA UART that emulates a 16550 */ +#include "imx.h" + +/* Memory map for Kzm Emulation Baseboard: + * 0x-0x3fff 16k secure ROM IGNORED + * 0x4000-0x00407fff Reserved IGNORED + * 0x00404000-0x00407fff ROM IGNORED + * 0x00408000-0x0fff Reserved IGNORED + * 0x1000-0x1fffbfff RAM aliasing IGNORED + * 0x1fffc000-0x1fff RAM EMULATED + * 0x2000-0x2fff Reserved IGNORED + * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x43f0 IO_AREA0 + * 0x43f9 UART1 EMULATED + * 0x43f94000 UART2 EMULATED + * 0x6800 AVIC EMULATED + * 0x53f8 CCM EMULATED + * 0x53f94000 PIT 1 EMULATED + * 0x53f98000 PIT 2 EMULATED + * 0x53f9 GPT EMULATED + * 0x8000-0x87ff RAM EMULATED + * 0x8800-0x8fff RAM Aliasing EMULATED + * 0xa000-0xafff NAND Flash IGNORED + * 0xb000-0xb3ff Unavailable IGNORED + * 0xb400-0xb4000fff 8-bit free space IGNORED + * 0xb4001000-0xb400100f Board controlIGNORED + * 0xb4001003 DIP switch + * 0xb4001010-0xb400101f 7-segment LEDIGNORED + * 0xb4001020-0xb400102f LED IGNORED + * 0xb4001030-0xb400103f LED IGNORED + * 0xb4001040-0xb400104f FPGA, UART EMULATED + * 0xb4001050-0xb400105f FPGA, UART EMULATED + * 0xb4001060-0xb40f FPGA IGNORED + * 0xb600-0xb61f LAN controller EMULATED + * 0xb620-0xb62f FPGA NAND Controller IGNORED + * 0xb630-0xb7ff Free IGNORED + * 0xb800-0xb8004fff Memory control registers IGNORED + * 0xc000-0xc3ff PCMCIA/CFIGNORED + * 0xc400-0x Reserved IGNORED + */ + +#define KZM_RAMADDRESS (0x8000) +#define KZM_FPGA (0xb4001040) + +static struct arm_boot_info kzm_binfo = { +.loader_start = KZM_RAMADDRESS, +.board_id = 1722, +}; + +static void kzm_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +ARMCPU *cpu; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *sram = g_new(Mem
[Qemu-devel] [Patch V10 0/5] i.MX31: Add initial support
Changes since V9: Added MAINTAINERS entry, rebased (and tested) against git tip. Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] Broken Microblaze timer
>>>>> "Peter" == Peter Crosthwaite writes: Peter> So ptimer has safeguards against misuse in periodic mode but Peter> not one-shot mode? This strikes me as inconsistent. I.E. for Peter> one use case the safeguard is in ptimer, and the other in the Peter> client device. I think if we are in the bussiness of putting Peter> these safeguards in ptimer itself then it should be there for Peter> all use cases yes? I.E. the fix for this is making sure Peter> one-shot ptimer give the cpu a look in. When a one-shot timer fires, it has to be reset by the CPU before it'll fire again. So the CPU always gets a look in --- or ought to. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] Broken Microblaze timer
>>>>> "Paolo" == Paolo Bonzini writes: Paolo> Il 14/06/2012 04:29, Peter Crosthwaite ha scritto: >> Obviously this sucks as a patch, but without this hack, the system >> freezes on boot. I managed to ascertain that its coming from the >> ptimer used by the system timer (hw/xilinx_timer.c). The CPU is >> either halted and never resumes, or the timer is flooding with halt >> requests and the CPU never gets another look in. >> >> The question is, is this a failure in ptimer, xilinx_timer or the >> async framework? Can ptimer be misused such that the CPU is locked >> up? Paolo> Yes, this looks like the ptimer is flooding the iothread so Paolo> that the CPU does not get an occasion to run. Paolo> Perhaps you want to limit the rate of the hw/xilinx_timer.c to Paolo> something like 1000 Hz or something like that. Changeset cf36b31db209a261ee3bc2737e788e1ced0a1bec Limit ptimer rate to something achievable is meant to fix this in the cases where the timer is auto-reloaded. xilinx_timer.c always uses the timer in one-shot mode, so it needs to be fixed in there. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [patch V9 5/5] i.MX31: KZM-ARM11-01 evaluation board
Board support for Kyoto Micro's KZM-ARM11-01, an evaluation board built around the Freescale i.MX31. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/kzm.c| 156 2 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 hw/kzm.c Index: qemu-working/Makefile.target === --- qemu-working.orig/Makefile.target 2012-06-07 11:32:03.972100328 +1000 +++ qemu-working/Makefile.target2012-06-07 11:32:06.004117344 +1000 @@ -368,7 +368,7 @@ obj-arm-y += vexpress.o obj-arm-y += strongarm.o obj-arm-y += collie.o obj-arm-y += pl041.o lm4549.o -obj-arm-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o +obj-arm-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o kzm.o obj-arm-$(CONFIG_FDT) += device_tree.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o Index: qemu-working/hw/kzm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/kzm.c 2012-06-07 11:32:06.004117344 +1000 @@ -0,0 +1,156 @@ +/* + * KZM Board System emulation. + * + * Copyright (c) 2008 OKL and 2011 NICTA + * Written by Hans at OK-Labs + * Updated by Peter Chubb. + * + * This code is licenced under the GPL, version 2 or later. + * See the file `COPYING' in the top level directory. + * + * It (partially) emulates a Kyoto Microcomputer + * KZM-ARM11-01 evaluation board, with a Freescale + * i.MX31 SoC + */ + +#include "sysbus.h" +#include "exec-memory.h" +#include "hw.h" +#include "arm-misc.h" +#include "devices.h" +#include "net.h" +#include "sysemu.h" +#include "boards.h" +#include "pc.h" /* for the FPGA UART that emulates a 16550 */ +#include "imx.h" + +/* Memory map for Kzm Emulation Baseboard: + * 0x-0x3fff 16k secure ROM IGNORED + * 0x4000-0x00407fff Reserved IGNORED + * 0x00404000-0x00407fff ROM IGNORED + * 0x00408000-0x0fff Reserved IGNORED + * 0x1000-0x1fffbfff RAM aliasing IGNORED + * 0x1fffc000-0x1fff RAM EMULATED + * 0x2000-0x2fff Reserved IGNORED + * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x43f0 IO_AREA0 + * 0x43f9 UART1 EMULATED + * 0x43f94000 UART2 EMULATED + * 0x6800 AVIC EMULATED + * 0x53f8 CCM EMULATED + * 0x53f94000 PIT 1 EMULATED + * 0x53f98000 PIT 2 EMULATED + * 0x53f9 GPT EMULATED + * 0x8000-0x87ff RAM EMULATED + * 0x8800-0x8fff RAM Aliasing EMULATED + * 0xa000-0xafff NAND Flash IGNORED + * 0xb000-0xb3ff Unavailable IGNORED + * 0xb400-0xb4000fff 8-bit free space IGNORED + * 0xb4001000-0xb400100f Board controlIGNORED + * 0xb4001003 DIP switch + * 0xb4001010-0xb400101f 7-segment LEDIGNORED + * 0xb4001020-0xb400102f LED IGNORED + * 0xb4001030-0xb400103f LED IGNORED + * 0xb4001040-0xb400104f FPGA, UART EMULATED + * 0xb4001050-0xb400105f FPGA, UART EMULATED + * 0xb4001060-0xb40f FPGA IGNORED + * 0xb600-0xb61f LAN controller EMULATED + * 0xb620-0xb62f FPGA NAND Controller IGNORED + * 0xb630-0xb7ff Free IGNORED + * 0xb800-0xb8004fff Memory control registers IGNORED + * 0xc000-0xc3ff PCMCIA/CFIGNORED + * 0xc400-0x Reserved IGNORED + */ + +#define KZM_RAMADDRESS (0x8000) +#define KZM_FPGA (0xb4001040) + +static struct arm_boot_info kzm_binfo = { +.loader_start = KZM_RAMADDRESS, +.board_id = 1722, +}; + +static void kzm_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +ARMCPU *cpu; +CPUARMState *env; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *ram_alias = g_new(MemoryRegion, 1); +qemu_irq *cpu_pic; +DeviceState *dev; +DeviceState *ccm; + +if (!cpu_model) { +cpu_model = "arm1136"; +} + +cpu = arm_cpu_init(cpu_model); +if (!cpu) { +fprintf(stderr, "Unable to find
[Qemu-devel] [patch V9 1/5] i.MX: UART support
Implement the Freescale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the Freescale i.MX series. This patch gives only a `bare-bones' implementation, enough to run Linux or OKL4, but that's about it. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |1 hw/imx.h| 16 + hw/imx_serial.c | 467 3 files changed, 484 insertions(+) create mode 100644 hw/imx_serial.c Index: qemu-working/Makefile.target === --- qemu-working.orig/Makefile.target 2012-06-07 11:31:58.972058181 +1000 +++ qemu-working/Makefile.target2012-06-07 11:32:00.460070764 +1000 @@ -368,6 +368,7 @@ obj-arm-y += vexpress.o obj-arm-y += strongarm.o obj-arm-y += collie.o obj-arm-y += pl041.o lm4549.o +obj-arm-y += imx_serial.o obj-arm-$(CONFIG_FDT) += device_tree.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o Index: qemu-working/hw/imx.h === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx.h 2012-06-07 11:32:00.460070764 +1000 @@ -0,0 +1,16 @@ +/* + * i.MX31 emulation + * + * Copyright (C) 2012 Peter Chubb + * NICTA + * + * This code is released under the GPL, version 2.0 or later + * See the file `../COPYING' for details. + */ + +#ifndef IMX_H +#define IMX_H + +void imx_serial_create(int uart, const target_phys_addr_t addr, qemu_irq irq); + +#endif /* IMX_H */ Index: qemu-working/hw/imx_serial.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_serial.c2012-06-07 11:32:00.460070764 +1000 @@ -0,0 +1,467 @@ +/* + * IMX31 UARTS + * + * Copyright (c) 2008 OKL + * Originally Written by Hans Jiang + * Copyright (c) 2011 NICTA Pty Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * This is a `bare-bones' implementation of the IMX series serial ports. + * TODO: + * -- implement FIFOs. The real hardware has 32 word transmit + * and receive FIFOs; we currently use a 1-char buffer + * -- implement DMA + * -- implement BAUD-rate and modem lines, for when the backend + * is a real serial device. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "qemu-char.h" +#include "imx.h" + +//#define DEBUG_SERIAL 1 +#ifdef DEBUG_SERIAL +#define DPRINTF(fmt, args...) \ +do { printf("imx_serial: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +//#define DEBUG_IMPLEMENTATION 1 +#ifdef DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +int32_t readbuff; + +uint32_t usr1; +uint32_t usr2; +uint32_t ucr1; +uint32_t ucr2; +uint32_t uts1; + +/* + * The registers below are implemented just so that the + * guest OS sees what it has written + */ +uint32_t onems; +uint32_t ufcr; +uint32_t ubmr; +uint32_t ubrc; +uint32_t ucr3; + +qemu_irq irq; +CharDriverState *chr; +} IMXSerialState; + +static const VMStateDescription vmstate_imx_serial = { +.name = "imx-serial", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_INT32(readbuff, IMXSerialState), +VMSTATE_UINT32(usr1, IMXSerialState), +VMSTATE_UINT32(usr2, IMXSerialState), +VMSTATE_UINT32(ucr1, IMXSerialState), +VMSTATE_UINT32(uts1, IMXSerialState), +VMSTATE_UINT32(onems, IMXSerialState), +VMSTATE_UINT32(ufcr, IMXSerialState), +VMSTATE_UINT32(ubmr, IMXSerialState), +VMSTATE_UINT32(ubrc, IMXSerialState), +VMSTATE_UINT32(ucr3, IMXSerialState), +VMSTATE_END_OF_LIST() +}, +}; + + +#define URXD_CHARRDY(1<<15) /* character read is valid */ +#define URXD_ERR(1<<14) /* Character has error */ +#define URXD_BRK(1<<11) /* Break received */ + +#define USR1_PARTYER(1<<15) /* Parity Error */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Tx ready */ +#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */ +#define USR1_ESCF (1<<11) /* Escape sequence interrupt */ +#define USR1_FRAM
[Qemu-devel] [patch V9 2/5] i.MX31: Clock Control Module
For Linux to be able to work out how fast its clocks are going, so that timer ticks come approximately at the right time, it needs to be able to query the clock control module (CCM). This is the start of a CCM implementation. It currently knows only about the MCU, HSP and IPG clocks --- i.e., the ones used to feed the periodic and general purpose timers. Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx.h| 10 + hw/imx_ccm.c| 321 3 files changed, 332 insertions(+), 1 deletion(-) Index: qemu-working/Makefile.target === --- qemu-working.orig/Makefile.target 2012-06-07 11:32:00.788073534 +1000 +++ qemu-working/Makefile.target2012-06-07 11:32:01.548079944 +1000 @@ -368,7 +368,7 @@ obj-arm-y += vexpress.o obj-arm-y += strongarm.o obj-arm-y += collie.o obj-arm-y += pl041.o lm4549.o -obj-arm-y += imx_serial.o +obj-arm-y += imx_serial.o imx_ccm.o obj-arm-$(CONFIG_FDT) += device_tree.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o Index: qemu-working/hw/imx.h === --- qemu-working.orig/hw/imx.h 2012-06-07 11:32:00.788073534 +1000 +++ qemu-working/hw/imx.h 2012-06-07 11:32:01.548079944 +1000 @@ -13,4 +13,14 @@ void imx_serial_create(int uart, const target_phys_addr_t addr, qemu_irq irq); +typedef enum { +NOCLK, +MCU, +HSP, +IPG, +CLK_32k +} IMXClk; + +uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock); + #endif /* IMX_H */ Index: qemu-working/hw/imx_ccm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_ccm.c 2012-06-07 11:32:01.552079977 +1000 @@ -0,0 +1,321 @@ +/* + * IMX31 Clock Control Module + * + * Copyright (C) 2012 NICTA + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * To get the timer frequencies right, we need to emulate at least part of + * the CCM. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "imx.h" + +#define CKIH_FREQ 2600 /* 26MHz crystal input */ +#define CKIL_FREQ32768 /* nominal 32khz clock */ + + +//#define DEBUG_CCM 1 +#ifdef DEBUG_CCM +#define DPRINTF(fmt, args...) \ +do { printf("imx_ccm: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +static int imx_ccm_post_load(void *opaque, int version_id); + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; + +uint32_t ccmr; +uint32_t pdr0; +uint32_t pdr1; +uint32_t mpctl; +uint32_t spctl; +uint32_t cgr[3]; +uint32_t pmcr0; +uint32_t pmcr1; + +/* Frequencies precalculated on register changes */ +uint32_t pll_refclk_freq; +uint32_t mcu_clk_freq; +uint32_t hsp_clk_freq; +uint32_t ipg_clk_freq; +} IMXCCMState; + +static const VMStateDescription vmstate_imx_ccm = { +.name = "imx-ccm", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(ccmr, IMXCCMState), +VMSTATE_UINT32(pdr0, IMXCCMState), +VMSTATE_UINT32(pdr1, IMXCCMState), +VMSTATE_UINT32(mpctl, IMXCCMState), +VMSTATE_UINT32(spctl, IMXCCMState), +VMSTATE_UINT32_ARRAY(cgr, IMXCCMState, 3), +VMSTATE_UINT32(pmcr0, IMXCCMState), +VMSTATE_UINT32(pmcr1, IMXCCMState), +VMSTATE_UINT32(pll_refclk_freq, IMXCCMState), +}, +.post_load = imx_ccm_post_load, +}; + +/* CCMR */ +#define CCMR_FPME (1<<0) +#define CCMR_MPE (1<<3) +#define CCMR_MDS (1<<7) +#define CCMR_FPMF (1<<26) +#define CCMR_PRCS (3<<1) + +/* PDR0 */ +#define PDR0_MCU_PODF_SHIFT (0) +#define PDR0_MCU_PODF_MASK (0x7) +#define PDR0_MAX_PODF_SHIFT (3) +#define PDR0_MAX_PODF_MASK (0x7) +#define PDR0_IPG_PODF_SHIFT (6) +#define PDR0_IPG_PODF_MASK (0x3) +#define PDR0_NFC_PODF_SHIFT (8) +#define PDR0_NFC_PODF_MASK (0x7) +#define PDR0_HSP_PODF_SHIFT (11) +#define PDR0_HSP_PODF_MASK (0x7) +#define PDR0_PER_PODF_SHIFT (16) +#define PDR0_PER_PODF_MASK (0x1f) +#define PDR0_CSI_PODF_SHIFT (23) +#define PDR0_CSI_PODF_MASK (0x1ff) + +#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \ + & PDR0_##name##_PODF_MASK) +#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \ + PDR0_##name##_PODF_SHIFT) +/* PLL control registers */ +#define PD(v) (((v) >> 26) & 0xf) +#define MFD(v) (((v) >> 16) & 0x3ff) +#define MFI(v) (((v) >> 10) & 0xf); +#define MFN(v) ((v) & 0x3ff) + +#define PLL_PD(x) (((x) & 0xf) << 26) +#defi
[Qemu-devel] [patch V9 3/5] i.MX31: Timers
Implement the timers on the Freescale i.MX31 SoC. This is not a complete implementation, but gives enough for Linux to boot and run. In particular external triggers, which are not useful under QEMU, are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx.h|8 hw/imx_timer.c | 689 3 files changed, 698 insertions(+), 1 deletion(-) create mode 100644 hw/imx_timer.c Index: qemu-working/Makefile.target === --- qemu-working.orig/Makefile.target 2012-06-07 11:32:01.892082843 +1000 +++ qemu-working/Makefile.target2012-06-07 11:32:02.612088902 +1000 @@ -368,7 +368,7 @@ obj-arm-y += vexpress.o obj-arm-y += strongarm.o obj-arm-y += collie.o obj-arm-y += pl041.o lm4549.o -obj-arm-y += imx_serial.o imx_ccm.o +obj-arm-y += imx_serial.o imx_ccm.o imx_timer.o obj-arm-$(CONFIG_FDT) += device_tree.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o Index: qemu-working/hw/imx.h === --- qemu-working.orig/hw/imx.h 2012-06-07 11:32:01.892082843 +1000 +++ qemu-working/hw/imx.h 2012-06-07 11:32:02.616088936 +1000 @@ -23,4 +23,12 @@ typedef enum { uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock); +void imx_timerp_create(const target_phys_addr_t addr, + qemu_irq irq, + DeviceState *ccm); +void imx_timerg_create(const target_phys_addr_t addr, + qemu_irq irq, + DeviceState *ccm); + + #endif /* IMX_H */ Index: qemu-working/hw/imx_timer.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_timer.c 2012-06-07 11:32:02.616088936 +1000 @@ -0,0 +1,689 @@ +/* + * IMX31 Timer + * + * Copyright (c) 2008 OK Labs + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * Updated by Peter Chubb + * + * This code is licenced under GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + */ + +#include "hw.h" +#include "qemu-timer.h" +#include "ptimer.h" +#include "sysbus.h" +#include "imx.h" + +//#define DEBUG_TIMER 1 +#ifdef DEBUG_TIMER +# define DPRINTF(fmt, args...) \ + do { printf("imx_timer: " fmt , ##args); } while (0) +#else +# define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_timer: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * GPT : General purpose timer + * + * This timer counts up continuously while it is enabled, resetting itself + * to 0 when it reaches TIMER_MAX (in freerun mode) or when it + * reaches the value of ocr1 (in periodic mode). WE simulate this using a + * QEMU ptimer counting down from ocr1 and reloading from ocr1 in + * periodic mode, or counting from ocr1 to zero, then TIMER_MAX - ocr1. + * waiting_rov is set when counting from TIMER_MAX. + * + * In the real hardware, there are three comparison registers that can + * trigger interrupts, and compare channel 1 can be used to + * force-reset the timer. However, this is a `bare-bones' + * implementation: only what Linux 3.x uses has been implemented + * (free-running timer from 0 to OCR1 or TIMER_MAX) . + */ + + +#define TIMER_MAX 0XUL + +/* Control register. Not all of these bits have any effect (yet) */ +#define GPT_CR_EN (1 << 0) /* GPT Enable */ +#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */ +#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ +#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ +#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ +#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ +#define GPT_CR_CLKSRC_SHIFT (6) +#define GPT_CR_CLKSRC_MASK (0x7) + +#define GPT_CR_FRR(1 << 9) /* Freerun or Restart */ +#define GPT_CR_SWR(1 << 15) /* Software Reset */ +#define GPT_CR_IM1(3 << 16) /* Input capture channel 1 mode (2 bits) */ +#define GPT_CR_IM2(3 << 18) /* Input capture channel 2 mode (2 bits) */ +#define GPT_CR_OM1(7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ +#define GPT_CR_OM2(7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ +#define GPT_CR_OM3(7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ +#define GPT_CR_FO1(1 << 29) /* Force Output Compare Channel 1 */ +#define GPT_CR_FO2(1 << 30) /* Force Output Compar
[Qemu-devel] [patch V9 4/5] i.MX31: Interrupt Controller
Implement the Freescale i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.x Vectors are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |2 hw/imx_avic.c | 408 2 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 hw/imx_avic.c Index: qemu-working/Makefile.target === --- qemu-working.orig/Makefile.target 2012-06-07 11:32:02.964091864 +1000 +++ qemu-working/Makefile.target2012-06-07 11:32:03.652097641 +1000 @@ -368,7 +368,7 @@ obj-arm-y += vexpress.o obj-arm-y += strongarm.o obj-arm-y += collie.o obj-arm-y += pl041.o lm4549.o -obj-arm-y += imx_serial.o imx_ccm.o imx_timer.o +obj-arm-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o obj-arm-$(CONFIG_FDT) += device_tree.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o Index: qemu-working/hw/imx_avic.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_avic.c 2012-06-07 11:32:03.656097675 +1000 @@ -0,0 +1,408 @@ +/* + * i.MX31 Vectored Interrupt Controller + * + * Note this is NOT the PL192 provided by ARM, but + * a custom implementation by Freescale. + * + * Copyright (c) 2008 OKL + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * + * This code is licenced under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * TODO: implement vectors. + */ + +#include "hw.h" +#include "sysbus.h" +#include "host-utils.h" + +#define DEBUG_INT 1 +#undef DEBUG_INT /* comment out for debugging */ + +#ifdef DEBUG_INT +#define DPRINTF(fmt, args...) \ +do { printf("imx_avic: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +#define IMX_AVIC_NUM_IRQS 64 + +/* Interrupt Control Bits */ +#define ABFLAG (1<<25) +#define ABFEN (1<<24) +#define NIDIS (1<<22) /* Normal Interrupt disable */ +#define FIDIS (1<<21) /* Fast interrupt disable */ +#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ +#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ +#define NM(1<<18) /* Normal interrupt mode */ + + +#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) +#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +uint64_t pending; +uint64_t enabled; +uint64_t is_fiq; +uint32_t intcntl; +uint32_t intmask; +qemu_irq irq; +qemu_irq fiq; +uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ +} IMXAVICState; + +static const VMStateDescription vmstate_imx_avic = { +.name = "imx-avic", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT64(pending, IMXAVICState), +VMSTATE_UINT64(enabled, IMXAVICState), +VMSTATE_UINT64(is_fiq, IMXAVICState), +VMSTATE_UINT32(intcntl, IMXAVICState), +VMSTATE_UINT32(intmask, IMXAVICState), +VMSTATE_UINT32_ARRAY(prio, IMXAVICState, PRIO_WORDS), +VMSTATE_END_OF_LIST() +}, +}; + + + +static inline int imx_avic_prio(IMXAVICState *s, int irq) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +return 0xf & (s->prio[word] >> part); +} + +static inline void imx_avic_set_prio(IMXAVICState *s, int irq, int prio) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +uint32_t mask = ~(0xf << part); +s->prio[word] &= mask; +s->prio[word] |= prio << part; +} + +/* Update interrupts. */ +static void imx_avic_update(IMXAVICState *s) +{ +int i; +uint64_t new = s->pending & s->enabled; +uint64_t flags; + +flags = new & s->is_fiq; +qemu_set_irq(s->fiq, !!flags); + +flags = new & ~s->is_fiq; +if (!flags || (s->intmask == 0x1f)) { +qemu_set_irq(s->irq, !!flags); +return; +} + +/* + * Take interrupt if there's a pending interrupt with + * priority higher than the value of intmask + */ +for (i = 0; i < IMX_AVIC_NUM_IRQS; i++) { +if (flags & (1UL << i)) { +if (imx_avic_prio(s, i) > s->intmask) { +qemu_s
[Qemu-devel] [patch V9 0/5] i.MX31: Add initial support
Changes since V8: Recovered my stuff-up from backup --- changes that were in V7 are back in! Andreas's comments addressed (except adding MAINTAINER field) Peter Maydell's comments against V6/7 are addressed. Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [patch] target-microblaze/translate.c fails to compile with gcc 4.7
n current qemu.git, I see: CCmicroblaze-softmmu/translate.o /home/peterc/src/work/QEMU/qemu-working/target-microblaze/translate.c: In function ‘dec_store’: /home/peterc/src/work/QEMU/qemu-working/target-microblaze/translate.c:1108:5: error: invalid initializer This is the obvious fix: --- target-microblaze/translate.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Index: qemu-working/target-microblaze/translate.c === --- qemu-working.orig/target-microblaze/translate.c 2012-06-07 10:52:56.210980100 +1000 +++ qemu-working/target-microblaze/translate.c 2012-06-07 11:47:19.682479289 +1000 @@ -1105,7 +1105,7 @@ static void gen_store(DisasContext *dc, static void dec_store(DisasContext *dc) { -TCGv t, *addr, swx_addr, r_check = 0; +TCGv t, *addr, swx_addr, r_check; int swx_skip = 0; unsigned int size, rev = 0, ex = 0; -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [patch v8 0/5] i.MX31 support
>>>>> "Andreas" == Andreas Färber writes: Andreas> Hello Peter, Am 06.06.2012 05:47, schrieb Peter Chubb: >> There are no major changes since last time, just rebased to current >> tip now that QEMU 1.2 is open. >> >> For those who have come into the story late, this is a series of >> patches to allow QEMU to emulate a Freescale i.MX31 on a Kyoto >> Microsystems evaluation board. It's pretty bare-bones, but runs >> Linux and seL4 nicely. Andreas> Something is wrong with the patch submission, they are shown Andreas> as attachments and Thunderbird doesn't let me comment Andreas> inline. Please use git-send-email to submit. This is a known issue with some thunderbird versions --- Mozilla/Mime support is a bit weird when it comes to emails with a Content-Disposition: inline with a filename. Andreas> Also the diffstat doesn't match the patch wrt file ordering, Andreas> so it would be advisable to use git-format-patch. Andreas> Our concept of topics in the subject seems to be troubling Andreas> you, you have added " support" since v7 (still readable, so Andreas> I'm okay) whereas what we usually use is a lower-case tag as Andreas> described here plus an active description of what it's doing Andreas> (e.g., "foo: Add/Introduce bar"): Andreas> https://live.gnome.org/Git/CommitMessages This series was broken in a couple of ways. Please ignore it! (my laptop got restored from a backup and in moving forward again I think some changes that were in v7 got lost, including this one). Andreas> On patch 5: Please use cpu_arm_init() in place of cpu_init() Andreas> and prefer ARMCPU. This is already in qemu.git and many more Andreas> conversions are in the QOM CPUState part 3 PULL and on Andreas> qom-next. I dunno what happened there. I put that in, then the result wouldn;t compile, so I reverted it. Andreas> Also note that arm_pic_init_cpu() and arm_load_kernel() are Andreas> being changed to take that ARMCPU, so this needs to be Andreas> coordinated. OK. Andreas> Please remove the semicolon after machine_init() and check Andreas> the indentation. After sysbus_create_varargs() for instance I Andreas> spot one space too few and below for imx_serial_create() Andreas> there's a double space. OK. Dunno why checkpatch didn't catch this. Andreas> Please also make all your TypeInfos static const, probably Andreas> same for QEMUMachine. OK. Andreas> The description sounds misleading: In qemu-system-arm all Andreas> boards are ARM architecture, and your wording may sound as if Andreas> the board were from ARM (Holdings plc) when it is from Kyoto Andreas> Micro and uses a Freescale SoC. Maybe also mention the exact Andreas> board name from the commit message and mention i.MX31? OK. Andreas> s/I.MX31/i.MX31/ in the header? Ok. Andreas> On patch 4: There's an empty line after type_init(), please Andreas> remove. OK. Andreas> On patch 3: In IMXTimerGState you're saving DeviceState Andreas> *ccm. That should probably become a QOM link<> property, Andreas> possibly after the initial submission. CC'ing Paolo. I'm not sure what this means. Andreas> What should be considered as a second step is factoring out Andreas> all the devices individually added to the board into an Andreas> i.MX31 SoC, which has implications on how the devices are Andreas> initialized (compare my recent prep_pci and Anthony's i440fx Andreas> patches). For a less sophisticated way using functions check Andreas> out exynos4210. The way it's done right now there's no Andreas> distinction of what is on the SoC and what is on the board, Andreas> so it needs to be done by you. Let's get the first round in first. Andreas> Missing is an entry to MAINTAINERS for this board and its Andreas> exclusive devices, naming who is to be cc'ed on patches. OK. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [patch v8 5/5] i.MX31 support: KZM-ARM11-01 evaluation board
Board support for Kyoto Micro's KZM-ARM11-01, an evaluation board built around the FreeScale i.MX31. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/kzm.c| 155 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 hw/kzm.c Index: qemu-working/hw/kzm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/kzm.c 2012-06-06 13:42:24.031963326 +1000 @@ -0,0 +1,155 @@ +/* + * KZM Board System emulation. + * + * Copyright (c) 2008 OKL and 2011 NICTA + * Written by Hans + * Updated by Peter Chubb. + * + * This code is licenced under the GPL, version 2 or later. + * See the file `COPYING' in the top level directory. + * + * It (partially) emulates a Kyoto Microcomputer + * KZM-ARM11-01 evaluation board, with a FreeScale + * I.MX31 SoC + */ + +#include "sysbus.h" +#include "exec-memory.h" +#include "hw.h" +#include "arm-misc.h" +#include "devices.h" +#include "net.h" +#include "sysemu.h" +#include "boards.h" +#include "pc.h" /* for the FPGA UART that emulates a 16550 */ +#include "imx.h" + +/* Memory map for Kzm Emulation Baseboard: + * 0x-0x3fff 16k secure ROM IGNORED + * 0x4000-0x00407fff Reserved IGNORED + * 0x00404000-0x00407fff ROM IGNORED + * 0x00408000-0x0fff Reserved IGNORED + * 0x1000-0x1fffbfff RAM aliasing IGNORED + * 0x1fffc000-0x1fff RAM EMULATED + * 0x2000-0x2fff Reserved IGNORED + * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x43f0 IO_AREA0 + * 0x43f9 UART1 EMULATED + * 0x43f94000 UART2 EMULATED + * 0x6800 AVIC EMULATED + * 0x53f8 CCM EMULATED + * 0x53f94000 PIT 1 EMULATED + * 0x53f98000 PIT 2 EMULATED + * 0x53f9 GPT EMULATED + * 0x8000-0x87ff RAM EMULATED + * 0x8800-0x8fff RAM Aliasing EMULATED + * 0xa000-0xafff NAND Flash IGNORED + * 0xb000-0xb3ff Unavailable IGNORED + * 0xb400-0xb4000fff 8-bit free space IGNORED + * 0xb4001000-0xb400100f Board controlIGNORED + * 0xb4001003 DIP switch + * 0xb4001010-0xb400101f 7-segment LEDIGNORED + * 0xb4001020-0xb400102f LED IGNORED + * 0xb4001030-0xb400103f LED IGNORED + * 0xb4001040-0xb400104f FPGA, UART EMULATED + * 0xb4001050-0xb400105f FPGA, UART EMULATED + * 0xb4001060-0xb40f FPGA IGNORED + * 0xb600-0xb61f LAN controller EMULATED + * 0xb620-0xb62f FPGA NAND Controller IGNORED + * 0xb630-0xb7ff Free IGNORED + * 0xb800-0xb8004fff Memory control registers IGNORED + * 0xc000-0xc3ff PCMCIA/CFIGNORED + * 0xc400-0x Reserved IGNORED + */ + +#define KZM_RAMADDRESS (0x8000) +#define KZM_FPGA (0xb4001040) + +static struct arm_boot_info kzm_binfo = { +.loader_start = KZM_RAMADDRESS, +.board_id = 1722, +}; + +static void kzm_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +CPUARMState *env; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *ram_alias = g_new(MemoryRegion, 1); +qemu_irq *cpu_pic; +DeviceState *dev; +DeviceState *ccm; + +if (!cpu_model) { +cpu_model = "arm1136"; +} + +env = cpu_init(cpu_model); +if (!env) { +fprintf(stderr, "Unable to find CPU definition\n"); +exit(1); +} + +/* On a real system, the first 16k is a `secure boot rom' */ + +memory_region_init_ram(ram, "kzm.ram", ram_size); +vmstate_register_ram_global(ram); +memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram); + +memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); +memory_region_add_subregion(address_space_mem, 0x8800, ram_alias); + +memory_region_init_ram(sram, "kzm.sram", 0x4000); +memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram); + + +cpu_pic = arm_pic_init_cpu(env); +de
[Qemu-devel] [patch v8 2/5] i.MX31 support: Clock Control Module
For Linux to be able to work out how fast its clocks are going, so that timer ticks come approximately at the right time, it needs to be able to query the clock control module (CCM). This is the start of a CCM implementation. It currently knows only about the MCU, HSP and IPG clocks --- i.e., the ones used to feed the periodic and general purpose timers. Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx.h| 10 + hw/imx_ccm.c| 321 3 files changed, 332 insertions(+), 1 deletion(-) Index: qemu-working/Makefile.target === --- qemu-working.orig/Makefile.target 2012-06-06 13:42:16.455921401 +1000 +++ qemu-working/Makefile.target2012-06-06 13:42:19.335937338 +1000 @@ -365,7 +365,7 @@ obj-arm-y += vexpress.o obj-arm-y += strongarm.o obj-arm-y += collie.o obj-arm-y += pl041.o lm4549.o -obj-arm-y += imx_serial.o +obj-arm-y += imx_serial.o imx_ccm.o obj-arm-$(CONFIG_FDT) += device_tree.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o Index: qemu-working/hw/imx_ccm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_ccm.c 2012-06-06 13:42:19.335937338 +1000 @@ -0,0 +1,321 @@ +/* + * IMX31 Clock Control Module + * + * Copyright (C) 2012 NICTA + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * To get the timer frequencies right, we need to emulate at least part of + * the CCM. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "imx.h" + +#define CKIH_FREQ 2600 /* 26MHz crystal input */ +#define CKIL_FREQ32768 /* nominal 32khz clock */ + + +//#define DEBUG_CCM 1 +#ifdef DEBUG_CCM +#define DPRINTF(fmt, args...) \ +do { printf("imx_ccm: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +static int imx_ccm_post_load(void *opaque, int version_id); + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; + +uint32_t ccmr; +uint32_t pdr0; +uint32_t pdr1; +uint32_t mpctl; +uint32_t spctl; +uint32_t cgr[3]; +uint32_t pmcr0; +uint32_t pmcr1; + +/* Frequencies precalculated on register changes */ +uint32_t pll_refclk_freq; +uint32_t mcu_clk_freq; +uint32_t hsp_clk_freq; +uint32_t ipg_clk_freq; +} IMXCCMState; + +static const VMStateDescription vmstate_imx_ccm = { +.name = "imx-ccm", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(ccmr, IMXCCMState), +VMSTATE_UINT32(pdr0, IMXCCMState), +VMSTATE_UINT32(pdr1, IMXCCMState), +VMSTATE_UINT32(mpctl, IMXCCMState), +VMSTATE_UINT32(spctl, IMXCCMState), +VMSTATE_UINT32_ARRAY(cgr, IMXCCMState, 3), +VMSTATE_UINT32(pmcr0, IMXCCMState), +VMSTATE_UINT32(pmcr1, IMXCCMState), +VMSTATE_UINT32(pll_refclk_freq, IMXCCMState), +}, +.post_load = imx_ccm_post_load, +}; + +/* CCMR */ +#define CCMR_FPME (1<<0) +#define CCMR_MPE (1<<3) +#define CCMR_MDS (1<<7) +#define CCMR_FPMF (1<<26) +#define CCMR_PRCS (3<<1) + +/* PDR0 */ +#define PDR0_MCU_PODF_SHIFT (0) +#define PDR0_MCU_PODF_MASK (0x7) +#define PDR0_MAX_PODF_SHIFT (3) +#define PDR0_MAX_PODF_MASK (0x7) +#define PDR0_IPG_PODF_SHIFT (6) +#define PDR0_IPG_PODF_MASK (0x3) +#define PDR0_NFC_PODF_SHIFT (8) +#define PDR0_NFC_PODF_MASK (0x7) +#define PDR0_HSP_PODF_SHIFT (11) +#define PDR0_HSP_PODF_MASK (0x7) +#define PDR0_PER_PODF_SHIFT (16) +#define PDR0_PER_PODF_MASK (0x1f) +#define PDR0_CSI_PODF_SHIFT (23) +#define PDR0_CSI_PODF_MASK (0x1ff) + +#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \ + & PDR0_##name##_PODF_MASK) +#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \ + PDR0_##name##_PODF_SHIFT) +/* PLL control registers */ +#define PD(v) (((v) >> 26) & 0xf) +#define MFD(v) (((v) >> 16) & 0x3ff) +#define MFI(v) (((v) >> 10) & 0xf); +#define MFN(v) ((v) & 0x3ff) + +#define PLL_PD(x) (((x) & 0xf) << 26) +#define PLL_MFD(x) (((x) & 0x3ff) << 16) +#define PLL_MFI(x) (((x) & 0xf) << 10) +#define PLL_MFN(x) (((x) & 0x3ff) << 0) + +uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock) +{ +IMXCCMState *s = container_of(dev, IMXCCMState, busdev.qdev); + +switch (clock) { +case NOCLK: +return 0; +case MCU: +return s->mcu_clk_freq; +case HSP: +return s->hsp_clk_freq; +case IPG: +re
[Qemu-devel] [patch v8 1/5] i.MX UART support
Implement the FreeScale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the FreeScale i.MX series. This patch gives only a `bare-bones' implementation, enough to run Linux or OKL4, but that's about it. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |1 hw/imx.h| 16 + hw/imx_serial.c | 467 3 files changed, 484 insertions(+) create mode 100644 hw/imx_serial.c Index: qemu-working/hw/imx_serial.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_serial.c2012-06-06 13:42:16.127919586 +1000 @@ -0,0 +1,467 @@ +/* + * IMX31 UARTS + * + * Copyright (c) 2008 OKL + * Originally Written by Hans Jiang + * Copyright (c) 2011 NICTA Pty Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * This is a `bare-bones' implementation of the IMX series serial ports. + * TODO: + * -- implement FIFOs. The real hardware has 32 word transmit + * and receive FIFOs; we currently use a 1-char buffer + * -- implement DMA + * -- implement BAUD-rate and modem lines, for when the backend + * is a real serial device. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "qemu-char.h" +#include "imx.h" + +//#define DEBUG_SERIAL 1 +#ifdef DEBUG_SERIAL +#define DPRINTF(fmt, args...) \ +do { printf("imx_serial: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +//#define DEBUG_IMPLEMENTATION 1 +#ifdef DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +int32_t readbuff; + +uint32_t usr1; +uint32_t usr2; +uint32_t ucr1; +uint32_t ucr2; +uint32_t uts1; + +/* + * The registers below are implemented just so that the + * guest OS sees what it has written + */ +uint32_t onems; +uint32_t ufcr; +uint32_t ubmr; +uint32_t ubrc; +uint32_t ucr3; + +qemu_irq irq; +CharDriverState *chr; +} IMXSerialState; + +static const VMStateDescription vmstate_imx_serial = { +.name = "imx-serial", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_INT32(readbuff, IMXSerialState), +VMSTATE_UINT32(usr1, IMXSerialState), +VMSTATE_UINT32(usr2, IMXSerialState), +VMSTATE_UINT32(ucr1, IMXSerialState), +VMSTATE_UINT32(uts1, IMXSerialState), +VMSTATE_UINT32(onems, IMXSerialState), +VMSTATE_UINT32(ufcr, IMXSerialState), +VMSTATE_UINT32(ubmr, IMXSerialState), +VMSTATE_UINT32(ubrc, IMXSerialState), +VMSTATE_UINT32(ucr3, IMXSerialState), +VMSTATE_END_OF_LIST() +}, +}; + + +#define URXD_CHARRDY(1<<15) /* character read is valid */ +#define URXD_ERR(1<<14) /* Character has error */ +#define URXD_BRK(1<<11) /* Break received */ + +#define USR1_PARTYER(1<<15) /* Parity Error */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Tx ready */ +#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */ +#define USR1_ESCF (1<<11) /* Escape sequence interrupt */ +#define USR1_FRAMERR(1<<10) /* Framing error */ +#define USR1_RRDY (1<<9)/* receiver ready */ +#define USR1_AGTIM (1<<8)/* Aging timer interrupt */ +#define USR1_DTRD (1<<7)/* DTR changed */ +#define USR1_RXDS (1<<6)/* Receiver is idle */ +#define USR1_AIRINT (1<<5)/* Aysnch IR interrupt */ +#define USR1_AWAKE (1<<4)/* Falling edge detected on RXd pin */ + +#define USR2_ADET (1<<15) /* Autobaud complete */ +#define USR2_TXFE (1<<14) /* Transmit FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR/DSR transition */ +#define USR2_IDLE (1<<12) /* UART has been idle for too long */ +#define USR2_ACST (1<<11) /* Autobaud counter stopped */ +#define USR2_RIDELT (1<<10) /* Ring Indicator delta */ +#define USR2_RIIN (1<<9)/* Ring Indicator Input */ +#define USR2_IRINT (1<<8)/* Serial Infrared Interrupt */ +#define USR2_WAKE (1<<7)/* Start bit detected */ +#def
[Qemu-devel] [patch v8 0/5] i.MX31 support
There are no major changes since last time, just rebased to current tip now that QEMU 1.2 is open. For those who have come into the story late, this is a series of patches to allow QEMU to emulate a Freescale i.MX31 on a Kyoto Microsystems evaluation board. It's pretty bare-bones, but runs Linux and seL4 nicely. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [patch v8 4/5] i.MX31 support: AVIC
Implement the FreeSCALE i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.0.x Vectors are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |2 hw/imx_avic.c | 409 2 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 hw/imx_avic.c Index: qemu-working/hw/imx_avic.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_avic.c 2012-06-06 13:42:23.007957660 +1000 @@ -0,0 +1,409 @@ +/* + * IMX31 Vectored Interrupt Controller + * + * Note this is NOT the PL192 provided by ARM, but + * a custom implementation by FreeScale. + * + * Copyright (c) 2008 OKL + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * + * This code is licenced under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * TODO: implement vectors. + */ + +#include "hw.h" +#include "sysbus.h" +#include "host-utils.h" + +#define DEBUG_INT 1 +#undef DEBUG_INT /* comment out for debugging */ + +#ifdef DEBUG_INT +#define DPRINTF(fmt, args...) \ +do { printf("imx_avic: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +#define IMX_AVIC_NUM_IRQS 64 + +/* Interrupt Control Bits */ +#define ABFLAG (1<<25) +#define ABFEN (1<<24) +#define NIDIS (1<<22) /* Normal Interrupt disable */ +#define FIDIS (1<<21) /* Fast interrupt disable */ +#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ +#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ +#define NM(1<<18) /* Normal interrupt mode */ + + +#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) +#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +uint64_t pending; +uint64_t enabled; +uint64_t is_fiq; +uint32_t intcntl; +uint32_t intmask; +qemu_irq irq; +qemu_irq fiq; +uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ +} IMXAVICState; + +static const VMStateDescription vmstate_imx_avic = { +.name = "imx-avic", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT64(pending, IMXAVICState), +VMSTATE_UINT64(enabled, IMXAVICState), +VMSTATE_UINT64(is_fiq, IMXAVICState), +VMSTATE_UINT32(intcntl, IMXAVICState), +VMSTATE_UINT32(intmask, IMXAVICState), +VMSTATE_UINT32_ARRAY(prio, IMXAVICState, PRIO_WORDS), +VMSTATE_END_OF_LIST() +}, +}; + + + +static inline int imx_avic_prio(IMXAVICState *s, int irq) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +return 0xf & (s->prio[word] >> part); +} + +static inline void imx_avic_set_prio(IMXAVICState *s, int irq, int prio) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +uint32_t mask = ~(0xf << part); +s->prio[word] &= mask; +s->prio[word] |= prio << part; +} + +/* Update interrupts. */ +static void imx_avic_update(IMXAVICState *s) +{ +int i; +uint64_t new = s->pending & s->enabled; +uint64_t flags; + +flags = new & s->is_fiq; +qemu_set_irq(s->fiq, !!flags); + +flags = new & ~s->is_fiq; +if (!flags || (s->intmask == 0x1f)) { +qemu_set_irq(s->irq, !!flags); +return; +} + +/* + * Take interrupt if there's a pending interrupt with + * priority higher than the value of intmask + */ +for (i = 0; i < IMX_AVIC_NUM_IRQS; i++) { +if (flags & (1UL << i)) { +if (imx_avic_prio(s, i) > s->intmask) { +qemu_set_irq(s->irq, 1); +return; +} +} +} +qemu_set_irq(s->irq, 0); +} + +static void imx_avic_set_irq(void *opaque, int irq, int level) +{ +IMXAVICState *s = (IMXAVICState *)opaque; + +if (level) { +DPRINTF("Raising IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending |= (1ULL << irq); +} else { +DPRINTF("Clearing IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending &= ~(1ULL << irq); +} + +
[Qemu-devel] [patch v8 3/5] i.MX31 support: Timers
Implement the timers on the FreeScale i.MX31 SoC. This is not a complete implementation, but gives enough for Linux to boot and run. In particular external triggers, which are not useful under QEMU, are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx.h|8 hw/imx_timer.c | 689 3 files changed, 698 insertions(+), 1 deletion(-) create mode 100644 hw/imx_timer.c Index: qemu-working/hw/imx_timer.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_timer.c 2012-06-06 13:42:21.315948297 +1000 @@ -0,0 +1,689 @@ +/* + * IMX31 Timer + * + * Copyright (c) 2008 OK Labs + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * Updated by Peter Chubb + * + * This code is licenced under GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + */ + +#include "hw.h" +#include "qemu-timer.h" +#include "ptimer.h" +#include "sysbus.h" +#include "imx.h" + +//#define DEBUG_TIMER 1 +#ifdef DEBUG_TIMER +# define DPRINTF(fmt, args...) \ + do { printf("imx_timer: " fmt , ##args); } while (0) +#else +# define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_timer: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * GPT : General purpose timer + * + * This timer counts up continuously while it is enabled, resetting itself + * to 0 when it reaches TIMER_MAX (in freerun mode) or when it + * reaches the value of ocr1 (in periodic mode). WE simulate this using a + * QEMU ptimer counting down from ocr1 and reloading from ocr1 in + * periodic mode, or counting from ocr1 to zero, then TIMER_MAX - ocr1. + * waiting_rov is set when counting from TIMER_MAX. + * + * In the real hardware, there are three comparison registers that can + * trigger interrupts, and compare channel 1 can be used to + * force-reset the timer. However, this is a `bare-bones' + * implementation: only what Linux 3.x uses has been implemented + * (free-running timer from 0 to OCR1 or TIMER_MAX) . + */ + + +#define TIMER_MAX 0XUL + +/* Control register. Not all of these bits have any effect (yet) */ +#define GPT_CR_EN (1 << 0) /* GPT Enable */ +#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */ +#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ +#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ +#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ +#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ +#define GPT_CR_CLKSRC_SHIFT (6) +#define GPT_CR_CLKSRC_MASK (0x7) + +#define GPT_CR_FRR(1 << 9) /* Freerun or Restart */ +#define GPT_CR_SWR(1 << 15) /* Software Reset */ +#define GPT_CR_IM1(3 << 16) /* Input capture channel 1 mode (2 bits) */ +#define GPT_CR_IM2(3 << 18) /* Input capture channel 2 mode (2 bits) */ +#define GPT_CR_OM1(7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ +#define GPT_CR_OM2(7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ +#define GPT_CR_OM3(7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ +#define GPT_CR_FO1(1 << 29) /* Force Output Compare Channel 1 */ +#define GPT_CR_FO2(1 << 30) /* Force Output Compare Channel 2 */ +#define GPT_CR_FO3(1 << 31) /* Force Output Compare Channel 3 */ + +#define GPT_SR_OF1 (1 << 0) +#define GPT_SR_ROV (1 << 5) + +#define GPT_IR_OF1IE (1 << 0) +#define GPT_IR_ROVIE (1 << 5) + +typedef struct { +SysBusDevice busdev; +ptimer_state *timer; +MemoryRegion iomem; +DeviceState *ccm; + +uint32_t cr; +uint32_t pr; +uint32_t sr; +uint32_t ir; +uint32_t ocr1; +uint32_t cnt; + +uint32_t waiting_rov; +qemu_irq irq; +} IMXTimerGState; + +static const VMStateDescription vmstate_imx_timerg = { +.name = "imx-timerg", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(cr, IMXTimerGState), +VMSTATE_UINT32(pr, IMXTimerGState), +VMSTATE_UINT32(sr, IMXTimerGState), +VMSTATE_UINT32(ir, IMXTimerGState), +VMSTATE_UINT32(ocr1, IMXTimerGState), +VMSTATE_UINT32(cnt, IMXTimerGState), +VMSTATE_UINT32(waiting_rov, IMXTimerGState), +VMSTATE_PTIMER(timer, IMXTimerGState), +VMSTATE_END_OF_LIST() +} +}; + +static
[Qemu-devel] [PATCH v7 1/5] i.MX: UART support
Implement the Freescale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the Freescale i.MX series. This patch gives only a `bare-bones' implementation, enough to run Linux or OKL4, but that's about it. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |1 hw/imx.h| 16 + hw/imx_serial.c | 467 3 files changed, 484 insertions(+) create mode 100644 hw/imx_serial.c Index: qemu-working/hw/imx_serial.c === --- /dev/null +++ qemu-working/hw/imx_serial.c @@ -0,0 +1,467 @@ +/* + * IMX31 UARTS + * + * Copyright (c) 2008 OKL + * Originally Written by Hans Jiang + * Copyright (c) 2011 NICTA Pty Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * This is a `bare-bones' implementation of the IMX series serial ports. + * TODO: + * -- implement FIFOs. The real hardware has 32 word transmit + * and receive FIFOs; we currently use a 1-char buffer + * -- implement DMA + * -- implement BAUD-rate and modem lines, for when the backend + * is a real serial device. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "qemu-char.h" +#include "imx.h" + +//#define DEBUG_SERIAL 1 +#ifdef DEBUG_SERIAL +#define DPRINTF(fmt, args...) \ +do { printf("imx_serial: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +//#define DEBUG_IMPLEMENTATION 1 +#ifdef DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +int32_t readbuff; + +uint32_t usr1; +uint32_t usr2; +uint32_t ucr1; +uint32_t ucr2; +uint32_t uts1; + +/* + * The registers below are implemented just so that the + * guest OS sees what it has written + */ +uint32_t onems; +uint32_t ufcr; +uint32_t ubmr; +uint32_t ubrc; +uint32_t ucr3; + +qemu_irq irq; +CharDriverState *chr; +} IMXSerialState; + +static const VMStateDescription vmstate_imx_serial = { +.name = "imx-serial", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_INT32(readbuff, IMXSerialState), +VMSTATE_UINT32(usr1, IMXSerialState), +VMSTATE_UINT32(usr2, IMXSerialState), +VMSTATE_UINT32(ucr1, IMXSerialState), +VMSTATE_UINT32(uts1, IMXSerialState), +VMSTATE_UINT32(onems, IMXSerialState), +VMSTATE_UINT32(ufcr, IMXSerialState), +VMSTATE_UINT32(ubmr, IMXSerialState), +VMSTATE_UINT32(ubrc, IMXSerialState), +VMSTATE_UINT32(ucr3, IMXSerialState), +VMSTATE_END_OF_LIST() +}, +}; + + +#define URXD_CHARRDY(1<<15) /* character read is valid */ +#define URXD_ERR(1<<14) /* Character has error */ +#define URXD_BRK(1<<11) /* Break received */ + +#define USR1_PARTYER(1<<15) /* Parity Error */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Tx ready */ +#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */ +#define USR1_ESCF (1<<11) /* Escape sequence interrupt */ +#define USR1_FRAMERR(1<<10) /* Framing error */ +#define USR1_RRDY (1<<9)/* receiver ready */ +#define USR1_AGTIM (1<<8)/* Aging timer interrupt */ +#define USR1_DTRD (1<<7)/* DTR changed */ +#define USR1_RXDS (1<<6)/* Receiver is idle */ +#define USR1_AIRINT (1<<5)/* Aysnch IR interrupt */ +#define USR1_AWAKE (1<<4)/* Falling edge detected on RXd pin */ + +#define USR2_ADET (1<<15) /* Autobaud complete */ +#define USR2_TXFE (1<<14) /* Transmit FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR/DSR transition */ +#define USR2_IDLE (1<<12) /* UART has been idle for too long */ +#define USR2_ACST (1<<11) /* Autobaud counter stopped */ +#define USR2_RIDELT (1<<10) /* Ring Indicator delta */ +#define USR2_RIIN (1<<9)/* Ring Indicator Input */ +#define USR2_IRINT (1<<8)/* Serial Infrared Interrupt */ +#define USR2_WAKE (1<<7)/* Start bit detected */ +#define USR2_DCDDELT(1<<6)/* Data Carrier Detect delta */ +#define USR2_DCDIN
[Qemu-devel] [PATCH v7 3/5] i.MX31: Timers
Implement the timers on the Freescale i.MX31 SoC. This is not a complete implementation, but gives enough for Linux to boot and run. In particular external triggers, which are not useful under QEMU, are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |2 hw/imx.h|8 hw/imx_timer.c | 689 3 files changed, 698 insertions(+), 1 deletion(-) create mode 100644 hw/imx_timer.c Index: qemu-working/hw/imx_timer.c === --- /dev/null +++ qemu-working/hw/imx_timer.c @@ -0,0 +1,689 @@ +/* + * IMX31 Timer + * + * Copyright (c) 2008 OK Labs + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * Updated by Peter Chubb + * + * This code is licenced under GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + */ + +#include "hw.h" +#include "qemu-timer.h" +#include "ptimer.h" +#include "sysbus.h" +#include "imx.h" + +//#define DEBUG_TIMER 1 +#ifdef DEBUG_TIMER +# define DPRINTF(fmt, args...) \ + do { printf("imx_timer: " fmt , ##args); } while (0) +#else +# define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_timer: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * GPT : General purpose timer + * + * This timer counts up continuously while it is enabled, resetting itself + * to 0 when it reaches TIMER_MAX (in freerun mode) or when it + * reaches the value of ocr1 (in periodic mode). WE simulate this using a + * QEMU ptimer counting down from ocr1 and reloading from ocr1 in + * periodic mode, or counting from ocr1 to zero, then TIMER_MAX - ocr1. + * waiting_rov is set when counting from TIMER_MAX. + * + * In the real hardware, there are three comparison registers that can + * trigger interrupts, and compare channel 1 can be used to + * force-reset the timer. However, this is a `bare-bones' + * implementation: only what Linux 3.x uses has been implemented + * (free-running timer from 0 to OCR1 or TIMER_MAX) . + */ + + +#define TIMER_MAX 0XUL + +/* Control register. Not all of these bits have any effect (yet) */ +#define GPT_CR_EN (1 << 0) /* GPT Enable */ +#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */ +#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ +#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ +#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ +#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ +#define GPT_CR_CLKSRC_SHIFT (6) +#define GPT_CR_CLKSRC_MASK (0x7) + +#define GPT_CR_FRR(1 << 9) /* Freerun or Restart */ +#define GPT_CR_SWR(1 << 15) /* Software Reset */ +#define GPT_CR_IM1(3 << 16) /* Input capture channel 1 mode (2 bits) */ +#define GPT_CR_IM2(3 << 18) /* Input capture channel 2 mode (2 bits) */ +#define GPT_CR_OM1(7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ +#define GPT_CR_OM2(7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ +#define GPT_CR_OM3(7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ +#define GPT_CR_FO1(1 << 29) /* Force Output Compare Channel 1 */ +#define GPT_CR_FO2(1 << 30) /* Force Output Compare Channel 2 */ +#define GPT_CR_FO3(1 << 31) /* Force Output Compare Channel 3 */ + +#define GPT_SR_OF1 (1 << 0) +#define GPT_SR_ROV (1 << 5) + +#define GPT_IR_OF1IE (1 << 0) +#define GPT_IR_ROVIE (1 << 5) + +typedef struct { +SysBusDevice busdev; +ptimer_state *timer; +MemoryRegion iomem; +DeviceState *ccm; + +uint32_t cr; +uint32_t pr; +uint32_t sr; +uint32_t ir; +uint32_t ocr1; +uint32_t cnt; + +uint32_t waiting_rov; +qemu_irq irq; +} IMXTimerGState; + +static const VMStateDescription vmstate_imx_timerg = { +.name = "imx-timerg", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(cr, IMXTimerGState), +VMSTATE_UINT32(pr, IMXTimerGState), +VMSTATE_UINT32(sr, IMXTimerGState), +VMSTATE_UINT32(ir, IMXTimerGState), +VMSTATE_UINT32(ocr1, IMXTimerGState), +VMSTATE_UINT32(cnt, IMXTimerGState), +VMSTATE_UINT32(waiting_rov, IMXTimerGState), +VMSTATE_PTIMER(timer, IMXTimerGState), +VMSTATE_END_OF_LIST() +} +}; + +static const IMXClk imx_timerg_clocks[] = { +NOCLK,
[Qemu-devel] [PATCH v7 2/5] i.MX31: Clock Control Module
For Linux to be able to work out how fast its clocks are going, so that timer ticks come approximately at the right time, it needs to be able to query the clock control module (CCM). This is the start of a CCM implementation. It currently knows only about the MCU, HSP and IPG clocks --- i.e., the ones used to feed the periodic and general purpose timers. Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx.h| 10 + hw/imx_ccm.c| 321 3 files changed, 332 insertions(+), 1 deletion(-) Index: qemu-working/Makefile.target === --- qemu-working.orig/Makefile.target +++ qemu-working/Makefile.target @@ -402,7 +402,7 @@ obj-arm-y += vexpress.o obj-arm-y += strongarm.o obj-arm-y += collie.o obj-arm-y += pl041.o lm4549.o -obj-arm-y += imx_serial.o +obj-arm-y += imx_serial.o imx_ccm.o obj-arm-$(CONFIG_FDT) += device_tree.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o Index: qemu-working/hw/imx_ccm.c === --- /dev/null +++ qemu-working/hw/imx_ccm.c @@ -0,0 +1,321 @@ +/* + * IMX31 Clock Control Module + * + * Copyright (C) 2012 NICTA + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * To get the timer frequencies right, we need to emulate at least part of + * the CCM. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "imx.h" + +#define CKIH_FREQ 2600 /* 26MHz crystal input */ +#define CKIL_FREQ32768 /* nominal 32khz clock */ + + +//#define DEBUG_CCM 1 +#ifdef DEBUG_CCM +#define DPRINTF(fmt, args...) \ +do { printf("imx_ccm: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +static int imx_ccm_post_load(void *opaque, int version_id); + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; + +uint32_t ccmr; +uint32_t pdr0; +uint32_t pdr1; +uint32_t mpctl; +uint32_t spctl; +uint32_t cgr[3]; +uint32_t pmcr0; +uint32_t pmcr1; + +/* Frequencies precalculated on register changes */ +uint32_t pll_refclk_freq; +uint32_t mcu_clk_freq; +uint32_t hsp_clk_freq; +uint32_t ipg_clk_freq; +} IMXCCMState; + +static const VMStateDescription vmstate_imx_ccm = { +.name = "imx-ccm", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(ccmr, IMXCCMState), +VMSTATE_UINT32(pdr0, IMXCCMState), +VMSTATE_UINT32(pdr1, IMXCCMState), +VMSTATE_UINT32(mpctl, IMXCCMState), +VMSTATE_UINT32(spctl, IMXCCMState), +VMSTATE_UINT32_ARRAY(cgr, IMXCCMState, 3), +VMSTATE_UINT32(pmcr0, IMXCCMState), +VMSTATE_UINT32(pmcr1, IMXCCMState), +VMSTATE_UINT32(pll_refclk_freq, IMXCCMState), +}, +.post_load = imx_ccm_post_load, +}; + +/* CCMR */ +#define CCMR_FPME (1<<0) +#define CCMR_MPE (1<<3) +#define CCMR_MDS (1<<7) +#define CCMR_FPMF (1<<26) +#define CCMR_PRCS (3<<1) + +/* PDR0 */ +#define PDR0_MCU_PODF_SHIFT (0) +#define PDR0_MCU_PODF_MASK (0x7) +#define PDR0_MAX_PODF_SHIFT (3) +#define PDR0_MAX_PODF_MASK (0x7) +#define PDR0_IPG_PODF_SHIFT (6) +#define PDR0_IPG_PODF_MASK (0x3) +#define PDR0_NFC_PODF_SHIFT (8) +#define PDR0_NFC_PODF_MASK (0x7) +#define PDR0_HSP_PODF_SHIFT (11) +#define PDR0_HSP_PODF_MASK (0x7) +#define PDR0_PER_PODF_SHIFT (16) +#define PDR0_PER_PODF_MASK (0x1f) +#define PDR0_CSI_PODF_SHIFT (23) +#define PDR0_CSI_PODF_MASK (0x1ff) + +#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \ + & PDR0_##name##_PODF_MASK) +#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \ + PDR0_##name##_PODF_SHIFT) +/* PLL control registers */ +#define PD(v) (((v) >> 26) & 0xf) +#define MFD(v) (((v) >> 16) & 0x3ff) +#define MFI(v) (((v) >> 10) & 0xf); +#define MFN(v) ((v) & 0x3ff) + +#define PLL_PD(x) (((x) & 0xf) << 26) +#define PLL_MFD(x) (((x) & 0x3ff) << 16) +#define PLL_MFI(x) (((x) & 0xf) << 10) +#define PLL_MFN(x) (((x) & 0x3ff) << 0) + +uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock) +{ +IMXCCMState *s = container_of(dev, IMXCCMState, busdev.qdev); + +switch (clock) { +case NOCLK: +return 0; +case MCU: +return s->mcu_clk_freq; +case HSP: +return s->hsp_clk_freq; +case IPG: +return s->ipg_clk_freq; +case CLK_32k: +return CKIL_FREQ; +} +return 0; +} + +/* + * Calculate PLL output frequency + */ +static
[Qemu-devel] [PATCH v7 4/5] i.MX31: Interrupt Controller
Implement the Freescale i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.x Vectors are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |2 hw/imx_avic.c | 409 2 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 hw/imx_avic.c Index: qemu-working/hw/imx_avic.c === --- /dev/null +++ qemu-working/hw/imx_avic.c @@ -0,0 +1,409 @@ +/* + * IMX31 Vectored Interrupt Controller + * + * Note this is NOT the PL192 provided by ARM, but + * a custom implementation by Freescale. + * + * Copyright (c) 2008 OKL + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * + * This code is licenced under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * TODO: implement vectors. + */ + +#include "hw.h" +#include "sysbus.h" +#include "host-utils.h" + +#define DEBUG_INT 1 +#undef DEBUG_INT /* comment out for debugging */ + +#ifdef DEBUG_INT +#define DPRINTF(fmt, args...) \ +do { printf("imx_avic: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +#define IMX_AVIC_NUM_IRQS 64 + +/* Interrupt Control Bits */ +#define ABFLAG (1<<25) +#define ABFEN (1<<24) +#define NIDIS (1<<22) /* Normal Interrupt disable */ +#define FIDIS (1<<21) /* Fast interrupt disable */ +#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ +#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ +#define NM(1<<18) /* Normal interrupt mode */ + + +#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) +#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +uint64_t pending; +uint64_t enabled; +uint64_t is_fiq; +uint32_t intcntl; +uint32_t intmask; +qemu_irq irq; +qemu_irq fiq; +uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ +} IMXAVICState; + +static const VMStateDescription vmstate_imx_avic = { +.name = "imx-avic", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT64(pending, IMXAVICState), +VMSTATE_UINT64(enabled, IMXAVICState), +VMSTATE_UINT64(is_fiq, IMXAVICState), +VMSTATE_UINT32(intcntl, IMXAVICState), +VMSTATE_UINT32(intmask, IMXAVICState), +VMSTATE_UINT32_ARRAY(prio, IMXAVICState, PRIO_WORDS), +VMSTATE_END_OF_LIST() +}, +}; + + + +static inline int imx_avic_prio(IMXAVICState *s, int irq) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +return 0xf & (s->prio[word] >> part); +} + +static inline void imx_avic_set_prio(IMXAVICState *s, int irq, int prio) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +uint32_t mask = ~(0xf << part); +s->prio[word] &= mask; +s->prio[word] |= prio << part; +} + +/* Update interrupts. */ +static void imx_avic_update(IMXAVICState *s) +{ +int i; +uint64_t new = s->pending & s->enabled; +uint64_t flags; + +flags = new & s->is_fiq; +qemu_set_irq(s->fiq, !!flags); + +flags = new & ~s->is_fiq; +if (!flags || (s->intmask == 0x1f)) { +qemu_set_irq(s->irq, !!flags); +return; +} + +/* + * Take interrupt if there's a pending interrupt with + * priority higher than the value of intmask + */ +for (i = 0; i < IMX_AVIC_NUM_IRQS; i++) { +if (flags & (1UL << i)) { +if (imx_avic_prio(s, i) > s->intmask) { +qemu_set_irq(s->irq, 1); +return; +} +} +} +qemu_set_irq(s->irq, 0); +} + +static void imx_avic_set_irq(void *opaque, int irq, int level) +{ +IMXAVICState *s = (IMXAVICState *)opaque; + +if (level) { +DPRINTF("Raising IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending |= (1ULL << irq); +} else { +DPRINTF("Clearing IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending &= ~(1ULL << irq); +} + +imx_avic_update(s); +} + + +static uint64_t imx_avic_read(void *opaque, +
[Qemu-devel] [PATCH v7 5/5] i.MX31: KZM-ARM11-01 evaluation board
Board support for Kyoto Micro's KZM-ARM11-01, an evaluation board built around the Freescale i.MX31. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/kzm.c| 155 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 hw/kzm.c Index: qemu-working/hw/kzm.c === --- /dev/null +++ qemu-working/hw/kzm.c @@ -0,0 +1,155 @@ +/* + * KZM Board System emulation. + * + * Copyright (c) 2008 OKL and 2011 NICTA + * Written by Hans + * Updated by Peter Chubb. + * + * This code is licenced under the GPL, version 2 or later. + * See the file `COPYING' in the top level directory. + * + * It (partially) emulates a Kyoto Microcomputer + * KZM-ARM11-01 evaluation board, with a Freescale + * I.MX31 SoC + */ + +#include "sysbus.h" +#include "exec-memory.h" +#include "hw.h" +#include "arm-misc.h" +#include "devices.h" +#include "net.h" +#include "sysemu.h" +#include "boards.h" +#include "pc.h" /* for the FPGA UART that emulates a 16550 */ +#include "imx.h" + +/* Memory map for Kzm Emulation Baseboard: + * 0x-0x3fff 16k secure ROM IGNORED + * 0x4000-0x00407fff Reserved IGNORED + * 0x00404000-0x00407fff ROM IGNORED + * 0x00408000-0x0fff Reserved IGNORED + * 0x1000-0x1fffbfff RAM aliasing IGNORED + * 0x1fffc000-0x1fff RAM EMULATED + * 0x2000-0x2fff Reserved IGNORED + * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x43f0 IO_AREA0 + * 0x43f9 UART1 EMULATED + * 0x43f94000 UART2 EMULATED + * 0x6800 AVIC EMULATED + * 0x53f8 CCM EMULATED + * 0x53f94000 PIT 1 EMULATED + * 0x53f98000 PIT 2 EMULATED + * 0x53f9 GPT EMULATED + * 0x8000-0x87ff RAM EMULATED + * 0x8800-0x8fff RAM Aliasing EMULATED + * 0xa000-0xafff NAND Flash IGNORED + * 0xb000-0xb3ff Unavailable IGNORED + * 0xb400-0xb4000fff 8-bit free space IGNORED + * 0xb4001000-0xb400100f Board controlIGNORED + * 0xb4001003 DIP switch + * 0xb4001010-0xb400101f 7-segment LEDIGNORED + * 0xb4001020-0xb400102f LED IGNORED + * 0xb4001030-0xb400103f LED IGNORED + * 0xb4001040-0xb400104f FPGA, UART EMULATED + * 0xb4001050-0xb400105f FPGA, UART EMULATED + * 0xb4001060-0xb40f FPGA IGNORED + * 0xb600-0xb61f LAN controller EMULATED + * 0xb620-0xb62f FPGA NAND Controller IGNORED + * 0xb630-0xb7ff Free IGNORED + * 0xb800-0xb8004fff Memory control registers IGNORED + * 0xc000-0xc3ff PCMCIA/CFIGNORED + * 0xc400-0x Reserved IGNORED + */ + +#define KZM_RAMADDRESS (0x8000) +#define KZM_FPGA (0xb4001040) + +static struct arm_boot_info kzm_binfo = { +.loader_start = KZM_RAMADDRESS, +.board_id = 1722, +}; + +static void kzm_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +CPUARMState *env; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *ram_alias = g_new(MemoryRegion, 1); +qemu_irq *cpu_pic; +DeviceState *dev; +DeviceState *ccm; + +if (!cpu_model) { +cpu_model = "arm1136"; +} + +env = cpu_init(cpu_model); +if (!env) { +fprintf(stderr, "Unable to find CPU definition\n"); +exit(1); +} + +/* On a real system, the first 16k is a `secure boot rom' */ + +memory_region_init_ram(ram, "kzm.ram", ram_size); +vmstate_register_ram_global(ram); +memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram); + +memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); +memory_region_add_subregion(address_space_mem, 0x8800, ram_alias); + +memory_region_init_ram(sram, "kzm.sram", 0x4000); +memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram); + + +cpu_pic = arm_pic_init_cpu(env); +dev = sysbus_create_varargs("imx_avic", 0x6800, +
[Qemu-devel] [PATCH v7 0/5] add i.MX31 support
This patch series adds rudimentary support for the Freescale i.MX31 SoC, and the Kyoto Micro KZM-ARM11-01, an evaluation board built around the Freescale i.MX31. Changes since last patch round: (v6) * shortened patch titles * canonised spelling of `Freescale' * Fixed 10 to 32-bit sign extension in the clock-control-module * Use a post-load hook in the clock-control-module instead of storing frequencies in the VMState. * Deleted undocumented second UART on KZM board's FPGA. Apart from that the patches are unchanged. Thanks to Peter M and Andreas F for comments. -- Dr Peter Chubbwww.nicta.com.au peter DOT chubb AT nicta.com.au http://www.ertos.nicta.com.au ERTOS within National ICT Australia >From Imagination to Impact Imagining the (ICT) Future
Re: [Qemu-devel] [PATCH v6 0/5] FreeSCALE i.MX31 support
>>>>> "Andreas" == Andreas Färber writes: Andreas> Am 23.04.2012 01:31, schrieb Peter Chubb: >> Hi all, Most of the files are unchanged since last time. Andreas> Indeed... On v5 I had asked you to shorten the subjects to Andreas> conform to our commit message scheme and to make patches Andreas> better readable. There were even suggestions. Also I Andreas> implicitly suggested to use one spelling of "Freescale" Andreas> consistently throughout your patches. Sorry, yes I missed that comment. V7 will come soon. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH v6 2/5] Implement i.MX31 Clock Control Module
>>>>> "Paolo" == Paolo Bonzini writes: Paolo> Il 23/04/2012 22:54, Peter Chubb ha scritto: Peter> What is this calculation supposed to do? It doesn't convert a Peter> 10-bit signed twos-complement number into an int32_t, unless Peter> I'm confused... Also, it's a rather opaque way to write "mfn &= Peter> 0x200;". >> >> I'll use a different way to calculate. Maybe: >> mfn <<= (32-10); >> mfn >= (32-10); Paolo> The magic that you wanted is Paolo>mfn |= -(mfn & 0x200); Yes. I'd actually been thinking of mfn -= 2 * (mfn & 0x200); but forgot the 2*. But the shifts should be faster, and that's wjhat I'm testing at the moment. Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH v6 5/5] FreeSCALE i.MX31 support: KZM-ARM11-01 evaluation board
>>>>> "Peter" == Peter Maydell writes: Peter> On 23 April 2012 00:31, Peter Chubb Peter> wrote: >> Board support for Kyoto Micro's KZM-ARM11-01, an evaluation board >> built around the FreeScale i.MX31. >> + if (serial_hds[3]) { >> + serial_mm_init(address_space_mem, KZM_FPGA, 0, >> + qdev_get_gpio_in(dev, 52), >> + 14745600, serial_hds[3], >> + DEVICE_NATIVE_ENDIAN); >> + } >> + if (serial_hds[2]) { /* touchscreen */ >> + serial_mm_init(address_space_mem, KZM_FPGA+0x10, 0, >> + qdev_get_gpio_in(dev, 52), >> + 14745600, serial_hds[2], >> + DEVICE_NATIVE_ENDIAN); >> + } Peter> Are these two devices really on the same IRQ? Yes. A single interrupt line comes from the FPGA into the AVIC. Inside the FPGA the interrupts for the UARTs, SD card and NAND flash are connected to that single interrupt line. The non-touchscreen FPGA UART isn't mentioned in the KZM manual, but is available on the board as a debug port. To avoid confusion I think I'll just get rid of it. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [PATCH v6 2/5] Implement i.MX31 Clock Control Module
>>>>> "Peter" == Peter Maydell writes: Peter> On 23 April 2012 00:31, Peter Chubb Peter> wrote: Peter> Rather than having the *_clk_freq saved and loaded in the Peter> vmstate, I think it would be nicer to have a post-load-hook Peter> that called update_clocks(). OK. >> /* mfn is 10-bit signed twos-complement */ >> + mfn -= (mfn & 0x200); Peter> What is this calculation supposed to do? It doesn't convert a Peter> 10-bit signed twos-complement number into an int32_t, unless Peter> I'm confused... Also, it's a rather opaque way to write "mfn &= Peter> 0x200;". I'll use a different way to calculate. Maybe: mfn <<= (32-10); mfn >>= (32-10); Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [PATCH v6 4/5] FreeSCALE i.MX31 support: AVIC
Implement the FreeSCALE i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.0.x Vectors are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |2 hw/imx_avic.c | 409 2 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 hw/imx_avic.c Index: qemu-working/hw/imx_avic.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_avic.c 2012-04-23 08:24:55.189274038 +1000 @@ -0,0 +1,409 @@ +/* + * IMX31 Vectored Interrupt Controller + * + * Note this is NOT the PL192 provided by ARM, but + * a custom implementation by FreeScale. + * + * Copyright (c) 2008 OKL + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * + * This code is licenced under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * TODO: implement vectors. + */ + +#include "hw.h" +#include "sysbus.h" +#include "host-utils.h" + +#define DEBUG_INT 1 +#undef DEBUG_INT /* comment out for debugging */ + +#ifdef DEBUG_INT +#define DPRINTF(fmt, args...) \ +do { printf("imx_avic: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +#define IMX_AVIC_NUM_IRQS 64 + +/* Interrupt Control Bits */ +#define ABFLAG (1<<25) +#define ABFEN (1<<24) +#define NIDIS (1<<22) /* Normal Interrupt disable */ +#define FIDIS (1<<21) /* Fast interrupt disable */ +#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ +#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ +#define NM(1<<18) /* Normal interrupt mode */ + + +#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) +#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +uint64_t pending; +uint64_t enabled; +uint64_t is_fiq; +uint32_t intcntl; +uint32_t intmask; +qemu_irq irq; +qemu_irq fiq; +uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ +} IMXAVICState; + +static const VMStateDescription vmstate_imx_avic = { +.name = "imx-avic", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT64(pending, IMXAVICState), +VMSTATE_UINT64(enabled, IMXAVICState), +VMSTATE_UINT64(is_fiq, IMXAVICState), +VMSTATE_UINT32(intcntl, IMXAVICState), +VMSTATE_UINT32(intmask, IMXAVICState), +VMSTATE_UINT32_ARRAY(prio, IMXAVICState, PRIO_WORDS), +VMSTATE_END_OF_LIST() +}, +}; + + + +static inline int imx_avic_prio(IMXAVICState *s, int irq) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +return 0xf & (s->prio[word] >> part); +} + +static inline void imx_avic_set_prio(IMXAVICState *s, int irq, int prio) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +uint32_t mask = ~(0xf << part); +s->prio[word] &= mask; +s->prio[word] |= prio << part; +} + +/* Update interrupts. */ +static void imx_avic_update(IMXAVICState *s) +{ +int i; +uint64_t new = s->pending & s->enabled; +uint64_t flags; + +flags = new & s->is_fiq; +qemu_set_irq(s->fiq, !!flags); + +flags = new & ~s->is_fiq; +if (!flags || (s->intmask == 0x1f)) { +qemu_set_irq(s->irq, !!flags); +return; +} + +/* + * Take interrupt if there's a pending interrupt with + * priority higher than the value of intmask + */ +for (i = 0; i < IMX_AVIC_NUM_IRQS; i++) { +if (flags & (1UL << i)) { +if (imx_avic_prio(s, i) > s->intmask) { +qemu_set_irq(s->irq, 1); +return; +} +} +} +qemu_set_irq(s->irq, 0); +} + +static void imx_avic_set_irq(void *opaque, int irq, int level) +{ +IMXAVICState *s = (IMXAVICState *)opaque; + +if (level) { +DPRINTF("Raising IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending |= (1ULL << irq); +} else { +DPRINTF("Clearing IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending &= ~(1ULL << irq); +} + +
[Qemu-devel] [PATCH v6 3/5] FreeSCALE i.MX31 support: Timers
Implement the timers on the FreeScale i.MX31 SoC. This is not a complete implementation, but gives enough for Linux to boot and run. In particular external triggers, which are not useful under QEMU, are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx.h|8 hw/imx_timer.c | 689 3 files changed, 698 insertions(+), 1 deletion(-) create mode 100644 hw/imx_timer.c Index: qemu-working/hw/imx_timer.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_timer.c 2012-04-23 08:24:54.045563023 +1000 @@ -0,0 +1,689 @@ +/* + * IMX31 Timer + * + * Copyright (c) 2008 OK Labs + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * Updated by Peter Chubb + * + * This code is licenced under GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + */ + +#include "hw.h" +#include "qemu-timer.h" +#include "ptimer.h" +#include "sysbus.h" +#include "imx.h" + +//#define DEBUG_TIMER 1 +#ifdef DEBUG_TIMER +# define DPRINTF(fmt, args...) \ + do { printf("imx_timer: " fmt , ##args); } while (0) +#else +# define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_timer: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * GPT : General purpose timer + * + * This timer counts up continuously while it is enabled, resetting itself + * to 0 when it reaches TIMER_MAX (in freerun mode) or when it + * reaches the value of ocr1 (in periodic mode). WE simulate this using a + * QEMU ptimer counting down from ocr1 and reloading from ocr1 in + * periodic mode, or counting from ocr1 to zero, then TIMER_MAX - ocr1. + * waiting_rov is set when counting from TIMER_MAX. + * + * In the real hardware, there are three comparison registers that can + * trigger interrupts, and compare channel 1 can be used to + * force-reset the timer. However, this is a `bare-bones' + * implementation: only what Linux 3.x uses has been implemented + * (free-running timer from 0 to OCR1 or TIMER_MAX) . + */ + + +#define TIMER_MAX 0XUL + +/* Control register. Not all of these bits have any effect (yet) */ +#define GPT_CR_EN (1 << 0) /* GPT Enable */ +#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */ +#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ +#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ +#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ +#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ +#define GPT_CR_CLKSRC_SHIFT (6) +#define GPT_CR_CLKSRC_MASK (0x7) + +#define GPT_CR_FRR(1 << 9) /* Freerun or Restart */ +#define GPT_CR_SWR(1 << 15) /* Software Reset */ +#define GPT_CR_IM1(3 << 16) /* Input capture channel 1 mode (2 bits) */ +#define GPT_CR_IM2(3 << 18) /* Input capture channel 2 mode (2 bits) */ +#define GPT_CR_OM1(7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ +#define GPT_CR_OM2(7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ +#define GPT_CR_OM3(7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ +#define GPT_CR_FO1(1 << 29) /* Force Output Compare Channel 1 */ +#define GPT_CR_FO2(1 << 30) /* Force Output Compare Channel 2 */ +#define GPT_CR_FO3(1 << 31) /* Force Output Compare Channel 3 */ + +#define GPT_SR_OF1 (1 << 0) +#define GPT_SR_ROV (1 << 5) + +#define GPT_IR_OF1IE (1 << 0) +#define GPT_IR_ROVIE (1 << 5) + +typedef struct { +SysBusDevice busdev; +ptimer_state *timer; +MemoryRegion iomem; +DeviceState *ccm; + +uint32_t cr; +uint32_t pr; +uint32_t sr; +uint32_t ir; +uint32_t ocr1; +uint32_t cnt; + +uint32_t waiting_rov; +qemu_irq irq; +} IMXTimerGState; + +static const VMStateDescription vmstate_imx_timerg = { +.name = "imx-timerg", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(cr, IMXTimerGState), +VMSTATE_UINT32(pr, IMXTimerGState), +VMSTATE_UINT32(sr, IMXTimerGState), +VMSTATE_UINT32(ir, IMXTimerGState), +VMSTATE_UINT32(ocr1, IMXTimerGState), +VMSTATE_UINT32(cnt, IMXTimerGState), +VMSTATE_UINT32(waiting_rov, IMXTimerGState), +VMSTATE_PTIMER(timer, IMXTimerGState), +VMSTATE_END_OF_LIST() +} +}; + +static
[Qemu-devel] [PATCH v6 1/5] i.MX UART support
Implement the FreeScale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the FreeScale i.MX series. This patch gives only a `bare-bones' implementation, enough to run Linux or OKL4, but that's about it. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |1 hw/imx.h| 16 + hw/imx_serial.c | 467 3 files changed, 484 insertions(+) create mode 100644 hw/imx_serial.c Index: qemu-working/hw/imx_serial.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_serial.c2012-04-23 08:24:51.730152297 +1000 @@ -0,0 +1,467 @@ +/* + * IMX31 UARTS + * + * Copyright (c) 2008 OKL + * Originally Written by Hans Jiang + * Copyright (c) 2011 NICTA Pty Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * This is a `bare-bones' implementation of the IMX series serial ports. + * TODO: + * -- implement FIFOs. The real hardware has 32 word transmit + * and receive FIFOs; we currently use a 1-char buffer + * -- implement DMA + * -- implement BAUD-rate and modem lines, for when the backend + * is a real serial device. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "qemu-char.h" +#include "imx.h" + +//#define DEBUG_SERIAL 1 +#ifdef DEBUG_SERIAL +#define DPRINTF(fmt, args...) \ +do { printf("imx_serial: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +//#define DEBUG_IMPLEMENTATION 1 +#ifdef DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +int32_t readbuff; + +uint32_t usr1; +uint32_t usr2; +uint32_t ucr1; +uint32_t ucr2; +uint32_t uts1; + +/* + * The registers below are implemented just so that the + * guest OS sees what it has written + */ +uint32_t onems; +uint32_t ufcr; +uint32_t ubmr; +uint32_t ubrc; +uint32_t ucr3; + +qemu_irq irq; +CharDriverState *chr; +} IMXSerialState; + +static const VMStateDescription vmstate_imx_serial = { +.name = "imx-serial", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_INT32(readbuff, IMXSerialState), +VMSTATE_UINT32(usr1, IMXSerialState), +VMSTATE_UINT32(usr2, IMXSerialState), +VMSTATE_UINT32(ucr1, IMXSerialState), +VMSTATE_UINT32(uts1, IMXSerialState), +VMSTATE_UINT32(onems, IMXSerialState), +VMSTATE_UINT32(ufcr, IMXSerialState), +VMSTATE_UINT32(ubmr, IMXSerialState), +VMSTATE_UINT32(ubrc, IMXSerialState), +VMSTATE_UINT32(ucr3, IMXSerialState), +VMSTATE_END_OF_LIST() +}, +}; + + +#define URXD_CHARRDY(1<<15) /* character read is valid */ +#define URXD_ERR(1<<14) /* Character has error */ +#define URXD_BRK(1<<11) /* Break received */ + +#define USR1_PARTYER(1<<15) /* Parity Error */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Tx ready */ +#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */ +#define USR1_ESCF (1<<11) /* Escape sequence interrupt */ +#define USR1_FRAMERR(1<<10) /* Framing error */ +#define USR1_RRDY (1<<9)/* receiver ready */ +#define USR1_AGTIM (1<<8)/* Aging timer interrupt */ +#define USR1_DTRD (1<<7)/* DTR changed */ +#define USR1_RXDS (1<<6)/* Receiver is idle */ +#define USR1_AIRINT (1<<5)/* Aysnch IR interrupt */ +#define USR1_AWAKE (1<<4)/* Falling edge detected on RXd pin */ + +#define USR2_ADET (1<<15) /* Autobaud complete */ +#define USR2_TXFE (1<<14) /* Transmit FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR/DSR transition */ +#define USR2_IDLE (1<<12) /* UART has been idle for too long */ +#define USR2_ACST (1<<11) /* Autobaud counter stopped */ +#define USR2_RIDELT (1<<10) /* Ring Indicator delta */ +#define USR2_RIIN (1<<9)/* Ring Indicator Input */ +#define USR2_IRINT (1<<8)/* Serial Infrared Interrupt */ +#define USR2_WAKE (1<<7)/* Start bit detected */ +#def
[Qemu-devel] [PATCH v6 5/5] FreeSCALE i.MX31 support: KZM-ARM11-01 evaluation board
Board support for Kyoto Micro's KZM-ARM11-01, an evaluation board built around the FreeScale i.MX31. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/kzm.c| 161 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 hw/kzm.c Index: qemu-working/hw/kzm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/kzm.c 2012-04-23 08:24:56.380974317 +1000 @@ -0,0 +1,161 @@ +/* + * KZM Board System emulation. + * + * Copyright (c) 2008 OKL and 2011 NICTA + * Written by Hans + * Updated by Peter Chubb. + * + * This code is licenced under the GPL, version 2 or later. + * See the file `COPYING' in the top level directory. + * + * It (partially) emulates a Kyoto Microcomputer + * KZM-ARM11-01 evaluation board, with a FreeScale + * I.MX31 SoC + */ + +#include "sysbus.h" +#include "exec-memory.h" +#include "hw.h" +#include "arm-misc.h" +#include "devices.h" +#include "net.h" +#include "sysemu.h" +#include "boards.h" +#include "pc.h" /* for the FPGA UART that emulates a 16550 */ +#include "imx.h" + +/* Memory map for Kzm Emulation Baseboard: + * 0x-0x3fff 16k secure ROM IGNORED + * 0x4000-0x00407fff Reserved IGNORED + * 0x00404000-0x00407fff ROM IGNORED + * 0x00408000-0x0fff Reserved IGNORED + * 0x1000-0x1fffbfff RAM aliasing IGNORED + * 0x1fffc000-0x1fff RAM EMULATED + * 0x2000-0x2fff Reserved IGNORED + * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x43f0 IO_AREA0 + * 0x43f9 UART1 EMULATED + * 0x43f94000 UART2 EMULATED + * 0x6800 AVIC EMULATED + * 0x53f8 CCM EMULATED + * 0x53f94000 PIT 1 EMULATED + * 0x53f98000 PIT 2 EMULATED + * 0x53f9 GPT EMULATED + * 0x8000-0x87ff RAM EMULATED + * 0x8800-0x8fff RAM Aliasing EMULATED + * 0xa000-0xafff NAND Flash IGNORED + * 0xb000-0xb3ff Unavailable IGNORED + * 0xb400-0xb4000fff 8-bit free space IGNORED + * 0xb4001000-0xb400100f Board controlIGNORED + * 0xb4001003 DIP switch + * 0xb4001010-0xb400101f 7-segment LEDIGNORED + * 0xb4001020-0xb400102f LED IGNORED + * 0xb4001030-0xb400103f LED IGNORED + * 0xb4001040-0xb400104f FPGA, UART EMULATED + * 0xb4001050-0xb400105f FPGA, UART EMULATED + * 0xb4001060-0xb40f FPGA IGNORED + * 0xb600-0xb61f LAN controller EMULATED + * 0xb620-0xb62f FPGA NAND Controller IGNORED + * 0xb630-0xb7ff Free IGNORED + * 0xb800-0xb8004fff Memory control registers IGNORED + * 0xc000-0xc3ff PCMCIA/CFIGNORED + * 0xc400-0x Reserved IGNORED + */ + +#define KZM_RAMADDRESS (0x8000) +#define KZM_FPGA (0xb4001040) + +static struct arm_boot_info kzm_binfo = { +.loader_start = KZM_RAMADDRESS, +.board_id = 1722, +}; + +static void kzm_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +CPUARMState *env; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *ram_alias = g_new(MemoryRegion, 1); +qemu_irq *cpu_pic; +DeviceState *dev; +DeviceState *ccm; + +if (!cpu_model) { +cpu_model = "arm1136"; +} + +env = cpu_init(cpu_model); +if (!env) { +fprintf(stderr, "Unable to find CPU definition\n"); +exit(1); +} + +/* On a real system, the first 16k is a `secure boot rom' */ + +memory_region_init_ram(ram, "kzm.ram", ram_size); +vmstate_register_ram_global(ram); +memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram); + +memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); +memory_region_add_subregion(address_space_mem, 0x8800, ram_alias); + +memory_region_init_ram(sram, "kzm.sram", 0x4000); +memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram); + + +cpu_pic = arm_pic_init_cpu(env); +de
[Qemu-devel] [PATCH v6 2/5] Implement i.MX31 Clock Control Module
For Linux to be able to work out how fast its clocks are going, so that timer ticks come approximately at the right time, it needs to be able to query the clock control module (CCM). This is the start of a CCM implementation. It currently knows only about the MCU, HSP and IPG clocks --- i.e., the ones used to feed the periodic and general purpose timers. Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx.h| 10 + hw/imx_ccm.c| 312 3 files changed, 323 insertions(+), 1 deletion(-) Index: qemu-working/Makefile.target === --- qemu-working.orig/Makefile.target 2012-04-23 08:24:52.106056219 +1000 +++ qemu-working/Makefile.target2012-04-23 08:24:52.945842194 +1000 @@ -399,7 +399,7 @@ obj-arm-y += vexpress.o obj-arm-y += strongarm.o obj-arm-y += collie.o obj-arm-y += pl041.o lm4549.o -obj-arm-y += imx_serial.o +obj-arm-y += imx_serial.o imx_ccm.o obj-arm-$(CONFIG_FDT) += device_tree.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o Index: qemu-working/hw/imx_ccm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_ccm.c 2012-04-23 08:24:52.945842194 +1000 @@ -0,0 +1,312 @@ +/* + * IMX31 Clock Control Module + * + * Copyright (C) 2012 NICTA + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * To get the timer frequencies right, we need to emulate at least part of + * the CCM. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "imx.h" + +#define CKIH_FREQ 2600 /* 26MHz crystal input */ +#define CKIL_FREQ32768 /* nominal 32khz clock */ + + +//#define DEBUG_CCM 1 +#ifdef DEBUG_CCM +#define DPRINTF(fmt, args...) \ +do { printf("imx_ccm: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; + +uint32_t ccmr; +uint32_t pdr0; +uint32_t pdr1; +uint32_t mpctl; +uint32_t spctl; +uint32_t cgr[3]; +uint32_t pmcr0; +uint32_t pmcr1; + +/* Frequencies precalculated on register changes */ +uint32_t pll_refclk_freq; +uint32_t mcu_clk_freq; +uint32_t hsp_clk_freq; +uint32_t ipg_clk_freq; +} IMXCCMState; + +static const VMStateDescription vmstate_imx_ccm = { +.name = "imx-ccm", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(ccmr, IMXCCMState), +VMSTATE_UINT32(pdr0, IMXCCMState), +VMSTATE_UINT32(pdr1, IMXCCMState), +VMSTATE_UINT32(mpctl, IMXCCMState), +VMSTATE_UINT32(spctl, IMXCCMState), +VMSTATE_UINT32_ARRAY(cgr, IMXCCMState, 3), +VMSTATE_UINT32(pmcr0, IMXCCMState), +VMSTATE_UINT32(pmcr1, IMXCCMState), +VMSTATE_UINT32(pll_refclk_freq, IMXCCMState), +VMSTATE_UINT32(mcu_clk_freq, IMXCCMState), +VMSTATE_UINT32(hsp_clk_freq, IMXCCMState), +VMSTATE_UINT32(ipg_clk_freq, IMXCCMState), +}, +}; + +/* CCMR */ +#define CCMR_FPME (1<<0) +#define CCMR_MPE (1<<3) +#define CCMR_MDS (1<<7) +#define CCMR_FPMF (1<<26) +#define CCMR_PRCS (3<<1) + +/* PDR0 */ +#define PDR0_MCU_PODF_SHIFT (0) +#define PDR0_MCU_PODF_MASK (0x7) +#define PDR0_MAX_PODF_SHIFT (3) +#define PDR0_MAX_PODF_MASK (0x7) +#define PDR0_IPG_PODF_SHIFT (6) +#define PDR0_IPG_PODF_MASK (0x3) +#define PDR0_NFC_PODF_SHIFT (8) +#define PDR0_NFC_PODF_MASK (0x7) +#define PDR0_HSP_PODF_SHIFT (11) +#define PDR0_HSP_PODF_MASK (0x7) +#define PDR0_PER_PODF_SHIFT (16) +#define PDR0_PER_PODF_MASK (0x1f) +#define PDR0_CSI_PODF_SHIFT (23) +#define PDR0_CSI_PODF_MASK (0x1ff) + +#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \ + & PDR0_##name##_PODF_MASK) +#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \ + PDR0_##name##_PODF_SHIFT) +/* PLL control registers */ +#define PD(v) (((v) >> 26) & 0xf) +#define MFD(v) (((v) >> 16) & 0x3ff) +#define MFI(v) (((v) >> 10) & 0xf); +#define MFN(v) ((v) & 0x3ff) + +#define PLL_PD(x) (((x) & 0xf) << 26) +#define PLL_MFD(x) (((x) & 0x3ff) << 16) +#define PLL_MFI(x) (((x) & 0xf) << 10) +#define PLL_MFN(x) (((x) & 0x3ff) << 0) + +uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock) +{ +IMXCCMState *s = container_of(dev, IMXCCMState, busdev.qdev); + +switch (clock) { +case NOCLK: +return 0; +case MCU: +return s->mcu_clk_freq; +case HSP: +
[Qemu-devel] [PATCH v6 0/5] FreeSCALE i.MX31 support
Hi all, Most of the files are unchanged since last time. Main differences are: -- Change the way the timers are hooked up to the board to address Peter M's review comments. -- Move timer tick rate limiting out of the imx-timers implementation into a separate patch (not in this series) against ptimer.c -- Move function prototypes in imx.h into the correct patch. Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [PATCH] Limit ptimer rate to something achievable
If a guest sets very short timeouts, and asks for a timer to be reloaded on timeout, QEMU can go to 100%CPU utilisation and become unresponsive, as it is spending all its time generating timeout interrupts. On real hardware this doesn't matter, as the interrupts are just coalesced, and the effect is to have the interrupt asserted all the time. This patch is a band-aid, that prevents timeouts less than 10 microseconds from being set. 10 microseconds is a limit that was determined empirically on a variety of machines as the shortest that allowed QEMU to pick up a control-a c sequence to get at the monitor. Reported-by: Anna Lyons Signed-off-by: Peter Chubb --- hw/ptimer.c | 13 + 1 file changed, 13 insertions(+) Index: qemu-working/hw/ptimer.c === --- qemu-working.orig/hw/ptimer.c 2012-04-20 15:09:09.317922659 +1000 +++ qemu-working/hw/ptimer.c2012-04-20 15:30:42.108486207 +1000 @@ -180,6 +180,19 @@ void ptimer_set_freq(ptimer_state *s, ui count = limit. */ void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload) { +/* + * Artificially limit timeout rate to something + * achievable under QEMU. Otherwise, QEMU spends all + * its time generating timer interrupts, and there + * is no forward progress. + * About ten microseconds is the fastest that really works + * on the current generation of host machines. + */ + +if (limit * s->period < 1 && s->period) { +limit = 1 / s->period; +} + s->limit = limit; if (reload) s->delta = limit; -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [patch V5 3/5] FreeSCALE i.MX31 support: Timers
>>>>> "Peter" == Peter Chubb writes: Peter> I'm not sure how to make qdev properties work. The timers need Peter> to be able to get at the CCM-generated frequencies, which of Peter> course are private to the CCM. I've just split the problematic function into two: iomx_timerg_create() and imx_timerp_create(). That gets rid of the strcmp, and makes it more obvious what's going on. Because there will only ever be one CCM, there's no point in making it a property. I'm still not sure what to do about rate-limiting timer timeouts. I agree with you, Peter M, that it should be handled in the QEMU timer layer somewhere. Having had another look at the code, I really don't want to touch it. Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [patch V5 3/5] FreeSCALE i.MX31 support: Timers
>>>>> "Peter" == Peter Maydell writes: Peter> On 3 April 2012 02:55, Peter Chubb Peter> wrote: >+/* >+ * Artificially limit tick rate to something >+ * achievable under QEMU. Otherwise, QEMU spends all >+ * its time generating timer interrupts, and there >+ * is no forward progress. >+ * About ten microseconds is the fastest that really works. >+ */ >+if ((value * 100)/s->freq < 10) { >+value = 10*100/s->freq; >+} >+ptimer_set_limit(s->timer, value, !!(s->cr & CR_IOVW)); >+break; + Peter> This seems like the wrong level to do this. If over-eager timer Peter> ticks are a problem we ought to be applying the limit globally Peter> in the timer infrastructure layer somewhere, not via ad-hoc Peter> bandaids in individual device models. There appears to be some attempt in some code paths to limit the interval between timer ticks to 250us in the timer code, but tracing the relationship between ptimers, qemu-timers and the underlying posix timers is difficult. In particular it's easy to create a ptimer that runs so fast that QEMU spends all its time there. On real hardware this isn't a problem --- interrupts end up being coalesced, I have a test image that reliably hangs without this hack and the corresponding one in the timerp code. It works on the real hardware. >> +void imx_timer_create(const char * const name, + >> const target_phys_addr_t addr, + >> qemu_irq irq, + DeviceState *ccm) >> +{ + IMXTimerGState *gp; + IMXTimerPState *pp; + >> DeviceState *dev; + + dev = sysbus_create_simple(name, addr, >> irq); + if (strcmp(name, "imx_timerp") == 0) { + pp = >> container_of(dev, IMXTimerPState, busdev.qdev); + pp->ccm = >> ccm; + } else { + gp = container_of(dev, IMXTimerGState, >> busdev.qdev); + gp->ccm = ccm; + } + +} Peter> This is wrong in two ways: (a) strcmp() on the device name is Peter> pretty ugly (b) this kind of helper creation method mustn't go Peter> reaching into the implementation of the device like this. If Peter> you need to hand something to the device it needs to be a qdev Peter> property. I'm not sure how to make qdev properties work. The timers need to be able to get at the CCM-generated frequencies, which of course are private to the CCM. The same thing happens in the imx_serial emulation, to hook the right serial device to the right host device. Is there any documentation or appropriate examples anywhere? -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [patch V5 2/5] Implement i.MX31 Clock Control Module
>>>>> "Peter" == Peter Maydell writes: Peter> On 3 April 2012 02:55, Peter Chubb Peter> wrote: > + > +uint32_t imx_timer_frequency(DeviceState *s, IMXClk clock); > +void imx_timer_create(const char * const name, > + const target_phys_addr_t addr, > + qemu_irq irq, > + DeviceState *ccm); > + Peter> These function prototypes should be in the other patch, surely? Yes. At least, the second one does. Thanks, moved to the imx_timer.c patch. >> +/* PDR0 */ +#define PDR0_MCU_PODF_SHIFT (0) +#define >> PDR0_MCU_PODF_MASK (0x7) +#define PDR0_MAX_PODF_SHIFT (3) +#define >> PDR0_MAX_PODF_MASK (0x7) +#define PDR0_IPG_PODF_SHIFT (6) +#define >> PDR0_IPG_PODF_MASK (0x3) +#define PDR0_NFC_PODF_SHIFT (8) +#define >> PDR0_NFC_PODF_MASK (7) Peter> Some consistency about whether you're using 7 or 0x7 for masks Peter> would be nice. Done. > +static void imx_ccm_reset(DeviceState *dev) > +{ > +IMXCCMState *s = container_of(dev, IMXCCMState, busdev.qdev); > + > +s->cgr[0] = s->cgr[1] = s->cgr[2] = 0x; > +s->pmcr0 = 0x80209828; > +s->pdr1 = 0x49fcfe7f; > +s->spctl = PLL_PD(1) | PLL_MFD(4) | PLL_MFI(0xc) | PLL_MFN(1); > + > +/* > + * Really should predicate this on arm_boot_info->is_linux > + * but I don't know how to do that. > + */ > +if (1) { > +imx_ccm_uboot_reset(s); > +} else { > +imx_ccm_hw_reset(s); > +} > +update_clocks(s); > +} > + Peter> Urgh. Device models need to act like the device. Setting up Peter> devices the way u-boot happens to initialise them should be Peter> done somewhere else, ie driven by our built in bootloader, if Peter> we do it at all. I'd like to be able to do arm-system-qemu -M kzm -nographic -kernel zImage and have it work the same as if it'd been booted on the real hardware. For now I've removed the u-boot stuff. Is there a sane way to add to the built-in bootloader? -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [patch V5 3/5] FreeSCALE i.MX31 support: Timers
Implement the timers on the FreeScale i.MX31 SoC. This is not a complete implementation, but gives enough for Linux to boot and run. In particular external triggers, which are not useful under QEMU, are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx_timer.c | 693 2 files changed, 694 insertions(+), 1 deletion(-) create mode 100644 hw/imx_timer.c Index: qemu-working/hw/imx_timer.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_timer.c 2012-04-03 11:48:49.788710797 +1000 @@ -0,0 +1,693 @@ +/* + * IMX31 Timer + * + * Copyright (c) 2008 OK Labs + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * Updated by Peter Chubb + * + * This code is licenced under GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + */ + +#include "hw.h" +#include "qemu-timer.h" +#include "ptimer.h" +#include "sysbus.h" +#include "imx.h" + +//#define DEBUG_TIMER 1 +#ifdef DEBUG_TIMER +# define DPRINTF(fmt, args...) \ + do { printf("imx_timer: " fmt , ##args); } while (0) +#else +# define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_timer: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * GPT : General purpose timer + * + * This timer counts up continuously while it is enabled, resetting itself + * to 0 when it reaches TIMER_MAX (in freerun mode) or when it + * reaches the value of ocr1 (in periodic mode). WE simulate this using a + * QEMU ptimer counting down from ocr1 and reloading from ocr1 in + * periodic mode, or counting from ocr1 to zero, then TIMER_MAX - ocr1. + * waiting_rov is set when counting from TIMER_MAX. + * + * In the real hardware, there are three comparison registers that can + * trigger interrupts, and compare channel 1 can be used to + * force-reset the timer. However, this is a `bare-bones' + * implementation: only what Linux 3.x uses has been implemented + * (free-running timer from 0 to OCR1 or TIMER_MAX) . + */ + + +#define TIMER_MAX 0XUL + +/* Control register. Not all of these bits have any effect (yet) */ +#define GPT_CR_EN (1 << 0) /* GPT Enable */ +#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */ +#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ +#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ +#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ +#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ +#define GPT_CR_CLKSRC_SHIFT (6) +#define GPT_CR_CLKSRC_MASK (0x7) + +#define GPT_CR_FRR(1 << 9) /* Freerun or Restart */ +#define GPT_CR_SWR(1 << 15) /* Software Reset */ +#define GPT_CR_IM1(3 << 16) /* Input capture channel 1 mode (2 bits) */ +#define GPT_CR_IM2(3 << 18) /* Input capture channel 2 mode (2 bits) */ +#define GPT_CR_OM1(7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ +#define GPT_CR_OM2(7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ +#define GPT_CR_OM3(7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ +#define GPT_CR_FO1(1 << 29) /* Force Output Compare Channel 1 */ +#define GPT_CR_FO2(1 << 30) /* Force Output Compare Channel 2 */ +#define GPT_CR_FO3(1 << 31) /* Force Output Compare Channel 3 */ + +#define GPT_SR_OF1 (1 << 0) +#define GPT_SR_ROV (1 << 5) + +#define GPT_IR_OF1IE (1 << 0) +#define GPT_IR_ROVIE (1 << 5) + +typedef struct { +SysBusDevice busdev; +ptimer_state *timer; +MemoryRegion iomem; +DeviceState *ccm; + +uint32_t cr; +uint32_t pr; +uint32_t sr; +uint32_t ir; +uint32_t ocr1; +uint32_t cnt; + +uint32_t waiting_rov; +qemu_irq irq; +} IMXTimerGState; + +static const VMStateDescription vmstate_imx_timerg = { +.name = "imx-timerg", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(cr, IMXTimerGState), +VMSTATE_UINT32(pr, IMXTimerGState), +VMSTATE_UINT32(sr, IMXTimerGState), +VMSTATE_UINT32(ir, IMXTimerGState), +VMSTATE_UINT32(ocr1, IMXTimerGState), +VMSTATE_UINT32(cnt, IMXTimerGState), +VMSTATE_UINT32(waiting_rov, IMXTimerGState), +VMSTATE_PTIMER(timer, IMXTimerGState), +VMSTATE_END_OF_LIST() +} +}; + +static const IMXClk imx_tim
[Qemu-devel] [patch V5 1/5] i.MX UART support
Implement the FreeScale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the FreeScale i.MX series. This patch gives only a `bare-bones' implementation, enough to run Linux or OKL4, but that's about it. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |1 hw/imx.h| 16 + hw/imx_serial.c | 467 3 files changed, 484 insertions(+) create mode 100644 hw/imx_serial.c Index: qemu-working/hw/imx_serial.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_serial.c2012-04-03 11:48:47.732705764 +1000 @@ -0,0 +1,467 @@ +/* + * IMX31 UARTS + * + * Copyright (c) 2008 OKL + * Originally Written by Hans Jiang + * Copyright (c) 2011 NICTA Pty Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * This is a `bare-bones' implementation of the IMX series serial ports. + * TODO: + * -- implement FIFOs. The real hardware has 32 word transmit + * and receive FIFOs; we currently use a 1-char buffer + * -- implement DMA + * -- implement BAUD-rate and modem lines, for when the backend + * is a real serial device. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "qemu-char.h" +#include "imx.h" + +//#define DEBUG_SERIAL 1 +#ifdef DEBUG_SERIAL +#define DPRINTF(fmt, args...) \ +do { printf("imx_serial: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +//#define DEBUG_IMPLEMENTATION 1 +#ifdef DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +int32_t readbuff; + +uint32_t usr1; +uint32_t usr2; +uint32_t ucr1; +uint32_t ucr2; +uint32_t uts1; + +/* + * The registers below are implemented just so that the + * guest OS sees what it has written + */ +uint32_t onems; +uint32_t ufcr; +uint32_t ubmr; +uint32_t ubrc; +uint32_t ucr3; + +qemu_irq irq; +CharDriverState *chr; +} IMXSerialState; + +static const VMStateDescription vmstate_imx_serial = { +.name = "imx-serial", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_INT32(readbuff, IMXSerialState), +VMSTATE_UINT32(usr1, IMXSerialState), +VMSTATE_UINT32(usr2, IMXSerialState), +VMSTATE_UINT32(ucr1, IMXSerialState), +VMSTATE_UINT32(uts1, IMXSerialState), +VMSTATE_UINT32(onems, IMXSerialState), +VMSTATE_UINT32(ufcr, IMXSerialState), +VMSTATE_UINT32(ubmr, IMXSerialState), +VMSTATE_UINT32(ubrc, IMXSerialState), +VMSTATE_UINT32(ucr3, IMXSerialState), +VMSTATE_END_OF_LIST() +}, +}; + + +#define URXD_CHARRDY(1<<15) /* character read is valid */ +#define URXD_ERR(1<<14) /* Character has error */ +#define URXD_BRK(1<<11) /* Break received */ + +#define USR1_PARTYER(1<<15) /* Parity Error */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Tx ready */ +#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */ +#define USR1_ESCF (1<<11) /* Escape sequence interrupt */ +#define USR1_FRAMERR(1<<10) /* Framing error */ +#define USR1_RRDY (1<<9)/* receiver ready */ +#define USR1_AGTIM (1<<8)/* Aging timer interrupt */ +#define USR1_DTRD (1<<7)/* DTR changed */ +#define USR1_RXDS (1<<6)/* Receiver is idle */ +#define USR1_AIRINT (1<<5)/* Aysnch IR interrupt */ +#define USR1_AWAKE (1<<4)/* Falling edge detected on RXd pin */ + +#define USR2_ADET (1<<15) /* Autobaud complete */ +#define USR2_TXFE (1<<14) /* Transmit FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR/DSR transition */ +#define USR2_IDLE (1<<12) /* UART has been idle for too long */ +#define USR2_ACST (1<<11) /* Autobaud counter stopped */ +#define USR2_RIDELT (1<<10) /* Ring Indicator delta */ +#define USR2_RIIN (1<<9)/* Ring Indicator Input */ +#define USR2_IRINT (1<<8)/* Serial Infrared Interrupt */ +#define USR2_WAKE (1<<7)/* Start bit detected */ +#def
[Qemu-devel] [patch V5 4/5] FreeSCALE i.MX31 support: AVIC
Implement the FreeSCALE i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.0.x Vectors are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb Reviewed-by: Peter Maydell --- Makefile.target |2 hw/imx_avic.c | 409 2 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 hw/imx_avic.c Index: qemu-working/hw/imx_avic.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_avic.c 2012-04-03 11:48:50.900713524 +1000 @@ -0,0 +1,409 @@ +/* + * IMX31 Vectored Interrupt Controller + * + * Note this is NOT the PL192 provided by ARM, but + * a custom implementation by FreeScale. + * + * Copyright (c) 2008 OKL + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * + * This code is licenced under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * TODO: implement vectors. + */ + +#include "hw.h" +#include "sysbus.h" +#include "host-utils.h" + +#define DEBUG_INT 1 +#undef DEBUG_INT /* comment out for debugging */ + +#ifdef DEBUG_INT +#define DPRINTF(fmt, args...) \ +do { printf("imx_avic: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +#define IMX_AVIC_NUM_IRQS 64 + +/* Interrupt Control Bits */ +#define ABFLAG (1<<25) +#define ABFEN (1<<24) +#define NIDIS (1<<22) /* Normal Interrupt disable */ +#define FIDIS (1<<21) /* Fast interrupt disable */ +#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ +#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ +#define NM(1<<18) /* Normal interrupt mode */ + + +#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) +#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +uint64_t pending; +uint64_t enabled; +uint64_t is_fiq; +uint32_t intcntl; +uint32_t intmask; +qemu_irq irq; +qemu_irq fiq; +uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ +} IMXAVICState; + +static const VMStateDescription vmstate_imx_avic = { +.name = "imx-avic", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT64(pending, IMXAVICState), +VMSTATE_UINT64(enabled, IMXAVICState), +VMSTATE_UINT64(is_fiq, IMXAVICState), +VMSTATE_UINT32(intcntl, IMXAVICState), +VMSTATE_UINT32(intmask, IMXAVICState), +VMSTATE_UINT32_ARRAY(prio, IMXAVICState, PRIO_WORDS), +VMSTATE_END_OF_LIST() +}, +}; + + + +static inline int imx_avic_prio(IMXAVICState *s, int irq) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +return 0xf & (s->prio[word] >> part); +} + +static inline void imx_avic_set_prio(IMXAVICState *s, int irq, int prio) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +uint32_t mask = ~(0xf << part); +s->prio[word] &= mask; +s->prio[word] |= prio << part; +} + +/* Update interrupts. */ +static void imx_avic_update(IMXAVICState *s) +{ +int i; +uint64_t new = s->pending & s->enabled; +uint64_t flags; + +flags = new & s->is_fiq; +qemu_set_irq(s->fiq, !!flags); + +flags = new & ~s->is_fiq; +if (!flags || (s->intmask == 0x1f)) { +qemu_set_irq(s->irq, !!flags); +return; +} + +/* + * Take interrupt if there's a pending interrupt with + * priority higher than the value of intmask + */ +for (i = 0; i < IMX_AVIC_NUM_IRQS; i++) { +if (flags & (1UL << i)) { +if (imx_avic_prio(s, i) > s->intmask) { +qemu_set_irq(s->irq, 1); +return; +} +} +} +qemu_set_irq(s->irq, 0); +} + +static void imx_avic_set_irq(void *opaque, int irq, int level) +{ +IMXAVICState *s = (IMXAVICState *)opaque; + +if (level) { +DPRINTF("Raising IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending |= (1ULL << irq); +} else { +DPRINTF("Clearing IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending &= ~(1ULL << irq); +} + +
[Qemu-devel] [patch V5 2/5] Implement i.MX31 Clock Control Module
For Linux to be able to work out how fast its clocks are going, so that timer ticks come approximately at the right time, it needs to be able to query the clock control module (CCM). This is the start of a CCM implementation. It currently knows only about the MCU, HSP and IPG clocks --- i.e., the ones used to feed the periodic and general purpose timers. Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx.h| 14 ++ hw/imx_ccm.c| 334 3 files changed, 349 insertions(+), 1 deletion(-) Index: qemu-working/Makefile.target === --- qemu-working.orig/Makefile.target 2012-04-03 11:48:48.088706634 +1000 +++ qemu-working/Makefile.target2012-04-03 11:48:48.776708322 +1000 @@ -393,7 +393,7 @@ obj-arm-y += vexpress.o obj-arm-y += strongarm.o obj-arm-y += collie.o obj-arm-y += pl041.o lm4549.o -obj-arm-y += imx_serial.o +obj-arm-y += imx_serial.o imx_ccm.o obj-arm-$(CONFIG_FDT) += device_tree.o obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o Index: qemu-working/hw/imx.h === --- qemu-working.orig/hw/imx.h 2012-04-03 11:48:48.088706634 +1000 +++ qemu-working/hw/imx.h 2012-04-03 11:48:48.776708322 +1000 @@ -13,4 +13,18 @@ void imx_serial_create(int uart, const target_phys_addr_t addr, qemu_irq irq); +typedef enum { +NOCLK, +MCU, +HSP, +IPG, +CLK_32k +} IMXClk; + +uint32_t imx_timer_frequency(DeviceState *s, IMXClk clock); +void imx_timer_create(const char * const name, + const target_phys_addr_t addr, + qemu_irq irq, + DeviceState *ccm); + #endif /* IMX_H */ Index: qemu-working/hw/imx_ccm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_ccm.c 2012-04-03 11:48:48.776708322 +1000 @@ -0,0 +1,334 @@ +/* + * IMX31 Clock Control Module + * + * Copyright (C) 2012 NICTA + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * To get the timer frequencies right, we need to emulate at least part of + * the CCM. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "imx.h" + +#define CKIH_FREQ 2600 /* 26MHz crystal input */ +#define CKIL_FREQ32768 /* nominal 32khz clock */ + + +//#define DEBUG_CCM 1 +#ifdef DEBUG_CCM +#define DPRINTF(fmt, args...) \ +do { printf("imx_ccm: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; + +uint32_t ccmr; +uint32_t pdr0; +uint32_t pdr1; +uint32_t mpctl; +uint32_t spctl; +uint32_t cgr[3]; +uint32_t pmcr0; +uint32_t pmcr1; + +/* Frequencies precalculated on register changes */ +uint32_t pll_refclk_freq; +uint32_t mcu_clk_freq; +uint32_t hsp_clk_freq; +uint32_t ipg_clk_freq; +} IMXCCMState; + +static const VMStateDescription vmstate_imx_ccm = { +.name = "imx-ccm", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(ccmr, IMXCCMState), +VMSTATE_UINT32(pdr0, IMXCCMState), +VMSTATE_UINT32(pdr1, IMXCCMState), +VMSTATE_UINT32(mpctl, IMXCCMState), +VMSTATE_UINT32(spctl, IMXCCMState), +VMSTATE_UINT32_ARRAY(cgr, IMXCCMState, 3), +VMSTATE_UINT32(pmcr0, IMXCCMState), +VMSTATE_UINT32(pmcr1, IMXCCMState), +VMSTATE_UINT32(pll_refclk_freq, IMXCCMState), +VMSTATE_UINT32(mcu_clk_freq, IMXCCMState), +VMSTATE_UINT32(hsp_clk_freq, IMXCCMState), +VMSTATE_UINT32(ipg_clk_freq, IMXCCMState), +}, +}; + +/* CCMR */ +#define CCMR_FPME (1<<0) +#define CCMR_MPE (1<<3) +#define CCMR_MDS (1<<7) +#define CCMR_FPMF (1<<26) +#define CCMR_PRCS (3<<1) + +/* PDR0 */ +#define PDR0_MCU_PODF_SHIFT (0) +#define PDR0_MCU_PODF_MASK (0x7) +#define PDR0_MAX_PODF_SHIFT (3) +#define PDR0_MAX_PODF_MASK (0x7) +#define PDR0_IPG_PODF_SHIFT (6) +#define PDR0_IPG_PODF_MASK (0x3) +#define PDR0_NFC_PODF_SHIFT (8) +#define PDR0_NFC_PODF_MASK (7) +#define PDR0_HSP_PODF_SHIFT (11) +#define PDR0_HSP_PODF_MASK (7) +#define PDR0_PER_PODF_SHIFT (16) +#define PDR0_PER_PODF_MASK (0x1f) +#define PDR0_CSI_PODF_SHIFT (23) +#define PDR0_CSI_PODF_MASK (0x1ff) + +#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \ + & PDR0_##name##_PODF_MASK) +#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \ + PDR0_##name##_PODF_SHIFT) +/* PLL control registers */ +#define PD(v) (((v
[Qemu-devel] [patch V5 0/5] i.MX31 support
This is the fifth round of patches for preliminary Freescale i.MX31 support. The only changes in the patches for imx UART and AVIC are the CamelCasing of the typedef names, and removal of unwanted #include files. The major change has been in the timer implementation. I've added a partial implementation of the clock control module, so that Linux gets the frequency of the clocks right, and totally reimplemented the general-purpose timer in terms of QEMU ptimers. This meant a small change to the board-level file, hw/kzm.c so that the timers could know about the CCM. I've tested the result with Linux 3.3.0 and a variety of unit tests. DVFS is still not implemented; but apart from that, timer ticks seem to come at around the right rate, and the timer values when read are sane. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [patch V5 5/5] FreeSCALE i.MX31 support: KZM-ARM11-01 evaluation board
Board support for Kyoto Micro's KZM-ARM11-01, an evaluation board built around the FreeScale i.MX31. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/kzm.c| 161 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 hw/kzm.c Index: qemu-working/hw/kzm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/kzm.c 2012-04-03 11:48:51.876715919 +1000 @@ -0,0 +1,161 @@ +/* + * KZM Board System emulation. + * + * Copyright (c) 2008 OKL and 2011 NICTA + * Written by Hans + * Updated by Peter Chubb. + * + * This code is licenced under the GPL, version 2 or later. + * See the file `COPYING' in the top level directory. + * + * It (partially) emulates a Kyoto Microcomputer + * KZM-ARM11-01 evaluation board, with a FreeScale + * I.MX31 SoC + */ + +#include "sysbus.h" +#include "exec-memory.h" +#include "hw.h" +#include "arm-misc.h" +#include "devices.h" +#include "net.h" +#include "sysemu.h" +#include "boards.h" +#include "pc.h" /* for the FPGA UART that emulates a 16550 */ +#include "imx.h" + +/* Memory map for Kzm Emulation Baseboard: + * 0x-0x3fff 16k secure ROM IGNORED + * 0x4000-0x00407fff Reserved IGNORED + * 0x00404000-0x00407fff ROM IGNORED + * 0x00408000-0x0fff Reserved IGNORED + * 0x1000-0x1fffbfff RAM aliasing IGNORED + * 0x1fffc000-0x1fff RAM EMULATED + * 0x2000-0x2fff Reserved IGNORED + * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x43f0 IO_AREA0 + * 0x43f9 UART1 EMULATED + * 0x43f94000 UART2 EMULATED + * 0x6800 AVIC EMULATED + * 0x53f8 CCM EMULATED + * 0x53f94000 PIT 1 EMULATED + * 0x53f98000 PIT 2 EMULATED + * 0x53f9 GPT EMULATED + * 0x8000-0x87ff RAM EMULATED + * 0x8800-0x8fff RAM Aliasing EMULATED + * 0xa000-0xafff NAND Flash IGNORED + * 0xb000-0xb3ff Unavailable IGNORED + * 0xb400-0xb4000fff 8-bit free space IGNORED + * 0xb4001000-0xb400100f Board controlIGNORED + * 0xb4001003 DIP switch + * 0xb4001010-0xb400101f 7-segment LEDIGNORED + * 0xb4001020-0xb400102f LED IGNORED + * 0xb4001030-0xb400103f LED IGNORED + * 0xb4001040-0xb400104f FPGA, UART EMULATED + * 0xb4001050-0xb400105f FPGA, UART EMULATED + * 0xb4001060-0xb40f FPGA IGNORED + * 0xb600-0xb61f LAN controller EMULATED + * 0xb620-0xb62f FPGA NAND Controller IGNORED + * 0xb630-0xb7ff Free IGNORED + * 0xb800-0xb8004fff Memory control registers IGNORED + * 0xc000-0xc3ff PCMCIA/CFIGNORED + * 0xc400-0x Reserved IGNORED + */ + +#define KZM_RAMADDRESS (0x8000) +#define KZM_FPGA (0xb4001040) + +static struct arm_boot_info kzm_binfo = { +.loader_start = KZM_RAMADDRESS, +.board_id = 1722, +}; + +static void kzm_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +CPUARMState *env; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *ram_alias = g_new(MemoryRegion, 1); +qemu_irq *cpu_pic; +DeviceState *dev; +DeviceState *ccm; + +if (!cpu_model) { +cpu_model = "arm1136"; +} + +env = cpu_init(cpu_model); +if (!env) { +fprintf(stderr, "Unable to find CPU definition\n"); +exit(1); +} + +/* On a real system, the first 16k is a `secure boot rom' */ + +memory_region_init_ram(ram, "kzm.ram", ram_size); +vmstate_register_ram_global(ram); +memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram); + +memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); +memory_region_add_subregion(address_space_mem, 0x8800, ram_alias); + +memory_region_init_ram(sram, "kzm.sram", 0x4000); +memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram); + + +cpu_pic = arm_pic_init_cpu(env); +de
Re: [Qemu-devel] [patch V4 1/4] i.MX UART support
Thanks for your reviewing time and expertise Peter. It's much appreciated. May I add your Reviewed-By: line to the imx-serial patch too? The only change is CamelCasing the typedef. Peter C -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
Re: [Qemu-devel] [patch V4 2/4] FreeSCALE i.MX31 support: Timers
>>>>> "Peter" == Peter Maydell writes: Peter> ...that would work better if I cc'd the people I meant to... Peter> On 15 March 2012 17:08, Peter Maydell Peter> wrote: >> On 9 March 2012 03:27, wrote: >>> Implement the timers on the FreeScale i.MX31 SoC. This is not a >>> complete implementation, but gives enough for Linux to boot and >>> run. In particular external triggers, which are not useful under >>> QEMU, are not implemented. >> >> >> The rest looks OK to me but I'm not very good with qemu's timer >> API. Paolo or Paul -- could you check this looks ok on that front? >> Yes please! I think there's a bug in there somewhere when using the G timer, as interrupts appear to arrive too far apart in some modes. The scaling is probably wrong somewhere. -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [patch V4 1/4] i.MX UART support
Implement the FreeScale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the FreeScale i.MX series. This patch gives only a `bare-bones' implementation, enough to run Linux or OKL4, but that's about it. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |1 hw/imx_serial.c | 466 2 files changed, 467 insertions(+) create mode 100644 hw/imx_serial.c Index: qemu-working/hw/imx_serial.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_serial.c2012-03-09 14:13:49.714061283 +1100 @@ -0,0 +1,466 @@ +/* + * IMX31 UARTS + * + * Copyright (c) 2008 OKL + * Originally Written by Hans Jiang + * Copyright (c) 2011 NICTA Pty Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * This is a `bare-bones' implementation of the IMX series serial ports. + * TODO: + * -- implement FIFOs. The real hardware has 32 word transmit + * and receive FIFOs; we currently use a 1-char buffer + * -- implement DMA + * -- implement BAUD-rate and modem lines, for when the backend + * is a real serial device. + */ + +#include "hw.h" +#include "sysbus.h" +#include "sysemu.h" +#include "qemu-char.h" +#include "imx.h" + +//#define DEBUG_SERIAL 1 +#ifdef DEBUG_SERIAL +#define DPRINTF(fmt, args...) \ +do { printf("imx_serial: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +//#define DEBUG_IMPLEMENTATION 1 +#ifdef DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +int32_t readbuff; + +uint32_t usr1; +uint32_t usr2; +uint32_t ucr1; +uint32_t ucr2; +uint32_t uts1; + +/* + * The registers below are implemented just so that the + * guest OS sees what it has written + */ +uint32_t onems; +uint32_t ufcr; +uint32_t ubmr; +uint32_t ubrc; +uint32_t ucr3; + +qemu_irq irq; +CharDriverState *chr; +} imx_state; + +static const VMStateDescription vmstate_imx_serial = { +.name = "imx-serial", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_INT32(readbuff, imx_state), +VMSTATE_UINT32(usr1, imx_state), +VMSTATE_UINT32(usr2, imx_state), +VMSTATE_UINT32(ucr1, imx_state), +VMSTATE_UINT32(uts1, imx_state), +VMSTATE_UINT32(onems, imx_state), +VMSTATE_UINT32(ufcr, imx_state), +VMSTATE_UINT32(ubmr, imx_state), +VMSTATE_UINT32(ubrc, imx_state), +VMSTATE_UINT32(ucr3, imx_state), +VMSTATE_END_OF_LIST() +}, +}; + + +#define URXD_CHARRDY(1<<15) /* character read is valid */ +#define URXD_ERR(1<<14) /* Character has error */ +#define URXD_BRK(1<<11) /* Break received */ + +#define USR1_PARTYER(1<<15) /* Parity Error */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Tx ready */ +#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */ +#define USR1_ESCF (1<<11) /* Escape sequence interrupt */ +#define USR1_FRAMERR(1<<10) /* Framing error */ +#define USR1_RRDY (1<<9)/* receiver ready */ +#define USR1_AGTIM (1<<8)/* Aging timer interrupt */ +#define USR1_DTRD (1<<7)/* DTR changed */ +#define USR1_RXDS (1<<6)/* Receiver is idle */ +#define USR1_AIRINT (1<<5)/* Aysnch IR interrupt */ +#define USR1_AWAKE (1<<4)/* Falling edge detected on RXd pin */ + +#define USR2_ADET (1<<15) /* Autobaud complete */ +#define USR2_TXFE (1<<14) /* Transmit FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR/DSR transition */ +#define USR2_IDLE (1<<12) /* UART has been idle for too long */ +#define USR2_ACST (1<<11) /* Autobaud counter stopped */ +#define USR2_RIDELT (1<<10) /* Ring Indicator delta */ +#define USR2_RIIN (1<<9)/* Ring Indicator Input */ +#define USR2_IRINT (1<<8)/* Serial Infrared Interrupt */ +#define USR2_WAKE (1<<7)/* Start bit detected */ +#define USR2_DCDDELT(1<<6)/* Data Carrier Detect delta */ +#define USR2_DCDIN (1<<5)/* Dat
[Qemu-devel] [patch V4 3/4] FreeSCALE i.MX31 support: AVIC
Implement the FreeSCALE i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.0.x Vectors are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx_avic.c | 409 2 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 hw/imx_avic.c Index: qemu-working/hw/imx_avic.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_avic.c 2012-03-09 14:13:52.878104591 +1100 @@ -0,0 +1,409 @@ +/* + * IMX31 Vectored Interrupt Controller + * + * Note this is NOT the PL192 provided by ARM, but + * a custom implementation by FreeScale. + * + * Copyright (c) 2008 OKL + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * + * This code is licenced under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * TODO: implement vectors. + */ + +#include "hw.h" +#include "sysbus.h" +#include "host-utils.h" + +#define DEBUG_INT 1 +#undef DEBUG_INT /* comment out for debugging */ + +#ifdef DEBUG_INT +#define DPRINTF(fmt, args...) \ +do { printf("imx_avic: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +#define IMX_AVIC_NUM_IRQS 64 + +/* Interrupt Control Bits */ +#define ABFLAG (1<<25) +#define ABFEN (1<<24) +#define NIDIS (1<<22) /* Normal Interrupt disable */ +#define FIDIS (1<<21) /* Fast interrupt disable */ +#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ +#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ +#define NM(1<<18) /* Normal interrupt mode */ + + +#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) +#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +uint64_t pending; +uint64_t enabled; +uint64_t is_fiq; +uint32_t intcntl; +uint32_t intmask; +qemu_irq irq; +qemu_irq fiq; +uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ +} imx_avic_state; + +static const VMStateDescription vmstate_imx_avic = { +.name = "imx-avic", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT64(pending, imx_avic_state), +VMSTATE_UINT64(enabled, imx_avic_state), +VMSTATE_UINT64(is_fiq, imx_avic_state), +VMSTATE_UINT32(intcntl, imx_avic_state), +VMSTATE_UINT32(intmask, imx_avic_state), +VMSTATE_UINT32_ARRAY(prio, imx_avic_state, PRIO_WORDS), +VMSTATE_END_OF_LIST() +}, +}; + + + +static inline int imx_avic_prio(imx_avic_state *s, int irq) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +return 0xf & (s->prio[word] >> part); +} + +static inline void imx_avic_set_prio(imx_avic_state *s, int irq, int prio) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +uint32_t mask = ~(0xf << part); +s->prio[word] &= mask; +s->prio[word] |= prio << part; +} + +/* Update interrupts. */ +static void imx_avic_update(imx_avic_state *s) +{ +int i; +uint64_t new = s->pending & s->enabled; +uint64_t flags; + +flags = new & s->is_fiq; +qemu_set_irq(s->fiq, !!flags); + +flags = new & ~s->is_fiq; +if (!flags || (s->intmask == 0x1f)) { +qemu_set_irq(s->irq, !!flags); +return; +} + +/* + * Take interrupt if there's a pending interrupt with + * priority higher than the value of intmask + */ +for (i = 0; i < IMX_AVIC_NUM_IRQS; i++) { +if (flags & (1UL << i)) { +if (imx_avic_prio(s, i) > s->intmask) { +qemu_set_irq(s->irq, 1); +return; +} +} +} +qemu_set_irq(s->irq, 0); +} + +static void imx_avic_set_irq(void *opaque, int irq, int level) +{ +imx_avic_state *s = (imx_avic_state *)opaque; + +if (level) { +DPRINTF("Raising IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending |= (1ULL << irq); +} else { +DPRINTF("Clearing IRQ %d, prio %d\n", +irq, imx_avic_prio(s, irq)); +s->pending &= ~(1ULL << irq); +} + +imx_
[Qemu-devel] [patch V4 4/4] FreeSCALE i.MX31 support: KZM-ARM11-01 evaluation board
Board support for Kyoto Micro's KZM-ARM11-01, an evaluation board built around the FreeScale i.MX31. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |1 hw/kzm.c| 159 2 files changed, 160 insertions(+) create mode 100644 hw/kzm.c Index: qemu-working/hw/kzm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/kzm.c 2012-03-09 14:13:54.578127780 +1100 @@ -0,0 +1,159 @@ +/* + * KZM Board System emulation. + * + * Copyright (c) 2008 OKL and 2011 NICTA + * Written by Hans + * Updated by Peter Chubb. + * + * This code is licenced under the GPL, version 2 or later. + * See the file `COPYING' in the top level directory. + * + * It (partially) emulates a Kyoto Microcomputer + * KZM-ARM11-01 evaluation board, with a FreeScale + * I.MX31 SoC + */ + +#include "sysbus.h" +#include "exec-memory.h" +#include "hw.h" +#include "arm-misc.h" +#include "primecell.h" +#include "devices.h" +#include "pci.h" +#include "net.h" +#include "sysemu.h" +#include "boards.h" +#include "pc.h" /* for the FPGA UART that emulates a 16550 */ +#include "imx.h" + +/* Memory map for Kzm Emulation Baseboard: + * 0x-0x3fff 16k secure ROM IGNORED + * 0x4000-0x00407fff Reserved IGNORED + * 0x00404000-0x00407fff ROM IGNORED + * 0x00408000-0x0fff Reserved IGNORED + * 0x1000-0x1fffBfff RAM aliasing IGNORED + * 0x1fffc000-0x1fff RAM EMULATED + * 0x2000-0x2fff Reserved IGNORED + * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x43f0 IO_AREA0 + * 0x43f9 UART1 EMULATED + * 0x43f94000 UART2 EMULATED + * 0x6800 PIC EMULATED + * 0x53f94000 PIT 1 EMULATED + * 0x53f98000 PIT 2 EMULATED + * 0x53f9 GPT EMULATED + * 0x8000-0x87ff RAM EMULATED + * 0x8800-0x8fff RAM Aliasing EMULATED + * 0xa000-0xafff NAND Flash IGNORED + * 0xb000-0xb3ff Unavailable IGNORED + * 0xb400-0xb4000fff 8-bit free space IGNORED + * 0xb4001000-0xb400100f Board controlIGNORED + * 0xb4001003 DIP switch + * 0xb4001010-0xb400101f 7-segment LEDIGNORED + * 0xb4001020-0xb400102f LED IGNORED + * 0xb4001030-0xb400103f LED IGNORED + * 0xb4001040-0xb400104f FPGA, UART EMULATED + * 0xb4001050-0xb400105f FPGA, UART EMULATED + * 0xb4001060-0xb40f FPGA IGNORED + * 0xb600-0xb61f LAN controller EMULATED + * 0xb620-0xb62f FPGA NAND Controller IGNORED + * 0xb630-0xb7ff Free IGNORED + * 0xb800-0xb8004fff Memory control registers IGNORED + * 0xc000-0xc3ff PCMCIA/CFIGNORED + * 0xc400-0x Reserved IGNORED + */ + +#define KZM_RAMADDRESS (0x8000) +#define KZM_FPGA (0xb4001040) + +static struct arm_boot_info kzm_binfo = { +.loader_start = KZM_RAMADDRESS, +.board_id = 1722, +}; + +static void kzm_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +CPUState *env; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *ram_alias = g_new(MemoryRegion, 1); +qemu_irq *cpu_pic; +DeviceState *dev; + +if (!cpu_model) { +cpu_model = "arm1136"; +} + +env = cpu_init(cpu_model); +if (!env) { +fprintf(stderr, "Unable to find CPU definition\n"); +exit(1); +} + +/* On a real system, the first 16k is a `secure boot rom' */ + +memory_region_init_ram(ram, "kzm.ram", ram_size); +vmstate_register_ram_global(ram); +memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram); + +memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); +memory_region_add_subregion(address_space_mem, 0x8800, ram_alias); + +memory_region_init_ram(sram, "kzm.sram", 0x4000); +memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram); + + +cpu_pic = arm_pic_init_cpu(env); +dev = sysbus_create_varargs("imx_avic&q
[Qemu-devel] [patch V4 0/4] Support for i.MX31 and the Kyoto KZM11 board
This is version 4 of the patchset. The major changes since the last round are: * Moved to new QEMU object model for devices -- this requred rearranging the intialisation of the serial device, to ensure that the lowest address uart got serial 0, so qemu -nographic would work as expected. * Hans Jiang and Alex Clench (original patch authors) have left OK-Labs, so the Signed-Off-By: line is changed to their boss who has given permission for release. * EPIT now honours prescaler and clocksource fields. * I *think* all previous comments have been addressed: -- now all files under GPL 2.0 or later -- better emulation of which fields in which registers are read-only -- AVIC implements priorities. Still to do: Clock module support --- assumes 50MHz ipg_clk clock source and prescaler etc., for the general purpose timer UART is very bare-bones -- ignores baud rate, and implements only a one character FIFO -- Dr Peter Chubb peter.chubb AT nicta.com.au http://www.ssrg.nicta.com.au Software Systems Research Group/NICTA
[Qemu-devel] [patch V4 2/4] FreeSCALE i.MX31 support: Timers
Implement the timers on the FreeScale i.MX31 SoC. This is not a complete implementation, but gives enough for Linux to boot and run. In particular external triggers, which are not useful under QEMU, are not implemented. Signed-off-by: Philip O'Sullivan Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx_timer.c | 575 2 files changed, 576 insertions(+), 1 deletion(-) create mode 100644 hw/imx_timer.c Index: qemu-working/hw/imx_timer.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_timer.c 2012-03-09 14:13:51.406084465 +1100 @@ -0,0 +1,575 @@ +/* + * IMX31 Timer + * + * Copyright (c) 2008 OK Labs + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * Updated by Peter Chubb + * + * This code is licenced under GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#include "hw.h" +#include "qemu-timer.h" +#include "ptimer.h" +#include "sysbus.h" + +//#define DEBUG_TIMER 1 +#ifdef DEBUG_TIMER +# define DPRINTF(fmt, args...) \ + do { printf("imx_timer: " fmt , ##args); } while (0) +#else +# define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_timer: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * GPT : General purpose timer + * + * This timer counts up continuously while it is enabled, resetting itself + * to 0 after it reaches TIMER_MAX (in freerun mode) or when it + * reaches the value of ocr1 (in periodic mode). Unfortunately, the + * Qemu ptimer abstraction doesn't have a mode like this, so the code + * uses Qemu timers directly. + * + * The code emulates a free-running timer by using Qemu's nanosecond + * clock, suitably scaled, using the remainder after dividing by the + * timer's period. In the real hardware, there are three comparison + * registers that can trigger interrupts, and compare channel 1 can be + * used to force-reset the timer. However, this is a `bare-bones' + * implementation: only what Linux 3.0.x uses has been implemented + * (free-running timer from 0 to OCR1 or TIMER_MAX) Likewise, only a + * single frequency is implemented, rather than all the complicated + * clock-source and prescaling logic that the real hardware implements + * (most of which doesn't make sense on Qemu) + */ + +#define TIMER_MAX 0XULL +#define GPT_FREQ 5000/* Hz == 50 MHz */ + +/* Control register. Not all of these bits have any effect (yet) */ +#define GPT_CR_EN (1 << 0) /* GPT Enable */ +#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */ +#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ +#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ +#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ +#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ +#define GPT_CR_CLKSRC (7 << 6) /* Clock source select (3 bits) */ +#define GPT_CR_FRR(1 << 9) /* Freerun or Restart */ +#define GPT_CR_SWR(1 << 15) /* Software Reset */ +#define GPT_CR_IM1(3 << 16) /* Input capture channel 1 mode (2 bits) */ +#define GPT_CR_IM2(3 << 18) /* Input capture channel 2 mode (2 bits) */ +#define GPT_CR_OM1(7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ +#define GPT_CR_OM2(7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ +#define GPT_CR_OM3(7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ +#define GPT_CR_FO1(1 << 29) /* Force Output Compare Channel 1 */ +#define GPT_CR_FO2(1 << 30) /* Force Output Compare Channel 2 */ +#define GPT_CR_FO3(1 << 31) /* Force Output Compare Channel 3 */ + +#define GPT_SR_OF1 (1 << 0) +#define GPT_SR_ROV (1 << 5) + +#define GPT_IR_OF1IE (1 << 0) +#define GPT_IR_ROVIE (1 << 5) + +typedef struct { +SysBusDevice busdev; +QEMUTimer *timer; +MemoryRegion iomem; +uint32_t cr; +uint32_t pr; +uint32_t sr; +uint32_t ir; +uint32_t ocr1; +uint32_t cnt; + +uint32_t waiting_rov; +qemu_irq irq; +} imx_timerg_state; + +static const VMStateDescription vmstate_imx_timerg = { +.name = "imx-timerg", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(cr, imx_timerg_state), +VMSTATE_UINT32(pr, imx_timerg_state), +VMSTATE_UINT32(sr, imx_timerg_state), +VMSTATE_UIN
Re: [Qemu-devel] [PATCH V3 3/4] Implement the FreeSCALE i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.0.x
>>>>> "Peter" == Peter Maydell writes: Peter> On 30 November 2011 03:36, Peter Chubb Peter> wrote: >> Signed-off-by: Hans Jang Signed-off-by: Adam >> Clench Signed-off-by: Peter Chubb >> >> --- >> Makefile.target | 2 hw/imx_avic.c | 378 >> 2 files >> changed, 379 insertions(+), 1 deletion(-) create mode 100644 >> hw/imx_avic.c >> >> Index: qemu-working/hw/imx_avic.c >> === >> --- /dev/null 1970-01-01 00:00:00.0 + +++ >> qemu-working/hw/imx_avic.c 2011-11-30 13:38:27.070791665 +1100 @@ >> -0,0 +1,378 @@ +/* + * IMX31 Vectored Interrupt Controller + * + * >> Note this is NOT the PL192 provided by ARM, but + * a custom >> implementation by FreeScale. + * + * Copyright (c) 2008 OKL + * >> Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans >> Jiang + * + * This code is licenced under the GPL version 2 or >> later. See + * the COPYING file in the top-level directory. + * + >> * TODO: implement vectors and priorities. Peter> Vectors are harder (they require support from the target-arm Peter> core implementation which isn't there) but I think you should Peter> implement priorities. That should be purely internal to this Peter> device, and it would be good not to have yet another interrupt Peter> controller in the tree which doesn't get interrupt priorities Peter> right (the NVIC being our other). OK, I've implemented them, but have no way to test them (because Linux doesn't use them!) Peter C
Re: [Qemu-devel] [PATCH V3 1/4] Implement the FreeScale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the FreeScale i.MX series.
>>>>> "Peter" == Peter Maydell writes: Peter> On 30 November 2011 03:36, Peter Chubb Peter> wrote: Commit messages should be Peter> formatted with a short summary line, then a blank line, then a Peter> more detailed description. You've put everything into one Peter> extremely long summary line here, which looks odd in git Peter> log. Try: Thanks I've fixed that now. >> top-level directory. Peter> Still GPL v2 only. Fixed. >> + uint32_t ubrm; Peter> The MCIMX31RM calls this UBMR, not UBRM... Fixed. Peter> My copy of the MCIMX31RM says we also set RXDS on reset. Fixed. >> + s->usr2 = USR2_TXFE | USR2_TXDC; Peter> Presumably we don't set DCDIN here because we haven't Peter> implemented the modem control signals yet? Exactly. But there's no harm in setting it, so I've added it in. >> + s->uts1 = UTS1_RXEMPTY | UTS1_TXEMPTY; + s->ubrm = 0; + >> s->ubrc = 0; Peter> RM says the reset value for UBRC is 0x4. OK. Peter> You also need to reset s->ucr1. (If you want to retain that Peter> hack in the init function then you still need to reset the Peter> other bits even if you don't allow reset to clear UARTEN.) OK. Fixed. >> + s->readbuff = 0; >> + imx_update(s); Peter> This will call qemu_set_irq() which is a bad idea in a reset Peter> function. Don't call imx_update() here, instead call it after Peter> calling imx_serial_reset() from your register write function. Does the infrastructure guarantee that any interrupt will be cleared when the reset function is called? >> + case 0x21: /* UCR2 */ >> + return 1; /* reset complete */ Peter> UCR2_SRST. Fixed. >> case 0x20: /* UCR1 */ >> + s->ucr1 = value; Peter> RM says the top 16 bits of UCR1 are read-only. Fixed. Peter> This doesn't implement writing to any of the other bits of Peter> UCR2. No, apart from the TXEN and RXEN bits they're all to do with >> + case 0x26: /* USR2 */ >> + /* >> + * Writing 1 to some bits clears them; all other >> + * values are ignored >> + */ >> + value &= (1<<15) | (1<<13) | (1<<12) | (1<<11) | (1<<10)| >> + (1<<8) | (1<<7) | (1<<6) | (1<<4) | (1<<2) | (1<<1); Peter> define and use USR2_FOO named constants. Done. >> UCR3 */ + case 0x23: /* UCR4 */ + case 0x24: /* UFCR */ + >> case 0x25: /* USR1 */ + case 0x2c: /* BIPR1 */ + /* TODO >> */ Peter> No IPRINTF() ? This one gets hit too often. >> + .qdev.size = sizeof (imx_state), Peter> Unnecessary space (and checkpatch will complain). I disagree -- there should be a space between the sizeof operator and the cast that is its operand. sizeof is not a function; and the parentheses in this case are part of its operand. I couldn't find any mention of sizeof in the Coding Style document. However, I'll go with whatever makes you happier (but note that the current qemu source mixes sizeof (type) and sizeof(type) all over the place). Look out for a new patch series real soon now... Peter C -- 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
Re: [Qemu-devel] [PATCH V3 1/4] Implement the FreeScale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the FreeScale i.MX series.
>>>>> "Peter" == Peter Maydell writes: Peter> On 1 December 2011 16:55, Peter Maydell Peter> wrote: >> On 30 November 2011 03:36, Peter Chubb >> wrote: >>> Signed-off-by: Hans Jang Peter> Is this email address correct? Trying to send this email got Peter> me: 550 550 ... User not known (state 17). He's left the company and noone knows where he is :-( Peter> -- PMM -- Dr Peter Chubb peter DOT chubb AT nicta.com.au http://www.ertos.nicta.com.au ERTOS within National ICT Australia All things shall perish from under the sky/Music alone shall live, never to die
Re: [Qemu-devel] [PATCH V3 0/4] i.MX31 and KZM board support
>>>>> "Stefan" == Stefan Weil writes: Stefan> Am 30.11.2011 04:36, schrieb Peter Chubb: >> Changes since last patchset: * All files now under GPL version 2 or >> later (I've talked with OK-Labs and they've agreed). Stefan> hw/imx_serial.c is still GPL 2 only. I did not review the Stefan> rest. Missed one, sorry. >> * `DPRINTF' like macro for printing out guest kernel and qemu >> implementation errors * Fixed bugs in avic implementation, as found >> by PMM * Use a static initialiser and sysbus_register_withprop() >> instead of calls to sysbus_register() adn vmstate_register() * >> Fixed bugs in imx_timer.c as noted by PMM and Andreas Stefan> Could you please use 'git send-email' to send the patches? Stefan> Patches which are appended to a mail make review and answering Stefan> difficult. I used quilt mail --send Peter C -- 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
[Qemu-devel] [PATCH V3 1/4] Implement the FreeScale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the FreeScale i.MX series.
Signed-off-by: Hans Jang Signed-off-by: Adam Clench Signed-off-by: Peter Chubb --- Makefile.target |1 hw/imx_serial.c | 320 2 files changed, 321 insertions(+) create mode 100644 hw/imx_serial.c Index: qemu-working/hw/imx_serial.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_serial.c2011-11-30 13:38:24.434778115 +1100 @@ -0,0 +1,320 @@ +/* + * IMX31 UARTS + * + * Copyright (c) 2008 OKL + * Originally Written by Hans Jiang + * Copyright (c) 2011 NICTA Pty Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * This is a `bare-bones' implementation of the IMX series serial ports. + * TODO: + * -- implement FIFOs. The real hardware has 32 word transmit + * and receive FIFOs; we currently use a 1-char buffer + * -- implement DMA + * -- implement BAUD-rate and modem lines, for when the backend + * is a real serial device. + */ + +#include "hw.h" +#include "sysbus.h" +#include "qemu-char.h" + +//#define DEBUG_SERIAL 1 + +#ifdef DEBUG_SERIAL +#define DPRINTF(fmt, args...) \ +do { printf("imx_serial: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +int32_t readbuff; + +uint32_t usr1; +uint32_t usr2; +uint32_t ucr1; +uint32_t uts1; + +uint32_t ubrm; +uint32_t ubrc; + +qemu_irq irq; +CharDriverState *chr; +} imx_state; + +static const VMStateDescription vmstate_imx_serial = { +.name = "imx-serial", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_INT32(readbuff, imx_state), +VMSTATE_UINT32(usr1, imx_state), +VMSTATE_UINT32(usr2, imx_state), +VMSTATE_UINT32(ucr1, imx_state), +VMSTATE_UINT32(uts1, imx_state), +VMSTATE_UINT32(ubrm, imx_state), +VMSTATE_UINT32(ubrc, imx_state), +VMSTATE_END_OF_LIST() +}, +}; + + +#define URXD_CHARRDY(1<<15) /* character read is valid */ + +#define USR1_TRDY (1<<13) /* Xmitter ready */ +#define USR1_RRDY (1<<9)/* receiver ready */ + +#define USR2_TXFE (1<<14) /* Transmit FIFO empty */ +#define USR2_TXDC (1<<3)/* Transmission complete */ +#define USR2_RDR(1<<0)/* Receive data ready */ + +#define UCR1_TRDYEN (1<<13) +#define UCR1_RRDYEN (1<<9) +#define UCR1_TXMPTYEN (1<<6) +#define UCR1_UARTEN (1<<0) + +#define UTS1_TXEMPTY(1<<6) +#define UTS1_RXEMPTY(1<<5) +#define UTS1_TXFULL (1<<4) +#define UTS1_RXFULL (1<<3) + +static void imx_update(imx_state *s) +{ +uint32_t flags; + +flags = ((s->usr1 & s->ucr1)) & (USR1_TRDY|USR1_RRDY); +if (!(s->ucr1 & UCR1_TXMPTYEN)) { +flags &= ~USR1_TRDY; +} + +if (flags) { +DPRINTF("imx_serial: raising interrupt\n"); +} + +qemu_set_irq(s->irq, !!flags); +} + +static void imx_serial_reset(DeviceState *dev) +{ +imx_state *s = container_of(dev, imx_state, busdev.qdev); + +s->usr1 = USR1_TRDY; +s->usr2 = USR2_TXFE | USR2_TXDC; +s->uts1 = UTS1_RXEMPTY | UTS1_TXEMPTY; +s->ubrm = 0; +s->ubrc = 0; +s->readbuff = 0; + +imx_update(s); +} + +static uint64_t imx_serial_read(void *opaque, target_phys_addr_t offset, +unsigned size) +{ +imx_state *s = (imx_state *)opaque; +uint32_t c; + +DPRINTF("read(offset=%x)\n", offset >> 2); +switch (offset >> 2) { +case 0x0: /* URXD */ +c = s->readbuff; +if (!(s->uts1 & UTS1_RXEMPTY)) { +/* Character is valid */ +c |= URXD_CHARRDY; +s->usr1 &= ~USR1_RRDY; +s->usr2 &= ~USR2_RDR; +s->uts1 |= UTS1_RXEMPTY; +imx_update(s); +qemu_chr_accept_input(s->chr); +} +return c; + +case 0x20: /* UCR1 */ +return s->ucr1; + +case 0x21: /* UCR2 */ +return 1; /* reset complete */ + +case 0x25: /* USR1 */ +return s->usr1; + +case 0x26: /* USR2 */ +return s->usr2; + +case 0x2A: /* BRM Modulator */ +return s-
[Qemu-devel] [PATCH V3 2/4] Implement the timers on the FreeScale i.MX31 SoC. This is not a complete implementation, but gives enough for Linux to boot and run.
Signed-off-by: Hans Jang Signed-off-by: Adam Clench Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx_timer.c | 460 2 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 hw/imx_timer.c Index: qemu-working/hw/imx_timer.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_timer.c 2011-11-30 13:38:25.818785258 +1100 @@ -0,0 +1,460 @@ +/* + * IMX31 Timer + * + * Copyright (c) 2008 OKL + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * Updated by Peter Chubb + * + * This code is licenced under GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#include "hw.h" +#include "qemu-timer.h" +#include "sysbus.h" + +//#define DEBUG_TIMER 1 + +#ifdef DEBUG_TIMER +# define DPRINTF(fmt, args...) \ +do { printf("imx_timer: " fmt , ##args); } while (0) +#else +# define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_timer: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * GPT : General purpose timer + */ + +#define TIMER_MAX 0xUL +#define GPT_FREQ 5000/* Hz == 50 MHz */ + +/* Control register. Not all of these bits have any effect (yet) */ +#define GPT_CR_EN (1 << 0)/* GPT Enable */ +#define GPT_CR_ENMODE (1 << 1) /* GPT Enable Mode */ +#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ +#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ +#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ +#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ +#define GPT_CR_CLKSRC (7 << 6) /* Clock source select (3 bits) */ +#define GPT_CR_FRR (1 << 9)/* Freerun or Restart */ +#define GPT_CR_SWR (1 << 15) +#define GPT_CR_IM1 (3 << 16) /* Input capture channel 1 mode (2 bits) */ +#define GPT_CR_IM2 (3 << 18) /* Input capture channel 2 mode (2 bits) */ +#define GPT_CR_OM1 (7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ +#define GPT_CR_OM2 (7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ +#define GPT_CR_OM3 (7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ +#define GPT_CR_FO1 (1 << 29) /* Force Output Compare Channel 1 */ +#define GPT_CR_FO2 (1 << 30) /* Force Output Compare Channel 2 */ +#define GPT_CR_FO3 (1 << 31) /* Force Output Compare Channel 3 */ + +#define GPT_SR_OF1 (1 << 0) +#define GPT_SR_ROV (1 << 5) + +#define GPT_IR_OF1IE (1 << 0) +#define GPT_IR_ROVIE (1 << 5) + +typedef struct { +SysBusDevice busdev; +QEMUTimer *timer; +MemoryRegion iomem; +uint32_t cr; +uint32_t sr; +uint32_t pr; +uint32_t ir; +uint32_t ocr1; +uint32_t cnt; + +int waiting_rov; +qemu_irq irq; +} imxg_timer_state; + +static const VMStateDescription vmstate_imxg_timer = { +.name = "imxg-timer", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(cr, imxg_timer_state), +VMSTATE_UINT32(sr, imxg_timer_state), +VMSTATE_UINT32(ir, imxg_timer_state), +VMSTATE_UINT32(cnt, imxg_timer_state), +VMSTATE_UINT32(ocr1, imxg_timer_state), +VMSTATE_TIMER(timer, imxg_timer_state), +VMSTATE_END_OF_LIST() +} +}; + + +/* Check all active timers, and schedule the next timer interrupt. */ +static void imxg_timer_update(imxg_timer_state *s) +{ +uint32_t flags = s->sr & s->ir & (GPT_SR_OF1 | GPT_SR_ROV); + +if ((s->cr & GPT_CR_EN) && flags) { +qemu_irq_raise(s->irq); +} else { +qemu_irq_lower(s->irq); +} +} + +static uint64_t imxg_timer_update_count(imxg_timer_state *s) +{ +uint64_t clk = qemu_get_clock_ns(vm_clock); + +s->cnt = ((uint32_t)muldiv64(clk, GPT_FREQ/100, + 1000)) % TIMER_MAX; +return clk; +} + +static void imxg_timer_run(imxg_timer_state *s, uint32_t timeout) +{ +uint64_t clk = imxg_timer_update_count(s); +uint32_t diff_cnt; +if (s->cnt < timeout) { +diff_cnt = (timeout - s->cnt); +s->waiting_rov = 0; +} else { +diff_cnt = (TIMER_MAX - s->cnt); +s->waiting_rov = 1; +} +qemu_mod_timer(s->timer, clk + diff_cnt * 1000 / (GPT_FREQ/100)); +} + +static uint64_t imxg_timer_read(void *opaque, target_phys_addr_t offset, +unsigned size) +{
[Qemu-devel] [PATCH V3 3/4] Implement the FreeSCALE i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.0.x
Signed-off-by: Hans Jang Signed-off-by: Adam Clench Signed-off-by: Peter Chubb --- Makefile.target |2 hw/imx_avic.c | 378 2 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 hw/imx_avic.c Index: qemu-working/hw/imx_avic.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_avic.c 2011-11-30 13:38:27.070791665 +1100 @@ -0,0 +1,378 @@ +/* + * IMX31 Vectored Interrupt Controller + * + * Note this is NOT the PL192 provided by ARM, but + * a custom implementation by FreeScale. + * + * Copyright (c) 2008 OKL + * Copyright (c) 2011 NICTA Pty Ltd + * Originally Written by Hans Jiang + * + * This code is licenced under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + * + * TODO: implement vectors and priorities. + */ + +#include "hw.h" +#include "sysbus.h" +#include "host-utils.h" + +#define DEBUG_INT 1 +#undef DEBUG_INT /* comment out for debugging */ + +#ifdef DEBUG_INT +#define DPRINTF(fmt, args...) \ +do { printf("imx_avic: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Define to 1 for messages about attempts to + * access unimplemented registers or similar. + */ +#define DEBUG_IMPLEMENTATION 1 +#if DEBUG_IMPLEMENTATION +# define IPRINTF(fmt, args...) \ +do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0) +#else +# define IPRINTF(fmt, args...) do {} while (0) +#endif + +#define IMX_INT_NUM_IRQS 64 + +/* Interrupt Control Bits */ +#define ABFLAG (1<<25) +#define ABFEN (1<<24) +#define NIDIS (1<<22) /* Normal Interrupt disable */ +#define FIDIS (1<<21) /* Fast interrupt disable */ +#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ +#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ +#define NM(1<<18) /* Normal interrupt mode */ + + +#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4) +#define PRIO_WORDS (IMX_INT_NUM_IRQS/PRIO_PER_WORD) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +uint64_t pending; +uint64_t enabled; +uint64_t is_fiq; +uint32_t intcntl; +uint32_t intmask; +qemu_irq irq; +qemu_irq fiq; +uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ +} imx_int_state; + +static const VMStateDescription vmstate_imx_avic = { +.name = "imx-avic", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT64(pending, imx_int_state), +VMSTATE_UINT64(enabled, imx_int_state), +VMSTATE_UINT64(is_fiq, imx_int_state), +VMSTATE_UINT32(intcntl, imx_int_state), +VMSTATE_UINT32(intmask, imx_int_state), +VMSTATE_UINT32_ARRAY(prio, imx_int_state, PRIO_WORDS), +VMSTATE_END_OF_LIST() +}, +}; + + + +static inline int imx_int_prio(imx_int_state *s, int irq) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +return 0xf & (s->prio[word] >> part); +} + +static inline void imx_int_set_prio(imx_int_state *s, int irq, int prio) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +uint32_t mask = ~(0xf << part); +s->prio[word] &= mask; +s->prio[word] |= prio << part; +} + +/* Update interrupts. */ +static void imx_int_update(imx_int_state *s) +{ +int i; +uint64_t new = s->pending; +uint64_t flags; + +flags = new & s->enabled & s->is_fiq; +qemu_set_irq(s->fiq, !!flags); + +flags = new & s->enabled & ~s->is_fiq; +if (!flags || (s->intmask == 0x1f)) { +qemu_set_irq(s->irq, !!flags); +return; +} + +/* + * Take interrupt if prio lower than the value of intmask + * (should really take highest priority interrupt here, + * but that would involve processing interrupt sources + * in priority order) + */ +for (i = 0; i < IMX_INT_NUM_IRQS; i++) { +if (flags & (1UL << i)) { +if (imx_int_prio(s, i) > s->intmask) { +qemu_set_irq(s->irq, 1); +return; +} +} +} +qemu_set_irq(s->irq, 0); +} + +static void imx_int_set_irq(void *opaque, int irq, int level) +{ +imx_int_state *s = (imx_int_state *)opaque; + +if (level) { +s->pending |= (1ULL << irq); +} else { +s->pending &= ~(1ULL << irq); +} + +imx_int_update(s); +} + + +static uint64_t imx_int_read(void *opaque, + target_phys_addr_t offset, unsigned size) +{ +imx_int_state *s = (imx_int_state *)opaque; + + +DPRINTF("read(offset = 0x%x)\n
[Qemu-devel] [PATCH V3 4/4] Board support for Kyoto Micros KZM-ARM11-01, an evaluation board built around the FreeScale i.MX31.
Signed-off-by: Hans Jang Signed-off-by: Adam Clench Signed-off-by: Peter Chubb --- Makefile.target |1 hw/kzm.c| 155 2 files changed, 156 insertions(+) create mode 100644 hw/kzm.c Index: qemu-working/hw/kzm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/kzm.c 2011-11-30 13:38:28.210797633 +1100 @@ -0,0 +1,155 @@ +/* + * KZM Board System emulation. + * + * Copyright (c) 2008 OKL and 2011 NICTA + * Written by Hans + * Updated by Peter Chubb. + * + * This code is licenced under the GPL, version 2 or later. + * + * It (partially) emulates a Kyoto Microcomputer + * KZM-ARM11-01 evaluation board, with a FreeScale + * I.MX31 SoC + */ + +#include "sysbus.h" +#include "exec-memory.h" +#include "hw.h" +#include "arm-misc.h" +#include "primecell.h" +#include "devices.h" +#include "pci.h" +#include "net.h" +#include "sysemu.h" +#include "boards.h" +#include "pc.h" /* for the FPGA UART that emulates a 16550 */ + +/* Memory map for Kzm Emulation Baseboard: + * 0x-0x3fff 16k secure ROM IGNORED + * 0x4000-0x00407fff Reserved IGNORED + * 0x00404000-0x00407fff ROM IGNORED + * 0x00408000-0x0fff Reserved IGNORED + * 0x1000-0x1fffBfff RAM aliasing IGNORED + * 0x1fffc000-0x1fff RAM EMULATED + * 0x2000-0x2fff Reserved IGNORED + * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x43f0 IO_AREA0 + * 0x43f9 UART1 EMULATED + * 0x43f94000 UART2 EMULATED + * 0x6800 PIC EMULATED + * 0x53f94000 PIT 1 EMULATED + * 0x53f98000 PIT 2 EMULATED + * 0x53f9 GPT EMULATED + * 0x8000-0x87ff RAM EMULATED + * 0x8800-0x8fff RAM Aliasing EMULATED + * 0xa000-0xafff NAND Flash IGNORED + * 0xb000-0xb3ff Unavailable IGNORED + * 0xb400-0xb4000fff 8-bit free space IGNORED + * 0xb4001000-0xb400100f Board controlIGNORED + * 0xb4001003 DIP switch + * 0xb4001010-0xb400101f 7-segment LEDIGNORED + * 0xb4001020-0xb400102f LED IGNORED + * 0xb4001030-0xb400103f LED IGNORED + * 0xb4001040-0xb400104f FPGA, UART EMULATED + * 0xb4001050-0xb400105f FPGA, UART EMULATED + * 0xb4001060-0xb40f FPGA IGNORED + * 0xb600-0xb61f LAN controller EMULATED + * 0xb620-0xb62f FPGA NAND Controller IGNORED + * 0xb630-0xb7ff Free IGNORED + * 0xb800-0xb8004fff Memory control registers IGNORED + * 0xc000-0xc3ff PCMCIA/CFIGNORED + * 0xc400-0x Reserved IGNORED + */ + +#define KZM_RAMADDRESS (0x8000) +#define KZM_FPGA (0xb4001040) + +static struct arm_boot_info kzm_binfo = { +.loader_start = KZM_RAMADDRESS, +.board_id = 1722, +}; + +static void kzm_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +CPUState *env; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *ram_alias = g_new(MemoryRegion, 1); +qemu_irq *cpu_pic; +DeviceState *dev; + +if (!cpu_model) { +cpu_model = "arm1136"; +} + +env = cpu_init(cpu_model); +if (!env) { +fprintf(stderr, "Unable to find CPU definition\n"); +exit(1); +} + +/* On a real system, the first 16k is a `secure boot rom' */ + +memory_region_init_ram(ram, NULL, "kzm.ram", ram_size); +memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram); + +memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); +memory_region_add_subregion(address_space_mem, 0x8800, ram_alias); + +memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000); +memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram); + + +cpu_pic = arm_pic_init_cpu(env); +dev = sysbus_create_varargs("imx_int", 0x6800, + cpu_pic[ARM_PIC_CPU_IRQ], + cpu_pic[ARM_PIC_CPU_FIQ], NULL); + + +sysbus_create_simple("imx_serial", 0x43f9,
[Qemu-devel] [PATCH V3 0/4] i.MX31 and KZM board support
Changes since last patchset: * All files now under GPL version 2 or later (I've talked with OK-Labs and they've agreed). * `DPRINTF' like macro for printing out guest kernel and qemu implementation errors * Fixed bugs in avic implementation, as found by PMM * Use a static initialiser and sysbus_register_withprop() instead of calls to sysbus_register() adn vmstate_register() * Fixed bugs in imx_timer.c as noted by PMM and Andreas -- 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
Re: [Qemu-devel] [PATCH V2 0/4] imx.31 and KZM board support
>>>>> "Andreas" == Andreas Färber writes: Andreas> Am 23.11.2011 01:51, schrieb Peter Chubb: >>>>>>> "Peter" == Peter Chubb writes: >> >> Peter> All comments received so far have been addressed --- I've added Peter> a macro, `scream' that gives at most 10 lines of output for OS Peter> error reporting. >> >> Except I noticed a thinko in the macro. The decrement should be >> inside the guard, thus: >> >> #define scream(fmt, args...) \ do { \ static int printable = 10;\ >> if (printable) { \ printable--;\ fprintf(stderr, fmt, ##args); \ } >> \ } while (0) Andreas> Another issue: Andreas> scream("black"); scream("black"); scream("black"); Andreas> scream("black"); scream("black"); scream("black"); Andreas> scream("black"); scream("black"); scream("black"); Andreas> scream("black"); scream("red"); Andreas> To show us "red", in addition to the integer count a Andreas> duplicate of the string contents would need to be stored and Andreas> compared to the newly formatted string. No, because it's a macro. Each time it appears the static count is instantiated--- so there's a count for each call site. Andreas> If we want to do this, it should go into a central file so Andreas> that it can be reused and centrally maintained. Agree -- but do we want to do this? For this patch series, Peter M says to just use hw_error() (even though he really doesn't like it). Peter C
[Qemu-devel] Who maintains checkpatch.pl now?
Who maintainss checkpatch.pl now? checkpatch.pl says to look for CHECKPATCH in the MAINTAINERS file, but that entry isn't there. The issue I'm encountering is that sizeof is not a function, but an operator, that takes as its operand either a variable or a cast. As such there needn't be any parentheses (if the operand is a variable), and there should a space before the cast. In the QEMU code at present, the use of whitespace around sizeof varies from file to file; checkpatch.pl complains about sizeof (struct foo) WARNING: space prohibited between function name and open parenthesis '(' If I fix the problem as in the appended patch, I start seeing other complaints: ERROR: space prohibited after that '*' (ctx:WxW) +#define PRIO_PER_WORD (sizeof (uint32_t) * 8 / 4) ^ Index: qemu-working/scripts/checkpatch.pl === --- qemu-working.orig/scripts/checkpatch.pl 2011-11-10 10:16:43.215022488 +1100 +++ qemu-working/scripts/checkpatch.pl 2011-11-25 14:02:30.908358997 +1100 @@ -1953,21 +1953,21 @@ sub process { } # check for spaces between functions and their parentheses. while ($line =~ /($Ident)\s+\(/g) { my $name = $1; my $ctx_before = substr($line, 0, $-[1]); my $ctx = "$ctx_before$name"; # Ignore those directives where spaces _are_ permitted. if ($name =~ /^(?: - if|for|while|switch|return|case| + if|for|while|switch|return|case|sizeof| volatile|__volatile__| __attribute__|format|__extension__| asm|__asm__)$/x) { # cpp #define statements have non-optional spaces, ie # if there is a space between the name and the open # parenthesis it is simply not a parameter group. } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) { -- 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
Re: [Qemu-devel] [PATCH V2 1/4] imx.31 and KZM board support: UART support
Thanks Peter, I've fixed the problems you noted, and have asked the OK-Labs folks about Licencing. When I hear back from them I'll roll a new patchset --- I don't expect `GPL v2 or later' to be a problem. -- Peter C -- 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
Re: [Qemu-devel] [PATCH V2 0/4] imx.31 and KZM board support
>>>>> "Peter" == Peter Chubb writes: Peter> All comments received so far have been addressed --- I've added Peter> a macro, `scream' that gives at most 10 lines of output for OS Peter> error reporting. Except I noticed a thinko in the macro. The decrement should be inside the guard, thus: #define scream(fmt, args...) \ do { \ static int printable = 10;\ if (printable) { \ printable--;\ fprintf(stderr, fmt, ##args); \ } \ } while (0) -- 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
Re: [Qemu-devel] [PATCH] imx.31 and KZM board support
>>>>> "Juan" == Juan Quintela writes: Juan> Peter Chubb wrote: Juan> This is not used. Shouldn't a call like this be needed? Juan>vmstate_register(&dev->qdev, -1, &vmstate_imxg_timer, s); Juan> ??? Yes!! Thanks for checking. I've altered the source ready for the next rollout of patches, which will be version 3. -- 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
Re: [Qemu-devel] [PATCH V2 4/4] imx.31 and KZM board support: Makefile and board
Board support for Kyoto Micro's KZM-ARM11-01, an evaluation board built around the FreeScale i.MX31. Signed-off-by: Hans Jang Signed-off-by: Adam Clench Signed-off-by: Peter Chubb --- Makefile.target |2 hw/kzm.c| 155 2 files changed, 157 insertions(+) create mode 100644 hw/kzm.c Index: qemu-working/hw/kzm.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/kzm.c 2011-11-22 14:47:11.358042471 +1100 @@ -0,0 +1,155 @@ +/* + * KZM Board System emulation. + * + * Copyright (c) 2008 OKL and 2011 NICTA + * Written by Hans + * Updated by Peter Chubb. + * + * This code is licenced under the GPL, version 2 or later. + * + * It (partially) emulates a Kyoto Microcomputer + * KZM-ARM11-01 evaluation board, with a FreeScale + * I.MX31 SoC + */ + +#include "sysbus.h" +#include "exec-memory.h" +#include "hw.h" +#include "arm-misc.h" +#include "primecell.h" +#include "devices.h" +#include "pci.h" +#include "net.h" +#include "sysemu.h" +#include "boards.h" +#include "pc.h" /* for the FPGA UART that emulates a 16550 */ + +/* Memory map for Kzm Emulation Baseboard: + * 0x-0x3fff 16k secure ROM IGNORED + * 0x4000-0x00407fff Reserved IGNORED + * 0x00404000-0x00407fff ROM IGNORED + * 0x00408000-0x0fff Reserved IGNORED + * 0x1000-0x1fffBfff RAM aliasing IGNORED + * 0x1fffc000-0x1fff RAM EMULATED + * 0x2000-0x2fff Reserved IGNORED + * 0x3000-0x7fff I.MX31 Internal Register Space + * 0x43f0 IO_AREA0 + * 0x43f9 UART1 EMULATED + * 0x43f94000 UART2 EMULATED + * 0x6800 PIC EMULATED + * 0x53f94000 PIT 1 EMULATED + * 0x53f98000 PIT 2 EMULATED + * 0x53f9 GPT EMULATED + * 0x8000-0x87ff RAM EMULATED + * 0x8800-0x8fff RAM Aliasing EMULATED + * 0xa000-0xafff NAND Flash IGNORED + * 0xb000-0xb3ff Unavailable IGNORED + * 0xb400-0xb4000fff 8-bit free space IGNORED + * 0xb4001000-0xb400100f Board controlIGNORED + * 0xb4001003 DIP switch + * 0xb4001010-0xb400101f 7-segment LEDIGNORED + * 0xb4001020-0xb400102f LED IGNORED + * 0xb4001030-0xb400103f LED IGNORED + * 0xb4001040-0xb400104f FPGA, UART EMULATED + * 0xb4001050-0xb400105f FPGA, UART EMULATED + * 0xb4001060-0xb40f FPGA IGNORED + * 0xb600-0xb61f LAN controller EMULATED + * 0xb620-0xb62f FPGA NAND Controller IGNORED + * 0xb630-0xb7ff Free IGNORED + * 0xb800-0xb8004fff Memory control registers IGNORED + * 0xc000-0xc3ff PCMCIA/CFIGNORED + * 0xc400-0x Reserved IGNORED + */ + +#define KZM_RAMADDRESS (0x8000) +#define KZM_FPGA (0xb4001040) + +static struct arm_boot_info kzm_binfo = { +.loader_start = KZM_RAMADDRESS, +.board_id = 1722, +}; + +static void kzm_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +CPUState *env; +MemoryRegion *address_space_mem = get_system_memory(); +MemoryRegion *ram = g_new(MemoryRegion, 1); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *ram_alias = g_new(MemoryRegion, 1); +qemu_irq *cpu_pic; +DeviceState *dev; + +if (!cpu_model) { +cpu_model = "arm1136"; +} + +env = cpu_init(cpu_model); +if (!env) { +fprintf(stderr, "Unable to find CPU definition\n"); +exit(1); +} + +/* On a real system, the first 16k is a `secure boot rom' */ + +memory_region_init_ram(ram, NULL, "kzm.ram", ram_size); +memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram); + +memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); +memory_region_add_subregion(address_space_mem, 0x8800, ram_alias); + +memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000); +memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram); + + +cpu_pic = arm_pic_init_cpu(env); +dev = sysbus_create_varargs("imx_int", 0x6800, + cpu_pic[ARM_PIC_CPU_IRQ], +
Re: [Qemu-devel] [PATCH V2 3/4] imx.31 and KZM board support: interrupt controller
Implement the FreeSCALE i.MX31 advanced vectored interrupt controller, at least to the extent it is used by Linux 3.0.x Signed-off-by: Hans Jang Signed-off-by: Adam Clench Signed-off-by: Peter Chubb --- hw/imx_avic.c | 363 ++ 1 file changed, 363 insertions(+) create mode 100644 hw/imx_avic.c Index: qemu-working/hw/imx_avic.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_avic.c 2011-11-22 14:47:10.706040936 +1100 @@ -0,0 +1,363 @@ +/* + * IMX31 Vectored Interrupt Controller + * + * Note this is NOT the PL192 provided by ARM, but + * a custom implementation by FreeScale. + * + * Copyright (c) 2008 OKL + * Written by Hans + * + * This code is licenced under the GPL version 2 or later. + * + * TODO: implement vectors and priorities. + */ + +#include "hw.h" +#include "sysbus.h" +#include /* ffsll */ + +#define DEBUG_INT 1 +#undef DEBUG_INT /* comment out for debugging */ + +#ifdef DEBUG_INT +#define DPRINTF(fmt, args...) \ +do { printf("imx_int: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Print a message at most ten times. + */ +#define scream(fmt, args...) \ +do { \ +static int printable = 10;\ +if (printable--) { \ +fprintf(stderr, fmt, ##args); \ +} \ +} while (0) + + +#define IMX_INT_NUM_IRQS 64 + +/* Interrupt Control Bits */ +#define ABFLAG (1<<25) +#define ABFEN (1<<24) +#define NIDIS (1<<22) /* Normal Interrupt disable */ +#define FIDIS (1<<21) /* Fast interrupt disable */ +#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */ +#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */ +#define NM(1<<18) /* Normal interrupt mode */ + + +#define PRIO_PER_WORD (sizeof (uint32_t) * 8 / 4) +#define PRIO_WORDS (IMX_INT_NUM_IRQS/PRIO_PER_WORD) + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +uint64_t pending; +uint64_t enabled; +uint64_t is_fiq; +uint32_t intcntl; +uint32_t intmask; +qemu_irq irq; +qemu_irq fiq; +uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */ +} imx_int_state; + +static const VMStateDescription vmstate_imx_avic = { +.name = "imx-avic", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField []) { +VMSTATE_UINT64(pending, imx_int_state), +VMSTATE_UINT64(enabled, imx_int_state), +VMSTATE_UINT64(is_fiq, imx_int_state), +VMSTATE_UINT32(intcntl, imx_int_state), +VMSTATE_UINT32(intmask, imx_int_state), +VMSTATE_UINT32_ARRAY(prio, imx_int_state, PRIO_WORDS), +VMSTATE_END_OF_LIST() +}, +}; + + + +static inline int imx_int_prio(imx_int_state *s, int irq) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +return 0xf & (s->prio[word] >> part); +} + +static inline void imx_int_set_prio(imx_int_state *s, int irq, int prio) +{ +uint32_t word = irq / PRIO_PER_WORD; +uint32_t part = 4 * (irq % PRIO_PER_WORD); +uint32_t mask = ~(0xf << part); +s->prio[word] &= mask; +s->prio[word] |= prio << part; +} + +/* Update interrupts. */ +static void imx_int_update(imx_int_state *s) +{ +int i; +uint64_t new = s->pending; +uint64_t flags; + +flags = new & s->enabled & s->is_fiq; +qemu_set_irq(s->fiq, !!flags); + +flags = new & s->enabled & ~s->is_fiq; +if (!flags || ((s->intmask & 0x1f) == 0x1f)) { +qemu_set_irq(s->irq, !!flags); +return; +} + +/* Take interrupt if prio lower than the value of intmask */ +for (i = 0; i < IMX_INT_NUM_IRQS; i++) { +if (flags & (1UL << i)) { +if (imx_int_prio(s, i) > s->intmask) { +qemu_set_irq(s->irq, 1); +return; +} +} +} + +} + +static void imx_int_set_irq(void *opaque, int irq, int level) +{ +imx_int_state *s = (imx_int_state *)opaque; + +if (level) { +s->pending |= (1ULL << irq); +} else { +s->pending &= ~(1ULL << irq); +} + +imx_int_update(s); +} + + +static uint64_t imx_int_read(void *opaque, + target_phys_addr_t offset, unsigned size) +{ +imx_int_state *s = (imx_int_state *)opaque; + + +DPRINTF("read(offset = 0x%x)\n", offset >> 2); +switch (offset >> 2) { +case 0: /* INTCNTL */ +return s->intcntl; + +case 1: /* Normal Interrupt Mask Register, NIMASK */ +return s->intmask; + +case 2: /* Interrupt Enable Number Register, INTENNUM */ +case 3: /* Interrupt Disable Number Regi
Re: [Qemu-devel] [PATCH V2 2/4] imx.31 and KZM board support: Timer support
Implement the timers on the FreeScale i.MX31 SoC. This is not a complete implementation, but gives enough for Linux to boot and run. Signed-off-by: Hans Jang Signed-off-by: Adam Clench Signed-off-by: Peter Chubb --- hw/imx_timer.c | 441 + 1 file changed, 441 insertions(+) create mode 100644 hw/imx_timer.c Index: qemu-working/hw/imx_timer.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_timer.c 2011-11-22 14:47:10.058038639 +1100 @@ -0,0 +1,441 @@ +/* + * IMX31 Timer + * + * Copyright (c) 2008 OKL + * Written by Hans + * Updated by Peter Chubb + * + * This code is licenced under GPL version 2 or later. + */ + +#include "hw.h" +#include "qemu-timer.h" +#include "sysbus.h" + +//#define DEBUG_TIMER 1 + +#ifdef DEBUG_TIMER +# define DPRINTF(fmt, args...) \ +do { printf("imx_timer: " fmt , ##args); } while (0) +#else +# define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Print a message at most ten times. + */ +#define scream(fmt, args...) \ +do { \ +static int printable = 10;\ +if (printable--) { \ +fprintf(stderr, fmt, ##args);\ +} \ +} while (0) + + +/* + * GPT : General purpose timer + */ + +#define TIMER_MAX 0xUL +#define GPT_FREQ 5000/* Hz == 50 MHz */ + +/* Control register. Not all of these bits have any effect (yet) */ +#define GPT_CR_EN (1 << 0)/* GPT Enable */ +#define GPT_CR_ENMODE (1 << 1) /* GPT Enable Mode */ +#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */ +#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */ +#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */ +#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */ +#define GPT_CR_CLKSRC (7 << 6) /* Clock source select (3 bits) */ +#define GPT_CR_FRR (1 << 9)/* Freerun or Restart */ +#define GPT_CR_SWR (1 << 15) +#define GPT_CR_IM1 (3 << 16) /* Input capture channel 1 mode (2 bits) */ +#define GPT_CR_IM2 (3 << 18) /* Input capture channel 2 mode (2 bits) */ +#define GPT_CR_OM1 (7 << 20) /* Output Compare Channel 1 Mode (3 bits) */ +#define GPT_CR_OM2 (7 << 23) /* Output Compare Channel 2 Mode (3 bits) */ +#define GPT_CR_OM3 (7 << 26) /* Output Compare Channel 3 Mode (3 bits) */ +#define GPT_CR_FO1 (1 << 29) /* Force Output Compare Channel 1 */ +#define GPT_CR_FO2 (1 << 30) /* Force Output Compare Channel 2 */ +#define GPT_CR_FO3 (1 << 31) /* Force Output Compare Channel 3 */ + + + + +#define GPT_SR_OF1 (1 << 0) +#define GPT_SR_ROV (1 << 5) +#define GPT_IR_OF1IE (1 << 0) +#define GPT_IR_ROVIE (1 << 5) + +typedef struct { +SysBusDevice busdev; +QEMUTimer *timer; +MemoryRegion iomem; +uint32_t cr; +uint32_t sr; +uint32_t pr; +uint32_t ir; +uint32_t ocr1; +uint32_t cnt; + +int waiting_rov; +qemu_irq irq; +} imxg_timer_state; + +static const VMStateDescription vmstate_imxg_timer = { +.name = "imxg-timer", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32(cr, imxg_timer_state), +VMSTATE_UINT32(sr, imxg_timer_state), +VMSTATE_UINT32(ir, imxg_timer_state), +VMSTATE_UINT32(cnt, imxg_timer_state), +VMSTATE_UINT32(ocr1, imxg_timer_state), +VMSTATE_TIMER(timer, imxg_timer_state), +VMSTATE_END_OF_LIST() +} +}; + + +/* Check all active timers, and schedule the next timer interrupt. */ +static void imxg_timer_update(imxg_timer_state *s) +{ +/* Update interrupts. */ +if ((s->cr & GPT_CR_EN) +&& (((s->sr & GPT_SR_OF1) && (s->ir & GPT_IR_OF1IE)) || +((s->sr & GPT_SR_ROV) && (s->ir & GPT_IR_ROVIE { +qemu_irq_raise(s->irq); +} else { +qemu_irq_lower(s->irq); +} +} + +static uint64_t imxg_timer_update_count(imxg_timer_state *s) +{ +uint64_t clk = qemu_get_clock_ns(vm_clock); + +s->cnt = ((uint32_t)muldiv64(clk, GPT_FREQ/100, + 1000)) % TIMER_MAX; +return clk; +} + +static void imxg_timer_run(imxg_timer_state *s, uint32_t timeout) +{ +uint64_t clk = imxg_timer_update_count(s); +uint32_t diff_cnt; +if (s->cnt < timeout) { +diff_cnt = (timeout - s->cnt); +s->waiting_rov = 0; +} else { +diff_cnt = (TIMER_MAX - s->cnt); +s->waiting_rov = 1; +} +qemu_mod_timer(s->timer, clk + diff_cnt * 1000 / (GPT_FREQ/100)); +/* + clk + muldiv64(get_ticks_per_sec(), +diff_cnt, GPT_FREQ)
Re: [Qemu-devel] [PATCH V2 1/4] imx.31 and KZM board support: UART support
Implement the FreeScale i.MX UART. This uart is used in a variety of SoCs, including some by Motorola, as well as in the FreeScale i.MX series. Signed-off-by: Hans Jang Signed-off-by: Adam Clench Signed-off-by: Peter Chubb --- hw/imx_serial.c | 307 1 file changed, 307 insertions(+) create mode 100644 hw/imx_serial.c Index: qemu-working/hw/imx_serial.c === --- /dev/null 1970-01-01 00:00:00.0 + +++ qemu-working/hw/imx_serial.c2011-11-22 14:47:09.242035743 +1100 @@ -0,0 +1,307 @@ +/* + * IMX31 UARTS + * + * Copyright (c) 2008 OKL + * Written by Hans + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * This is a `bare-bones' implementation of the IMX series serial ports. + * TODO: + * -- implement FIFOs. The real hardware has 32 word transmit + * and receive FIFOs + * -- implement DMA + * -- implement BAUD-rate and modem lines, for when the backend + * is a real serial device. + */ + +#include "hw.h" +#include "sysbus.h" +#include "qemu-char.h" + +//#define DEBUG_SERIAL 1 + +#ifdef DEBUG_SERIAL +#define DPRINTF(fmt, args...) \ +do { printf("imx_serial: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while (0) +#endif + +/* + * Print a message at most ten times. + */ +#define scream(fmt, args...) \ +do { \ +static int printable = 10;\ +if (printable--) { \ +fprintf(stderr, fmt, ##args); \ +} \ +} while (0) + + +typedef struct { +SysBusDevice busdev; +MemoryRegion iomem; +int32_t readbuff; + +uint32_t usr1; +uint32_t usr2; +uint32_t ucr1; +uint32_t uts1; + +uint32_t ubrm; +uint32_t ubrc; + +qemu_irq irq; +CharDriverState *chr; +} imx_state; + +static const VMStateDescription vmstate_imx_serial = { +.name = "imx-serial", +.version_id = 1, +.minimum_version_id = 1, +.minimum_version_id_old = 1, +.fields = (VMStateField []) { +VMSTATE_UINT32(usr1, imx_state), +VMSTATE_UINT32(usr2, imx_state), +VMSTATE_UINT32(ucr1, imx_state), +VMSTATE_UINT32(uts1, imx_state), +VMSTATE_UINT32(ubrm, imx_state), +VMSTATE_UINT32(ubrc, imx_state), +VMSTATE_END_OF_LIST() +}, +}; + + +#define URXD_CHARRDY(1<<15) /* character read is valid */ + +#define USR1_TRDY (1<<13) /* Xmitter ready */ +#define USR1_RRDY (1<<9)/* receiver ready */ + +#define USR2_TXFE (1<<14) /* Transmit FIFO empty */ +#define USR2_RDR(1<<0)/* Receive data ready */ +#define USR2_TXDC (1<<3)/* Transmission complete */ + +#define UCR1_UARTEN (1<<0) +#define UCR1_RRDYEN (1<<9) +#define UCR1_TRDYEN (1<<13) +#define UCR1_TXMPTYEN (1<<6) + +#define UTS1_TXEMPTY(1<<6) +#define UTS1_RXEMPTY(1<<5) +#define UTS1_TXFULL (1<<4) +#define UTS1_RXFULL (1<<3) + +static void imx_update(imx_state *s) +{ +uint32_t flags; + +flags = ((s->usr1 & s->ucr1)) & (USR1_TRDY|USR1_RRDY); +if (!(s->ucr1 & UCR1_TXMPTYEN)) { +flags &= ~USR1_TRDY; +} + +qemu_set_irq(s->irq, !!flags); +} + +static void imx_serial_reset(imx_state *s) +{ +s->usr1 = USR1_TRDY; +s->usr2 = USR2_TXFE | USR2_TXDC; +s->uts1 = UTS1_RXEMPTY; +s->ubrm = 0; +s->ubrc = 0; +s->readbuff = 0; +} + +static uint64_t imx_serial_read(void *opaque, target_phys_addr_t offset, +unsigned size) +{ +imx_state *s = (imx_state *)opaque; +uint32_t c; + +DPRINTF("read(offset=%x)\n", offset >> 2); +switch (offset >> 2) { +case 0x0: /* URXD */ +c = s->readbuff; +s->usr1 &= ~USR1_RRDY; +s->usr2 &= ~USR2_RDR; +s->uts1 |= UTS1_RXEMPTY; +imx_update(s); +qemu_chr_accept_input(s->chr); +return c | URXD_CHARRDY; + +case 0x20: /* UCR1 */ +return s->ucr1; + +case 0x21: /* UCR2 */ +return 1; /* reset complete */ + +case 0x25: /* USR1 */ +imx_update(s); +return s->usr1; + +case 0x26: /* USR2 */ +imx_update(s); +return s->usr2; + + +case 0x2A: /* BRM Modulator */ +return s->ubrm; + +case 0x2B: /* Baud Rate Count */ +return s->ubrc; + +case 0x2d: /* UTS1 */ +return s->uts1; + + +case 0x22: /* UCR3 */ +case 0x23: /* UCR4 */ +case 0x24: /* UFCR */ +case 0x29: /* BRM Incremental */ +return 0x0; /* TODO */ + +default: +scream("imx_serial_read: bad offset: 0x%x\n", (int)offset); +r
[Qemu-devel] [PATCH V2 0/4] imx.31 and KZM board support
Here follow four patches in separate emails, to implement basic i.mx31 SoC support, and the KZM evaluation board built around this chip. The patch to the Makefile to build all the files is in the last of the series, rather than changing Makefile.hw in each patch. All comments received so far have been addressed --- I've added a macro, `scream' that gives at most 10 lines of output for OS error reporting. Signed-off-by lines are in each individual patch. The work was originally done by people at OK-Labs sufficient to get OK-L4 running; I've cleaned it up and added sufficient new functionality to get Linux running with an initial RAM disk. -- 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
Re: [Qemu-devel] [PATCH] [ARM] Fix sp804 dual-timer
Properly implement dual-timer read/write for the sp804 dual timer module. Based on ARM specs at http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html Signed-off-by: Hans Jang Signed-off-by: David Mirabito Signed-off-by: Peter Chubb --- hw/arm_timer.c | 41 +++-- 1 file changed, 35 insertions(+), 6 deletions(-) Index: qemu-working/hw/arm_timer.c === --- qemu-working.orig/hw/arm_timer.c2011-11-22 14:21:50.873221242 +1100 +++ qemu-working/hw/arm_timer.c 2011-11-22 14:22:21.986129734 +1100 @@ -163,64 +163,93 @@ static arm_timer_state *arm_timer_init(u s->freq = freq; s->control = TIMER_CTRL_IE; bh = qemu_bh_new(arm_timer_tick, s); s->timer = ptimer_init(bh); vmstate_register(NULL, -1, &vmstate_arm_timer, s); return s; } /* 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=/com.arm.doc.ddi0271d/index.html +*/ typedef struct { SysBusDevice busdev; MemoryRegion iomem; arm_timer_state *timer[2]; int level[2]; qemu_irq irq; } sp804_state; +static const uint8_t sp804_ids[] = { +/* Timer ID */ +0x04, 0x18, 0x14, 0, +/* PrimeCell ID */ +0xd, 0xf0, 0x05, 0xb1 +}; + /* Merge the IRQs from the two component devices. */ static void sp804_set_irq(void *opaque, int irq, int level) { sp804_state *s = (sp804_state *)opaque; s->level[irq] = level; qemu_set_irq(s->irq, s->level[0] || s->level[1]); } static uint64_t sp804_read(void *opaque, target_phys_addr_t offset, unsigned size) { sp804_state *s = (sp804_state *)opaque; -/* ??? 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); } + +/* TimerPeriphID */ +if (offset >= 0xfe0 && offset <= 0xffc) { +return sp804_ids[(offset - 0xfe0) >> 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("%s: Bad offset %x\n", __func__, (int)offset); +return 0; } static void sp804_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { sp804_state *s = (sp804_state *)opaque; 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 likely */ +hw_error("%s: Bad offset %x\n", __func__, (int)offset); } static const MemoryRegionOps sp804_ops = { .read = sp804_read, .write = sp804_write, .endianness = DEVICE_NATIVE_ENDIAN, }; static const VMStateDescription vmstate_sp804 = { .name = "sp804", -- 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