// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <ddk/device.h>
#include <ddk/driver.h>
#include <hw/reg.h>
#include <zircon/types.h>
#include <zircon/device/i2c.h>
#include <zircon/listnode.h>
#include <zircon/thread_annotations.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>

#include "intel-i2c-controller.h"
#include "intel-i2c-slave.h"

// Time out after 2 seconds.
static const zx_duration_t timeout_ns = ZX_SEC(2);

//TODO We should be using interrupts during long operations, but
//the plumbing isn't all there for that apparently.
#define DO_UNTIL(condition, action, poll_interval)                            \
    ({                                                                        \
        const zx_time_t deadline = zx_deadline_after(timeout_ns);             \
        int wait_for_condition_value;                                         \
        while (!(wait_for_condition_value = !!(condition))) {                 \
            zx_time_t now = zx_clock_get_monotonic();                 \
            if (now >= deadline)                                              \
                break;                                                        \
            if (poll_interval)                                                \
                zx_nanosleep(zx_deadline_after(poll_interval));               \
            {action;}                                                         \
        }                                                                     \
        wait_for_condition_value;                                             \
    })

#define WAIT_FOR(condition, poll_interval) DO_UNTIL(condition, , poll_interval)

// This is a controller implementation constant.  This value is likely lower
// than reality, but it is a conservative choice.
// TODO(teisenbe): Discover this/look it up from a table
const uint32_t kRxFifoDepth = 8;

// Implement the functionality of the i2c slave devices.

static int bus_is_idle(intel_serialio_i2c_device_t *controller) {
    uint32_t i2c_sta = readl(&controller->regs->i2c_sta);
    return !(i2c_sta & (0x1 << I2C_STA_CA)) &&
           (i2c_sta & (0x1 << I2C_STA_TFCE));
}

static int stop_detected(intel_serialio_i2c_device_t *controller) {
    return (readl(&controller->regs->raw_intr_stat) &
            (0x1 << INTR_STOP_DETECTION));
}

static int rx_fifo_empty(intel_serialio_i2c_device_t *controller) {
    return !(readl(&controller->regs->i2c_sta) & (0x1 << I2C_STA_RFNE));
}

// Thread safety analysis cannot see the control flow through the
// gotos, and cannot prove that the lock is unheld at return through
// all paths.
zx_status_t intel_serialio_i2c_slave_transfer(
    intel_serialio_i2c_slave_device_t* slave, i2c_slave_segment_t *segments, int segment_count)
    TA_NO_THREAD_SAFETY_ANALYSIS {
    zx_status_t status = ZX_OK;

    for (int i = 0; i < segment_count; i++) {
        if (segments[i].type != I2C_SEGMENT_TYPE_READ &&
            segments[i].type != I2C_SEGMENT_TYPE_WRITE) {
            status = ZX_ERR_INVALID_ARGS;
            goto transfer_finish_2;
        }
    }

    intel_serialio_i2c_device_t* controller = slave->controller;

    uint32_t ctl_addr_mode_bit;
    uint32_t tar_add_addr_mode_bit;
    if (slave->chip_address_width == I2C_7BIT_ADDRESS) {
        ctl_addr_mode_bit = CTL_ADDRESSING_MODE_7BIT;
        tar_add_addr_mode_bit = TAR_ADD_WIDTH_7BIT;
    } else if (slave->chip_address_width == I2C_10BIT_ADDRESS) {
        ctl_addr_mode_bit = CTL_ADDRESSING_MODE_10BIT;
        tar_add_addr_mode_bit = TAR_ADD_WIDTH_10BIT;
    } else {
        printf("Bad address width.\n");
        status = ZX_ERR_INVALID_ARGS;
        goto transfer_finish_2;
    }

    mtx_lock(&slave->controller->mutex);

    if (!WAIT_FOR(bus_is_idle(controller), ZX_USEC(50))) {
        status = ZX_ERR_TIMED_OUT;
        goto transfer_finish_1;
    }

    // Set the target adress value and width.
    RMWREG32(&controller->regs->ctl, CTL_ADDRESSING_MODE, 1, ctl_addr_mode_bit);
    writel((tar_add_addr_mode_bit << TAR_ADD_WIDTH) |
           (slave->chip_address << TAR_ADD_IC_TAR),
           &controller->regs->tar_add);

    // Enable the controller.
    RMWREG32(&controller->regs->i2c_en, I2C_EN_ENABLE, 1, 1);

    int last_type = I2C_SEGMENT_TYPE_END;
    if (segment_count)
        last_type = segments->type;

    while (segment_count--) {
        int len = segments->len;
        uint8_t* buf = segments->buf;

        // If this segment is in the same direction as the last, inject a
        // restart at its start.
        uint32_t restart = 0;
        if (last_type == segments->type)
            restart = 1;
        size_t outstanding_reads = 0;
        while (len--) {
            // Build the cmd register value.
            uint32_t cmd = (restart << DATA_CMD_RESTART);
            restart = 0;
            switch (segments->type) {
            case I2C_SEGMENT_TYPE_WRITE:
                // Wait if the TX FIFO is full
                if (!(readl(&controller->regs->i2c_sta) &
                      (0x1 << I2C_STA_TFNF))) {
                    status = intel_serialio_i2c_wait_for_tx_empty(
                        controller, zx_deadline_after(timeout_ns));
                    if (status != ZX_OK) {
                        goto transfer_finish_1;
                    }
                }
                cmd |= (*buf << DATA_CMD_DAT);
                cmd |= (DATA_CMD_CMD_WRITE << DATA_CMD_CMD);
                buf++;
                break;
            case I2C_SEGMENT_TYPE_READ:
                cmd |= (DATA_CMD_CMD_READ << DATA_CMD_CMD);
                break;
            default:
                // shouldn't be reachable
                printf("invalid i2c segment type: %d\n", segments->type);
                status = ZX_ERR_INVALID_ARGS;
                goto transfer_finish_1;
            }

            if (!len && !segment_count) {
                cmd |= (0x1 << DATA_CMD_STOP);
            }

            if (segments->type == I2C_SEGMENT_TYPE_READ) {
                status = intel_serialio_i2c_issue_rx(controller, cmd);
                outstanding_reads++;
            } else if (segments->type == I2C_SEGMENT_TYPE_WRITE) {
                status = intel_serialio_i2c_issue_tx(controller, cmd);
            } else {
                __builtin_trap();
            }
            if (status != ZX_OK) {
                goto transfer_finish_1;
            }

            // If this is a read, extract data if it's ready.
            while (outstanding_reads) {
                // If len is > 0 and the queue has more space, we can go queue up more work.
                if (len > 0 && outstanding_reads < kRxFifoDepth) {
                    if (rx_fifo_empty(controller)) {
                        break;
                    }
                } else {
                    if (rx_fifo_empty(controller)) {
                        // If we've issued all of our read requests, make sure
                        // that the FIFO threshold will be crossed when the
                        // reads are ready.
                        uint32_t rx_threshold;
                        intel_serialio_i2c_get_rx_fifo_threshold(controller, &rx_threshold);
                        if (len == 0 && outstanding_reads < rx_threshold) {
                            status = intel_serialio_i2c_set_rx_fifo_threshold(controller,
                                                                              outstanding_reads);
                            if (status != ZX_OK) {
                                goto transfer_finish_1;
                            }
                        }

                        // Wait for the FIFO to get some data.
                        status = intel_serialio_i2c_wait_for_rx_full(controller,
                                                                     zx_deadline_after(timeout_ns));
                        if (status != ZX_OK) {
                            goto transfer_finish_1;
                        }

                        // Restore the RX threshold in case we changed it
                        status = intel_serialio_i2c_set_rx_fifo_threshold(controller,
                                                                          rx_threshold);
                        if (status != ZX_OK) {
                            goto transfer_finish_1;
                        }
                    }
                }

                status = intel_serialio_i2c_read_rx(controller, buf);
                if (status != ZX_OK) {
                    goto transfer_finish_1;
                }
                buf++;
                outstanding_reads--;
            }
        }
        if (outstanding_reads != 0) {
            __builtin_trap();
        }

        last_type = segments->type;
        segments++;
    }

    // Clear out the stop detect interrupt signal.
    status = intel_serialio_i2c_wait_for_stop_detect(controller, zx_deadline_after(timeout_ns));
    if (status != ZX_OK) {
        goto transfer_finish_1;
    }
    status = intel_serialio_i2c_clear_stop_detect(controller);
    if (status != ZX_OK) {
        goto transfer_finish_1;
    }

    if (!WAIT_FOR(bus_is_idle(controller), ZX_USEC(50))) {
        status = ZX_ERR_TIMED_OUT;
        goto transfer_finish_1;
    }

    // Read the data_cmd register to pull data out of the RX FIFO.
    if (!DO_UNTIL(rx_fifo_empty(controller),
                  readl(&controller->regs->data_cmd), 0)) {
        status = ZX_ERR_TIMED_OUT;
        goto transfer_finish_1;
    }

    status = intel_serialio_i2c_check_for_error(controller);
    // fall-through for error processing

transfer_finish_1:
    if (status < 0) {
        intel_serialio_i2c_reset_controller(controller);
    }
    mtx_unlock(&controller->mutex);
transfer_finish_2:
    return status;
}

// Implement the char protocol for the slave devices.

static zx_status_t intel_serialio_i2c_slave_read(
    void* ctx, void* buf, size_t count, zx_off_t off, size_t* actual) {
    intel_serialio_i2c_slave_device_t* slave = ctx;
    i2c_slave_segment_t segment = {
        .type = I2C_SEGMENT_TYPE_READ,
        .buf = buf,
        .len = count,
    };
    zx_status_t status = intel_serialio_i2c_slave_transfer(slave, &segment, 1);
    if (status == ZX_OK) {
        *actual = count;
    }
    return status;
}

static zx_status_t intel_serialio_i2c_slave_write(
    void* ctx, const void* buf, size_t count, zx_off_t off, size_t* actual) {
    intel_serialio_i2c_slave_device_t* slave = ctx;
    i2c_slave_segment_t segment = {
        .type = I2C_SEGMENT_TYPE_WRITE,
        .buf = (void*)buf,
        .len = count,
    };
    zx_status_t status = intel_serialio_i2c_slave_transfer(slave, &segment, 1);
    if (status == ZX_OK) {
        *actual = count;
    }
    return status;
}

static zx_status_t intel_serialio_i2c_slave_transfer_ioctl(
    intel_serialio_i2c_slave_device_t* slave, uint32_t op, const void* in_buf, size_t in_len,
    void* out_buf, size_t out_len, size_t* out_actual) {
    zx_status_t status;
    const size_t base_size = sizeof(i2c_slave_ioctl_segment_t);

    size_t read_len = 0;
    size_t write_len = 0;
    int segment_count = 0;
    const i2c_slave_ioctl_segment_t* ioctl_segment = (const i2c_slave_ioctl_segment_t*)in_buf;
    const void* end = (uint8_t*)in_buf + in_len;
    // Check that the inputs and output buffer are valid.
    while ((void*)ioctl_segment < end) {
        if (ioctl_segment->type == I2C_SEGMENT_TYPE_END) {
            // Advance past the segment, which should be the beginning of write
            // data or the end (if there are no writes).
            ioctl_segment++;
            break;
        }
        if ((void*)((uint8_t*)ioctl_segment + base_size) > end) {
            status = ZX_ERR_INVALID_ARGS;
            goto slave_transfer_ioctl_finish_2;
        }

        int len = ioctl_segment->len;

        switch (ioctl_segment->type) {
        case I2C_SEGMENT_TYPE_READ:
            read_len += len;
            break;
        case I2C_SEGMENT_TYPE_WRITE:
            write_len += len;
            break;
        }
        ioctl_segment++;
        segment_count++;
    }
    if ((void*)((uint8_t*)ioctl_segment + write_len) != end) {
        status = ZX_ERR_INVALID_ARGS;
        goto slave_transfer_ioctl_finish_2;
    }
    if (out_len < read_len) {
        status = ZX_ERR_INVALID_ARGS;
        goto slave_transfer_ioctl_finish_2;
    }
    uint8_t* data = (uint8_t*)ioctl_segment;

    // Build a list of segments to transfer.
    i2c_slave_segment_t* segments =
        calloc(segment_count, sizeof(*segments));
    if (!segments) {
        status = ZX_ERR_NO_MEMORY;
        goto slave_transfer_ioctl_finish_2;
    }
    i2c_slave_segment_t* cur_segment = segments;
    uintptr_t out_addr = (uintptr_t)out_buf;
    ioctl_segment = (const i2c_slave_ioctl_segment_t*)in_buf;
    for (int i = 0; i < segment_count; i++) {
        int len = ioctl_segment->len;

        switch (ioctl_segment->type) {
        case I2C_SEGMENT_TYPE_READ:
            cur_segment->type = I2C_SEGMENT_TYPE_READ;
            cur_segment->len = len;
            cur_segment->buf = (uint8_t*)out_addr;
            out_addr += len;
            break;
        case I2C_SEGMENT_TYPE_WRITE:
            cur_segment->type = I2C_SEGMENT_TYPE_WRITE;
            cur_segment->len = len;
            cur_segment->buf = data;
            data += len;
            break;
        default:
            // invalid segment type
            status = ZX_ERR_INVALID_ARGS;
            goto slave_transfer_ioctl_finish_1;
            break;
        }

        cur_segment++;
        ioctl_segment++;
    }

    status = intel_serialio_i2c_slave_transfer(slave, segments, segment_count);
    if (status == ZX_OK) {
        *out_actual = read_len;
    }

slave_transfer_ioctl_finish_1:
    free(segments);
slave_transfer_ioctl_finish_2:
    return status;
}

zx_status_t intel_serialio_i2c_slave_get_irq(intel_serialio_i2c_slave_device_t* slave,
                                             zx_handle_t* out) {
    if (slave->chip_address == 0xa) {
        zx_handle_t irq;
        zx_status_t status = zx_interrupt_create(get_root_resource(), 0x1f,
                            ZX_INTERRUPT_MODE_LEVEL_LOW, &irq);
        if (status != ZX_OK) {
            return status;
        }
        *out = irq;
        return ZX_OK;
    } else if (slave->chip_address == 0x49) {
        zx_handle_t irq;
        zx_status_t status = zx_interrupt_create(get_root_resource(), 0x33,
                            ZX_INTERRUPT_MODE_LEVEL_LOW, &irq);
        if (status != ZX_OK) {
            return status;
        }
        *out = irq;
        return ZX_OK;
    } else if (slave->chip_address == 0x10) {
        // Acer12
        zx_handle_t irq;
        zx_status_t status = zx_interrupt_create(get_root_resource(), 0x1f,
                            ZX_INTERRUPT_MODE_LEVEL_LOW, &irq);
        if (status != ZX_OK) {
            return status;
        }
        *out = irq;
        return ZX_OK;
    } else if (slave->chip_address == 0x50) {
        zx_handle_t irq;
        zx_status_t status = zx_interrupt_create(get_root_resource(), 0x18,
                            ZX_INTERRUPT_MODE_EDGE_LOW, &irq);
        if (status != ZX_OK) {
            return status;
        }
        *out = irq;
        return ZX_OK;
    }

    return ZX_ERR_NOT_FOUND;
}

static zx_status_t intel_serialio_i2c_slave_ioctl(
    void* ctx, uint32_t op, const void* in_buf, size_t in_len,
    void* out_buf, size_t out_len, size_t* out_actual) {
    intel_serialio_i2c_slave_device_t* slave = ctx;
    switch (op) {
    case IOCTL_I2C_SLAVE_TRANSFER:
        return intel_serialio_i2c_slave_transfer_ioctl(
            slave, op, in_buf, in_len, out_buf, out_len, out_actual);
        break;
    default:
        return ZX_ERR_INVALID_ARGS;
    }
}

static void intel_serialio_i2c_slave_release(void* ctx) {
    intel_serialio_i2c_slave_device_t* slave = ctx;
    free(slave);
}

// Implement the device protocol for the slave devices.

zx_protocol_device_t intel_serialio_i2c_slave_device_proto = {
    .version = DEVICE_OPS_VERSION,
    .read = intel_serialio_i2c_slave_read,
    .write = intel_serialio_i2c_slave_write,
    .ioctl = intel_serialio_i2c_slave_ioctl,
    .release = intel_serialio_i2c_slave_release,
};
