/*
 * 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 "hw/sysbus.h"
#include "hw/char/serial.h"
#include "hw/intc/nios2_vic.h"
#include "hw/qdev-properties.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"

struct Nios2MachineState {
    MachineState parent_obj;

    MemoryRegion phys_tcm;
    MemoryRegion phys_tcm_alias;
    MemoryRegion phys_ram;
    MemoryRegion phys_ram_alias;

    bool vic;
};

#define TYPE_NIOS2_MACHINE  MACHINE_TYPE_NAME("10m50-ghrd")
OBJECT_DECLARE_TYPE(Nios2MachineState, MachineClass, NIOS2_MACHINE)

#define BINARY_DEVICE_TREE_FILE    "10m50-devboard.dtb"

static void nios2_10m50_ghrd_init(MachineState *machine)
{
    Nios2MachineState *nms = NIOS2_MACHINE(machine);
    Nios2CPU *cpu;
    DeviceState *dev;
    MemoryRegion *address_space_mem = get_system_memory();
    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 irq[32];
    int i;

    /* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */
    memory_region_init_ram(&nms->phys_tcm, NULL, "nios2.tcm", tcm_size,
                           &error_abort);
    memory_region_init_alias(&nms->phys_tcm_alias, NULL, "nios2.tcm.alias",
                             &nms->phys_tcm, 0, tcm_size);
    memory_region_add_subregion(address_space_mem, tcm_base, &nms->phys_tcm);
    memory_region_add_subregion(address_space_mem, 0xc0000000 + tcm_base,
                                &nms->phys_tcm_alias);

    /* Physical DRAM with alias at 0xc0000000 */
    memory_region_init_ram(&nms->phys_ram, NULL, "nios2.ram", ram_size,
                           &error_abort);
    memory_region_init_alias(&nms->phys_ram_alias, NULL, "nios2.ram.alias",
                             &nms->phys_ram, 0, ram_size);
    memory_region_add_subregion(address_space_mem, ram_base, &nms->phys_ram);
    memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base,
                                &nms->phys_ram_alias);

    /* Create CPU.  We need to set eic_present between init and realize. */
    cpu = NIOS2_CPU(object_new(TYPE_NIOS2_CPU));

    /* Enable the External Interrupt Controller within the CPU. */
    cpu->eic_present = nms->vic;

    /* Configure new exception vectors. */
    cpu->reset_addr = 0xd4000000;
    cpu->exception_addr = 0xc8000120;
    cpu->fast_tlb_miss_addr = 0xc0000100;

    qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal);

    if (nms->vic) {
        DeviceState *dev = qdev_new(TYPE_NIOS2_VIC);
        MemoryRegion *dev_mr;
        qemu_irq cpu_irq;

        object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_fatal);
        sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);

        cpu_irq = qdev_get_gpio_in_named(DEVICE(cpu), "EIC", 0);
        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq);
        for (int i = 0; i < 32; i++) {
            irq[i] = qdev_get_gpio_in(dev, i);
        }

        dev_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
        memory_region_add_subregion(address_space_mem, 0x18002000, dev_mr);
    } else {
        for (i = 0; i < 32; i++) {
            irq[i] = qdev_get_gpio_in_named(DEVICE(cpu), "IRQ", i);
        }
    }

    /* Register: Altera 16550 UART */
    serial_mm_init(address_space_mem, 0xf8001600, 2, irq[1], 115200,
                   serial_hd(0), DEVICE_NATIVE_ENDIAN);

    /* Register: Timer sys_clk_timer  */
    dev = qdev_new("ALTR.timer");
    qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
    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_new("ALTR.timer");
    qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xe0000880);
    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[5]);

    nios2_load_kernel(cpu, ram_base, ram_size, machine->initrd_filename,
                      BINARY_DEVICE_TREE_FILE, NULL);
}

static bool get_vic(Object *obj, Error **errp)
{
    Nios2MachineState *nms = NIOS2_MACHINE(obj);
    return nms->vic;
}

static void set_vic(Object *obj, bool value, Error **errp)
{
    Nios2MachineState *nms = NIOS2_MACHINE(obj);
    nms->vic = value;
}

static void nios2_10m50_ghrd_class_init(ObjectClass *oc, void *data)
{
    MachineClass *mc = MACHINE_CLASS(oc);

    mc->desc = "Altera 10M50 GHRD Nios II design";
    mc->init = nios2_10m50_ghrd_init;
    mc->is_default = true;

    object_class_property_add_bool(oc, "vic", get_vic, set_vic);
    object_class_property_set_description(oc, "vic",
        "Set on/off to enable/disable the Vectored Interrupt Controller");
}

static const TypeInfo nios2_10m50_ghrd_type_info = {
    .name          = TYPE_NIOS2_MACHINE,
    .parent        = TYPE_MACHINE,
    .instance_size = sizeof(Nios2MachineState),
    .class_init    = nios2_10m50_ghrd_class_init,
};

static void nios2_10m50_ghrd_type_init(void)
{
    type_register_static(&nios2_10m50_ghrd_type_info);
}
type_init(nios2_10m50_ghrd_type_init);
