/*
 * Generic watchdog device model for SBSA
 *
 * The watchdog device has been implemented as revision 1 variant of
 * the ARM SBSA specification v6.0
 * (https://developer.arm.com/documentation/den0029/d?lang=en)
 *
 * Copyright Linaro.org 2020
 *
 * Authors:
 *  Shashi Mallela <shashi.mallela@linaro.org>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
 * option) any later version.  See the COPYING file in the top-level directory.
 *
 */

#include "qemu/osdep.h"
#include "sysemu/reset.h"
#include "sysemu/watchdog.h"
#include "hw/watchdog/sbsa_gwdt.h"
#include "qemu/timer.h"
#include "migration/vmstate.h"
#include "qemu/log.h"
#include "qemu/module.h"

static WatchdogTimerModel model = {
    .wdt_name = TYPE_WDT_SBSA,
    .wdt_description = "SBSA-compliant generic watchdog device",
};

static const VMStateDescription vmstate_sbsa_gwdt = {
    .name = "sbsa-gwdt",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_TIMER_PTR(timer, SBSA_GWDTState),
        VMSTATE_UINT32(wcs, SBSA_GWDTState),
        VMSTATE_UINT32(worl, SBSA_GWDTState),
        VMSTATE_UINT32(woru, SBSA_GWDTState),
        VMSTATE_UINT32(wcvl, SBSA_GWDTState),
        VMSTATE_UINT32(wcvu, SBSA_GWDTState),
        VMSTATE_END_OF_LIST()
    }
};

typedef enum WdtRefreshType {
    EXPLICIT_REFRESH = 0,
    TIMEOUT_REFRESH = 1,
} WdtRefreshType;

static uint64_t sbsa_gwdt_rread(void *opaque, hwaddr addr, unsigned int size)
{
    SBSA_GWDTState *s = SBSA_GWDT(opaque);
    uint32_t ret = 0;

    switch (addr) {
    case SBSA_GWDT_WRR:
        /* watch refresh read has no effect and returns 0 */
        ret = 0;
        break;
    case SBSA_GWDT_W_IIDR:
        ret = s->id;
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame read :"
                        " 0x%x\n", (int)addr);
    }
    return ret;
}

static uint64_t sbsa_gwdt_read(void *opaque, hwaddr addr, unsigned int size)
{
    SBSA_GWDTState *s = SBSA_GWDT(opaque);
    uint32_t ret = 0;

    switch (addr) {
    case SBSA_GWDT_WCS:
        ret = s->wcs;
        break;
    case SBSA_GWDT_WOR:
        ret = s->worl;
        break;
    case SBSA_GWDT_WORU:
         ret = s->woru;
         break;
    case SBSA_GWDT_WCV:
        ret = s->wcvl;
        break;
    case SBSA_GWDT_WCVU:
        ret = s->wcvu;
        break;
    case SBSA_GWDT_W_IIDR:
        ret = s->id;
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame read :"
                        " 0x%x\n", (int)addr);
    }
    return ret;
}

static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
{
    uint64_t timeout = 0;

    timer_del(s->timer);

    if (s->wcs & SBSA_GWDT_WCS_EN) {
        /*
         * Extract the upper 16 bits from woru & 32 bits from worl
         * registers to construct the 48 bit offset value
         */
        timeout = s->woru;
        timeout <<= 32;
        timeout |= s->worl;
        timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, SBSA_TIMER_FREQ);
        timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);

        if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
                (!(s->wcs & SBSA_GWDT_WCS_WS0)))) {
            /* store the current timeout value into compare registers */
            s->wcvu = timeout >> 32;
            s->wcvl = timeout;
        }
        timer_mod(s->timer, timeout);
    }
}

static void sbsa_gwdt_rwrite(void *opaque, hwaddr offset, uint64_t data,
                             unsigned size) {
    SBSA_GWDTState *s = SBSA_GWDT(opaque);

    if (offset == SBSA_GWDT_WRR) {
        s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);

        sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
    } else {
        qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame write :"
                        " 0x%x\n", (int)offset);
    }
}

static void sbsa_gwdt_write(void *opaque, hwaddr offset, uint64_t data,
                             unsigned size) {
    SBSA_GWDTState *s = SBSA_GWDT(opaque);

    switch (offset) {
    case SBSA_GWDT_WCS:
        s->wcs = data & SBSA_GWDT_WCS_EN;
        qemu_set_irq(s->irq, 0);
        sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
        break;

    case SBSA_GWDT_WOR:
        s->worl = data;
        s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
        qemu_set_irq(s->irq, 0);
        sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
        break;

    case SBSA_GWDT_WORU:
        s->woru = data & SBSA_GWDT_WOR_MASK;
        s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
        qemu_set_irq(s->irq, 0);
        sbsa_gwdt_update_timer(s, EXPLICIT_REFRESH);
        break;

    case SBSA_GWDT_WCV:
        s->wcvl = data;
        break;

    case SBSA_GWDT_WCVU:
        s->wcvu = data;
        break;

    default:
        qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame write :"
                " 0x%x\n", (int)offset);
    }
    return;
}

static void wdt_sbsa_gwdt_reset(DeviceState *dev)
{
    SBSA_GWDTState *s = SBSA_GWDT(dev);

    timer_del(s->timer);

    s->wcs  = 0;
    s->wcvl = 0;
    s->wcvu = 0;
    s->worl = 0;
    s->woru = 0;
    s->id = SBSA_GWDT_ID;
}

static void sbsa_gwdt_timer_sysinterrupt(void *opaque)
{
    SBSA_GWDTState *s = SBSA_GWDT(opaque);

    if (!(s->wcs & SBSA_GWDT_WCS_WS0)) {
        s->wcs |= SBSA_GWDT_WCS_WS0;
        sbsa_gwdt_update_timer(s, TIMEOUT_REFRESH);
        qemu_set_irq(s->irq, 1);
    } else {
        s->wcs |= SBSA_GWDT_WCS_WS1;
        qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
        /*
         * Reset the watchdog only if the guest gets notified about
         * expiry. watchdog_perform_action() may temporarily relinquish
         * the BQL; reset before triggering the action to avoid races with
         * sbsa_gwdt instructions.
         */
        switch (get_watchdog_action()) {
        case WATCHDOG_ACTION_DEBUG:
        case WATCHDOG_ACTION_NONE:
        case WATCHDOG_ACTION_PAUSE:
            break;
        default:
            wdt_sbsa_gwdt_reset(DEVICE(s));
        }
        watchdog_perform_action();
    }
}

static const MemoryRegionOps sbsa_gwdt_rops = {
    .read = sbsa_gwdt_rread,
    .write = sbsa_gwdt_rwrite,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
    .valid.unaligned = false,
};

static const MemoryRegionOps sbsa_gwdt_ops = {
    .read = sbsa_gwdt_read,
    .write = sbsa_gwdt_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
    .valid.unaligned = false,
};

static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
{
    SBSA_GWDTState *s = SBSA_GWDT(dev);
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);

    memory_region_init_io(&s->rmmio, OBJECT(dev),
                          &sbsa_gwdt_rops, s,
                          "sbsa_gwdt.refresh",
                          SBSA_GWDT_RMMIO_SIZE);

    memory_region_init_io(&s->cmmio, OBJECT(dev),
                          &sbsa_gwdt_ops, s,
                          "sbsa_gwdt.control",
                          SBSA_GWDT_CMMIO_SIZE);

    sysbus_init_mmio(sbd, &s->rmmio);
    sysbus_init_mmio(sbd, &s->cmmio);

    sysbus_init_irq(sbd, &s->irq);

    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sbsa_gwdt_timer_sysinterrupt,
                dev);
}

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

    dc->realize = wdt_sbsa_gwdt_realize;
    dc->reset = wdt_sbsa_gwdt_reset;
    dc->hotpluggable = false;
    set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
    dc->vmsd = &vmstate_sbsa_gwdt;
    dc->desc = "SBSA-compliant generic watchdog device";
}

static const TypeInfo wdt_sbsa_gwdt_info = {
    .class_init = wdt_sbsa_gwdt_class_init,
    .parent = TYPE_SYS_BUS_DEVICE,
    .name  = TYPE_WDT_SBSA,
    .instance_size  = sizeof(SBSA_GWDTState),
};

static void wdt_sbsa_gwdt_register_types(void)
{
    watchdog_add_model(&model);
    type_register_static(&wdt_sbsa_gwdt_info);
}

type_init(wdt_sbsa_gwdt_register_types)
