// Copyright 2018 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 "aml-gxl-gpio.h"

#include <fuchsia/hardware/platform/bus/c/banjo.h>
#include <fuchsia/hardware/platform/device/c/banjo.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/platform-defs.h>
#include <lib/device-protocol/platform-device.h>

#include <memory>
#include <utility>

#include <fbl/alloc_checker.h>
#include <fbl/array.h>
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>

#include "s912-blocks.h"
#include "src/devices/gpio/drivers/aml-gxl-gpio/aml-gxl-gpio-bind.h"

namespace {

constexpr int kGpioInterruptPolarityShift = 16;
constexpr int kMaxGpioIndex = 255;
constexpr int kBitsPerGpioInterrupt = 8;
constexpr int kBitsPerFilterSelect = 4;

uint32_t GetUnusedIrqIndex(uint8_t status) {
  // First isolate the rightmost 0-bit
  uint8_t zero_bit_set = static_cast<uint8_t>(~status & (status + 1));
  // Count no. of leading zeros
  return __builtin_ctz(zero_bit_set);
}

}  // namespace

namespace gpio {

// MMIO indices (based on vim-gpio.c gpio_mmios)
enum {
  MMIO_GPIO = 0,
  MMIO_GPIO_A0 = 1,
  MMIO_GPIO_INTERRUPTS = 2,
};

zx_status_t AmlGxlGpio::Create(zx_device_t* parent) {
  zx_status_t status;

  pdev_protocol_t pdev;
  if ((status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &pdev)) != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::Create: ZX_PROTOCOL_PDEV not available");
    return status;
  }

  pbus_protocol_t pbus;
  if ((status = device_get_protocol(parent, ZX_PROTOCOL_PBUS, &pbus)) != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::Create: ZX_PROTOCOL_PBUS not available");
    return status;
  }

  mmio_buffer_t mmio;
  status = pdev_map_mmio_buffer(&pdev, MMIO_GPIO, ZX_CACHE_POLICY_UNCACHED_DEVICE, &mmio);
  if (status != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::Create: pdev_map_mmio_buffer failed");
    return status;
  }

  ddk::MmioBuffer mmio_gpio(mmio);

  status = pdev_map_mmio_buffer(&pdev, MMIO_GPIO_A0, ZX_CACHE_POLICY_UNCACHED_DEVICE, &mmio);
  if (status != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::Create: pdev_map_mmio_buffer failed");
    return status;
  }

  ddk::MmioBuffer mmio_gpio_a0(mmio);

  status =
      pdev_map_mmio_buffer(&pdev, MMIO_GPIO_INTERRUPTS, ZX_CACHE_POLICY_UNCACHED_DEVICE, &mmio);
  if (status != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::Create: pdev_map_mmio_buffer failed");
    return status;
  }

  ddk::MmioBuffer mmio_interrupt(mmio);

  pdev_device_info_t info;
  if ((status = pdev_get_device_info(&pdev, &info)) != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::Create: pdev_get_device_info failed");
    return status;
  }

  const AmlGpioBlock* gpio_blocks;
  const AmlPinMuxBlock* pinmux_blocks;
  const AmlGpioInterrupt* gpio_interrupt;
  size_t block_count;

  switch (info.pid) {
    case PDEV_PID_AMLOGIC_S912:
      gpio_blocks = s912_gpio_blocks;
      pinmux_blocks = s912_pinmux_blocks;
      gpio_interrupt = &s912_interrupt_block;
      block_count = countof(s912_gpio_blocks);
      break;
    default:
      zxlogf(ERROR, "AmlGxlGpio::Create: unsupported SOC PID %u", info.pid);
      return ZX_ERR_INVALID_ARGS;
  }

  fbl::AllocChecker ac;

  fbl::Array<uint16_t> irq_info(new (&ac) uint16_t[info.irq_count], info.irq_count);
  if (!ac.check()) {
    zxlogf(ERROR, "AmlGxlGpio::Create: irq_info alloc failed");
    return ZX_ERR_NO_MEMORY;
  }

  std::unique_ptr<AmlGxlGpio> device(new (&ac) AmlGxlGpio(
      parent, pdev, std::move(mmio_gpio), std::move(mmio_gpio_a0), std::move(mmio_interrupt),
      gpio_blocks, gpio_interrupt, pinmux_blocks, block_count, std::move(irq_info)));
  if (!ac.check()) {
    zxlogf(ERROR, "AmlGxlGpio::Create: device object alloc failed");
    return ZX_ERR_NO_MEMORY;
  }

  device->Bind(pbus);

  if ((status = device->DdkAdd("aml-gxl-gpio")) != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::Create: DdkAdd failed");
    return status;
  }

  __UNUSED auto* unused = device.release();

  return ZX_OK;
}

void AmlGxlGpio::Bind(const pbus_protocol_t& pbus) {
  gpio_impl_protocol_t gpio_proto = {
      .ops = &gpio_impl_protocol_ops_,
      .ctx = this,
  };

  pbus_register_protocol(&pbus, ZX_PROTOCOL_GPIO_IMPL, reinterpret_cast<uint8_t*>(&gpio_proto),
                         sizeof(gpio_proto));
}

zx_status_t AmlGxlGpio::AmlPinToBlock(const uint32_t pin, const AmlGpioBlock** out_block,
                                      uint32_t* out_pin_index) const {
  ZX_DEBUG_ASSERT(out_block && out_pin_index);

  uint32_t block_index = pin / kPinsPerBlock;
  if (block_index >= block_count_) {
    return ZX_ERR_NOT_FOUND;
  }
  const AmlGpioBlock* block = &gpio_blocks_[block_index];
  uint32_t pin_index = pin % kPinsPerBlock;
  if (pin_index >= block->pin_count) {
    return ZX_ERR_NOT_FOUND;
  }
  pin_index += block->output_shift;
  *out_block = block;
  *out_pin_index = pin_index;
  return ZX_OK;
}

zx_status_t AmlGxlGpio::GpioImplConfigIn(uint32_t index, uint32_t flags) {
  zx_status_t status;

  const AmlGpioBlock* block;
  uint32_t pin_index;
  if ((status = AmlPinToBlock(index, &block, &pin_index)) != ZX_OK) {
    zxlogf(ERROR, "AmGxlGpio::GpioImplConfigIn: pin not found %u", index);
    return status;
  }

  // Set the GPIO as IN or OUT
  {
    fbl::AutoLock al(&mmio_lock_);
    uint32_t regval = Read32GpioReg(block->mmio_index, block->oen_offset);
    // Set the GPIO as pull-up or pull-down
    uint32_t pull_reg_val = Read32GpioReg(block->mmio_index, block->pull_offset);
    uint32_t pull_en_reg_val = Read32GpioReg(block->mmio_index, block->pull_en_offset);
    uint32_t pull_pin_index = pin_index;
    if (block->output_write_shift) {
      // Handling special case where output_offset is
      // different for OEN/OUT/PU-PD for GPIOA0 block
      pull_pin_index += block->output_write_shift;
    }
    if (flags & GPIO_NO_PULL) {
      pull_en_reg_val &= ~(1 << pin_index);
    } else {
      if (flags & GPIO_PULL_UP) {
        pull_reg_val |= (1 << pull_pin_index);
      } else {
        pull_reg_val &= ~(1 << pull_pin_index);
      }
      pull_en_reg_val |= (1 << pin_index);
    }
    Write32GpioReg(block->mmio_index, block->pull_offset, pull_reg_val);
    Write32GpioReg(block->mmio_index, block->pull_en_offset, pull_en_reg_val);
    regval |= (1 << pin_index);
    Write32GpioReg(block->mmio_index, block->oen_offset, regval);
  }

  return ZX_OK;
}

zx_status_t AmlGxlGpio::GpioImplConfigOut(uint32_t index, uint8_t initial_value) {
  zx_status_t status;

  const AmlGpioBlock* block;
  uint32_t pin_index;
  if ((status = AmlPinToBlock(index, &block, &pin_index)) != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::GpioImplConfigOut: pin not found %u", index);
    return status;
  }

  {
    fbl::AutoLock al(&mmio_lock_);

    // Set value before configuring for output
    uint32_t regval = Read32GpioReg(block->mmio_index, block->output_offset);
    // output_write_shift is handling special case where output_offset is
    // different for OEN/OUT for GPIOA0 block
    if (initial_value) {
      regval |= (1 << (pin_index + block->output_write_shift));
    } else {
      regval &= ~(1 << (pin_index + block->output_write_shift));
    }
    Write32GpioReg(block->mmio_index, block->output_offset, regval);

    regval = Read32GpioReg(block->mmio_index, block->oen_offset);
    regval &= ~(1 << pin_index);
    Write32GpioReg(block->mmio_index, block->oen_offset, regval);
  }

  return ZX_OK;
}

zx_status_t AmlGxlGpio::GpioImplSetAltFunction(uint32_t pin, uint64_t function) {
  if (function > kAltFunctionMax) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  uint32_t block_index = pin / kPinsPerBlock;
  if (block_index >= block_count_) {
    return ZX_ERR_NOT_FOUND;
  }
  const AmlPinMuxBlock* block = &pinmux_blocks_[block_index];
  uint32_t pin_index = pin % kPinsPerBlock;
  const AmlPinMux* mux = &block->mux[pin_index];

  const AmlGpioBlock* gpio_block = &gpio_blocks_[block_index];

  {
    fbl::AutoLock al(&mmio_lock_);
    for (uint64_t i = 0; i < kAltFunctionMax; i++) {
      uint32_t reg_index = mux->regs[i];

      if (reg_index) {
        uint32_t mask = (1 << mux->bits[i]);
        uint32_t regval = Read32GpioReg(gpio_block->mmio_index, reg_index);

        if (i == function - 1) {
          regval |= mask;
        } else {
          regval &= ~mask;
        }
        Write32GpioReg(gpio_block->mmio_index, reg_index, regval);
      }
    }
  }

  return ZX_OK;
}

zx_status_t AmlGxlGpio::GpioImplRead(uint32_t pin, uint8_t* out_value) {
  zx_status_t status;

  const AmlGpioBlock* block;
  uint32_t pin_index;
  if ((status = AmlPinToBlock(pin, &block, &pin_index)) != ZX_OK) {
    zxlogf(ERROR, "AmGxlGpio::GpioImplRead: pin not found %u", pin);
    return status;
  }

  uint32_t regval = 0;
  {
    fbl::AutoLock al(&mmio_lock_);
    regval = Read32GpioReg(block->mmio_index, block->input_offset);
  }

  const uint32_t readmask = 1 << pin_index;
  if (regval & readmask) {
    *out_value = 1;
  } else {
    *out_value = 0;
  }

  return ZX_OK;
}

zx_status_t AmlGxlGpio::GpioImplWrite(uint32_t pin, uint8_t value) {
  zx_status_t status;

  const AmlGpioBlock* block;
  uint32_t pin_index;
  if ((status = AmlPinToBlock(pin, &block, &pin_index)) != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::GpioImplWrite: pin not found %u", pin);
    return status;
  }

  if (block->output_write_shift) {
    // Handling special case where output_offset is
    // different for OEN/OUT for GPIOA0 block
    pin_index += block->output_write_shift;
  }

  {
    fbl::AutoLock al(&mmio_lock_);
    uint32_t regval = Read32GpioReg(block->mmio_index, block->output_offset);
    if (value) {
      regval |= (1 << pin_index);
    } else {
      regval &= ~(1 << pin_index);
    }
    Write32GpioReg(block->mmio_index, block->output_offset, regval);
  }

  return ZX_OK;
}

zx_status_t AmlGxlGpio::GpioImplGetInterrupt(uint32_t pin, uint32_t flags, zx::interrupt* out_irq) {
  if (pin > kMaxGpioIndex) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::AutoLock al(&irq_lock_);

  uint32_t index = GetUnusedIrqIndex(irq_status_);
  if (index > irq_info_.size()) {
    return ZX_ERR_NO_RESOURCES;
  }

  for (uint32_t i = 0; i < irq_info_.size(); i++) {
    if (irq_info_[i] == pin) {
      zxlogf(ERROR, "GPIO Interrupt already configured for this pin %u", (int)index);
      return ZX_ERR_ALREADY_EXISTS;
    }
  }

  zxlogf(DEBUG, "GPIO Interrupt index %d allocated", (int)index);

  zx_status_t status;
  const AmlGpioBlock* block;
  uint32_t pin_index;
  if ((status = AmlPinToBlock(pin, &block, &pin_index)) != ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::GpioImplGetInterrupt: pin not found %u", pin);
    return status;
  }

  uint32_t flags_ = flags;
  if (flags == ZX_INTERRUPT_MODE_EDGE_LOW) {
    // GPIO controller sets the polarity
    flags_ = ZX_INTERRUPT_MODE_EDGE_HIGH;
  } else if (flags == ZX_INTERRUPT_MODE_LEVEL_LOW) {
    flags_ = ZX_INTERRUPT_MODE_LEVEL_HIGH;
  }

  {
    fbl::AutoLock al(&mmio_lock_);
    // Configure GPIO Interrupt EDGE and Polarity
    uint32_t mode_reg_val = Read32GpioInterruptReg(gpio_interrupt_->edge_polarity_offset);

    switch (flags & ZX_INTERRUPT_MODE_MASK) {
      case ZX_INTERRUPT_MODE_EDGE_LOW:
        mode_reg_val = mode_reg_val | (1 << index);
        mode_reg_val = mode_reg_val | ((1 << index) << kGpioInterruptPolarityShift);
        break;
      case ZX_INTERRUPT_MODE_EDGE_HIGH:
        mode_reg_val = mode_reg_val | (1 << index);
        mode_reg_val = mode_reg_val & ~((1 << index) << kGpioInterruptPolarityShift);
        break;
      case ZX_INTERRUPT_MODE_LEVEL_LOW:
        mode_reg_val = mode_reg_val & ~(1 << index);
        mode_reg_val = mode_reg_val | ((1 << index) << kGpioInterruptPolarityShift);
        break;
      case ZX_INTERRUPT_MODE_LEVEL_HIGH:
        mode_reg_val = mode_reg_val & ~(1 << index);
        mode_reg_val = mode_reg_val & ~((1 << index) << kGpioInterruptPolarityShift);
        break;
      default:
        return ZX_ERR_INVALID_ARGS;
    }
    Write32GpioInterruptReg(gpio_interrupt_->edge_polarity_offset, mode_reg_val);

    // Configure Interrupt Select Filter
    uint32_t regval = Read32GpioInterruptReg(gpio_interrupt_->filter_select_offset);
    Write32GpioInterruptReg(gpio_interrupt_->filter_select_offset,
                            regval | (0x7 << (index * kBitsPerFilterSelect)));

    // Configure GPIO interrupt
    const uint32_t pin_select_bit = index * kBitsPerGpioInterrupt;
    const uint32_t pin_select_offset = gpio_interrupt_->pin_select_offset + (pin_select_bit / 32);
    const uint32_t pin_select_index = pin_select_bit % 32;
    // Select GPIO IRQ(index) and program it to the requested GPIO PIN
    mmio_interrupt_.ModifyBits((pin % kPinsPerBlock) + block->pin_start, pin_select_index,
                               kBitsPerGpioInterrupt, pin_select_offset * sizeof(uint32_t));
  }

  // Create Interrupt Object
  if ((status = pdev_get_interrupt(&pdev_, index, flags_, out_irq->reset_and_get_address())) !=
      ZX_OK) {
    zxlogf(ERROR, "AmlGxlGpio::GpioImplGetInterrupt: pdev_get_interrupt failed %d", status);
    return status;
  }

  irq_status_ |= static_cast<uint8_t>(1 << index);
  irq_info_[index] = static_cast<uint16_t>(pin);

  return ZX_OK;
}

zx_status_t AmlGxlGpio::GpioImplReleaseInterrupt(uint32_t pin) {
  fbl::AutoLock al(&irq_lock_);

  for (uint32_t i = 0; i < irq_info_.size(); i++) {
    if (irq_info_[i] == pin) {
      irq_status_ &= static_cast<uint8_t>(~(1 << i));
      irq_info_[i] = kMaxGpioIndex + 1;
      return ZX_OK;
    }
  }

  return ZX_ERR_NOT_FOUND;
}

zx_status_t AmlGxlGpio::GpioImplSetPolarity(uint32_t pin, uint32_t polarity) {
  int irq_index = -1;
  if (pin > kMaxGpioIndex) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::AutoLock al(&irq_lock_);

  for (uint32_t i = 0; i < irq_info_.size(); i++) {
    if (irq_info_[i] == pin) {
      irq_index = i;
      break;
    }
  }

  if (irq_index == -1) {
    return ZX_ERR_NOT_FOUND;
  }

  {
    fbl::AutoLock al(&mmio_lock_);

    // Configure GPIO Interrupt EDGE and Polarity
    uint32_t mode_reg_val = Read32GpioInterruptReg(gpio_interrupt_->edge_polarity_offset);
    if (polarity == GPIO_POLARITY_HIGH) {
      mode_reg_val &= ~((1 << irq_index) << kGpioInterruptPolarityShift);
    } else {
      mode_reg_val |= ((1 << irq_index) << kGpioInterruptPolarityShift);
    }
    Write32GpioInterruptReg(gpio_interrupt_->edge_polarity_offset, mode_reg_val);
  }

  return ZX_OK;
}

zx_status_t aml_gpio_bind(void* ctx, zx_device_t* parent) {
  return gpio::AmlGxlGpio::Create(parent);
}

static constexpr zx_driver_ops_t driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = aml_gpio_bind;
  return ops;
}();

}  // namespace gpio

ZIRCON_DRIVER(aml_gpio, gpio::driver_ops, "zircon", "0.1");
