// 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-mailbox.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>

#include "aml-mailbox-hw.h"
#include "src/devices/scpi/drivers/aml-scpi-s912/aml-mailbox-s912-bind.h"

namespace mailbox {

mailbox_type_t AmlMailbox::GetRxMailbox(mailbox_type_t tx_mailbox) {
  switch (tx_mailbox) {
    case MAILBOX_TYPE_AP_SECURE_MAILBOX:
      return MAILBOX_TYPE_SCP_SECURE_MAILBOX;
    case MAILBOX_TYPE_AP_NS_LOW_PRIORITY_MAILBOX:
      return MAILBOX_TYPE_SCP_NS_LOW_PRIORITY_MAILBOX;
    case MAILBOX_TYPE_AP_NS_HIGH_PRIORITY_MAILBOX:
      return MAILBOX_TYPE_SCP_NS_HIGH_PRIORITY_MAILBOX;
    default:
      return MAILBOX_TYPE_INVALID_MAILBOX;
  }
}

size_t AmlMailbox::GetNumWords(size_t size) { return (size / 4 + ((size % 4) ? 1 : 0)); }

void AmlMailbox::DdkUnbind(ddk::UnbindTxn txn) { txn.Reply(); }

void AmlMailbox::DdkRelease() { delete this; }

zx_status_t AmlMailbox::MailboxSendCommand(const mailbox_channel_t* channel,
                                           const mailbox_data_buf_t* mdata) {
  if (!channel || !mdata) {
    return ZX_ERR_INVALID_ARGS;
  }

  mailbox_type_t rx_mailbox_id;
  if (MAILBOX_TYPE_INVALID_MAILBOX == (rx_mailbox_id = GetRxMailbox(channel->mailbox))) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::AutoLock mailbox_lock(&mailbox_chan_lock_[channel->mailbox]);

  aml_mailbox_block_t* rx_mailbox = &vim2_mailbox_block[rx_mailbox_id];
  aml_mailbox_block_t* tx_mailbox = &vim2_mailbox_block[channel->mailbox];

  if (mdata->tx_size != 0) {
    ZX_DEBUG_ASSERT(mdata->tx_size % sizeof(uint32_t) == 0);

    size_t num = GetNumWords(mdata->tx_size);
    uint32_t* tx_payload = (uint32_t*)(mdata->tx_buffer);
    for (size_t i = 0; i < num; i++) {
      // AP writes parameters to Payload
      mailbox_payload_mmio_->Write32(tx_payload[i], tx_mailbox->payload_offset + (i << 2));
    }
  }

  // AP writes command to AP Mailbox
  mailbox_mmio_->Write32(mdata->cmd, tx_mailbox->set_offset);

  zx_status_t status = inth_[rx_mailbox_id].wait(nullptr);
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-mailbox: zx_interrupt_wait failed: %d", status);
    return status;
  }

  // AP reads the Payload to get requested information
  if (channel->rx_size != 0) {
    ZX_DEBUG_ASSERT(channel->rx_size % sizeof(uint32_t) == 0);

    size_t num = GetNumWords(channel->rx_size);
    uint32_t* rx_payload = (uint32_t*)(channel->rx_buffer);
    for (size_t i = 0; i < num; i++) {
      rx_payload[i] = mailbox_payload_mmio_->Read32(rx_mailbox->payload_offset + (i << 2));
    }
  }

  // AP writes to the Mailbox CLR register
  mailbox_mmio_->Write32(1, rx_mailbox->clr_offset);
  return ZX_OK;
}

zx_status_t AmlMailbox::Bind() {
  zx_device_prop_t props[] = {
      {BIND_PLATFORM_DEV_VID, 0, PDEV_VID_AMLOGIC},
      {BIND_PLATFORM_DEV_DID, 0, PDEV_DID_AMLOGIC_MAILBOX},
  };

  return DdkAdd(ddk::DeviceAddArgs("aml-mailbox").set_props(props));
}

zx_status_t AmlMailbox::InitPdev() {
  if (!pdev_.is_valid()) {
    return ZX_ERR_NO_RESOURCES;
  }

  // Map MMIOs
  zx_status_t status = pdev_.MapMmio(MMIO_MAILBOX, &mailbox_mmio_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-mailbox: could not map mailbox mmio: %d", status);
    return status;
  }

  status = pdev_.MapMmio(MMIO_MAILBOX_PAYLOAD, &mailbox_payload_mmio_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-mailbox: could not map payload mmio: %d", status);
    return status;
  }

  for (uint32_t i = 0; i < kNumMailboxes; i++) {
    status = pdev_.GetInterrupt(i, &inth_[i]);
    if (status != ZX_OK) {
      zxlogf(ERROR, "aml-mailbox: could not map interrupt: %d", status);
      return status;
    }

    mtx_init(&mailbox_chan_lock_[i], mtx_plain);
  }

  return status;
}

zx_status_t AmlMailbox::Create(zx_device_t* parent) {
  fbl::AllocChecker ac;
  auto mailbox_device = fbl::make_unique_checked<AmlMailbox>(&ac, parent);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  zx_status_t status = mailbox_device->InitPdev();
  if (status != ZX_OK) {
    return status;
  }

  status = mailbox_device->Bind();
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-mailbox driver failed to get added: %d", status);
    return status;
  } else {
    zxlogf(INFO, "aml-mailbox driver added");
  }

  // mailbox_device intentionally leaked as it is now held by DevMgr
  __UNUSED auto ptr = mailbox_device.release();

  return ZX_OK;
}

zx_status_t aml_mailbox_bind(void* ctx, zx_device_t* parent) {
  return mailbox::AmlMailbox::Create(parent);
}

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

}  // namespace mailbox

ZIRCON_DRIVER(aml_mailbox, mailbox::driver_ops, "zircon", "0.1");
