/* Copyright (C) 2007-2008 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program 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 General Public License for more details.
*/
#include "migration/qemu-file.h"
#include "hw/arm/pic.h"
#include "hw/android/goldfish/device.h"
#include "hw/irq.h"
#include "hw/hw.h"

enum {
    INTERRUPT_STATUS        = 0x00, // number of pending interrupts
    INTERRUPT_NUMBER        = 0x04,
    INTERRUPT_DISABLE_ALL   = 0x08,
    INTERRUPT_DISABLE       = 0x0c,
    INTERRUPT_ENABLE        = 0x10
};

struct goldfish_int_state {
    struct goldfish_device dev;
    uint32_t level;
    uint32_t pending_count;
    uint32_t irq_enabled;
    uint32_t fiq_enabled;
    qemu_irq parent_irq;
    qemu_irq parent_fiq;
};

#define  GOLDFISH_INT_SAVE_VERSION  1

#define  QFIELD_STRUCT  struct goldfish_int_state
QFIELD_BEGIN(goldfish_int_fields)
    QFIELD_INT32(level),
    QFIELD_INT32(pending_count),
    QFIELD_INT32(irq_enabled),
    QFIELD_INT32(fiq_enabled),
QFIELD_END

static void goldfish_int_save(QEMUFile*  f, void*  opaque)
{
    struct goldfish_int_state*  s = opaque;

    qemu_put_struct(f, goldfish_int_fields, s);
}

static int  goldfish_int_load(QEMUFile*  f, void*  opaque, int  version_id)
{
    struct goldfish_int_state*  s = opaque;

    if (version_id != GOLDFISH_INT_SAVE_VERSION)
        return -1;

    return qemu_get_struct(f, goldfish_int_fields, s);
}

static void goldfish_int_update(struct goldfish_int_state *s)
{
    uint32_t flags;

    flags = (s->level & s->irq_enabled);
    qemu_set_irq(s->parent_irq, flags != 0);

    flags = (s->level & s->fiq_enabled);
    qemu_set_irq(s->parent_fiq, flags != 0);
}

static void goldfish_int_set_irq(void *opaque, int irq, int level)
{
    struct goldfish_int_state *s = (struct goldfish_int_state *)opaque;
    uint32_t mask = (1U << irq);

    if(level) {
        if(!(s->level & mask)) {
            if(s->irq_enabled & mask)
                s->pending_count++;
            s->level |= mask;
        }
    }
    else {
        if(s->level & mask) {
            if(s->irq_enabled & mask)
                s->pending_count--;
            s->level &= ~mask;
        }
    }
    goldfish_int_update(s);
}

static uint32_t goldfish_int_read(void *opaque, hwaddr offset)
{
    struct goldfish_int_state *s = (struct goldfish_int_state *)opaque;

    switch (offset) {
    case INTERRUPT_STATUS: /* IRQ_STATUS */
        return s->pending_count;
    case INTERRUPT_NUMBER: {
        int i;
        uint32_t pending = s->level & s->irq_enabled;
        for(i = 0; i < 32; i++) {
            if(pending & (1U << i))
                return i;
        }
        return 0;
    }
    default:
        cpu_abort (cpu_single_env, "goldfish_int_read: Bad offset %x\n", offset);
        return 0;
    }
}

static void goldfish_int_write(void *opaque, hwaddr offset, uint32_t value)
{
    struct goldfish_int_state *s = (struct goldfish_int_state *)opaque;
    uint32_t mask = (1U << value);

    switch (offset) {
        case INTERRUPT_DISABLE_ALL:
            s->pending_count = 0;
            s->level = 0;
            break;

        case INTERRUPT_DISABLE:
            if(s->irq_enabled & mask) {
                if(s->level & mask)
                    s->pending_count--;
                s->irq_enabled &= ~mask;
            }
            break;
        case INTERRUPT_ENABLE:
            if(!(s->irq_enabled & mask)) {
                s->irq_enabled |= mask;
                if(s->level & mask)
                    s->pending_count++;
            }
            break;

    default:
        cpu_abort (cpu_single_env, "goldfish_int_write: Bad offset %x\n", offset);
        return;
    }
    goldfish_int_update(s);
}

static CPUReadMemoryFunc *goldfish_int_readfn[] = {
    goldfish_int_read,
    goldfish_int_read,
    goldfish_int_read
};

static CPUWriteMemoryFunc *goldfish_int_writefn[] = {
    goldfish_int_write,
    goldfish_int_write,
    goldfish_int_write
};

qemu_irq*  goldfish_interrupt_init(uint32_t base, qemu_irq parent_irq, qemu_irq parent_fiq)
{
    int ret;
    struct goldfish_int_state *s;
    qemu_irq*  qi;

    s = g_malloc0(sizeof(*s));
    qi = qemu_allocate_irqs(goldfish_int_set_irq, s, GFD_MAX_IRQ);
    s->dev.name = "goldfish_interrupt_controller";
    s->dev.id = -1;
    s->dev.base = base;
    s->dev.size = 0x1000;
    s->parent_irq = parent_irq;
    s->parent_fiq = parent_fiq;

    ret = goldfish_device_add(&s->dev, goldfish_int_readfn, goldfish_int_writefn, s);
    if(ret) {
        g_free(s);
        return NULL;
    }

    register_savevm(NULL,
                    "goldfish_int",
                    0,
                    GOLDFISH_INT_SAVE_VERSION,
                    goldfish_int_save,
                    goldfish_int_load,
                    s);

    return qi;
}

