/* SPDX-License-Identifier: GPL-2.0-only */

/*
 * NXP PCF8574 8-port I2C GPIO expansion chip.
 * Copyright (c) 2024 KNS Group (YADRO).
 * Written by Dmitrii Sharikhin <d.sharikhin@yadro.com>
 */

#include "qemu/osdep.h"
#include "hw/i2c/i2c.h"
#include "hw/gpio/pcf8574.h"
#include "hw/irq.h"
#include "migration/vmstate.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "qom/object.h"

/*
 * PCF8574 and compatible chips incorporate quasi-bidirectional
 * IO. Electrically it means that device sustain pull-up to line
 * unless IO port is configured as output _and_ driven low.
 *
 * IO access is implemented as simple I2C single-byte read
 * or write operation. So, to configure line to input user write 1
 * to corresponding bit. To configure line to output and drive it low
 * user write 0 to corresponding bit.
 *
 * In essence, user can think of quasi-bidirectional IO as
 * open-drain line, except presence of builtin rising edge acceleration
 * embedded in PCF8574 IC
 *
 * PCF8574 has interrupt request line, which is being pulled down when
 * port line state differs from last read. Port read operation clears
 * state and INT line returns to high state via pullup.
 */

OBJECT_DECLARE_SIMPLE_TYPE(PCF8574State, PCF8574)

#define PORTS_COUNT (8)

struct PCF8574State {
    I2CSlave parent_obj;
    uint8_t  lastrq;     /* Last requested state. If changed - assert irq */
    uint8_t  input;      /* external electrical line state */
    uint8_t  output;     /* Pull-up (1) or drive low (0) on bit */
    qemu_irq handler[PORTS_COUNT];
    qemu_irq intrq;      /* External irq request */
};

static void pcf8574_reset(DeviceState *dev)
{
    PCF8574State *s = PCF8574(dev);
    s->lastrq = MAKE_64BIT_MASK(0, PORTS_COUNT);
    s->input  = MAKE_64BIT_MASK(0, PORTS_COUNT);
    s->output = MAKE_64BIT_MASK(0, PORTS_COUNT);
}

static inline uint8_t pcf8574_line_state(PCF8574State *s)
{
    /* we driving line low or external circuit does that */
    return s->input & s->output;
}

static uint8_t pcf8574_rx(I2CSlave *i2c)
{
    PCF8574State *s = PCF8574(i2c);
    uint8_t linestate = pcf8574_line_state(s);
    if (s->lastrq != linestate) {
        s->lastrq = linestate;
        if (s->intrq) {
            qemu_set_irq(s->intrq, 1);
        }
    }
    return linestate;
}

static int pcf8574_tx(I2CSlave *i2c, uint8_t data)
{
    PCF8574State *s = PCF8574(i2c);
    uint8_t prev;
    uint8_t diff;
    uint8_t actual;
    int line = 0;

    prev = pcf8574_line_state(s);
    s->output = data;
    actual = pcf8574_line_state(s);

    for (diff = (actual ^ prev); diff; diff &= ~(1 << line)) {
        line = ctz32(diff);
        if (s->handler[line]) {
            qemu_set_irq(s->handler[line], (actual >> line) & 1);
        }
    }

    if (s->intrq) {
        qemu_set_irq(s->intrq, actual == s->lastrq);
    }

    return 0;
}

static const VMStateDescription vmstate_pcf8574 = {
    .name               = "pcf8574",
    .version_id         = 0,
    .minimum_version_id = 0,
    .fields = (VMStateField[]) {
        VMSTATE_I2C_SLAVE(parent_obj, PCF8574State),
        VMSTATE_UINT8(lastrq, PCF8574State),
        VMSTATE_UINT8(input,  PCF8574State),
        VMSTATE_UINT8(output, PCF8574State),
        VMSTATE_END_OF_LIST()
    }
};

static void pcf8574_gpio_set(void *opaque, int line, int level)
{
    PCF8574State *s = (PCF8574State *) opaque;
    assert(line >= 0 && line < ARRAY_SIZE(s->handler));

    if (level) {
        s->input |=  (1 << line);
    } else {
        s->input &= ~(1 << line);
    }

    if (pcf8574_line_state(s) != s->lastrq && s->intrq) {
        qemu_set_irq(s->intrq, 0);
    }
}

static void pcf8574_realize(DeviceState *dev, Error **errp)
{
    PCF8574State *s = PCF8574(dev);

    qdev_init_gpio_in(dev, pcf8574_gpio_set, ARRAY_SIZE(s->handler));
    qdev_init_gpio_out(dev, s->handler, ARRAY_SIZE(s->handler));
    qdev_init_gpio_out_named(dev, &s->intrq, "nINT", 1);
}

static void pcf8574_class_init(ObjectClass *klass, void *data)
{
    DeviceClass   *dc = DEVICE_CLASS(klass);
    I2CSlaveClass *k  = I2C_SLAVE_CLASS(klass);

    k->recv     = pcf8574_rx;
    k->send     = pcf8574_tx;
    dc->realize = pcf8574_realize;
    device_class_set_legacy_reset(dc, pcf8574_reset);
    dc->vmsd    = &vmstate_pcf8574;
}

static const TypeInfo pcf8574_infos[] = {
    {
        .name          = TYPE_PCF8574,
        .parent        = TYPE_I2C_SLAVE,
        .instance_size = sizeof(PCF8574State),
        .class_init    = pcf8574_class_init,
    }
};

DEFINE_TYPES(pcf8574_infos);
