// 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::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");
