/*
 * Motorola ColdFire MCF5206 SoC embedded peripheral emulation.
 *
 * Copyright (c) 2007 CodeSourcery.
 *
 * This code is licensed under the GPL
 */
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "cpu.h"
#include "hw/hw.h"
#include "hw/m68k/mcf.h"
#include "qemu/timer.h"
#include "hw/ptimer.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"

/* General purpose timer module.  */
typedef struct {
    uint16_t tmr;
    uint16_t trr;
    uint16_t tcr;
    uint16_t ter;
    ptimer_state *timer;
    qemu_irq irq;
    int irq_state;
} m5206_timer_state;

#define TMR_RST 0x01
#define TMR_CLK 0x06
#define TMR_FRR 0x08
#define TMR_ORI 0x10
#define TMR_OM  0x20
#define TMR_CE  0xc0

#define TER_CAP 0x01
#define TER_REF 0x02

static void m5206_timer_update(m5206_timer_state *s)
{
    if ((s->tmr & TMR_ORI) != 0 && (s->ter & TER_REF))
        qemu_irq_raise(s->irq);
    else
        qemu_irq_lower(s->irq);
}

static void m5206_timer_reset(m5206_timer_state *s)
{
    s->tmr = 0;
    s->trr = 0;
}

static void m5206_timer_recalibrate(m5206_timer_state *s)
{
    int prescale;
    int mode;

    ptimer_stop(s->timer);

    if ((s->tmr & TMR_RST) == 0)
        return;

    prescale = (s->tmr >> 8) + 1;
    mode = (s->tmr >> 1) & 3;
    if (mode == 2)
        prescale *= 16;

    if (mode == 3 || mode == 0)
        hw_error("m5206_timer: mode %d not implemented\n", mode);
    if ((s->tmr & TMR_FRR) == 0)
        hw_error("m5206_timer: free running mode not implemented\n");

    /* Assume 66MHz system clock.  */
    ptimer_set_freq(s->timer, 66000000 / prescale);

    ptimer_set_limit(s->timer, s->trr, 0);

    ptimer_run(s->timer, 0);
}

static void m5206_timer_trigger(void *opaque)
{
    m5206_timer_state *s = (m5206_timer_state *)opaque;
    s->ter |= TER_REF;
    m5206_timer_update(s);
}

static uint32_t m5206_timer_read(m5206_timer_state *s, uint32_t addr)
{
    switch (addr) {
    case 0:
        return s->tmr;
    case 4:
        return s->trr;
    case 8:
        return s->tcr;
    case 0xc:
        return s->trr - ptimer_get_count(s->timer);
    case 0x11:
        return s->ter;
    default:
        return 0;
    }
}

static void m5206_timer_write(m5206_timer_state *s, uint32_t addr, uint32_t val)
{
    switch (addr) {
    case 0:
        if ((s->tmr & TMR_RST) != 0 && (val & TMR_RST) == 0) {
            m5206_timer_reset(s);
        }
        s->tmr = val;
        m5206_timer_recalibrate(s);
        break;
    case 4:
        s->trr = val;
        m5206_timer_recalibrate(s);
        break;
    case 8:
        s->tcr = val;
        break;
    case 0xc:
        ptimer_set_count(s->timer, val);
        break;
    case 0x11:
        s->ter &= ~val;
        break;
    default:
        break;
    }
    m5206_timer_update(s);
}

static m5206_timer_state *m5206_timer_init(qemu_irq irq)
{
    m5206_timer_state *s;
    QEMUBH *bh;

    s = (m5206_timer_state *)g_malloc0(sizeof(m5206_timer_state));
    bh = qemu_bh_new(m5206_timer_trigger, s);
    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
    s->irq = irq;
    m5206_timer_reset(s);
    return s;
}

/* System Integration Module.  */

typedef struct {
    M68kCPU *cpu;
    MemoryRegion iomem;
    m5206_timer_state *timer[2];
    void *uart[2];
    uint8_t scr;
    uint8_t icr[14];
    uint16_t imr; /* 1 == interrupt is masked.  */
    uint16_t ipr;
    uint8_t rsr;
    uint8_t swivr;
    uint8_t par;
    /* Include the UART vector registers here.  */
    uint8_t uivr[2];
} m5206_mbar_state;

/* Interrupt controller.  */

static int m5206_find_pending_irq(m5206_mbar_state *s)
{
    int level;
    int vector;
    uint16_t active;
    int i;

    level = 0;
    vector = 0;
    active = s->ipr & ~s->imr;
    if (!active)
        return 0;

    for (i = 1; i < 14; i++) {
        if (active & (1 << i)) {
            if ((s->icr[i] & 0x1f) > level) {
                level = s->icr[i] & 0x1f;
                vector = i;
            }
        }
    }

    if (level < 4)
        vector = 0;

    return vector;
}

static void m5206_mbar_update(m5206_mbar_state *s)
{
    int irq;
    int vector;
    int level;

    irq = m5206_find_pending_irq(s);
    if (irq) {
        int tmp;
        tmp = s->icr[irq];
        level = (tmp >> 2) & 7;
        if (tmp & 0x80) {
            /* Autovector.  */
            vector = 24 + level;
        } else {
            switch (irq) {
            case 8: /* SWT */
                vector = s->swivr;
                break;
            case 12: /* UART1 */
                vector = s->uivr[0];
                break;
            case 13: /* UART2 */
                vector = s->uivr[1];
                break;
            default:
                /* Unknown vector.  */
                fprintf(stderr, "Unhandled vector for IRQ %d\n", irq);
                vector = 0xf;
                break;
            }
        }
    } else {
        level = 0;
        vector = 0;
    }
    m68k_set_irq_level(s->cpu, level, vector);
}

static void m5206_mbar_set_irq(void *opaque, int irq, int level)
{
    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
    if (level) {
        s->ipr |= 1 << irq;
    } else {
        s->ipr &= ~(1 << irq);
    }
    m5206_mbar_update(s);
}

/* System Integration Module.  */

static void m5206_mbar_reset(m5206_mbar_state *s)
{
    s->scr = 0xc0;
    s->icr[1] = 0x04;
    s->icr[2] = 0x08;
    s->icr[3] = 0x0c;
    s->icr[4] = 0x10;
    s->icr[5] = 0x14;
    s->icr[6] = 0x18;
    s->icr[7] = 0x1c;
    s->icr[8] = 0x1c;
    s->icr[9] = 0x80;
    s->icr[10] = 0x80;
    s->icr[11] = 0x80;
    s->icr[12] = 0x00;
    s->icr[13] = 0x00;
    s->imr = 0x3ffe;
    s->rsr = 0x80;
    s->swivr = 0x0f;
    s->par = 0;
}

static uint64_t m5206_mbar_read(m5206_mbar_state *s,
                                uint64_t offset, unsigned size)
{
    if (offset >= 0x100 && offset < 0x120) {
        return m5206_timer_read(s->timer[0], offset - 0x100);
    } else if (offset >= 0x120 && offset < 0x140) {
        return m5206_timer_read(s->timer[1], offset - 0x120);
    } else if (offset >= 0x140 && offset < 0x160) {
        return mcf_uart_read(s->uart[0], offset - 0x140, size);
    } else if (offset >= 0x180 && offset < 0x1a0) {
        return mcf_uart_read(s->uart[1], offset - 0x180, size);
    }
    switch (offset) {
    case 0x03: return s->scr;
    case 0x14 ... 0x20: return s->icr[offset - 0x13];
    case 0x36: return s->imr;
    case 0x3a: return s->ipr;
    case 0x40: return s->rsr;
    case 0x41: return 0;
    case 0x42: return s->swivr;
    case 0x50:
        /* DRAM mask register.  */
        /* FIXME: currently hardcoded to 128Mb.  */
        {
            uint32_t mask = ~0;
            while (mask > ram_size)
                mask >>= 1;
            return mask & 0x0ffe0000;
        }
    case 0x5c: return 1; /* DRAM bank 1 empty.  */
    case 0xcb: return s->par;
    case 0x170: return s->uivr[0];
    case 0x1b0: return s->uivr[1];
    }
    hw_error("Bad MBAR read offset 0x%x", (int)offset);
    return 0;
}

static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
                             uint64_t value, unsigned size)
{
    if (offset >= 0x100 && offset < 0x120) {
        m5206_timer_write(s->timer[0], offset - 0x100, value);
        return;
    } else if (offset >= 0x120 && offset < 0x140) {
        m5206_timer_write(s->timer[1], offset - 0x120, value);
        return;
    } else if (offset >= 0x140 && offset < 0x160) {
        mcf_uart_write(s->uart[0], offset - 0x140, value, size);
        return;
    } else if (offset >= 0x180 && offset < 0x1a0) {
        mcf_uart_write(s->uart[1], offset - 0x180, value, size);
        return;
    }
    switch (offset) {
    case 0x03:
        s->scr = value;
        break;
    case 0x14 ... 0x20:
        s->icr[offset - 0x13] = value;
        m5206_mbar_update(s);
        break;
    case 0x36:
        s->imr = value;
        m5206_mbar_update(s);
        break;
    case 0x40:
        s->rsr &= ~value;
        break;
    case 0x41:
        /* TODO: implement watchdog.  */
        break;
    case 0x42:
        s->swivr = value;
        break;
    case 0xcb:
        s->par = value;
        break;
    case 0x170:
        s->uivr[0] = value;
        break;
    case 0x178: case 0x17c: case 0x1c8: case 0x1bc:
        /* Not implemented: UART Output port bits.  */
        break;
    case 0x1b0:
        s->uivr[1] = value;
        break;
    default:
        hw_error("Bad MBAR write offset 0x%x", (int)offset);
        break;
    }
}

/* Internal peripherals use a variety of register widths.
   This lookup table allows a single routine to handle all of them.  */
static const uint8_t m5206_mbar_width[] =
{
  /* 000-040 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  2, 2, 2, 2,
  /* 040-080 */ 1, 2, 2, 2,  4, 1, 2, 4,  1, 2, 4, 2,  2, 4, 2, 2,
  /* 080-0c0 */ 4, 2, 2, 4,  2, 2, 4, 2,  2, 4, 2, 2,  4, 2, 2, 4,
  /* 0c0-100 */ 2, 2, 1, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,
  /* 100-140 */ 2, 2, 2, 2,  1, 0, 0, 0,  2, 2, 2, 2,  1, 0, 0, 0,
  /* 140-180 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
  /* 180-1c0 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
  /* 1c0-200 */ 1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
};

static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset);
static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset);

static uint32_t m5206_mbar_readb(void *opaque, hwaddr offset)
{
    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
    offset &= 0x3ff;
    if (offset >= 0x200) {
        hw_error("Bad MBAR read offset 0x%x", (int)offset);
    }
    if (m5206_mbar_width[offset >> 2] > 1) {
        uint16_t val;
        val = m5206_mbar_readw(opaque, offset & ~1);
        if ((offset & 1) == 0) {
            val >>= 8;
        }
        return val & 0xff;
    }
    return m5206_mbar_read(s, offset, 1);
}

static uint32_t m5206_mbar_readw(void *opaque, hwaddr offset)
{
    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
    int width;
    offset &= 0x3ff;
    if (offset >= 0x200) {
        hw_error("Bad MBAR read offset 0x%x", (int)offset);
    }
    width = m5206_mbar_width[offset >> 2];
    if (width > 2) {
        uint32_t val;
        val = m5206_mbar_readl(opaque, offset & ~3);
        if ((offset & 3) == 0)
            val >>= 16;
        return val & 0xffff;
    } else if (width < 2) {
        uint16_t val;
        val = m5206_mbar_readb(opaque, offset) << 8;
        val |= m5206_mbar_readb(opaque, offset + 1);
        return val;
    }
    return m5206_mbar_read(s, offset, 2);
}

static uint32_t m5206_mbar_readl(void *opaque, hwaddr offset)
{
    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
    int width;
    offset &= 0x3ff;
    if (offset >= 0x200) {
        hw_error("Bad MBAR read offset 0x%x", (int)offset);
    }
    width = m5206_mbar_width[offset >> 2];
    if (width < 4) {
        uint32_t val;
        val = m5206_mbar_readw(opaque, offset) << 16;
        val |= m5206_mbar_readw(opaque, offset + 2);
        return val;
    }
    return m5206_mbar_read(s, offset, 4);
}

static void m5206_mbar_writew(void *opaque, hwaddr offset,
                              uint32_t value);
static void m5206_mbar_writel(void *opaque, hwaddr offset,
                              uint32_t value);

static void m5206_mbar_writeb(void *opaque, hwaddr offset,
                              uint32_t value)
{
    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
    int width;
    offset &= 0x3ff;
    if (offset >= 0x200) {
        hw_error("Bad MBAR write offset 0x%x", (int)offset);
    }
    width = m5206_mbar_width[offset >> 2];
    if (width > 1) {
        uint32_t tmp;
        tmp = m5206_mbar_readw(opaque, offset & ~1);
        if (offset & 1) {
            tmp = (tmp & 0xff00) | value;
        } else {
            tmp = (tmp & 0x00ff) | (value << 8);
        }
        m5206_mbar_writew(opaque, offset & ~1, tmp);
        return;
    }
    m5206_mbar_write(s, offset, value, 1);
}

static void m5206_mbar_writew(void *opaque, hwaddr offset,
                              uint32_t value)
{
    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
    int width;
    offset &= 0x3ff;
    if (offset >= 0x200) {
        hw_error("Bad MBAR write offset 0x%x", (int)offset);
    }
    width = m5206_mbar_width[offset >> 2];
    if (width > 2) {
        uint32_t tmp;
        tmp = m5206_mbar_readl(opaque, offset & ~3);
        if (offset & 3) {
            tmp = (tmp & 0xffff0000) | value;
        } else {
            tmp = (tmp & 0x0000ffff) | (value << 16);
        }
        m5206_mbar_writel(opaque, offset & ~3, tmp);
        return;
    } else if (width < 2) {
        m5206_mbar_writeb(opaque, offset, value >> 8);
        m5206_mbar_writeb(opaque, offset + 1, value & 0xff);
        return;
    }
    m5206_mbar_write(s, offset, value, 2);
}

static void m5206_mbar_writel(void *opaque, hwaddr offset,
                              uint32_t value)
{
    m5206_mbar_state *s = (m5206_mbar_state *)opaque;
    int width;
    offset &= 0x3ff;
    if (offset >= 0x200) {
        hw_error("Bad MBAR write offset 0x%x", (int)offset);
    }
    width = m5206_mbar_width[offset >> 2];
    if (width < 4) {
        m5206_mbar_writew(opaque, offset, value >> 16);
        m5206_mbar_writew(opaque, offset + 2, value & 0xffff);
        return;
    }
    m5206_mbar_write(s, offset, value, 4);
}

static const MemoryRegionOps m5206_mbar_ops = {
    .old_mmio = {
        .read = {
            m5206_mbar_readb,
            m5206_mbar_readw,
            m5206_mbar_readl,
        },
        .write = {
            m5206_mbar_writeb,
            m5206_mbar_writew,
            m5206_mbar_writel,
        },
    },
    .endianness = DEVICE_NATIVE_ENDIAN,
};

qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, M68kCPU *cpu)
{
    m5206_mbar_state *s;
    qemu_irq *pic;

    s = (m5206_mbar_state *)g_malloc0(sizeof(m5206_mbar_state));

    memory_region_init_io(&s->iomem, NULL, &m5206_mbar_ops, s,
                          "mbar", 0x00001000);
    memory_region_add_subregion(sysmem, base, &s->iomem);

    pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14);
    s->timer[0] = m5206_timer_init(pic[9]);
    s->timer[1] = m5206_timer_init(pic[10]);
    s->uart[0] = mcf_uart_init(pic[12], serial_hds[0]);
    s->uart[1] = mcf_uart_init(pic[13], serial_hds[1]);
    s->cpu = cpu;

    m5206_mbar_reset(s);
    return pic;
}
