Patchwork PATCH: minimal support for mcf5282 (68k coldfire) and uC5282 board

login
register
mail settings
Submitter Till Straumann
Date Sept. 11, 2009, 3 p.m.
Message ID <4AAA65F0.3050406@TU-Berlin.de>
Download mbox | patch
Permalink /patch/33478/
State Superseded
Headers show

Comments

Till Straumann - Sept. 11, 2009, 3 p.m.
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

Patch

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",