Hello all,
Attached it a patch against the latest cvs base. This adds support for the Mainstone II board. Included is support for the ethernet device ( SMC911x ) and ramdisk ( initrd ). Kernel sources used are from Kernel.org mainline. More device support to follow.
Feedback and comment welcome. Enjoy, Armin
diff -ruN qemu/hw/boards.h qemu_new/hw/boards.h --- qemu/hw/boards.h 2007-11-17 22:46:57.000000000 -1000 +++ qemu_new/hw/boards.h 2007-11-22 09:07:20.000000000 -1000 @@ -92,4 +92,7 @@ /* dummy_m68k.c */ extern QEMUMachine dummy_m68k_machine; +/* Arm PXA27x - mainstone.c */ +extern QEMUMachine mainstone2_machine; + #endif diff -ruN qemu/hw/mainstone.c qemu_new/hw/mainstone.c --- qemu/hw/mainstone.c 1969-12-31 14:00:00.000000000 -1000 +++ qemu_new/hw/mainstone.c 2007-11-22 09:57:21.000000000 -1000 @@ -0,0 +1,311 @@ +/* + * PXA270-based Intel Mainstone platforms. + * + * Copyright (c) 2007 by Armin Kuster <[EMAIL PROTECTED]> or + * <[EMAIL PROTECTED]> + * + * Code based on spitz platform by Andrzej Zaborowski <[EMAIL PROTECTED]> + * + * This code is licensed under the GNU GPL v2. + */ +#include "hw.h" +#include "pxa.h" +#include "arm-misc.h" +#include "sysemu.h" +#include "qemu-timer.h" +#include "net.h" +#include "devices.h" +#include "console.h" +#include "boards.h" + +#define MST_ETH_PHYS 0x10000300 +#define MST_FPGA_PHYS 0x08000000 + +/* Mainstone FPGA for extern irqs */ +#define FPGA_GPIO_PIN 0 +#define MST_NUM_IRQS 16 +#define MST_BASE MST_FPGA_PHYS +#define MST_LEDDAT1 0x10 +#define MST_LEDDAT2 0x14 +#define MST_LEDCTRL 0x40 +#define MST_GPSWR 0x60 +#define MST_MSCWR1 0x80 +#define MST_MSCWR2 0x84 +#define MST_MSCWR3 0x88 +#define MST_MSCRD 0x90 +#define MST_INTMSKENA 0xc0 +#define MST_INTSETCLR 0xd0 +#define MST_PCMCIA0 0xe0 +#define MST_PCMCIA1 0xe4 + +/* IRQ definitions */ +#define ETHERNET_IRQ 3 + +typedef struct mst_irq_state{ + target_phys_addr_t target_base; + qemu_irq *parent; + qemu_irq *pins; + + uint32_t prev_level; + uint32_t leddat1; + uint32_t leddat2; + uint32_t ledctrl; + uint32_t gpswr; + uint32_t mscwr1; + uint32_t mscwr2; + uint32_t mscwr3; + uint32_t mscrd; + uint32_t intmskena; + uint32_t intsetclr; + uint32_t pcmcia0; + uint32_t pcmcia1; +}mst_irq_state; + +static void +mst_fpga_update_gpio(mst_irq_state *s) +{ + uint32_t level, diff; + int bit; + level = s->prev_level ^ s->intsetclr; + + for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { + bit = ffs(diff) - 1; + qemu_set_irq(s->pins[bit], (level >> bit) & 1 ); + } + s->prev_level = level; +} + +static void +mst_fpga_set_irq(void *opaque, int irq, int level) +{ + mst_irq_state *s = (mst_irq_state *)opaque; + + if (level) + s->prev_level |= 1u << irq; + else + s->prev_level &= ~(1u << irq); + + if(s->intmskena & (1u << irq)) { + s->intsetclr = 1u << irq; + qemu_set_irq(s->parent[0], level); + } +} + + +static uint32_t +mst_fpga_readb(void *opaque, target_phys_addr_t addr) +{ + mst_irq_state *s = (mst_irq_state *) opaque; + addr -= s->target_base; + + switch (addr) { + case MST_LEDDAT1: + return s->leddat1; + case MST_LEDDAT2: + return s->leddat2; + case MST_LEDCTRL: + return s->ledctrl; + case MST_GPSWR: + return s->gpswr; + case MST_MSCWR1: + return s->mscwr1; + case MST_MSCWR2: + return s->mscwr2; + case MST_MSCWR3: + return s->mscwr3; + case MST_MSCRD: + return s->mscrd; + case MST_INTMSKENA: + return s->intmskena; + case MST_INTSETCLR: + return s->intsetclr; + case MST_PCMCIA0: + return s->pcmcia0; + case MST_PCMCIA1: + return s->pcmcia1; + default: + printf("Mainstone - mst_fpga_readb: Bad register offset " + REG_FMT " \n", addr); + } + return 0; +} + +static void +mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) +{ + mst_irq_state *s = (mst_irq_state *) opaque; + addr -= s->target_base; + value &= 0xffffffff; + + switch (addr) { + case MST_LEDDAT1: + s->leddat1 = value; + break; + case MST_LEDDAT2: + s->leddat2 = value; + break; + case MST_LEDCTRL: + s->ledctrl = value; + break; + case MST_GPSWR: + s->gpswr = value; + break; + case MST_MSCWR1: + s->mscwr1 = value; + break; + case MST_MSCWR2: + s->mscwr2 = value; + break; + case MST_MSCWR3: + s->mscwr3 = value; + break; + case MST_MSCRD: + s->mscrd = value; + break; + case MST_INTMSKENA: /* Mask interupt */ + s->intmskena = (value & 0xFEEFF); + mst_fpga_update_gpio(s); + break; + case MST_INTSETCLR: /* clear or set interrupt */ + s->intsetclr = (value & 0xFEEFF); + break; + case MST_PCMCIA0: + s->pcmcia0 = value; + break; + case MST_PCMCIA1: + s->pcmcia1 = value; + break; + default: + printf("Mainstone - mst_fpga_writeb: Bad register offset " + REG_FMT " \n", addr); + } +} + +CPUReadMemoryFunc *mst_fpga_readfn[] = { + mst_fpga_readb, + mst_fpga_readb, + mst_fpga_readb, +}; +CPUWriteMemoryFunc *mst_fpga_writefn[] = { + mst_fpga_writeb, + mst_fpga_writeb, + mst_fpga_writeb, +}; + +static void +mst_fpga_save(QEMUFile *f, void *opaque) +{ + struct mst_irq_state *s = (mst_irq_state *) opaque; + + qemu_put_be32s(f, &s->prev_level); + qemu_put_be32s(f, &s->leddat1); + qemu_put_be32s(f, &s->leddat2); + qemu_put_be32s(f, &s->ledctrl); + qemu_put_be32s(f, &s->gpswr); + qemu_put_be32s(f, &s->mscwr1); + qemu_put_be32s(f, &s->mscwr2); + qemu_put_be32s(f, &s->mscwr3); + qemu_put_be32s(f, &s->mscrd); + qemu_put_be32s(f, &s->intmskena); + qemu_put_be32s(f, &s->intsetclr); + qemu_put_be32s(f, &s->pcmcia0); + qemu_put_be32s(f, &s->pcmcia1); +} + +static int +mst_fpga_load(QEMUFile *f, void *opaque, int version_id) +{ + mst_irq_state *s = (mst_irq_state *) opaque; + + qemu_get_be32s(f, &s->prev_level); + qemu_get_be32s(f, &s->leddat1); + qemu_get_be32s(f, &s->leddat2); + qemu_get_be32s(f, &s->ledctrl); + qemu_get_be32s(f, &s->gpswr); + qemu_get_be32s(f, &s->mscwr1); + qemu_get_be32s(f, &s->mscwr2); + qemu_get_be32s(f, &s->mscwr3); + qemu_get_be32s(f, &s->mscrd); + qemu_get_be32s(f, &s->intmskena); + qemu_get_be32s(f, &s->intsetclr); + qemu_get_be32s(f, &s->pcmcia0); + qemu_get_be32s(f, &s->pcmcia1); + return 0; +} + +static qemu_irq +*mst_irq_init(struct pxa2xx_state_s *cpu, uint32_t base, int irq) +{ + mst_irq_state *s; + int iomemtype; + qemu_irq *qi; + + s = (mst_irq_state *) + qemu_mallocz(sizeof(mst_irq_state)); + + if (!s) + return NULL; + s->target_base = base; + s->parent = &cpu->pic[irq]; + + /* alloc the external 16 irqs */ + qi = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS); + s->pins = qi; + + iomemtype = cpu_register_io_memory(0, mst_fpga_readfn, + mst_fpga_writefn, s); + cpu_register_physical_memory(MST_BASE, 0x00100000, iomemtype); + register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s); + return qi; +} + +enum mainstone_model_e { mainstone }; + +static void mainstone_common_init(int ram_size, int vga_ram_size, + DisplayState *ds, const char *kernel_filename, + const char *kernel_cmdline, const char *initrd_filename, + const char *cpu_model, enum mainstone_model_e model, int arm_id) +{ + uint32_t mainstone_ram = 0x04000000; + uint32_t mainstone_rom = 0x00800000; + struct pxa2xx_state_s *cpu; + qemu_irq *mst_irq; + + if (!cpu_model) + cpu_model = "pxa270-c5"; + + /* Setup CPU & memory */ + if (ram_size < mainstone_ram + mainstone_rom + PXA2XX_INTERNAL_SIZE) { + fprintf(stderr, "This platform requires %i bytes of memory\n", + mainstone_ram + mainstone_rom + PXA2XX_INTERNAL_SIZE); + exit(1); + } + + cpu = pxa270_init(mainstone_ram, ds, cpu_model); + cpu_register_physical_memory(0, mainstone_rom, + qemu_ram_alloc(mainstone_rom) | IO_MEM_ROM); + + /* Setup initial (reset) machine state */ + cpu->env->regs[15] = PXA2XX_SDRAM_BASE; + + mst_irq = mst_irq_init(cpu, MST_BASE, PXA2XX_PIC_GPIO_0); + smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]); + + arm_load_kernel(cpu->env, mainstone_ram, kernel_filename, kernel_cmdline, + initrd_filename, arm_id, PXA2XX_SDRAM_BASE); +} + +static void mainstone_init(int ram_size, int vga_ram_size, + const char *boot_device, DisplayState *ds, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + mainstone_common_init(ram_size, vga_ram_size, ds, kernel_filename, + kernel_cmdline, initrd_filename, cpu_model, mainstone, 0x196); +} + +QEMUMachine mainstone2_machine = { + "mainstone", + "Mainstone II (PXA27x)", + mainstone_init, +}; diff -ruN qemu/Makefile.target qemu_new/Makefile.target --- qemu/Makefile.target 2007-11-18 12:34:46.000000000 -1000 +++ qemu_new/Makefile.target 2007-11-22 09:06:58.000000000 -1000 @@ -499,6 +499,7 @@ VL_OBJS+= spitz.o ide.o serial.o nand.o ecc.o VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o omap_i2c.o VL_OBJS+= palm.o tsc210x.o +VL_OBJS+= mainstone.o smc91c111.o CPPFLAGS += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), sh4) diff -ruN qemu/vl.c qemu_new/vl.c --- qemu/vl.c 2007-11-18 15:05:22.000000000 -1000 +++ qemu_new/vl.c 2007-11-22 09:51:45.000000000 -1000 @@ -7451,6 +7451,7 @@ qemu_register_machine(&lm3s811evb_machine); qemu_register_machine(&lm3s6965evb_machine); qemu_register_machine(&connex_machine); + qemu_register_machine(&mainstone2_machine); #elif defined(TARGET_SH4) qemu_register_machine(&shix_machine); qemu_register_machine(&r2d_machine);