|
|
1.1 ! root 1: /* ! 2: * Motorola ColdFire MCF5208 SoC emulation. ! 3: * ! 4: * Copyright (c) 2007 CodeSourcery. ! 5: * ! 6: * This code is licenced under the GPL ! 7: */ ! 8: #include "hw.h" ! 9: #include "mcf.h" ! 10: #include "qemu-timer.h" ! 11: #include "sysemu.h" ! 12: #include "net.h" ! 13: #include "boards.h" ! 14: ! 15: #define SYS_FREQ 66000000 ! 16: ! 17: #define PCSR_EN 0x0001 ! 18: #define PCSR_RLD 0x0002 ! 19: #define PCSR_PIF 0x0004 ! 20: #define PCSR_PIE 0x0008 ! 21: #define PCSR_OVW 0x0010 ! 22: #define PCSR_DBG 0x0020 ! 23: #define PCSR_DOZE 0x0040 ! 24: #define PCSR_PRE_SHIFT 8 ! 25: #define PCSR_PRE_MASK 0x0f00 ! 26: ! 27: typedef struct { ! 28: qemu_irq irq; ! 29: ptimer_state *timer; ! 30: uint16_t pcsr; ! 31: uint16_t pmr; ! 32: uint16_t pcntr; ! 33: } m5208_timer_state; ! 34: ! 35: static void m5208_timer_update(m5208_timer_state *s) ! 36: { ! 37: if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF)) ! 38: qemu_irq_raise(s->irq); ! 39: else ! 40: qemu_irq_lower(s->irq); ! 41: } ! 42: ! 43: static void m5208_timer_write(m5208_timer_state *s, int offset, ! 44: uint32_t value) ! 45: { ! 46: int prescale; ! 47: int limit; ! 48: switch (offset) { ! 49: case 0: ! 50: /* The PIF bit is set-to-clear. */ ! 51: if (value & PCSR_PIF) { ! 52: s->pcsr &= ~PCSR_PIF; ! 53: value &= ~PCSR_PIF; ! 54: } ! 55: /* Avoid frobbing the timer if we're just twiddling IRQ bits. */ ! 56: if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) { ! 57: s->pcsr = value; ! 58: m5208_timer_update(s); ! 59: return; ! 60: } ! 61: ! 62: if (s->pcsr & PCSR_EN) ! 63: ptimer_stop(s->timer); ! 64: ! 65: s->pcsr = value; ! 66: ! 67: prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT); ! 68: ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale); ! 69: if (s->pcsr & PCSR_RLD) ! 70: limit = s->pmr; ! 71: else ! 72: limit = 0xffff; ! 73: ptimer_set_limit(s->timer, limit, 0); ! 74: ! 75: if (s->pcsr & PCSR_EN) ! 76: ptimer_run(s->timer, 0); ! 77: break; ! 78: case 2: ! 79: s->pmr = value; ! 80: s->pcsr &= ~PCSR_PIF; ! 81: if ((s->pcsr & PCSR_RLD) == 0) { ! 82: if (s->pcsr & PCSR_OVW) ! 83: ptimer_set_count(s->timer, value); ! 84: } else { ! 85: ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW); ! 86: } ! 87: break; ! 88: case 4: ! 89: break; ! 90: default: ! 91: /* Should never happen. */ ! 92: abort(); ! 93: } ! 94: m5208_timer_update(s); ! 95: } ! 96: ! 97: static void m5208_timer_trigger(void *opaque) ! 98: { ! 99: m5208_timer_state *s = (m5208_timer_state *)opaque; ! 100: s->pcsr |= PCSR_PIF; ! 101: m5208_timer_update(s); ! 102: } ! 103: ! 104: typedef struct { ! 105: m5208_timer_state timer[2]; ! 106: } m5208_sys_state; ! 107: ! 108: static uint32_t m5208_sys_read(void *opaque, target_phys_addr_t addr) ! 109: { ! 110: m5208_sys_state *s = (m5208_sys_state *)opaque; ! 111: switch (addr) { ! 112: /* PIT0 */ ! 113: case 0xfc080000: ! 114: return s->timer[0].pcsr; ! 115: case 0xfc080002: ! 116: return s->timer[0].pmr; ! 117: case 0xfc080004: ! 118: return ptimer_get_count(s->timer[0].timer); ! 119: /* PIT1 */ ! 120: case 0xfc084000: ! 121: return s->timer[1].pcsr; ! 122: case 0xfc084002: ! 123: return s->timer[1].pmr; ! 124: case 0xfc084004: ! 125: return ptimer_get_count(s->timer[1].timer); ! 126: ! 127: /* SDRAM Controller. */ ! 128: case 0xfc0a8110: /* SDCS0 */ ! 129: { ! 130: int n; ! 131: for (n = 0; n < 32; n++) { ! 132: if (ram_size < (2u << n)) ! 133: break; ! 134: } ! 135: return (n - 1) | 0x40000000; ! 136: } ! 137: case 0xfc0a8114: /* SDCS1 */ ! 138: return 0; ! 139: ! 140: default: ! 141: cpu_abort(cpu_single_env, "m5208_sys_read: Bad offset 0x%x\n", ! 142: (int)addr); ! 143: return 0; ! 144: } ! 145: } ! 146: ! 147: static void m5208_sys_write(void *opaque, target_phys_addr_t addr, ! 148: uint32_t value) ! 149: { ! 150: m5208_sys_state *s = (m5208_sys_state *)opaque; ! 151: switch (addr) { ! 152: /* PIT0 */ ! 153: case 0xfc080000: ! 154: case 0xfc080002: ! 155: case 0xfc080004: ! 156: m5208_timer_write(&s->timer[0], addr & 0xf, value); ! 157: return; ! 158: /* PIT1 */ ! 159: case 0xfc084000: ! 160: case 0xfc084002: ! 161: case 0xfc084004: ! 162: m5208_timer_write(&s->timer[1], addr & 0xf, value); ! 163: return; ! 164: default: ! 165: cpu_abort(cpu_single_env, "m5208_sys_write: Bad offset 0x%x\n", ! 166: (int)addr); ! 167: break; ! 168: } ! 169: } ! 170: ! 171: static CPUReadMemoryFunc *m5208_sys_readfn[] = { ! 172: m5208_sys_read, ! 173: m5208_sys_read, ! 174: m5208_sys_read ! 175: }; ! 176: ! 177: static CPUWriteMemoryFunc *m5208_sys_writefn[] = { ! 178: m5208_sys_write, ! 179: m5208_sys_write, ! 180: m5208_sys_write ! 181: }; ! 182: ! 183: static void mcf5208_sys_init(qemu_irq *pic) ! 184: { ! 185: int iomemtype; ! 186: m5208_sys_state *s; ! 187: QEMUBH *bh; ! 188: int i; ! 189: ! 190: s = (m5208_sys_state *)qemu_mallocz(sizeof(m5208_sys_state)); ! 191: iomemtype = cpu_register_io_memory(0, m5208_sys_readfn, ! 192: m5208_sys_writefn, s); ! 193: /* SDRAMC. */ ! 194: cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype); ! 195: /* Timers. */ ! 196: for (i = 0; i < 2; i++) { ! 197: bh = qemu_bh_new(m5208_timer_trigger, &s->timer[i]); ! 198: s->timer[i].timer = ptimer_init(bh); ! 199: cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000, ! 200: iomemtype); ! 201: s->timer[i].irq = pic[4 + i]; ! 202: } ! 203: } ! 204: ! 205: static void mcf5208evb_init(int ram_size, int vga_ram_size, ! 206: const char *boot_device, DisplayState *ds, ! 207: const char *kernel_filename, const char *kernel_cmdline, ! 208: const char *initrd_filename, const char *cpu_model) ! 209: { ! 210: CPUState *env; ! 211: int kernel_size; ! 212: uint64_t elf_entry; ! 213: target_ulong entry; ! 214: qemu_irq *pic; ! 215: ! 216: if (!cpu_model) ! 217: cpu_model = "m5208"; ! 218: env = cpu_init(cpu_model); ! 219: if (!env) { ! 220: fprintf(stderr, "Unable to find m68k CPU definition\n"); ! 221: exit(1); ! 222: } ! 223: ! 224: /* Initialize CPU registers. */ ! 225: env->vbr = 0; ! 226: /* TODO: Configure BARs. */ ! 227: ! 228: /* DRAM at 0x20000000 */ ! 229: cpu_register_physical_memory(0x40000000, ram_size, ! 230: qemu_ram_alloc(ram_size) | IO_MEM_RAM); ! 231: ! 232: /* Internal SRAM. */ ! 233: cpu_register_physical_memory(0x80000000, 16384, ! 234: qemu_ram_alloc(16384) | IO_MEM_RAM); ! 235: ! 236: /* Internal peripherals. */ ! 237: pic = mcf_intc_init(0xfc048000, env); ! 238: ! 239: mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]); ! 240: mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]); ! 241: mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]); ! 242: ! 243: mcf5208_sys_init(pic); ! 244: ! 245: if (nb_nics > 1) { ! 246: fprintf(stderr, "Too many NICs\n"); ! 247: exit(1); ! 248: } ! 249: if (nd_table[0].vlan) { ! 250: if (nd_table[0].model == NULL ! 251: || strcmp(nd_table[0].model, "mcf_fec") == 0) { ! 252: mcf_fec_init(&nd_table[0], 0xfc030000, pic + 36); ! 253: } else if (strcmp(nd_table[0].model, "?") == 0) { ! 254: fprintf(stderr, "qemu: Supported NICs: mcf_fec\n"); ! 255: exit (1); ! 256: } else { ! 257: fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model); ! 258: exit (1); ! 259: } ! 260: } ! 261: ! 262: /* 0xfc000000 SCM. */ ! 263: /* 0xfc004000 XBS. */ ! 264: /* 0xfc008000 FlexBus CS. */ ! 265: /* 0xfc030000 FEC. */ ! 266: /* 0xfc040000 SCM + Power management. */ ! 267: /* 0xfc044000 eDMA. */ ! 268: /* 0xfc048000 INTC. */ ! 269: /* 0xfc058000 I2C. */ ! 270: /* 0xfc05c000 QSPI. */ ! 271: /* 0xfc060000 UART0. */ ! 272: /* 0xfc064000 UART0. */ ! 273: /* 0xfc068000 UART0. */ ! 274: /* 0xfc070000 DMA timers. */ ! 275: /* 0xfc080000 PIT0. */ ! 276: /* 0xfc084000 PIT1. */ ! 277: /* 0xfc088000 EPORT. */ ! 278: /* 0xfc08c000 Watchdog. */ ! 279: /* 0xfc090000 clock module. */ ! 280: /* 0xfc0a0000 CCM + reset. */ ! 281: /* 0xfc0a4000 GPIO. */ ! 282: /* 0xfc0a8000 SDRAM controller. */ ! 283: ! 284: /* Load kernel. */ ! 285: if (!kernel_filename) { ! 286: fprintf(stderr, "Kernel image must be specified\n"); ! 287: exit(1); ! 288: } ! 289: ! 290: kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL); ! 291: entry = elf_entry; ! 292: if (kernel_size < 0) { ! 293: kernel_size = load_uboot(kernel_filename, &entry, NULL); ! 294: } ! 295: if (kernel_size < 0) { ! 296: kernel_size = load_image(kernel_filename, phys_ram_base); ! 297: entry = 0x20000000; ! 298: } ! 299: if (kernel_size < 0) { ! 300: fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); ! 301: exit(1); ! 302: } ! 303: ! 304: env->pc = entry; ! 305: } ! 306: ! 307: QEMUMachine mcf5208evb_machine = { ! 308: "mcf5208evb", ! 309: "MCF5206EVB", ! 310: mcf5208evb_init, ! 311: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.