blob: bc69963483fc79e4a91f8e4956df1db6309a6b7c [file] [log] [blame]
// 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-a1/a1-hiu.h>
#include <soc/aml-a1/a1-hw.h>
namespace amlogic_clock::a1 {
constexpr uint32_t kA1SyspllSize = 6 * sizeof(uint32_t);
constexpr uint32_t kA1HifipllSize = 6 * sizeof(uint32_t);
// There is no OD in A1 PLL
#define PLL_PARAMS(_rate, _n, _m, _frac) \
{ .rate = _rate, .n = _n, .m = _m, .frac = _frac }
static constexpr hhi_pll_rate_t a1_sys_pll_support_rates[] = {
PLL_PARAMS(768'000'000, 1, 32, 0), // 768M
PLL_PARAMS(792'000'000, 1, 33, 0), // 792M
PLL_PARAMS(816'000'000, 1, 34, 0), // 816M
PLL_PARAMS(840'000'000, 1, 35, 0), // 840M
PLL_PARAMS(864'000'000, 1, 36, 0), // 864M
PLL_PARAMS(888'000'000, 1, 37, 0), // 888M
PLL_PARAMS(912'000'000, 1, 38, 0), // 912M
PLL_PARAMS(936'000'000, 1, 39, 0), // 936M
PLL_PARAMS(960'000'000, 1, 40, 0), // 960M
PLL_PARAMS(984'000'000, 1, 41, 0), // 984M
PLL_PARAMS(1'008'000'000, 1, 42, 0), // 1008M
PLL_PARAMS(1'032'000'000, 1, 43, 0), // 1032M
PLL_PARAMS(1'056'000'000, 1, 44, 0), // 1056M
PLL_PARAMS(1'080'000'000, 1, 45, 0), // 1080M
PLL_PARAMS(1'104'000'000, 1, 46, 0), // 1104M
PLL_PARAMS(1'128'000'000, 1, 47, 0), // 1128M
PLL_PARAMS(1'152'000'000, 1, 48, 0), // 1152M
PLL_PARAMS(1'176'000'000, 1, 49, 0), // 1176M
PLL_PARAMS(1'200'000'000, 1, 50, 0), // 1200M
PLL_PARAMS(1'224'000'000, 1, 51, 0), // 1224M
PLL_PARAMS(1'248'000'000, 1, 52, 0), // 1248M
PLL_PARAMS(1'272'000'000, 1, 53, 0), // 1272M
PLL_PARAMS(1'296'000'000, 1, 54, 0), // 1296M
PLL_PARAMS(1'320'000'000, 1, 55, 0), // 1320M
PLL_PARAMS(1'344'000'000, 1, 56, 0), // 1344M
PLL_PARAMS(1'368'000'000, 1, 57, 0), // 1368M
PLL_PARAMS(1'392'000'000, 1, 58, 0), // 1392M
PLL_PARAMS(1'416'000'000, 1, 59, 0), // 1416M
PLL_PARAMS(1'440'000'000, 1, 60, 0), // 1440M
PLL_PARAMS(1'464'000'000, 1, 61, 0), // 1464M
PLL_PARAMS(1'488'000'000, 1, 62, 0), // 1488M
PLL_PARAMS(1'512'000'000, 1, 63, 0), // 1512M
PLL_PARAMS(1'536'000'000, 1, 64, 0), // 1536M
};
static constexpr hhi_pll_rate_t a1_hifi_pll_support_rates[] = {
PLL_PARAMS(614'400'000, 5, 128, 0), // 614.4M
};
#undef PLL_PARAMS
static constexpr struct reg_sequence a1_syspll_default[] = {
{.reg_offset = 0x1 << 2, .def = 0x01800000},
{.reg_offset = 0x2 << 2, .def = 0x00001100},
{.reg_offset = 0x3 << 2, .def = 0x10022300},
{.reg_offset = 0x4 << 2, .def = 0x00300000},
{.reg_offset = 0x0 << 2, .def = 0x01f18440},
{.reg_offset = 0x0 << 2, .def = 0x11f18440, .delay_us = 10},
{.reg_offset = 0x0 << 2, .def = 0x15f18440, .delay_us = 40},
{.reg_offset = 0x2 << 2, .def = 0x00001140},
{.reg_offset = 0x2 << 2, .def = 0x00001100},
};
static constexpr meson_clk_pll_data_t a1_syspll_rates = {
.init_regs = a1_syspll_default,
.init_count = std::size(a1_syspll_default),
};
static constexpr struct reg_sequence a1_hifipll_default[] = {
{.reg_offset = 0x0 << 2, .def = 0x01f19480, .delay_us = 10},
{.reg_offset = 0x0 << 2, .def = 0x11f19480},
{.reg_offset = 0x1 << 2, .def = 0x01800000},
{.reg_offset = 0x2 << 2, .def = 0x00001100},
{.reg_offset = 0x3 << 2, .def = 0x10022200},
{.reg_offset = 0x4 << 2, .def = 0x00301000, .delay_us = 10},
{.reg_offset = 0x0 << 2, .def = 0x15f11480, .delay_us = 10},
};
static constexpr meson_clk_pll_data_t a1_hifipll_rates = {
.init_regs = a1_hifipll_default,
.init_count = std::size(a1_hifipll_default),
.repeatedly_toggling = true,
};
std::unique_ptr<AmlMesonPllDevice> CreatePllDevice(fdf::MmioBuffer* mmio, const uint32_t pll_num) {
switch (pll_num) {
case a1::SYS_PLL:
return AmlA1PllDevice::Create(
mmio->View(A1_ANACTRL_SYSPLL_CTRL0, kA1SyspllSize), &a1_syspll_rates,
cpp20::span(a1_sys_pll_support_rates, std::size(a1_sys_pll_support_rates)));
case a1::HIFI_PLL:
return AmlA1PllDevice::Create(
mmio->View(A1_ANACTRL_HIFIPLL_CTRL0, kA1HifipllSize), &a1_hifipll_rates,
cpp20::span(a1_hifi_pll_support_rates, std::size(a1_hifi_pll_support_rates)));
default:
ZX_ASSERT_MSG(0, "Not supported");
break;
}
ZX_ASSERT(0);
return nullptr;
}
std::unique_ptr<AmlMesonPllDevice> AmlA1PllDevice::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<AmlA1PllDevice>(new (&ac) AmlA1PllDevice(std::move(view), data, rates_table));
if (!ac.check()) {
return nullptr;
}
ZX_ASSERT(dev->Initialize() == ZX_OK);
return dev;
}
} // namespace amlogic_clock::a1