/*
 * Freescale i.MX RNGC emulation
 *
 * Copyright (C) 2020 Martin Kaiser <martin@kaiser.cx>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 * This driver provides the minimum functionality to initialize and seed
 * an rngc and to read random numbers. The rngb that is found in imx25
 * chipsets is also supported.
 */

#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qemu/guest-random.h"
#include "hw/irq.h"
#include "hw/misc/imx_rngc.h"
#include "migration/vmstate.h"

#define RNGC_NAME "i.MX RNGC"

#define RNGC_VER_ID  0x00
#define RNGC_COMMAND 0x04
#define RNGC_CONTROL 0x08
#define RNGC_STATUS  0x0C
#define RNGC_FIFO    0x14

/* These version info are reported by the rngb in an imx258 chip. */
#define RNG_TYPE_RNGB 0x1
#define V_MAJ 0x2
#define V_MIN 0x40

#define RNGC_CMD_BIT_SW_RST    0x40
#define RNGC_CMD_BIT_CLR_ERR   0x20
#define RNGC_CMD_BIT_CLR_INT   0x10
#define RNGC_CMD_BIT_SEED      0x02
#define RNGC_CMD_BIT_SELF_TEST 0x01

#define RNGC_CTRL_BIT_MASK_ERR  0x40
#define RNGC_CTRL_BIT_MASK_DONE 0x20
#define RNGC_CTRL_BIT_AUTO_SEED 0x10

/* the current status for self-test and seed operations */
#define OP_IDLE 0
#define OP_RUN  1
#define OP_DONE 2

static uint64_t imx_rngc_read(void *opaque, hwaddr offset, unsigned size)
{
    IMXRNGCState *s = IMX_RNGC(opaque);
    uint64_t val = 0;

    switch (offset) {
    case RNGC_VER_ID:
        val |= RNG_TYPE_RNGB << 28 | V_MAJ << 8 | V_MIN;
        break;

    case RNGC_COMMAND:
        if (s->op_seed == OP_RUN) {
            val |= RNGC_CMD_BIT_SEED;
        }
        if (s->op_self_test == OP_RUN) {
            val |= RNGC_CMD_BIT_SELF_TEST;
        }
        break;

    case RNGC_CONTROL:
        /*
         * The CTL_ACC and VERIF_MODE bits are not supported yet.
         * They read as 0.
         */
        val |= s->mask;
        if (s->auto_seed) {
            val |= RNGC_CTRL_BIT_AUTO_SEED;
        }
        /*
         * We don't have an internal fifo like the real hardware.
         * There's no need for strategy to handle fifo underflows.
         * We return the FIFO_UFLOW_RESPONSE bits as 0.
         */
        break;

    case RNGC_STATUS:
        /*
         * We never report any statistics test or self-test errors or any
         * other errors. STAT_TEST_PF, ST_PF and ERROR are always 0.
         */

        /*
         * We don't have an internal fifo, see above. Therefore, we
         * report back the default fifo size (5 32-bit words) and
         * indicate that our fifo is always full.
         */
        val |= 5 << 12 | 5 << 8;

        /* We always have a new seed available. */
        val |= 1 << 6;

        if (s->op_seed == OP_DONE) {
            val |= 1 << 5;
        }
        if (s->op_self_test == OP_DONE) {
            val |= 1 << 4;
        }
        if (s->op_seed == OP_RUN || s->op_self_test == OP_RUN) {
            /*
             * We're busy if self-test is running or if we're
             * seeding the prng.
             */
            val |= 1 << 1;
        } else {
            /*
             * We're ready to provide secure random numbers whenever
             * we're not busy.
             */
            val |= 1;
        }
        break;

    case RNGC_FIFO:
        qemu_guest_getrandom_nofail(&val, sizeof(val));
        break;
    }

    return val;
}

static void imx_rngc_do_reset(IMXRNGCState *s)
{
    s->op_self_test = OP_IDLE;
    s->op_seed = OP_IDLE;
    s->mask = 0;
    s->auto_seed = false;
}

static void imx_rngc_write(void *opaque, hwaddr offset, uint64_t value,
                           unsigned size)
{
    IMXRNGCState *s = IMX_RNGC(opaque);

    switch (offset) {
    case RNGC_COMMAND:
        if (value & RNGC_CMD_BIT_SW_RST) {
            imx_rngc_do_reset(s);
        }

        /*
         * For now, both CLR_ERR and CLR_INT clear the interrupt. We
         * don't report any errors yet.
         */
        if (value & (RNGC_CMD_BIT_CLR_ERR | RNGC_CMD_BIT_CLR_INT)) {
            qemu_irq_lower(s->irq);
        }

        if (value & RNGC_CMD_BIT_SEED) {
            s->op_seed = OP_RUN;
            qemu_bh_schedule(s->seed_bh);
        }

        if (value & RNGC_CMD_BIT_SELF_TEST) {
            s->op_self_test = OP_RUN;
            qemu_bh_schedule(s->self_test_bh);
        }
        break;

    case RNGC_CONTROL:
        /*
         * The CTL_ACC and VERIF_MODE bits are not supported yet.
         * We ignore them if they're set by the caller.
         */

        if (value & RNGC_CTRL_BIT_MASK_ERR) {
            s->mask |= RNGC_CTRL_BIT_MASK_ERR;
        } else {
            s->mask &= ~RNGC_CTRL_BIT_MASK_ERR;
        }

        if (value & RNGC_CTRL_BIT_MASK_DONE) {
            s->mask |= RNGC_CTRL_BIT_MASK_DONE;
        } else {
            s->mask &= ~RNGC_CTRL_BIT_MASK_DONE;
        }

        if (value & RNGC_CTRL_BIT_AUTO_SEED) {
            s->auto_seed = true;
        } else {
            s->auto_seed = false;
        }
        break;
    }
}

static const MemoryRegionOps imx_rngc_ops = {
    .read  = imx_rngc_read,
    .write = imx_rngc_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
};

static void imx_rngc_self_test(void *opaque)
{
    IMXRNGCState *s = IMX_RNGC(opaque);

    s->op_self_test = OP_DONE;
    if (!(s->mask & RNGC_CTRL_BIT_MASK_DONE)) {
        qemu_irq_raise(s->irq);
    }
}

static void imx_rngc_seed(void *opaque)
{
    IMXRNGCState *s = IMX_RNGC(opaque);

    s->op_seed = OP_DONE;
    if (!(s->mask & RNGC_CTRL_BIT_MASK_DONE)) {
        qemu_irq_raise(s->irq);
    }
}

static void imx_rngc_realize(DeviceState *dev, Error **errp)
{
    IMXRNGCState *s = IMX_RNGC(dev);
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);

    memory_region_init_io(&s->iomem, OBJECT(s), &imx_rngc_ops, s,
                          TYPE_IMX_RNGC, 0x1000);
    sysbus_init_mmio(sbd, &s->iomem);

    sysbus_init_irq(sbd, &s->irq);
    s->self_test_bh = qemu_bh_new_guarded(imx_rngc_self_test, s,
                                          &dev->mem_reentrancy_guard);
    s->seed_bh = qemu_bh_new_guarded(imx_rngc_seed, s,
                                     &dev->mem_reentrancy_guard);
}

static void imx_rngc_reset(DeviceState *dev)
{
    IMXRNGCState *s = IMX_RNGC(dev);

    imx_rngc_do_reset(s);
}

static const VMStateDescription vmstate_imx_rngc = {
    .name = RNGC_NAME,
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (const VMStateField[]) {
        VMSTATE_UINT8(op_self_test, IMXRNGCState),
        VMSTATE_UINT8(op_seed, IMXRNGCState),
        VMSTATE_UINT8(mask, IMXRNGCState),
        VMSTATE_BOOL(auto_seed, IMXRNGCState),
        VMSTATE_END_OF_LIST()
    }
};

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

    dc->realize = imx_rngc_realize;
    dc->reset = imx_rngc_reset;
    dc->desc = RNGC_NAME,
    dc->vmsd = &vmstate_imx_rngc;
}

static const TypeInfo imx_rngc_info = {
    .name          = TYPE_IMX_RNGC,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(IMXRNGCState),
    .class_init    = imx_rngc_class_init,
};

static void imx_rngc_register_types(void)
{
    type_register_static(&imx_rngc_info);
}

type_init(imx_rngc_register_types)
