/*
 * QEMU ICH9 TCO emulation
 *
 * Copyright (c) 2015 Paulo Alcantara <pcacjr@zytor.com>
 *
 * 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 "sysemu/watchdog.h"
#include "hw/i386/ich9.h"
#include "migration/vmstate.h"

#include "hw/acpi/ich9_tco.h"
#include "trace.h"

enum {
    TCO_RLD_DEFAULT         = 0x0000,
    TCO_DAT_IN_DEFAULT      = 0x00,
    TCO_DAT_OUT_DEFAULT     = 0x00,
    TCO1_STS_DEFAULT        = 0x0000,
    TCO2_STS_DEFAULT        = 0x0000,
    TCO1_CNT_DEFAULT        = 0x0000,
    TCO2_CNT_DEFAULT        = 0x0008,
    TCO_MESSAGE1_DEFAULT    = 0x00,
    TCO_MESSAGE2_DEFAULT    = 0x00,
    TCO_WDCNT_DEFAULT       = 0x00,
    TCO_TMR_DEFAULT         = 0x0004,
    SW_IRQ_GEN_DEFAULT      = 0x03,
};

static inline void tco_timer_reload(TCOIORegs *tr)
{
    int ticks = tr->tco.tmr & TCO_TMR_MASK;
    int64_t nsec = (int64_t)ticks * TCO_TICK_NSEC;

    trace_tco_timer_reload(ticks, nsec / 1000000);
    tr->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + nsec;
    timer_mod(tr->tco_timer, tr->expire_time);
}

static inline void tco_timer_stop(TCOIORegs *tr)
{
    tr->expire_time = -1;
    timer_del(tr->tco_timer);
}

static void tco_timer_expired(void *opaque)
{
    TCOIORegs *tr = opaque;
    ICH9LPCPMRegs *pm = container_of(tr, ICH9LPCPMRegs, tco_regs);
    ICH9LPCState *lpc = container_of(pm, ICH9LPCState, pm);
    uint32_t gcs = pci_get_long(lpc->chip_config + ICH9_CC_GCS);

    trace_tco_timer_expired(tr->timeouts_no,
                            lpc->pin_strap.spkr_hi,
                            !!(gcs & ICH9_CC_GCS_NO_REBOOT));
    tr->tco.rld = 0;
    tr->tco.sts1 |= TCO_TIMEOUT;
    if (++tr->timeouts_no == 2) {
        tr->tco.sts2 |= TCO_SECOND_TO_STS;
        tr->tco.sts2 |= TCO_BOOT_STS;
        tr->timeouts_no = 0;

        if (!lpc->pin_strap.spkr_hi && !(gcs & ICH9_CC_GCS_NO_REBOOT)) {
            watchdog_perform_action();
            tco_timer_stop(tr);
            return;
        }
    }

    if (pm->smi_en & ICH9_PMIO_SMI_EN_TCO_EN) {
        ich9_generate_smi();
    }
    tr->tco.rld = tr->tco.tmr;
    tco_timer_reload(tr);
}

/* NOTE: values of 0 or 1 will be ignored by ICH */
static inline int can_start_tco_timer(TCOIORegs *tr)
{
    return !(tr->tco.cnt1 & TCO_TMR_HLT) && tr->tco.tmr > 1;
}

static uint32_t tco_ioport_readw(TCOIORegs *tr, uint32_t addr)
{
    uint16_t rld;
    uint32_t ret = 0;

    switch (addr) {
    case TCO_RLD:
        if (tr->expire_time != -1) {
            int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
            int64_t elapsed = (tr->expire_time - now) / TCO_TICK_NSEC;
            rld = (uint16_t)elapsed | (tr->tco.rld & ~TCO_RLD_MASK);
        } else {
            rld = tr->tco.rld;
        }
        ret = rld;
        break;
    case TCO_DAT_IN:
        ret = tr->tco.din;
        break;
    case TCO_DAT_OUT:
        ret = tr->tco.dout;
        break;
    case TCO1_STS:
        ret = tr->tco.sts1;
        break;
    case TCO2_STS:
        ret = tr->tco.sts2;
        break;
    case TCO1_CNT:
        ret = tr->tco.cnt1;
        break;
    case TCO2_CNT:
        ret = tr->tco.cnt2;
        break;
    case TCO_MESSAGE1:
        ret = tr->tco.msg1;
        break;
    case TCO_MESSAGE2:
        ret = tr->tco.msg2;
        break;
    case TCO_WDCNT:
        ret = tr->tco.wdcnt;
        break;
    case TCO_TMR:
        ret = tr->tco.tmr;
        break;
    case SW_IRQ_GEN:
        ret = tr->sw_irq_gen;
        break;
    }
    trace_tco_io_read(addr, ret);
    return ret;
}

static void tco_ioport_writew(TCOIORegs *tr, uint32_t addr, uint32_t val)
{
    trace_tco_io_write(addr, val);
    switch (addr) {
    case TCO_RLD:
        tr->timeouts_no = 0;
        if (can_start_tco_timer(tr)) {
            tr->tco.rld = tr->tco.tmr;
            tco_timer_reload(tr);
        } else {
            tr->tco.rld = val;
        }
        break;
    case TCO_DAT_IN:
        tr->tco.din = val;
        tr->tco.sts1 |= SW_TCO_SMI;
        ich9_generate_smi();
        break;
    case TCO_DAT_OUT:
        tr->tco.dout = val;
        tr->tco.sts1 |= TCO_INT_STS;
        /* TODO: cause an interrupt, as selected by the TCO_INT_SEL bits */
        break;
    case TCO1_STS:
        tr->tco.sts1 = val & TCO1_STS_MASK;
        break;
    case TCO2_STS:
        tr->tco.sts2 = val & TCO2_STS_MASK;
        break;
    case TCO1_CNT:
        val &= TCO1_CNT_MASK;
        /*
         * once TCO_LOCK bit is set, it can not be cleared by software. a reset
         * is required to change this bit from 1 to 0 -- it defaults to 0.
         */
        tr->tco.cnt1 = val | (tr->tco.cnt1 & TCO_LOCK);
        if (can_start_tco_timer(tr)) {
            tr->tco.rld = tr->tco.tmr;
            tco_timer_reload(tr);
        } else {
            tco_timer_stop(tr);
        }
        break;
    case TCO2_CNT:
        tr->tco.cnt2 = val;
        break;
    case TCO_MESSAGE1:
        tr->tco.msg1 = val;
        break;
    case TCO_MESSAGE2:
        tr->tco.msg2 = val;
        break;
    case TCO_WDCNT:
        tr->tco.wdcnt = val;
        break;
    case TCO_TMR:
        tr->tco.tmr = val;
        break;
    case SW_IRQ_GEN:
        tr->sw_irq_gen = val;
        break;
    }
}

static uint64_t tco_io_readw(void *opaque, hwaddr addr, unsigned width)
{
    TCOIORegs *tr = opaque;
    return tco_ioport_readw(tr, addr);
}

static void tco_io_writew(void *opaque, hwaddr addr, uint64_t val,
                          unsigned width)
{
    TCOIORegs *tr = opaque;
    tco_ioport_writew(tr, addr, val);
}

static const MemoryRegionOps tco_io_ops = {
    .read = tco_io_readw,
    .write = tco_io_writew,
    .valid.min_access_size = 1,
    .valid.max_access_size = 4,
    .impl.min_access_size = 1,
    .impl.max_access_size = 2,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

void acpi_pm_tco_init(TCOIORegs *tr, MemoryRegion *parent)
{
    *tr = (TCOIORegs) {
        .tco = {
            .rld      = TCO_RLD_DEFAULT,
            .din      = TCO_DAT_IN_DEFAULT,
            .dout     = TCO_DAT_OUT_DEFAULT,
            .sts1     = TCO1_STS_DEFAULT,
            .sts2     = TCO2_STS_DEFAULT,
            .cnt1     = TCO1_CNT_DEFAULT,
            .cnt2     = TCO2_CNT_DEFAULT,
            .msg1     = TCO_MESSAGE1_DEFAULT,
            .msg2     = TCO_MESSAGE2_DEFAULT,
            .wdcnt    = TCO_WDCNT_DEFAULT,
            .tmr      = TCO_TMR_DEFAULT,
        },
        .sw_irq_gen    = SW_IRQ_GEN_DEFAULT,
        .tco_timer     = timer_new_ns(QEMU_CLOCK_VIRTUAL, tco_timer_expired, tr),
        .expire_time   = -1,
        .timeouts_no   = 0,
    };
    memory_region_init_io(&tr->io, memory_region_owner(parent),
                          &tco_io_ops, tr, "sm-tco", ICH9_PMIO_TCO_LEN);
    memory_region_add_subregion(parent, ICH9_PMIO_TCO_RLD, &tr->io);
}

const VMStateDescription vmstate_tco_io_sts = {
    .name = "tco io device status",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields      = (VMStateField[]) {
        VMSTATE_UINT16(tco.rld, TCOIORegs),
        VMSTATE_UINT8(tco.din, TCOIORegs),
        VMSTATE_UINT8(tco.dout, TCOIORegs),
        VMSTATE_UINT16(tco.sts1, TCOIORegs),
        VMSTATE_UINT16(tco.sts2, TCOIORegs),
        VMSTATE_UINT16(tco.cnt1, TCOIORegs),
        VMSTATE_UINT16(tco.cnt2, TCOIORegs),
        VMSTATE_UINT8(tco.msg1, TCOIORegs),
        VMSTATE_UINT8(tco.msg2, TCOIORegs),
        VMSTATE_UINT8(tco.wdcnt, TCOIORegs),
        VMSTATE_UINT16(tco.tmr, TCOIORegs),
        VMSTATE_UINT8(sw_irq_gen, TCOIORegs),
        VMSTATE_TIMER_PTR(tco_timer, TCOIORegs),
        VMSTATE_INT64(expire_time, TCOIORegs),
        VMSTATE_UINT8(timeouts_no, TCOIORegs),
        VMSTATE_END_OF_LIST()
    }
};
