qemu/hw/nios2/10m50_devboard.c
Marek Vasut b786256488 nios2: Add Altera 10M50 GHRD emulation
Add the Altera 10M50 Nios2 GHRD model. This allows emulating the
10M50 development kit with the Nios2 GHRD loaded in the FPGA. It
is possible to boot Linux kernel and run userspace, thus far only
from initrd as storage support is not yet implemented.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Wulff <crwulff@gmail.com>
Cc: Jeff Da Silva <jdasilva@altera.com>
Cc: Ley Foon Tan <lftan@altera.com>
Cc: Sandra Loosemore <sandra@codesourcery.com>
Cc: Yves Vandervennet <yvanderv@altera.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Message-Id: <20170118220146.489-7-marex@denx.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2017-01-24 13:10:35 -08:00

127 lines
4.5 KiB
C

/*
* Altera 10M50 Nios2 GHRD
*
* Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
*
* Based on LabX device code
*
* Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "hw/sysbus.h"
#include "hw/hw.h"
#include "hw/char/serial.h"
#include "sysemu/sysemu.h"
#include "hw/boards.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
#include "qemu/config-file.h"
#include "boot.h"
#define BINARY_DEVICE_TREE_FILE "10m50-devboard.dtb"
static void nios2_10m50_ghrd_init(MachineState *machine)
{
Nios2CPU *cpu;
DeviceState *dev;
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *phys_tcm = g_new(MemoryRegion, 1);
MemoryRegion *phys_tcm_alias = g_new(MemoryRegion, 1);
MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
MemoryRegion *phys_ram_alias = g_new(MemoryRegion, 1);
ram_addr_t tcm_base = 0x0;
ram_addr_t tcm_size = 0x1000; /* 1 kiB, but QEMU limit is 4 kiB */
ram_addr_t ram_base = 0x08000000;
ram_addr_t ram_size = 0x08000000;
qemu_irq *cpu_irq, irq[32];
int i;
/* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */
memory_region_init_ram(phys_tcm, NULL, "nios2.tcm", tcm_size, &error_abort);
memory_region_init_alias(phys_tcm_alias, NULL, "nios2.tcm.alias",
phys_tcm, 0, tcm_size);
vmstate_register_ram_global(phys_tcm);
memory_region_add_subregion(address_space_mem, tcm_base, phys_tcm);
memory_region_add_subregion(address_space_mem, 0xc0000000 + tcm_base,
phys_tcm_alias);
/* Physical DRAM with alias at 0xc0000000 */
memory_region_init_ram(phys_ram, NULL, "nios2.ram", ram_size, &error_abort);
memory_region_init_alias(phys_ram_alias, NULL, "nios2.ram.alias",
phys_ram, 0, ram_size);
vmstate_register_ram_global(phys_ram);
memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base,
phys_ram_alias);
/* Create CPU -- FIXME */
cpu = cpu_nios2_init("nios2");
/* Register: CPU interrupt controller (PIC) */
cpu_irq = nios2_cpu_pic_init(cpu);
/* Register: Internal Interrupt Controller (IIC) */
dev = qdev_create(NULL, "altera,iic");
qdev_prop_set_ptr(dev, "cpu", cpu);
qdev_init_nofail(dev);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq[0]);
for (i = 0; i < 32; i++) {
irq[i] = qdev_get_gpio_in(dev, i);
}
/* Register: Altera 16550 UART */
serial_mm_init(address_space_mem, 0xf8001600, 2, irq[1], 115200,
serial_hds[0], DEVICE_NATIVE_ENDIAN);
/* Register: Timer sys_clk_timer */
dev = qdev_create(NULL, "ALTR.timer");
qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xf8001440);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[0]);
/* Register: Timer sys_clk_timer_1 */
dev = qdev_create(NULL, "ALTR.timer");
qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xe0000880);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[5]);
/* Configure new exception vectors and reset CPU for it to take effect. */
cpu->reset_addr = 0xd4000000;
cpu->exception_addr = 0xc8000120;
cpu->fast_tlb_miss_addr = 0xc0000100;
nios2_load_kernel(cpu, ram_base, ram_size, machine->initrd_filename,
BINARY_DEVICE_TREE_FILE, NULL);
}
static void nios2_10m50_ghrd_machine_init(struct MachineClass *mc)
{
mc->desc = "Altera 10M50 GHRD Nios II design";
mc->init = nios2_10m50_ghrd_init;
mc->is_default = 1;
}
DEFINE_MACHINE("10m50-ghrd", nios2_10m50_ghrd_machine_init);