// Copyright 2020 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 "src/devices/rtc/drivers/pl031-rtc/pl031-rtc.h"

#include <lib/device-protocol/pdev.h>
#include <lib/zx/clock.h>
#include <lib/zx/time.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <ddk/debug.h>
#include <ddk/driver.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/platform/device.h>
#include <ddktl/fidl.h>

#include "src/devices/rtc/drivers/pl031-rtc/pl031_rtc_bind.h"
#include "src/devices/rtc/lib/rtc/include/librtc_llcpp.h"

namespace rtc {

zx_status_t Pl031::Bind(void* /*unused*/, zx_device_t* dev) {
  ddk::PDev pdev(dev);
  if (!pdev.is_valid()) {
    return ZX_ERR_NO_RESOURCES;
  }

  // Carve out some address space for this device.
  std::optional<ddk::MmioBuffer> mmio;
  zx_status_t status = pdev.MapMmio(0, &mmio);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s failed to map mmio: %s", __func__, zx_status_get_string(status));
    return status;
  }

  auto pl031_device = std::make_unique<Pl031>(dev, *std::move(mmio));

  status = pl031_device->DdkAdd(ddk::DeviceAddArgs("rtc").set_proto_id(ZX_PROTOCOL_RTC));
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s error adding device: %s", __func__, zx_status_get_string(status));
    return status;
  }

  // Retrieve and sanitize the RTC value. Set the RTC to the value.
  FidlRtc::Time rtc = SecondsToRtc(MmioRead32(&pl031_device->regs_->dr));
  rtc = SanitizeRtc(rtc);
  status = pl031_device->SetRtc(rtc);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s failed to set rtc: %s", __func__, zx_status_get_string(status));
  }

  // The object is owned by the DDK, now that it has been added. It will be deleted
  // when the device is released.
  __UNUSED auto ptr = pl031_device.release();

  return status;
}

Pl031::Pl031(zx_device_t* parent, ddk::MmioBuffer mmio)
    : RtcDeviceType(parent),
      mmio_(std::move(mmio)),
      regs_(reinterpret_cast<MMIO_PTR Pl031Regs*>(mmio_.get())) {}

void Pl031::Get(GetCompleter::Sync& completer) {
  FidlRtc::Time rtc = SecondsToRtc(MmioRead32(&regs_->dr));
  completer.Reply(rtc);
}

void Pl031::Set(FidlRtc::Time rtc, SetCompleter::Sync& completer) { completer.Reply(SetRtc(rtc)); }

zx_status_t Pl031::DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
  DdkTransaction transaction(txn);
  FidlRtc::Device::Dispatch(this, msg, &transaction);
  return transaction.Status();
}

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

zx_status_t Pl031::SetRtc(FidlRtc::Time rtc) {
  if (!IsRtcValid(rtc)) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  MmioWrite32(static_cast<uint32_t>(SecondsSinceEpoch(rtc)), &regs_->lr);

  // Set the UTC offset.
  const zx::time time_since_epoch = zx::time(SecondsSinceEpoch(rtc) * 1'000'000'000);
  const zx::duration utc_offset = time_since_epoch - zx::clock::get_monotonic();

  // TODO(fxb/31358): Replace get_root_resource().
  const zx_status_t status = zx_clock_adjust(get_root_resource(), ZX_CLOCK_UTC, utc_offset.get());
  if (status != ZX_OK) {
    zxlogf(ERROR, "The RTC driver was unable to set the UTC clock!");
  }

  return ZX_OK;
}

zx_driver_ops_t pl031_driver_ops = {
    .version = DRIVER_OPS_VERSION,
    .bind = Pl031::Bind,
};

}  // namespace rtc

ZIRCON_DRIVER(pl031, rtc::pl031_driver_ops, "zircon", "0.1");
