// Copyright 2022 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 <algorithm>
#include <iterator>

#include <fbl/alloc_checker.h>
#include <soc/aml-a5/a5-hiu.h>
#include <soc/aml-a5/a5-hw.h>

namespace amlogic_clock::a5 {

constexpr uint32_t kA5HifiPllSize = 8 * sizeof(uint32_t);
constexpr uint32_t kA5MpllSize = 2 * sizeof(uint32_t);

#define HHI_PLL_RATE(_rate, _n, _m, _frac, _od) \
  { .rate = _rate, .n = _n, .m = _m, .frac = _frac, .od = _od, }

static constexpr hhi_pll_rate_t a5_sys_pll_support_rates[] = {
    HHI_PLL_RATE(1'200'000'000, 0, 0, 0, 0),  // padding, unused
};

static constexpr hhi_pll_rate_t a5_hifipll_support_rates[] = {
    HHI_PLL_RATE(768'000'000, 1, 128, 27307, 2),  // 768'000'000 HZ
};
#undef HHI_PLL_RATE

#define HHI_MPLL_RATE(_rate, _n_in, _sdm_in) \
  { .rate = _rate, .n = _n_in, .m = 0, .frac = _sdm_in, .od = 0, }

static constexpr hhi_pll_rate_t a5_mpll_support_rates[] = {
    HHI_MPLL_RATE(491'520'000, 4, 1131),
};
#undef HHI_MPLL_RATE

static constexpr struct reg_sequence a5_hifipll_default[] = {
    {.reg_offset = 0x0 << 2, .def = 0x30020480, .delay_us = 0},
    {.reg_offset = 0x1 << 2, .def = 0x00006aab, .delay_us = 0},
    {.reg_offset = 0x2 << 2, .def = 0x00000000, .delay_us = 0},
    {.reg_offset = 0x3 << 2, .def = 0x6a285c00, .delay_us = 0},
    {.reg_offset = 0x4 << 2, .def = 0x65771290, .delay_us = 0},
    {.reg_offset = 0x5 << 2, .def = 0x39272000, .delay_us = 0},
    {.reg_offset = 0x6 << 2, .def = 0x56540000, .delay_us = 0},  // 768'000'000 HZ
};

static constexpr meson_clk_pll_data_t a5_hifipll_rates = {
    .init_regs = a5_hifipll_default,
    .init_count = std::size(a5_hifipll_default),
};

static constexpr struct reg_sequence a5_mpll_default[] = {
    {.reg_offset = 0x0 << 2, .def = 0x4040046B, .delay_us = 0},  // 491'520'000 HZ
    {.reg_offset = 0x1 << 2, .def = 0x40000033, .delay_us = 0},
};

static constexpr meson_clk_pll_data_t a5_mpll_rates = {
    .init_regs = a5_mpll_default,
    .init_count = std::size(a5_mpll_default),
};

std::unique_ptr<AmlMesonPllDevice> CreatePllDevice(fdf::MmioBuffer* mmio, const uint32_t pll_num) {
  switch (pll_num) {
    case SYS_PLL:
      return AmlA5SysPllDevice::Create(
          cpp20::span(a5_sys_pll_support_rates, std::size(a5_sys_pll_support_rates)));
    case HIFI_PLL:
      return AmlA5HifiPllDevice::Create(
          mmio->View(A5_ANACTRL_HIFIPLL_CTRL0, kA5HifiPllSize), &a5_hifipll_rates,
          cpp20::span(a5_hifipll_support_rates, std::size(a5_hifipll_support_rates)));
    case MPLL0:
      return AmlA5MpllDevice::Create(
          mmio->View(A5_ANACTRL_MPLL_CTRL1, kA5MpllSize), &a5_mpll_rates,
          cpp20::span(a5_mpll_support_rates, std::size(a5_mpll_support_rates)));
    case MPLL1:
      return AmlA5MpllDevice::Create(
          mmio->View(A5_ANACTRL_MPLL_CTRL3, kA5MpllSize), &a5_mpll_rates,
          cpp20::span(a5_mpll_support_rates, std::size(a5_mpll_support_rates)));
    case MPLL2:
      return AmlA5MpllDevice::Create(
          mmio->View(A5_ANACTRL_MPLL_CTRL5, kA5MpllSize), &a5_mpll_rates,
          cpp20::span(a5_mpll_support_rates, std::size(a5_mpll_support_rates)));
    case MPLL3:
      return AmlA5MpllDevice::Create(
          mmio->View(A5_ANACTRL_MPLL_CTRL7, kA5MpllSize), &a5_mpll_rates,
          cpp20::span(a5_mpll_support_rates, std::size(a5_mpll_support_rates)));
    default:
      ZX_ASSERT_MSG(0, "Not supported");
      break;
  }

  ZX_ASSERT(0);
  return nullptr;
}

std::unique_ptr<AmlMesonPllDevice> AmlA5SysPllDevice::Create(
    const cpp20::span<const hhi_pll_rate_t> rates_table) {
  fbl::AllocChecker ac;

  auto dev = std::unique_ptr<AmlA5SysPllDevice>(new (&ac) AmlA5SysPllDevice(rates_table));
  if (!ac.check()) {
    return nullptr;
  }

  ZX_ASSERT(dev->Initialize() == ZX_OK);

  return dev;
}

std::unique_ptr<AmlMesonPllDevice> AmlA5HifiPllDevice::Create(
    fdf::MmioView view, const meson_clk_pll_data_t* data,
    const cpp20::span<const hhi_pll_rate_t> rates_table) {
  fbl::AllocChecker ac;

  auto dev = std::unique_ptr<AmlA5HifiPllDevice>(
      new (&ac) AmlA5HifiPllDevice(std::move(view), data, rates_table));
  if (!ac.check()) {
    return nullptr;
  }

  ZX_ASSERT(dev->Initialize() == ZX_OK);

  return dev;
}

std::unique_ptr<AmlMesonPllDevice> AmlA5MpllDevice::Create(
    fdf::MmioView view, const meson_clk_pll_data_t* data,
    const cpp20::span<const hhi_pll_rate_t> rates_table) {
  fbl::AllocChecker ac;

  auto dev = std::unique_ptr<AmlA5MpllDevice>(
      new (&ac) AmlA5MpllDevice(std::move(view), data, rates_table));
  if (!ac.check()) {
    return nullptr;
  }

  ZX_ASSERT(dev->Initialize() == ZX_OK);

  return dev;
}

}  // namespace amlogic_clock::a5
