blob: beebcd4eacaabcb69d840ae9e45b749879886654 [file] [log] [blame]
// 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 <zircon/types.h>
#include <iterator>
#include <soc/aml-s905d2/s905d2-hiu.h>
// PLL Rate tables
#define HHI_PLL_RATE(_rate, _n, _m, _frac, _od) \
{ .rate = _rate, .n = _n, .m = _m, .frac = _frac, .od = _od, }
/* These settings work for hifi, sys, pcie, and gp0 plls
While it would be possible to dynamically calculate the four components
to generate a desired rate, it makes more sense at this time to have a table
of settings for some known needed rates. The documentation fo the Amlogic
plls is somewhat thin and by using the tables we will have known tested good
rates to choose from.
fout = 24MHz*m/(n*(1 << od))
*/
static const hhi_pll_rate_t s905d2_hiu_pll_rates[] = {
HHI_PLL_RATE(768000000, 1, 128, 0, 2), /*DCO=3072M*/
HHI_PLL_RATE(846000000, 1, 141, 0, 2), /*DCO=3384M*/
HHI_PLL_RATE(1200000000, 1, 200, 0, 2), /*DCO=4800M*/
HHI_PLL_RATE(1296000000, 1, 216, 0, 2), /*DCO=5184M*/
HHI_PLL_RATE(1398000000, 1, 233, 0, 2), /*DCO=5592M*/
HHI_PLL_RATE(1494000000, 1, 249, 0, 2), /*DCO=5976M*/
HHI_PLL_RATE(1512000000, 1, 126, 0, 1), /*DCO=3024M*/
HHI_PLL_RATE(1536000000, 1, 128, 0, 1), /*DCO=3072M*/
HHI_PLL_RATE(1608000000, 1, 134, 0, 1), /*DCO=3216M*/
HHI_PLL_RATE(1704000000, 1, 142, 0, 1), /*DCO=3408M*/
HHI_PLL_RATE(1800000000, 1, 150, 0, 1), /*DCO=3600M*/
HHI_PLL_RATE(1896000000, 1, 158, 0, 1), /*DCO=3792M*/
HHI_PLL_RATE(1908000000, 1, 159, 0, 1), /*DCO=3816M*/
HHI_PLL_RATE(2016000000, 1, 168, 0, 1), /*DCO=4200M*/
HHI_PLL_RATE(2100000000, 1, 175, 0, 1), /*DCO=4375M*/
HHI_PLL_RATE(2208000000, 1, 184, 0, 1), /*DCO=4600M*/
HHI_PLL_RATE(3072000000, 1, 128, 0, 0), /*DCO=3072M*/
};
/* PCIE PLL rates, OD is fixed at 9. Adding this to the above sorted HUI PLL table will make this
the first entry, and hence the default rate for many PLLs. Created new table to avoid changing
default initial rate for other PLLs.
fout = 24MHz*m/(n*(1 << od))
*/
static const hhi_pll_rate_t s905d2_pcie_pll_rates[] = {
HHI_PLL_RATE(100000000, 1, 150, 0, 9), /*DCO=3600M*/
};
/* Find frequency in the rate table and return pointer to the entry.
At this point this assumes even integer frequencies. This will be expanded later
to handle fractional cases.
*/
zx_status_t s905d2_pll_fetch_rate(aml_pll_dev_t* pll_dev, uint64_t freq,
const hhi_pll_rate_t** pll_rate) {
for (uint32_t i = 0; i < pll_dev->rate_count; i++) {
if (freq == pll_dev->rate_table[i].rate) {
*pll_rate = &pll_dev->rate_table[i];
return ZX_OK;
}
}
*pll_rate = nullptr;
return ZX_ERR_NOT_SUPPORTED;
}
const hhi_pll_rate_t* s905d2_pll_get_rate_table(hhi_plls_t pll_num) {
switch (pll_num) {
case GP0_PLL:
case HIFI_PLL:
case SYS_PLL:
case SYS1_PLL:
return s905d2_hiu_pll_rates;
case PCIE_PLL:
return s905d2_pcie_pll_rates;
default:
return nullptr;
}
}
size_t s905d2_get_rate_table_count(hhi_plls_t pll_num) {
switch (pll_num) {
case GP0_PLL:
case HIFI_PLL:
case SYS_PLL:
case SYS1_PLL:
return std::size(s905d2_hiu_pll_rates);
case PCIE_PLL:
return std::size(s905d2_pcie_pll_rates);
default:
return 0;
}
}