/*
 * Maxim MAX1110/1111 ADC chip emulation.
 *
 * Copyright (c) 2006 Openedhand Ltd.
 * Written by Andrzej Zaborowski <balrog@zabor.org>
 *
 * This code is licensed under the GNU GPLv2.
 *
 * Contributions after 2012-01-13 are licensed under the terms of the
 * GNU GPL, version 2 or (at your option) any later version.
 */

#include "qemu/osdep.h"
#include "hw/adc/max111x.h"
#include "hw/irq.h"
#include "migration/vmstate.h"
#include "qemu/module.h"
#include "hw/qdev-properties.h"

/* Control-byte bitfields */
#define CB_PD0		(1 << 0)
#define CB_PD1		(1 << 1)
#define CB_SGL		(1 << 2)
#define CB_UNI		(1 << 3)
#define CB_SEL0		(1 << 4)
#define CB_SEL1		(1 << 5)
#define CB_SEL2		(1 << 6)
#define CB_START	(1 << 7)

#define CHANNEL_NUM(v, b0, b1, b2)	\
                        ((((v) >> (2 + (b0))) & 4) |	\
                         (((v) >> (3 + (b1))) & 2) |	\
                         (((v) >> (4 + (b2))) & 1))

static uint32_t max111x_read(MAX111xState *s)
{
    if (!s->tb1)
        return 0;

    switch (s->cycle ++) {
    case 1:
        return s->rb2;
    case 2:
        return s->rb3;
    }

    return 0;
}

/* Interpret a control-byte */
static void max111x_write(MAX111xState *s, uint32_t value)
{
    int measure, chan;

    /* Ignore the value if START bit is zero */
    if (!(value & CB_START))
        return;

    s->cycle = 0;

    if (!(value & CB_PD1)) {
        s->tb1 = 0;
        return;
    }

    s->tb1 = value;

    if (s->inputs == 8)
        chan = CHANNEL_NUM(value, 1, 0, 2);
    else
        chan = CHANNEL_NUM(value & ~CB_SEL0, 0, 1, 2);

    if (value & CB_SGL)
        measure = s->input[chan] - s->com;
    else
        measure = s->input[chan] - s->input[chan ^ 1];

    if (!(value & CB_UNI))
        measure ^= 0x80;

    s->rb2 = (measure >> 2) & 0x3f;
    s->rb3 = (measure << 6) & 0xc0;

    /* FIXME: When should the IRQ be lowered?  */
    qemu_irq_raise(s->interrupt);
}

static uint32_t max111x_transfer(SSIPeripheral *dev, uint32_t value)
{
    MAX111xState *s = MAX_111X(dev);
    max111x_write(s, value);
    return max111x_read(s);
}

static const VMStateDescription vmstate_max111x = {
    .name = "max111x",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_SSI_PERIPHERAL(parent_obj, MAX111xState),
        VMSTATE_UINT8(tb1, MAX111xState),
        VMSTATE_UINT8(rb2, MAX111xState),
        VMSTATE_UINT8(rb3, MAX111xState),
        VMSTATE_INT32_EQUAL(inputs, MAX111xState, NULL),
        VMSTATE_INT32(com, MAX111xState),
        VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs,
                                   vmstate_info_uint8, uint8_t),
        VMSTATE_END_OF_LIST()
    }
};

static void max111x_input_set(void *opaque, int line, int value)
{
    MAX111xState *s = MAX_111X(opaque);

    assert(line >= 0 && line < s->inputs);
    s->input[line] = value;
}

static int max111x_init(SSIPeripheral *d, int inputs)
{
    DeviceState *dev = DEVICE(d);
    MAX111xState *s = MAX_111X(dev);

    qdev_init_gpio_out(dev, &s->interrupt, 1);
    qdev_init_gpio_in(dev, max111x_input_set, inputs);

    s->inputs = inputs;

    return 0;
}

static void max1110_realize(SSIPeripheral *dev, Error **errp)
{
    max111x_init(dev, 8);
}

static void max1111_realize(SSIPeripheral *dev, Error **errp)
{
    max111x_init(dev, 4);
}

static void max111x_reset(DeviceState *dev)
{
    MAX111xState *s = MAX_111X(dev);
    int i;

    for (i = 0; i < s->inputs; i++) {
        s->input[i] = s->reset_input[i];
    }
    s->com = 0;
    s->tb1 = 0;
    s->rb2 = 0;
    s->rb3 = 0;
    s->cycle = 0;
}

static Property max1110_properties[] = {
    /* Reset values for ADC inputs */
    DEFINE_PROP_UINT8("input0", MAX111xState, reset_input[0], 0xf0),
    DEFINE_PROP_UINT8("input1", MAX111xState, reset_input[1], 0xe0),
    DEFINE_PROP_UINT8("input2", MAX111xState, reset_input[2], 0xd0),
    DEFINE_PROP_UINT8("input3", MAX111xState, reset_input[3], 0xc0),
    DEFINE_PROP_END_OF_LIST(),
};

static Property max1111_properties[] = {
    /* Reset values for ADC inputs */
    DEFINE_PROP_UINT8("input0", MAX111xState, reset_input[0], 0xf0),
    DEFINE_PROP_UINT8("input1", MAX111xState, reset_input[1], 0xe0),
    DEFINE_PROP_UINT8("input2", MAX111xState, reset_input[2], 0xd0),
    DEFINE_PROP_UINT8("input3", MAX111xState, reset_input[3], 0xc0),
    DEFINE_PROP_UINT8("input4", MAX111xState, reset_input[4], 0xb0),
    DEFINE_PROP_UINT8("input5", MAX111xState, reset_input[5], 0xa0),
    DEFINE_PROP_UINT8("input6", MAX111xState, reset_input[6], 0x90),
    DEFINE_PROP_UINT8("input7", MAX111xState, reset_input[7], 0x80),
    DEFINE_PROP_END_OF_LIST(),
};

static void max111x_class_init(ObjectClass *klass, void *data)
{
    SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    k->transfer = max111x_transfer;
    dc->reset = max111x_reset;
    dc->vmsd = &vmstate_max111x;
    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}

static const TypeInfo max111x_info = {
    .name          = TYPE_MAX_111X,
    .parent        = TYPE_SSI_PERIPHERAL,
    .instance_size = sizeof(MAX111xState),
    .class_init    = max111x_class_init,
    .abstract      = true,
};

static void max1110_class_init(ObjectClass *klass, void *data)
{
    SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    k->realize = max1110_realize;
    device_class_set_props(dc, max1110_properties);
}

static const TypeInfo max1110_info = {
    .name          = TYPE_MAX_1110,
    .parent        = TYPE_MAX_111X,
    .class_init    = max1110_class_init,
};

static void max1111_class_init(ObjectClass *klass, void *data)
{
    SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    k->realize = max1111_realize;
    device_class_set_props(dc, max1111_properties);
}

static const TypeInfo max1111_info = {
    .name          = TYPE_MAX_1111,
    .parent        = TYPE_MAX_111X,
    .class_init    = max1111_class_init,
};

static void max111x_register_types(void)
{
    type_register_static(&max111x_info);
    type_register_static(&max1110_info);
    type_register_static(&max1111_info);
}

type_init(max111x_register_types)
