// 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 "intel-i2c-subordinate.h"

#include <fuchsia/hardware/i2c/c/fidl.h>
#include <lib/fit/function.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/clock.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <zircon/listnode.h>
#include <zircon/types.h>

#include "intel-i2c-controller.h"

namespace intel_i2c {

// Time out after 2 seconds.
constexpr zx::duration kTimeout = zx::sec(2);

// TODO We should be using interrupts during long operations, but
// the plumbing isn't all there for that apparently.
bool DoUntil(const fit::function<bool()>& condition, fit::function<void()> action,
             const zx::duration poll_interval) {
  const zx::time deadline = zx::deadline_after(kTimeout);
  bool wait_for_condition_value;
  while (!(wait_for_condition_value = condition())) {
    zx::time now = zx::clock::get_monotonic();
    if (now >= deadline)
      break;
    if (poll_interval != zx::duration(0))
      zx::nanosleep(zx::deadline_after(poll_interval));
    action();
  }
  return wait_for_condition_value;
}

bool WaitFor(const fit::function<bool()>& condition, const zx::duration poll_interval) {
  return DoUntil(
      condition, [] {}, poll_interval);
}

std::unique_ptr<IntelI2cSubordinate> IntelI2cSubordinate::Create(
    IntelI2cController* controller, const uint8_t chip_address_width, const uint16_t chip_address,
    const uint32_t i2c_class, const uint16_t vendor_id, const uint16_t device_id) {
  if (chip_address_width != kI2c7BitAddress && chip_address_width != kI2c10BitAddress) {
    zxlogf(ERROR, "Bad address width.");
    return nullptr;
  }

  return std::unique_ptr<IntelI2cSubordinate>(new IntelI2cSubordinate(
      controller, chip_address_width, chip_address, i2c_class, vendor_id, device_id));
}

zx_status_t IntelI2cSubordinate::Transfer(const IntelI2cSubordinateSegment* segments,
                                          int segment_count) {
  zx_status_t status = ZX_OK;
  int last_type = fuchsia_hardware_i2c_SegmentType_END;

  for (int i = 0; i < segment_count; i++) {
    if (segments[i].type != fuchsia_hardware_i2c_SegmentType_READ &&
        segments[i].type != fuchsia_hardware_i2c_SegmentType_WRITE) {
      status = ZX_ERR_INVALID_ARGS;
      return status;
    }
  }

  if (!WaitFor(fit::bind_member(controller_, &IntelI2cController::IsBusIdle), zx::usec(50))) {
    status = ZX_ERR_TIMED_OUT;
    return status;
  }

  const uint32_t ctl_addr_mode_bit =
      (chip_address_width_ == kI2c7BitAddress) ? kCtlAddressingMode7Bit : kCtlAddressingMode10Bit;
  const uint32_t tar_add_addr_mode_bit =
      (chip_address_width_ == kI2c7BitAddress) ? kTarAddWidth7Bit : kTarAddWidth10Bit;

  controller_->SetAddressingMode(ctl_addr_mode_bit);
  controller_->SetTargetAddress(tar_add_addr_mode_bit, chip_address_);

  controller_->Enable();

  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-- || outstanding_reads) {
      // Build the cmd register value.
      uint32_t cmd = (restart << kDataCmdRestart);
      restart = 0;
      switch (segments->type) {
        case fuchsia_hardware_i2c_SegmentType_WRITE:
          // Wait if the TX FIFO is full
          if (controller_->IsTxFifoFull()) {
            status = controller_->WaitForTxEmpty(zx::deadline_after(kTimeout));
            if (status != ZX_OK) {
              return status;
            }
          }
          cmd |= (*buf << kDataCmdDat);
          cmd |= (kDataCmdCmdWrite << kDataCmdCmd);
          buf++;
          break;
        case fuchsia_hardware_i2c_SegmentType_READ:
          cmd |= (kDataCmdCmdRead << kDataCmdCmd);
          break;
        default:
          // shouldn't be reachable
          printf("invalid i2c segment type: %d\n", segments->type);
          status = ZX_ERR_INVALID_ARGS;
          return status;
      }

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

      if (segments->type == fuchsia_hardware_i2c_SegmentType_READ) {
        status = controller_->IssueRx(cmd);
        outstanding_reads++;
      } else if (segments->type == fuchsia_hardware_i2c_SegmentType_WRITE) {
        status = controller_->IssueTx(cmd);
      } else {
        __builtin_trap();
      }
      if (status != ZX_OK) {
        return status;
      }

      // If its a read then queue up more reads until we hit fifo_depth.
      // (We use fifo_depth - 1 because going to the full fifo_depth
      // causes an overflow interrupt).
      if (outstanding_reads != 0 && len > 0 &&
          outstanding_reads < (size_t)(controller_->GetRxFifoDepth() - 1)) {
        continue;
      }

      uint32_t rx_data_left = controller_->GetRxFifoLevel();
      // If this is a read, extract data if it's ready.
      while (outstanding_reads) {
        while (rx_data_left == 0) {
          // Make sure that the FIFO threshold will be crossed when
          // the reads are ready.
          uint32_t rx_threshold = static_cast<uint32_t>(outstanding_reads);
          status = controller_->SetRxFifoThreshold(rx_threshold);
          if (status != ZX_OK) {
            return status;
          }

          // Clear the RX threshold signal
          status = controller_->FlushRxFullIrq();
          if (status != ZX_OK) {
            return status;
          }

          // Wait for the FIFO to get some data.
          status = controller_->WaitForRxFull(zx::deadline_after(kTimeout));
          if (status != ZX_OK) {
            return status;
          }
          rx_data_left = controller_->GetRxFifoLevel();
        }

        *buf = controller_->ReadRx();
        buf++;
        outstanding_reads--;
        rx_data_left--;
      }
    }
    if (outstanding_reads != 0) {
      __builtin_trap();
    }

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

  // Clear out the stop detect interrupt signal.
  status = controller_->WaitForStopDetect(zx::deadline_after(kTimeout));
  if (status != ZX_OK) {
    return status;
  }
  status = controller_->ClearStopDetect();
  if (status != ZX_OK) {
    return status;
  }

  if (!WaitFor(fit::bind_member(controller_, &IntelI2cController::IsBusIdle), zx::usec(50))) {
    status = ZX_ERR_TIMED_OUT;
    return status;
  }

  // Read the data_cmd register to pull data out of the RX FIFO.
  if (!DoUntil(
          fit::bind_member(controller_, &IntelI2cController::IsRxFifoEmpty),
          [this]() { controller_->ReadRx(); }, zx::duration(0))) {
    status = ZX_ERR_TIMED_OUT;
    return status;
  }

  status = controller_->CheckForError();

  return status;
}

}  // namespace intel_i2c
