From patchwork Fri Sep 11 15:00:00 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Till Straumann X-Patchwork-Id: 33478 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by bilbo.ozlabs.org (Postfix) with ESMTPS id D9ABAB7067 for ; Sat, 12 Sep 2009 02:45:43 +1000 (EST) Received: from localhost ([127.0.0.1]:40622 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Mm9Fj-0004I7-S9 for incoming@patchwork.ozlabs.org; Fri, 11 Sep 2009 12:45:39 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Mm7bk-0004cS-Qn for qemu-devel@nongnu.org; Fri, 11 Sep 2009 11:00:17 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Mm7bg-0004Ym-Av for qemu-devel@nongnu.org; Fri, 11 Sep 2009 11:00:16 -0400 Received: from [199.232.76.173] (port=48117 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Mm7be-0004YI-JZ for qemu-devel@nongnu.org; Fri, 11 Sep 2009 11:00:10 -0400 Received: from mailbox.alumni.tu-berlin.de ([130.149.4.218]:59788) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Mm7bc-0001kf-3X for qemu-devel@nongnu.org; Fri, 11 Sep 2009 11:00:08 -0400 X-tubIT-Incoming-IP: 201.145.80.158 Received: from [201.145.80.158] (helo=[192.168.1.69]) by mailbox.alumni.tu-berlin.de (exim-4.69) with esmtpsa [TLSv1:DHE-RSA-AES256-SHA:256] id 1Mm7bX-0000Tw-7H; Fri, 11 Sep 2009 17:00:04 +0200 Message-ID: <4AAA65F0.3050406@TU-Berlin.de> Date: Fri, 11 Sep 2009 10:00:00 -0500 From: Till Straumann User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: qemu-devel@nongnu.org, Joel Sherrill X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. X-Mailman-Approved-At: Fri, 11 Sep 2009 12:29:51 -0400 Cc: Subject: [Qemu-devel] PATCH: minimal support for mcf5282 (68k coldfire) and uC5282 board X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Hi. The attached patch (against qemu-0.11.0-rc1) adds minimal support for the mcf5282 CPU and an emulation of the uC5282 board (by Arcturus Networks Inc [-- I'm not affiliated with them]). The patch also includes the fix for the FEC ethernet controller that I recently posted. Please CC me with any replies -- I'm not subscribed to this list. WKR -- Till Only in qemu-0.11.0-rc1: build diff -cr qemu-0.11.0-rc1.orig/hw/mcf5208.c qemu-0.11.0-rc1/hw/mcf5208.c *** qemu-0.11.0-rc1.orig/hw/mcf5208.c 2009-07-29 19:38:19.000000000 -0500 --- qemu-0.11.0-rc1/hw/mcf5208.c 2009-09-08 22:48:36.000000000 -0500 *************** *** 193,198 **** --- 193,251 ---- } } + static uint32_t m5208_resetc_read(void *opaque, target_phys_addr_t addr) + { + switch (addr) { + case 0x0: /* RCR */ + case 0x1: /* RSR */ + return 0; + + default: + hw_error("m5208_resetc_read: Bad offset 0x%x\n", (int)addr); + return 0; + } + } + + static void m5208_resetc_write(void *opaque, target_phys_addr_t addr, + uint32_t value) + { + switch (addr) { + case 0x0: /* RCR */ + if ( value & 0x80 ) { + qemu_system_shutdown_request(); + } + break; + case 0x1: /* RSR */ + break; + + default: + hw_error("m5208_resetc_write: Bad offset 0x%x\n", (int)addr); + break; + } + } + + static CPUReadMemoryFunc *m5208_resetc_readfn[] = { + m5208_resetc_read, + m5208_resetc_read, + m5208_resetc_read + }; + + static CPUWriteMemoryFunc *m5208_resetc_writefn[] = { + m5208_resetc_write, + m5208_resetc_write, + m5208_resetc_write + }; + + static void mcf5208_resetc_init(target_phys_addr_t offset) + { + int iomemtype; + + iomemtype = cpu_register_io_memory(m5208_resetc_readfn, + m5208_resetc_writefn, NULL); + cpu_register_physical_memory(offset, 0x4, iomemtype); + } + + static void mcf5208evb_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, *************** *** 225,236 **** qemu_ram_alloc(16384) | IO_MEM_RAM); /* Internal peripherals. */ ! pic = mcf_intc_init(0xfc048000, env); mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]); mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]); mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]); mcf5208_sys_init(pic); if (nb_nics > 1) { --- 278,291 ---- qemu_ram_alloc(16384) | IO_MEM_RAM); /* Internal peripherals. */ ! pic = mcf_intc_init(0xfc048000, env, 0); mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]); mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]); mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]); + mcf5208_resetc_init(0xfc0a0000); + mcf5208_sys_init(pic); if (nb_nics > 1) { *************** *** 288,294 **** static QEMUMachine mcf5208evb_machine = { .name = "mcf5208evb", ! .desc = "MCF5206EVB", .init = mcf5208evb_init, .is_default = 1, }; --- 343,349 ---- static QEMUMachine mcf5208evb_machine = { .name = "mcf5208evb", ! .desc = "MCF5208EVB", .init = mcf5208evb_init, .is_default = 1, }; *************** *** 298,301 **** --- 353,485 ---- qemu_register_machine(&mcf5208evb_machine); } + static void mcf5282_sys_init(qemu_irq *pic) + { + int iomemtype; + m5208_timer_state *s; + QEMUBH *bh; + int i; + + /* Timers. */ + for (i = 0; i < 4; i++) { + s = (m5208_timer_state *)qemu_mallocz(sizeof(m5208_timer_state)); + bh = qemu_bh_new(m5208_timer_trigger, s); + s->timer = ptimer_init(bh); + iomemtype = cpu_register_io_memory(m5208_timer_readfn, + m5208_timer_writefn, s); + cpu_register_physical_memory(0x40150000 + 0x10000 * i, 0x00000008, + iomemtype); + s->irq = pic[55 + i]; + } + } + + static void uc5282_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; + int kernel_size; + uint64_t elf_entry; + target_ulong entry; + qemu_irq *pic; + + if (!cpu_model) + cpu_model = "m5208"; + env = cpu_init(cpu_model); + if (!env) { + fprintf(stderr, "Unable to find m68k CPU definition\n"); + exit(1); + } + + /* Initialize CPU registers. */ + env->vbr = 0; + /* TODO: Configure BARs. */ + + /* DRAM at 0x00000000 */ + cpu_register_physical_memory(0x00000000, ram_size, + qemu_ram_alloc(ram_size) | IO_MEM_RAM); + + /* Internal SRAM. */ + cpu_register_physical_memory(0x20000000, 65536, + qemu_ram_alloc(65536) | IO_MEM_RAM); + + /* Internal peripherals. */ + pic = mcf_intc_init(0x40000c00, env, 1); + + mcf_uart_mm_init(0x40000200, pic[13], serial_hds[0]); + mcf_uart_mm_init(0x40000240, pic[14], serial_hds[1]); + mcf_uart_mm_init(0x40000280, pic[15], serial_hds[2]); + + mcf5208_resetc_init(0x40110000); + + mcf5282_sys_init(pic); + + if (nb_nics > 1) { + fprintf(stderr, "Too many NICs\n"); + exit(1); + } + if (nd_table[0].vlan) + mcf_fec_init(&nd_table[0], 0x40001000, pic + 23); + + /* 0xfc000000 SCM. */ + /* 0xfc004000 XBS. */ + /* 0xfc008000 FlexBus CS. */ + /* 0xfc030000 FEC. */ + /* 0xfc040000 SCM + Power management. */ + /* 0xfc044000 eDMA. */ + /* 0xfc048000 INTC. */ + /* 0xfc058000 I2C. */ + /* 0xfc05c000 QSPI. */ + /* 0xfc060000 UART0. */ + /* 0xfc064000 UART0. */ + /* 0xfc068000 UART0. */ + /* 0xfc070000 DMA timers. */ + /* 0xfc080000 PIT0. */ + /* 0xfc084000 PIT1. */ + /* 0xfc088000 EPORT. */ + /* 0xfc08c000 Watchdog. */ + /* 0xfc090000 clock module. */ + /* 0xfc0a0000 CCM + reset. */ + /* 0xfc0a4000 GPIO. */ + /* 0xfc0a8000 SDRAM controller. */ + + /* Load kernel. */ + if (!kernel_filename) { + fprintf(stderr, "Kernel image must be specified\n"); + exit(1); + } + + kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL); + entry = elf_entry; + if (kernel_size < 0) { + kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL); + } + if (kernel_size < 0) { + kernel_size = load_image_targphys(kernel_filename, 0x00000000, + ram_size); + entry = 0x00000000; + } + if (kernel_size < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); + exit(1); + } + + env->pc = entry; + } + + static QEMUMachine uc5282_machine = { + .name = "uc5282", + .desc = "uC5282", + .init = uc5282_init, + .is_default = 0, + }; + + static void uc5282_machine_init(void) + { + qemu_register_machine(&uc5282_machine); + } + + machine_init(mcf5208evb_machine_init); + machine_init(uc5282_machine_init); diff -cr qemu-0.11.0-rc1.orig/hw/mcf_fec.c qemu-0.11.0-rc1/hw/mcf_fec.c *** qemu-0.11.0-rc1.orig/hw/mcf_fec.c 2009-07-29 19:38:19.000000000 -0500 --- qemu-0.11.0-rc1/hw/mcf_fec.c 2009-09-08 22:43:10.000000000 -0500 *************** *** 172,178 **** if (bd.flags & FEC_BD_L) { /* Last buffer in frame. */ DPRINTF("Sending packet\n"); ! qemu_send_packet(s->vc, frame, len); ptr = frame; frame_size = 0; s->eir |= FEC_INT_TXF; --- 172,178 ---- if (bd.flags & FEC_BD_L) { /* Last buffer in frame. */ DPRINTF("Sending packet\n"); ! qemu_send_packet(s->vc, frame, frame_size); ptr = frame; frame_size = 0; s->eir |= FEC_INT_TXF; *************** *** 217,223 **** static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr) { mcf_fec_state *s = (mcf_fec_state *)opaque; ! switch (addr & 0x3ff) { case 0x004: return s->eir; case 0x008: return s->eimr; case 0x010: return s->rx_enabled ? (1 << 24) : 0; /* RDAR */ --- 217,224 ---- static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr) { mcf_fec_state *s = (mcf_fec_state *)opaque; ! addr &= 0x3ff; ! switch (addr) { case 0x004: return s->eir; case 0x008: return s->eimr; case 0x010: return s->rx_enabled ? (1 << 24) : 0; /* RDAR */ *************** *** 246,251 **** --- 247,254 ---- case 0x184: return s->etdsr; case 0x188: return s->emrbr; default: + if ( addr >= 0x200 && addr < 0x2e4 ) + return 0xdeadbeef; /* FIXME: MIB counters not implemented */ hw_error("mcf_fec_read: Bad address 0x%x\n", (int)addr); return 0; } *************** *** 254,260 **** static void mcf_fec_write(void *opaque, target_phys_addr_t addr, uint32_t value) { mcf_fec_state *s = (mcf_fec_state *)opaque; ! switch (addr & 0x3ff) { case 0x004: s->eir &= ~value; break; --- 257,264 ---- static void mcf_fec_write(void *opaque, target_phys_addr_t addr, uint32_t value) { mcf_fec_state *s = (mcf_fec_state *)opaque; ! addr &= 0x3ff; ! switch (addr) { case 0x004: s->eir &= ~value; break; *************** *** 285,290 **** --- 289,295 ---- case 0x040: /* TODO: Implement MII. */ s->mmfr = value; + s->eir |= FEC_INT_MII; break; case 0x044: s->mscr = value & 0xfe; *************** *** 342,347 **** --- 347,354 ---- s->emrbr = value & 0x7f0; break; default: + if ( addr >= 0x200 && addr < 0x2e4 ) + return; /* FIXME: MIB counters not implemented */ hw_error("mcf_fec_write Bad address 0x%x\n", (int)addr); } mcf_fec_update(s); diff -cr qemu-0.11.0-rc1.orig/hw/mcf.h qemu-0.11.0-rc1/hw/mcf.h *** qemu-0.11.0-rc1.orig/hw/mcf.h 2009-07-29 19:38:19.000000000 -0500 --- qemu-0.11.0-rc1/hw/mcf.h 2009-09-08 18:57:24.000000000 -0500 *************** *** 10,16 **** CharDriverState *chr); /* mcf_intc.c */ ! qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env); /* mcf_fec.c */ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq); --- 10,16 ---- CharDriverState *chr); /* mcf_intc.c */ ! qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env, int is_uc5282); /* mcf_fec.c */ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq); diff -cr qemu-0.11.0-rc1.orig/hw/mcf_intc.c qemu-0.11.0-rc1/hw/mcf_intc.c *** qemu-0.11.0-rc1.orig/hw/mcf_intc.c 2009-07-29 19:38:19.000000000 -0500 --- qemu-0.11.0-rc1/hw/mcf_intc.c 2009-09-08 18:56:58.000000000 -0500 *************** *** 16,37 **** uint8_t icr[64]; CPUState *env; int active_vector; } mcf_intc_state; static void mcf_intc_update(mcf_intc_state *s) { uint64_t active; int i; int best; ! int best_level; active = (s->ipr | s->ifr) & s->enabled & ~s->imr; best_level = 0; best = 64; if (active) { for (i = 0; i < 64; i++) { ! if ((active & 1) != 0 && s->icr[i] >= best_level) { ! best_level = s->icr[i]; best = i; } active >>= 1; --- 16,53 ---- uint8_t icr[64]; CPUState *env; int active_vector; + int uc5282_intc; } mcf_intc_state; + static inline int get_int_level(mcf_intc_state *s, int i) + { + return s->uc5282_intc ? (s->icr[i] >> 3) : s->icr[i]; + } + + static inline int get_int_prio(mcf_intc_state *s, int i) + { + return s->uc5282_intc ? (s->icr[i] & 7) : 0; + } + + static void mcf_intc_update(mcf_intc_state *s) { uint64_t active; int i; int best; ! int best_level, best_prio,level,prio; active = (s->ipr | s->ifr) & s->enabled & ~s->imr; best_level = 0; + best_prio = 0; best = 64; if (active) { for (i = 0; i < 64; i++) { ! level = get_int_level(s,i); ! prio = get_int_prio(s,i); ! if ((active & 1) != 0 && level >= best_level && prio >= best_prio) { ! best_level = level; ! best_prio = prio; best = i; } active >>= 1; *************** *** 139,151 **** mcf_intc_write }; ! qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env) { mcf_intc_state *s; int iomemtype; s = qemu_mallocz(sizeof(mcf_intc_state)); s->env = env; mcf_intc_reset(s); iomemtype = cpu_register_io_memory(mcf_intc_readfn, --- 155,168 ---- mcf_intc_write }; ! qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env, int uc5282_intc) { mcf_intc_state *s; int iomemtype; s = qemu_mallocz(sizeof(mcf_intc_state)); s->env = env; + s->uc5282_intc = uc5282_intc; mcf_intc_reset(s); iomemtype = cpu_register_io_memory(mcf_intc_readfn, diff -cr qemu-0.11.0-rc1.orig/target-m68k/helper.c qemu-0.11.0-rc1/target-m68k/helper.c *** qemu-0.11.0-rc1.orig/target-m68k/helper.c 2009-07-29 19:38:24.000000000 -0500 --- qemu-0.11.0-rc1/target-m68k/helper.c 2009-09-08 19:40:10.000000000 -0500 *************** *** 290,295 **** --- 293,301 ---- case 0x801: /* VBR */ env->vbr = val; break; + case 0xc05: /* rambar */ + env->rambar0 = val; + break; /* TODO: Implement control registers. */ default: cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",