[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] PATCH: minimal support for mcf5282 (68k coldfire) and uC528
From: |
Till Straumann |
Subject: |
[Qemu-devel] PATCH: minimal support for mcf5282 (68k coldfire) and uC5282 board |
Date: |
Fri, 11 Sep 2009 10:00:00 -0500 |
User-agent: |
Thunderbird 2.0.0.23 (X11/20090817) |
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",
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] PATCH: minimal support for mcf5282 (68k coldfire) and uC5282 board,
Till Straumann <=