Guan Xuetao | fbbdf98 | 2012-08-10 14:42:27 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Generic PKUnity SoC machine and board descriptor |
| 3 | * |
| 4 | * Copyright (C) 2010-2012 Guan Xuetao |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License version 2 as |
| 8 | * published by the Free Software Foundation, or any later version. |
| 9 | * See the COPYING file in the top-level directory. |
| 10 | */ |
| 11 | #include "console.h" |
| 12 | #include "elf.h" |
| 13 | #include "exec-memory.h" |
| 14 | #include "sysbus.h" |
| 15 | #include "boards.h" |
| 16 | #include "loader.h" |
| 17 | #include "pc.h" |
| 18 | |
| 19 | #undef DEBUG_PUV3 |
| 20 | #include "puv3.h" |
| 21 | |
| 22 | #define KERNEL_LOAD_ADDR 0x03000000 |
| 23 | #define KERNEL_MAX_SIZE 0x00800000 /* Just a guess */ |
| 24 | |
Guan Xuetao | 5c8556a | 2012-08-10 14:42:28 +0800 | [diff] [blame] | 25 | static void puv3_intc_cpu_handler(void *opaque, int irq, int level) |
| 26 | { |
| 27 | CPUUniCore32State *env = opaque; |
| 28 | |
| 29 | assert(irq == 0); |
| 30 | if (level) { |
| 31 | cpu_interrupt(env, CPU_INTERRUPT_HARD); |
| 32 | } else { |
| 33 | cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); |
| 34 | } |
| 35 | } |
| 36 | |
Guan Xuetao | fbbdf98 | 2012-08-10 14:42:27 +0800 | [diff] [blame] | 37 | static void puv3_soc_init(CPUUniCore32State *env) |
| 38 | { |
Guan Xuetao | 5c8556a | 2012-08-10 14:42:28 +0800 | [diff] [blame] | 39 | qemu_irq *cpu_intc, irqs[PUV3_IRQS_NR]; |
| 40 | DeviceState *dev; |
Guan Xuetao | 79683f6 | 2012-08-10 14:42:33 +0800 | [diff] [blame] | 41 | MemoryRegion *i8042 = g_new(MemoryRegion, 1); |
Guan Xuetao | 5c8556a | 2012-08-10 14:42:28 +0800 | [diff] [blame] | 42 | int i; |
| 43 | |
| 44 | /* Initialize interrupt controller */ |
| 45 | cpu_intc = qemu_allocate_irqs(puv3_intc_cpu_handler, env, 1); |
| 46 | dev = sysbus_create_simple("puv3_intc", PUV3_INTC_BASE, *cpu_intc); |
| 47 | for (i = 0; i < PUV3_IRQS_NR; i++) { |
| 48 | irqs[i] = qdev_get_gpio_in(dev, i); |
| 49 | } |
Guan Xuetao | 56d07a9 | 2012-08-10 14:42:29 +0800 | [diff] [blame] | 50 | |
| 51 | /* Initialize minimal necessary devices for kernel booting */ |
Guan Xuetao | f716c19 | 2012-08-10 14:42:31 +0800 | [diff] [blame] | 52 | sysbus_create_simple("puv3_pm", PUV3_PM_BASE, NULL); |
Guan Xuetao | 1ea3489 | 2012-08-10 14:42:32 +0800 | [diff] [blame] | 53 | sysbus_create_simple("puv3_dma", PUV3_DMA_BASE, NULL); |
Guan Xuetao | 56d07a9 | 2012-08-10 14:42:29 +0800 | [diff] [blame] | 54 | sysbus_create_simple("puv3_ost", PUV3_OST_BASE, irqs[PUV3_IRQS_OST0]); |
Guan Xuetao | a89d01c | 2012-08-10 14:42:30 +0800 | [diff] [blame] | 55 | sysbus_create_varargs("puv3_gpio", PUV3_GPIO_BASE, |
| 56 | irqs[PUV3_IRQS_GPIOLOW0], irqs[PUV3_IRQS_GPIOLOW1], |
| 57 | irqs[PUV3_IRQS_GPIOLOW2], irqs[PUV3_IRQS_GPIOLOW3], |
| 58 | irqs[PUV3_IRQS_GPIOLOW4], irqs[PUV3_IRQS_GPIOLOW5], |
| 59 | irqs[PUV3_IRQS_GPIOLOW6], irqs[PUV3_IRQS_GPIOLOW7], |
| 60 | irqs[PUV3_IRQS_GPIOHIGH], NULL); |
Guan Xuetao | 79683f6 | 2012-08-10 14:42:33 +0800 | [diff] [blame] | 61 | |
| 62 | /* Keyboard (i8042), mouse disabled for nographic */ |
| 63 | i8042_mm_init(irqs[PUV3_IRQS_PS2_KBD], NULL, i8042, PUV3_REGS_OFFSET, 4); |
| 64 | memory_region_add_subregion(get_system_memory(), PUV3_PS2_BASE, i8042); |
Guan Xuetao | fbbdf98 | 2012-08-10 14:42:27 +0800 | [diff] [blame] | 65 | } |
| 66 | |
| 67 | static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size) |
| 68 | { |
| 69 | MemoryRegion *ram_memory = g_new(MemoryRegion, 1); |
| 70 | |
| 71 | /* SDRAM at address zero. */ |
| 72 | memory_region_init_ram(ram_memory, "puv3.ram", ram_size); |
| 73 | vmstate_register_ram_global(ram_memory); |
| 74 | memory_region_add_subregion(get_system_memory(), 0, ram_memory); |
| 75 | } |
| 76 | |
| 77 | static void puv3_load_kernel(const char *kernel_filename) |
| 78 | { |
| 79 | int size; |
| 80 | |
| 81 | assert(kernel_filename != NULL); |
| 82 | |
| 83 | /* only zImage format supported */ |
| 84 | size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR, |
| 85 | KERNEL_MAX_SIZE); |
| 86 | if (size < 0) { |
| 87 | hw_error("Load kernel error: '%s'\n", kernel_filename); |
| 88 | } |
| 89 | |
| 90 | /* cheat curses that we have a graphic console, only under ocd console */ |
| 91 | graphic_console_init(NULL, NULL, NULL, NULL, NULL); |
| 92 | } |
| 93 | |
| 94 | static void puv3_init(ram_addr_t ram_size, const char *boot_device, |
| 95 | const char *kernel_filename, const char *kernel_cmdline, |
| 96 | const char *initrd_filename, const char *cpu_model) |
| 97 | { |
| 98 | CPUUniCore32State *env; |
| 99 | |
| 100 | if (initrd_filename) { |
| 101 | hw_error("Please use kernel built-in initramdisk.\n"); |
| 102 | } |
| 103 | |
| 104 | if (!cpu_model) { |
| 105 | cpu_model = "UniCore-II"; |
| 106 | } |
| 107 | |
| 108 | env = cpu_init(cpu_model); |
| 109 | if (!env) { |
| 110 | hw_error("Unable to find CPU definition\n"); |
| 111 | } |
| 112 | |
| 113 | puv3_soc_init(env); |
| 114 | puv3_board_init(env, ram_size); |
| 115 | puv3_load_kernel(kernel_filename); |
| 116 | } |
| 117 | |
| 118 | static QEMUMachine puv3_machine = { |
| 119 | .name = "puv3", |
| 120 | .desc = "PKUnity Version-3 based on UniCore32", |
| 121 | .init = puv3_init, |
Guan Xuetao | 220c214 | 2012-08-10 14:42:35 +0800 | [diff] [blame] | 122 | .is_default = 1, |
Guan Xuetao | fbbdf98 | 2012-08-10 14:42:27 +0800 | [diff] [blame] | 123 | .use_scsi = 0, |
| 124 | }; |
| 125 | |
| 126 | static void puv3_machine_init(void) |
| 127 | { |
| 128 | qemu_register_machine(&puv3_machine); |
| 129 | } |
| 130 | |
| 131 | machine_init(puv3_machine_init) |