/*
 * IMX6 System Reset Controller
 *
 * Copyright (c) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 */

#include "qemu/osdep.h"
#include "hw/misc/imx6_src.h"
#include "sysemu/sysemu.h"
#include "qemu/bitops.h"
#include "qemu/log.h"
#include "arm-powerctl.h"

#ifndef DEBUG_IMX6_SRC
#define DEBUG_IMX6_SRC 0
#endif

#define DPRINTF(fmt, args...) \
    do { \
        if (DEBUG_IMX6_SRC) { \
            fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX6_SRC, \
                                             __func__, ##args); \
        } \
    } while (0)

static char const *imx6_src_reg_name(uint32_t reg)
{
    static char unknown[20];

    switch (reg) {
    case SRC_SCR:
        return "SRC_SCR";
    case SRC_SBMR1:
        return "SRC_SBMR1";
    case SRC_SRSR:
        return "SRC_SRSR";
    case SRC_SISR:
        return "SRC_SISR";
    case SRC_SIMR:
        return "SRC_SIMR";
    case SRC_SBMR2:
        return "SRC_SBMR2";
    case SRC_GPR1:
        return "SRC_GPR1";
    case SRC_GPR2:
        return "SRC_GPR2";
    case SRC_GPR3:
        return "SRC_GPR3";
    case SRC_GPR4:
        return "SRC_GPR4";
    case SRC_GPR5:
        return "SRC_GPR5";
    case SRC_GPR6:
        return "SRC_GPR6";
    case SRC_GPR7:
        return "SRC_GPR7";
    case SRC_GPR8:
        return "SRC_GPR8";
    case SRC_GPR9:
        return "SRC_GPR9";
    case SRC_GPR10:
        return "SRC_GPR10";
    default:
        sprintf(unknown, "%d ?", reg);
        return unknown;
    }
}

static const VMStateDescription vmstate_imx6_src = {
    .name = TYPE_IMX6_SRC,
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32_ARRAY(regs, IMX6SRCState, SRC_MAX),
        VMSTATE_END_OF_LIST()
    },
};

static void imx6_src_reset(DeviceState *dev)
{
    IMX6SRCState *s = IMX6_SRC(dev);

    DPRINTF("\n");

    memset(s->regs, 0, sizeof(s->regs));

    /* Set reset values */
    s->regs[SRC_SCR] = 0x521;
    s->regs[SRC_SRSR] = 0x1;
    s->regs[SRC_SIMR] = 0x1F;
}

static uint64_t imx6_src_read(void *opaque, hwaddr offset, unsigned size)
{
    uint32_t value = 0;
    IMX6SRCState *s = (IMX6SRCState *)opaque;
    uint32_t index = offset >> 2;

    if (index < SRC_MAX) {
        value = s->regs[index];
    } else {
        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
                      HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset);

    }

    DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx6_src_reg_name(index), value);

    return value;
}

static void imx6_src_write(void *opaque, hwaddr offset, uint64_t value,
                           unsigned size)
{
    IMX6SRCState *s = (IMX6SRCState *)opaque;
    uint32_t index = offset >> 2;
    unsigned long change_mask;
    unsigned long current_value = value;

    if (index >=  SRC_MAX) {
        qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
                      HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset);
        return;
    }

    DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx6_src_reg_name(index),
            (uint32_t)current_value);

    change_mask = s->regs[index] ^ (uint32_t)current_value;

    switch (index) {
    case SRC_SCR:
        /*
         * On real hardware when the system reset controller starts a
         * secondary CPU it runs through some boot ROM code which reads
         * the SRC_GPRX registers controlling the start address and branches
         * to it.
         * Here we are taking a short cut and branching directly to the
         * requested address (we don't want to run the boot ROM code inside
         * QEMU)
         */
        if (EXTRACT(change_mask, CORE3_ENABLE)) {
            if (EXTRACT(current_value, CORE3_ENABLE)) {
                /* CORE 3 is brought up */
                arm_set_cpu_on(3, s->regs[SRC_GPR7], s->regs[SRC_GPR8],
                               3, false);
            } else {
                /* CORE 3 is shut down */
                arm_set_cpu_off(3);
            }
            /* We clear the reset bits as the processor changed state */
            clear_bit(CORE3_RST_SHIFT, &current_value);
            clear_bit(CORE3_RST_SHIFT, &change_mask);
        }
        if (EXTRACT(change_mask, CORE2_ENABLE)) {
            if (EXTRACT(current_value, CORE2_ENABLE)) {
                /* CORE 2 is brought up */
                arm_set_cpu_on(2, s->regs[SRC_GPR5], s->regs[SRC_GPR6],
                               3, false);
            } else {
                /* CORE 3 is shut down */
                arm_set_cpu_off(2);
            }
            /* We clear the reset bits as the processor changed state */
            clear_bit(CORE2_RST_SHIFT, &current_value);
            clear_bit(CORE2_RST_SHIFT, &change_mask);
        }
        if (EXTRACT(change_mask, CORE1_ENABLE)) {
            if (EXTRACT(current_value, CORE1_ENABLE)) {
                /* CORE 1 is brought up */
                arm_set_cpu_on(1, s->regs[SRC_GPR3], s->regs[SRC_GPR4],
                               3, false);
            } else {
                /* CORE 3 is shut down */
                arm_set_cpu_off(1);
            }
            /* We clear the reset bits as the processor changed state */
            clear_bit(CORE1_RST_SHIFT, &current_value);
            clear_bit(CORE1_RST_SHIFT, &change_mask);
        }
        if (EXTRACT(change_mask, CORE0_RST)) {
            arm_reset_cpu(0);
            clear_bit(CORE0_RST_SHIFT, &current_value);
        }
        if (EXTRACT(change_mask, CORE1_RST)) {
            arm_reset_cpu(1);
            clear_bit(CORE1_RST_SHIFT, &current_value);
        }
        if (EXTRACT(change_mask, CORE2_RST)) {
            arm_reset_cpu(2);
            clear_bit(CORE2_RST_SHIFT, &current_value);
        }
        if (EXTRACT(change_mask, CORE3_RST)) {
            arm_reset_cpu(3);
            clear_bit(CORE3_RST_SHIFT, &current_value);
        }
        if (EXTRACT(change_mask, SW_IPU2_RST)) {
            /* We pretend the IPU2 is reset */
            clear_bit(SW_IPU2_RST_SHIFT, &current_value);
        }
        if (EXTRACT(change_mask, SW_IPU1_RST)) {
            /* We pretend the IPU1 is reset */
            clear_bit(SW_IPU1_RST_SHIFT, &current_value);
        }
        s->regs[index] = current_value;
        break;
    default:
        s->regs[index] = current_value;
        break;
    }
}

static const struct MemoryRegionOps imx6_src_ops = {
    .read = imx6_src_read,
    .write = imx6_src_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid = {
        /*
         * Our device would not work correctly if the guest was doing
         * unaligned access. This might not be a limitation on the real
         * device but in practice there is no reason for a guest to access
         * this device unaligned.
         */
        .min_access_size = 4,
        .max_access_size = 4,
        .unaligned = false,
    },
};

static void imx6_src_realize(DeviceState *dev, Error **errp)
{
    IMX6SRCState *s = IMX6_SRC(dev);

    memory_region_init_io(&s->iomem, OBJECT(dev), &imx6_src_ops, s,
                          TYPE_IMX6_SRC, 0x1000);
    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
}

static void imx6_src_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->realize = imx6_src_realize;
    dc->reset = imx6_src_reset;
    dc->vmsd = &vmstate_imx6_src;
    dc->desc = "i.MX6 System Reset Controller";
}

static const TypeInfo imx6_src_info = {
    .name          = TYPE_IMX6_SRC,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(IMX6SRCState),
    .class_init    = imx6_src_class_init,
};

static void imx6_src_register_types(void)
{
    type_register_static(&imx6_src_info);
}

type_init(imx6_src_register_types)
