diff options
Diffstat (limited to 'hw/xtensa/xtfpga.c')
-rw-r--r-- | hw/xtensa/xtfpga.c | 414 |
1 files changed, 302 insertions, 112 deletions
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 1971ecfdc5..76ea970215 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -44,33 +44,39 @@ #include "sysemu/device_tree.h" #include "qemu/error-report.h" #include "bootparam.h" +#include "xtensa_memory.h" -typedef struct LxBoardDesc { - hwaddr flash_base; - size_t flash_size; - size_t flash_boot_base; - size_t flash_sector_size; +typedef struct XtfpgaFlashDesc { + hwaddr base; + size_t size; + size_t boot_base; + size_t sector_size; +} XtfpgaFlashDesc; + +typedef struct XtfpgaBoardDesc { + const XtfpgaFlashDesc *flash; size_t sram_size; -} LxBoardDesc; + const hwaddr *io; +} XtfpgaBoardDesc; -typedef struct Lx60FpgaState { +typedef struct XtfpgaFpgaState { MemoryRegion iomem; uint32_t leds; uint32_t switches; -} Lx60FpgaState; +} XtfpgaFpgaState; -static void lx60_fpga_reset(void *opaque) +static void xtfpga_fpga_reset(void *opaque) { - Lx60FpgaState *s = opaque; + XtfpgaFpgaState *s = opaque; s->leds = 0; s->switches = 0; } -static uint64_t lx60_fpga_read(void *opaque, hwaddr addr, +static uint64_t xtfpga_fpga_read(void *opaque, hwaddr addr, unsigned size) { - Lx60FpgaState *s = opaque; + XtfpgaFpgaState *s = opaque; switch (addr) { case 0x0: /*build date code*/ @@ -88,10 +94,10 @@ static uint64_t lx60_fpga_read(void *opaque, hwaddr addr, return 0; } -static void lx60_fpga_write(void *opaque, hwaddr addr, +static void xtfpga_fpga_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - Lx60FpgaState *s = opaque; + XtfpgaFpgaState *s = opaque; switch (addr) { case 0x8: /*LEDs (off = 0, on = 1)*/ @@ -106,26 +112,26 @@ static void lx60_fpga_write(void *opaque, hwaddr addr, } } -static const MemoryRegionOps lx60_fpga_ops = { - .read = lx60_fpga_read, - .write = lx60_fpga_write, +static const MemoryRegionOps xtfpga_fpga_ops = { + .read = xtfpga_fpga_read, + .write = xtfpga_fpga_write, .endianness = DEVICE_NATIVE_ENDIAN, }; -static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space, +static XtfpgaFpgaState *xtfpga_fpga_init(MemoryRegion *address_space, hwaddr base) { - Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState)); + XtfpgaFpgaState *s = g_malloc(sizeof(XtfpgaFpgaState)); - memory_region_init_io(&s->iomem, NULL, &lx60_fpga_ops, s, - "lx60.fpga", 0x10000); + memory_region_init_io(&s->iomem, NULL, &xtfpga_fpga_ops, s, + "xtfpga.fpga", 0x10000); memory_region_add_subregion(address_space, base, &s->iomem); - lx60_fpga_reset(s); - qemu_register_reset(lx60_fpga_reset, s); + xtfpga_fpga_reset(s); + qemu_register_reset(xtfpga_fpga_reset, s); return s; } -static void lx60_net_init(MemoryRegion *address_space, +static void xtfpga_net_init(MemoryRegion *address_space, hwaddr base, hwaddr descriptors, hwaddr buffers, @@ -154,7 +160,7 @@ static void lx60_net_init(MemoryRegion *address_space, } static pflash_t *xtfpga_flash_init(MemoryRegion *address_space, - const LxBoardDesc *board, + const XtfpgaBoardDesc *board, DriveInfo *dinfo, int be) { SysBusDevice *s; @@ -163,14 +169,14 @@ static pflash_t *xtfpga_flash_init(MemoryRegion *address_space, qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), &error_abort); qdev_prop_set_uint32(dev, "num-blocks", - board->flash_size / board->flash_sector_size); - qdev_prop_set_uint64(dev, "sector-length", board->flash_sector_size); + board->flash->size / board->flash->sector_size); + qdev_prop_set_uint64(dev, "sector-length", board->flash->sector_size); qdev_prop_set_uint8(dev, "width", 2); qdev_prop_set_bit(dev, "big-endian", be); - qdev_prop_set_string(dev, "name", "lx60.io.flash"); + qdev_prop_set_string(dev, "name", "xtfpga.io.flash"); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); - memory_region_add_subregion(address_space, board->flash_base, + memory_region_add_subregion(address_space, board->flash->base, sysbus_mmio_get_region(s, 0)); return OBJECT_CHECK(pflash_t, (dev), "cfi.pflash01"); } @@ -182,31 +188,31 @@ static uint64_t translate_phys_addr(void *opaque, uint64_t addr) return cpu_get_phys_page_debug(CPU(cpu), addr); } -static void lx60_reset(void *opaque) +static void xtfpga_reset(void *opaque) { XtensaCPU *cpu = opaque; cpu_reset(CPU(cpu)); } -static uint64_t lx60_io_read(void *opaque, hwaddr addr, +static uint64_t xtfpga_io_read(void *opaque, hwaddr addr, unsigned size) { return 0; } -static void lx60_io_write(void *opaque, hwaddr addr, +static void xtfpga_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { } -static const MemoryRegionOps lx60_io_ops = { - .read = lx60_io_read, - .write = lx60_io_write, +static const MemoryRegionOps xtfpga_io_ops = { + .read = xtfpga_io_read, + .write = xtfpga_io_write, .endianness = DEVICE_NATIVE_ENDIAN, }; -static void lx_init(const LxBoardDesc *board, MachineState *machine) +static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine) { #ifdef TARGET_WORDS_BIGENDIAN int be = 1; @@ -216,7 +222,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) MemoryRegion *system_memory = get_system_memory(); XtensaCPU *cpu = NULL; CPUXtensaState *env = NULL; - MemoryRegion *ram, *rom, *system_io; + MemoryRegion *system_io; DriveInfo *dinfo; pflash_t *flash = NULL; QemuOpts *machine_opts = qemu_get_machine_opts(); @@ -224,6 +230,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); const char *dtb_filename = qemu_opt_get(machine_opts, "dtb"); const char *initrd_filename = qemu_opt_get(machine_opts, "initrd"); + const unsigned system_io_size = 224 * 1024 * 1024; int n; for (n = 0; n < smp_cpus; n++) { @@ -231,25 +238,43 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) env = &cpu->env; env->sregs[PRID] = n; - qemu_register_reset(lx60_reset, cpu); + qemu_register_reset(xtfpga_reset, cpu); /* Need MMU initialized prior to ELF loading, * so that ELF gets loaded into virtual addresses */ cpu_reset(CPU(cpu)); } - ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, NULL, "lx60.dram", machine->ram_size, - &error_fatal); - memory_region_add_subregion(system_memory, 0, ram); + if (env) { + XtensaMemory sysram = env->config->sysram; + + sysram.location[0].size = machine->ram_size; + xtensa_create_memory_regions(&env->config->instrom, "xtensa.instrom", + system_memory); + xtensa_create_memory_regions(&env->config->instram, "xtensa.instram", + system_memory); + xtensa_create_memory_regions(&env->config->datarom, "xtensa.datarom", + system_memory); + xtensa_create_memory_regions(&env->config->dataram, "xtensa.dataram", + system_memory); + xtensa_create_memory_regions(&sysram, "xtensa.sysram", + system_memory); + } system_io = g_malloc(sizeof(*system_io)); - memory_region_init_io(system_io, NULL, &lx60_io_ops, NULL, "lx60.io", - 224 * 1024 * 1024); - memory_region_add_subregion(system_memory, 0xf0000000, system_io); - lx60_fpga_init(system_io, 0x0d020000); + memory_region_init_io(system_io, NULL, &xtfpga_io_ops, NULL, "xtfpga.io", + system_io_size); + memory_region_add_subregion(system_memory, board->io[0], system_io); + if (board->io[1]) { + MemoryRegion *io = g_malloc(sizeof(*io)); + + memory_region_init_alias(io, NULL, "xtfpga.io.cached", + system_io, 0, system_io_size); + memory_region_add_subregion(system_memory, board->io[1], io); + } + xtfpga_fpga_init(system_io, 0x0d020000); if (nd_table[0].used) { - lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000, + xtfpga_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000, xtensa_get_extint(env, 1), nd_table); } @@ -269,21 +294,24 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) if (kernel_filename) { uint32_t entry_point = env->pc; size_t bp_size = 3 * get_tag_size(0); /* first/last and memory tags */ - uint32_t tagptr = 0xfe000000 + board->sram_size; + uint32_t tagptr = env->config->sysrom.location[0].addr + + board->sram_size; uint32_t cur_tagptr; BpMemInfo memory_location = { .type = tswap32(MEMORY_TYPE_CONVENTIONAL), - .start = tswap32(0), - .end = tswap32(machine->ram_size), + .start = tswap32(env->config->sysram.location[0].addr), + .end = tswap32(env->config->sysram.location[0].addr + + machine->ram_size), }; uint32_t lowmem_end = machine->ram_size < 0x08000000 ? machine->ram_size : 0x08000000; uint32_t cur_lowmem = QEMU_ALIGN_UP(lowmem_end / 2, 4096); - rom = g_malloc(sizeof(*rom)); - memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size, - &error_fatal); - memory_region_add_subregion(system_memory, 0xfe000000, rom); + lowmem_end += env->config->sysram.location[0].addr; + cur_lowmem += env->config->sysram.location[0].addr; + + xtensa_create_memory_regions(&env->config->sysrom, "xtensa.sysrom", + system_memory); if (kernel_cmdline) { bp_size += get_tag_size(strlen(kernel_cmdline) + 1); @@ -372,146 +400,308 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) } } if (entry_point != env->pc) { - static const uint8_t jx_a0[] = { + uint8_t boot[] = { #ifdef TARGET_WORDS_BIGENDIAN - 0x0a, 0, 0, + 0x60, 0x00, 0x08, /* j 1f */ + 0x00, /* .literal_position */ + 0x00, 0x00, 0x00, 0x00, /* .literal entry_pc */ + 0x00, 0x00, 0x00, 0x00, /* .literal entry_a2 */ + /* 1: */ + 0x10, 0xff, 0xfe, /* l32r a0, entry_pc */ + 0x12, 0xff, 0xfe, /* l32r a2, entry_a2 */ + 0x0a, 0x00, 0x00, /* jx a0 */ #else - 0xa0, 0, 0, + 0x06, 0x02, 0x00, /* j 1f */ + 0x00, /* .literal_position */ + 0x00, 0x00, 0x00, 0x00, /* .literal entry_pc */ + 0x00, 0x00, 0x00, 0x00, /* .literal entry_a2 */ + /* 1: */ + 0x01, 0xfe, 0xff, /* l32r a0, entry_pc */ + 0x21, 0xfe, 0xff, /* l32r a2, entry_a2 */ + 0xa0, 0x00, 0x00, /* jx a0 */ #endif }; - env->regs[0] = entry_point; - cpu_physical_memory_write(env->pc, jx_a0, sizeof(jx_a0)); + uint32_t entry_pc = tswap32(entry_point); + uint32_t entry_a2 = tswap32(tagptr); + + memcpy(boot + 4, &entry_pc, sizeof(entry_pc)); + memcpy(boot + 8, &entry_a2, sizeof(entry_a2)); + cpu_physical_memory_write(env->pc, boot, sizeof(boot)); } } else { if (flash) { MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash); MemoryRegion *flash_io = g_malloc(sizeof(*flash_io)); + uint32_t size = env->config->sysrom.location[0].size; - memory_region_init_alias(flash_io, NULL, "lx60.flash", - flash_mr, board->flash_boot_base, - board->flash_size - board->flash_boot_base < 0x02000000 ? - board->flash_size - board->flash_boot_base : 0x02000000); - memory_region_add_subregion(system_memory, 0xfe000000, - flash_io); + if (board->flash->size - board->flash->boot_base < size) { + size = board->flash->size - board->flash->boot_base; + } + + memory_region_init_alias(flash_io, NULL, "xtfpga.flash", + flash_mr, board->flash->boot_base, size); + memory_region_add_subregion(system_memory, + env->config->sysrom.location[0].addr, + flash_io); + } else { + xtensa_create_memory_regions(&env->config->sysrom, "xtensa.sysrom", + system_memory); } } } -static void xtensa_lx60_init(MachineState *machine) +static const hwaddr xtfpga_mmu_io[2] = { + 0xf0000000, +}; + +static const hwaddr xtfpga_nommu_io[2] = { + 0x90000000, + 0x70000000, +}; + +static const XtfpgaFlashDesc lx60_flash = { + .base = 0x08000000, + .size = 0x00400000, + .sector_size = 0x10000, +}; + +static void xtfpga_lx60_init(MachineState *machine) { - static const LxBoardDesc lx60_board = { - .flash_base = 0x08000000, - .flash_size = 0x00400000, - .flash_sector_size = 0x10000, + static const XtfpgaBoardDesc lx60_board = { + .flash = &lx60_flash, .sram_size = 0x20000, + .io = xtfpga_mmu_io, + }; + xtfpga_init(&lx60_board, machine); +} + +static void xtfpga_lx60_nommu_init(MachineState *machine) +{ + static const XtfpgaBoardDesc lx60_board = { + .flash = &lx60_flash, + .sram_size = 0x20000, + .io = xtfpga_nommu_io, + }; + xtfpga_init(&lx60_board, machine); +} + +static const XtfpgaFlashDesc lx200_flash = { + .base = 0x08000000, + .size = 0x01000000, + .sector_size = 0x20000, +}; + +static void xtfpga_lx200_init(MachineState *machine) +{ + static const XtfpgaBoardDesc lx200_board = { + .flash = &lx200_flash, + .sram_size = 0x2000000, + .io = xtfpga_mmu_io, + }; + xtfpga_init(&lx200_board, machine); +} + +static void xtfpga_lx200_nommu_init(MachineState *machine) +{ + static const XtfpgaBoardDesc lx200_board = { + .flash = &lx200_flash, + .sram_size = 0x2000000, + .io = xtfpga_nommu_io, + }; + xtfpga_init(&lx200_board, machine); +} + +static const XtfpgaFlashDesc ml605_flash = { + .base = 0x08000000, + .size = 0x01000000, + .sector_size = 0x20000, +}; + +static void xtfpga_ml605_init(MachineState *machine) +{ + static const XtfpgaBoardDesc ml605_board = { + .flash = &ml605_flash, + .sram_size = 0x2000000, + .io = xtfpga_mmu_io, }; - lx_init(&lx60_board, machine); + xtfpga_init(&ml605_board, machine); } -static void xtensa_lx200_init(MachineState *machine) +static void xtfpga_ml605_nommu_init(MachineState *machine) { - static const LxBoardDesc lx200_board = { - .flash_base = 0x08000000, - .flash_size = 0x01000000, - .flash_sector_size = 0x20000, + static const XtfpgaBoardDesc ml605_board = { + .flash = &ml605_flash, .sram_size = 0x2000000, + .io = xtfpga_nommu_io, }; - lx_init(&lx200_board, machine); + xtfpga_init(&ml605_board, machine); } -static void xtensa_ml605_init(MachineState *machine) +static const XtfpgaFlashDesc kc705_flash = { + .base = 0x00000000, + .size = 0x08000000, + .boot_base = 0x06000000, + .sector_size = 0x20000, +}; + +static void xtfpga_kc705_init(MachineState *machine) { - static const LxBoardDesc ml605_board = { - .flash_base = 0x08000000, - .flash_size = 0x01000000, - .flash_sector_size = 0x20000, + static const XtfpgaBoardDesc kc705_board = { + .flash = &kc705_flash, .sram_size = 0x2000000, + .io = xtfpga_mmu_io, }; - lx_init(&ml605_board, machine); + xtfpga_init(&kc705_board, machine); } -static void xtensa_kc705_init(MachineState *machine) +static void xtfpga_kc705_nommu_init(MachineState *machine) { - static const LxBoardDesc kc705_board = { - .flash_base = 0x00000000, - .flash_size = 0x08000000, - .flash_boot_base = 0x06000000, - .flash_sector_size = 0x20000, + static const XtfpgaBoardDesc kc705_board = { + .flash = &kc705_flash, .sram_size = 0x2000000, + .io = xtfpga_nommu_io, }; - lx_init(&kc705_board, machine); + xtfpga_init(&kc705_board, machine); } -static void xtensa_lx60_class_init(ObjectClass *oc, void *data) +static void xtfpga_lx60_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "lx60 EVB (" XTENSA_DEFAULT_CPU_MODEL ")"; - mc->init = xtensa_lx60_init; + mc->init = xtfpga_lx60_init; mc->max_cpus = 4; mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE; } -static const TypeInfo xtensa_lx60_type = { +static const TypeInfo xtfpga_lx60_type = { .name = MACHINE_TYPE_NAME("lx60"), .parent = TYPE_MACHINE, - .class_init = xtensa_lx60_class_init, + .class_init = xtfpga_lx60_class_init, +}; + +static void xtfpga_lx60_nommu_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "lx60 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")"; + mc->init = xtfpga_lx60_nommu_init; + mc->max_cpus = 4; + mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE; +} + +static const TypeInfo xtfpga_lx60_nommu_type = { + .name = MACHINE_TYPE_NAME("lx60-nommu"), + .parent = TYPE_MACHINE, + .class_init = xtfpga_lx60_nommu_class_init, }; -static void xtensa_lx200_class_init(ObjectClass *oc, void *data) +static void xtfpga_lx200_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "lx200 EVB (" XTENSA_DEFAULT_CPU_MODEL ")"; - mc->init = xtensa_lx200_init; + mc->init = xtfpga_lx200_init; mc->max_cpus = 4; mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE; } -static const TypeInfo xtensa_lx200_type = { +static const TypeInfo xtfpga_lx200_type = { .name = MACHINE_TYPE_NAME("lx200"), .parent = TYPE_MACHINE, - .class_init = xtensa_lx200_class_init, + .class_init = xtfpga_lx200_class_init, }; -static void xtensa_ml605_class_init(ObjectClass *oc, void *data) +static void xtfpga_lx200_nommu_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "lx200 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")"; + mc->init = xtfpga_lx200_nommu_init; + mc->max_cpus = 4; + mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE; +} + +static const TypeInfo xtfpga_lx200_nommu_type = { + .name = MACHINE_TYPE_NAME("lx200-nommu"), + .parent = TYPE_MACHINE, + .class_init = xtfpga_lx200_nommu_class_init, +}; + +static void xtfpga_ml605_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "ml605 EVB (" XTENSA_DEFAULT_CPU_MODEL ")"; - mc->init = xtensa_ml605_init; + mc->init = xtfpga_ml605_init; mc->max_cpus = 4; mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE; } -static const TypeInfo xtensa_ml605_type = { +static const TypeInfo xtfpga_ml605_type = { .name = MACHINE_TYPE_NAME("ml605"), .parent = TYPE_MACHINE, - .class_init = xtensa_ml605_class_init, + .class_init = xtfpga_ml605_class_init, +}; + +static void xtfpga_ml605_nommu_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "ml605 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")"; + mc->init = xtfpga_ml605_nommu_init; + mc->max_cpus = 4; + mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE; +} + +static const TypeInfo xtfpga_ml605_nommu_type = { + .name = MACHINE_TYPE_NAME("ml605-nommu"), + .parent = TYPE_MACHINE, + .class_init = xtfpga_ml605_nommu_class_init, }; -static void xtensa_kc705_class_init(ObjectClass *oc, void *data) +static void xtfpga_kc705_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "kc705 EVB (" XTENSA_DEFAULT_CPU_MODEL ")"; - mc->init = xtensa_kc705_init; + mc->init = xtfpga_kc705_init; mc->max_cpus = 4; mc->default_cpu_type = XTENSA_DEFAULT_CPU_TYPE; } -static const TypeInfo xtensa_kc705_type = { +static const TypeInfo xtfpga_kc705_type = { .name = MACHINE_TYPE_NAME("kc705"), .parent = TYPE_MACHINE, - .class_init = xtensa_kc705_class_init, + .class_init = xtfpga_kc705_class_init, +}; + +static void xtfpga_kc705_nommu_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "kc705 noMMU EVB (" XTENSA_DEFAULT_CPU_NOMMU_MODEL ")"; + mc->init = xtfpga_kc705_nommu_init; + mc->max_cpus = 4; + mc->default_cpu_type = XTENSA_DEFAULT_CPU_NOMMU_TYPE; +} + +static const TypeInfo xtfpga_kc705_nommu_type = { + .name = MACHINE_TYPE_NAME("kc705-nommu"), + .parent = TYPE_MACHINE, + .class_init = xtfpga_kc705_nommu_class_init, }; -static void xtensa_lx_machines_init(void) +static void xtfpga_machines_init(void) { - type_register_static(&xtensa_lx60_type); - type_register_static(&xtensa_lx200_type); - type_register_static(&xtensa_ml605_type); - type_register_static(&xtensa_kc705_type); + type_register_static(&xtfpga_lx60_type); + type_register_static(&xtfpga_lx200_type); + type_register_static(&xtfpga_ml605_type); + type_register_static(&xtfpga_kc705_type); + type_register_static(&xtfpga_lx60_nommu_type); + type_register_static(&xtfpga_lx200_nommu_type); + type_register_static(&xtfpga_ml605_nommu_type); + type_register_static(&xtfpga_kc705_nommu_type); } -type_init(xtensa_lx_machines_init) +type_init(xtfpga_machines_init) |