- Reset improvements, enable coherence manager on ae350, k210 clk
  improvements, other fixes
This commit is contained in:
Tom Rini
2021-10-07 09:00:45 -04:00
20 changed files with 311 additions and 95 deletions

View File

@@ -1026,6 +1026,7 @@ T: git https://source.denx.de/u-boot/custodians/u-boot-riscv.git
F: arch/riscv/
F: cmd/riscv/
F: doc/usage/sbi.rst
F: drivers/sysreset/sysreset_sbi.c
F: drivers/timer/andes_plmt_timer.c
F: drivers/timer/sifive_clint_timer.c
F: tools/prelink-riscv.c

View File

@@ -9,6 +9,22 @@
#include <cpu_func.h>
#include <irq_func.h>
#include <asm/cache.h>
#include <asm/csr.h>
#define CSR_MCACHE_CTL 0x7ca
#define CSR_MMISC_CTL 0x7d0
#define CSR_MARCHID 0xf12
#define V5_MCACHE_CTL_IC_EN_OFFSET 0
#define V5_MCACHE_CTL_DC_EN_OFFSET 1
#define V5_MCACHE_CTL_DC_COHEN_OFFSET 19
#define V5_MCACHE_CTL_DC_COHSTA_OFFSET 20
#define V5_MCACHE_CTL_IC_EN BIT(V5_MCACHE_CTL_IC_EN_OFFSET)
#define V5_MCACHE_CTL_DC_EN BIT(V5_MCACHE_CTL_DC_EN_OFFSET)
#define V5_MCACHE_CTL_DC_COHEN_EN BIT(V5_MCACHE_CTL_DC_COHEN_OFFSET)
#define V5_MCACHE_CTL_DC_COHSTA_EN BIT(V5_MCACHE_CTL_DC_COHSTA_OFFSET)
/*
* cleanup_before_linux() is called just before we call linux
@@ -27,3 +43,29 @@ int cleanup_before_linux(void)
return 0;
}
void harts_early_init(void)
{
if (CONFIG_IS_ENABLED(RISCV_MMODE)) {
unsigned long long mcache_ctl_val = csr_read(CSR_MCACHE_CTL);
if (!(mcache_ctl_val & V5_MCACHE_CTL_DC_COHEN_EN))
mcache_ctl_val |= V5_MCACHE_CTL_DC_COHEN_EN;
if (!(mcache_ctl_val & V5_MCACHE_CTL_IC_EN))
mcache_ctl_val |= V5_MCACHE_CTL_IC_EN;
if (!(mcache_ctl_val & V5_MCACHE_CTL_DC_EN))
mcache_ctl_val |= V5_MCACHE_CTL_DC_EN;
csr_write(CSR_MCACHE_CTL, mcache_ctl_val);
/*
* Check DC_COHEN_EN, if cannot write to mcache_ctl,
* we assume this bitmap not support L2 CM
*/
mcache_ctl_val = csr_read(CSR_MCACHE_CTL);
if ((mcache_ctl_val & V5_MCACHE_CTL_DC_COHEN_EN)) {
/* Wait for DC_COHSTA bit be set */
while (!(mcache_ctl_val & V5_MCACHE_CTL_DC_COHSTA_EN))
mcache_ctl_val = csr_read(CSR_MCACHE_CTL);
}
}
}

View File

@@ -6,6 +6,7 @@
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <dm/lists.h>
#include <init.h>
#include <log.h>
#include <asm/encoding.h>
@@ -138,7 +139,17 @@ int arch_cpu_init_dm(void)
int arch_early_init_r(void)
{
return riscv_cpu_probe();
int ret;
ret = riscv_cpu_probe();
if (ret)
return ret;
if (IS_ENABLED(CONFIG_SYSRESET_SBI))
device_bind_driver(gd->dm_root, "sbi-sysreset",
"sbi-sysreset", NULL);
return 0;
}
/**

View File

@@ -12,7 +12,6 @@
#include <linux/types.h>
enum sbi_ext_id {
#ifdef CONFIG_SBI_V01
SBI_EXT_0_1_SET_TIMER = 0x0,
SBI_EXT_0_1_CONSOLE_PUTCHAR = 0x1,
SBI_EXT_0_1_CONSOLE_GETCHAR = 0x2,
@@ -22,11 +21,12 @@ enum sbi_ext_id {
SBI_EXT_0_1_REMOTE_SFENCE_VMA = 0x6,
SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID = 0x7,
SBI_EXT_0_1_SHUTDOWN = 0x8,
#endif
SBI_EXT_BASE = 0x10,
SBI_EXT_TIME = 0x54494D45,
SBI_EXT_IPI = 0x735049,
SBI_EXT_RFENCE = 0x52464E43,
SBI_EXT_HSM = 0x48534D,
SBI_EXT_SRST = 0x53525354,
};
enum sbi_ext_base_fid {
@@ -51,6 +51,41 @@ enum sbi_ext_rfence_fid {
SBI_EXT_RFENCE_REMOTE_FENCE_I = 0,
SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
};
enum sbi_ext_hsm_fid {
SBI_EXT_HSM_HART_START = 0,
SBI_EXT_HSM_HART_STOP,
SBI_EXT_HSM_HART_STATUS,
SBI_EXT_HSM_HART_SUSPEND,
};
enum sbi_hsm_hart_status {
SBI_HSM_HART_STATUS_STARTED = 0,
SBI_HSM_HART_STATUS_STOPPED,
SBI_HSM_HART_STATUS_START_PENDING,
SBI_HSM_HART_STATUS_STOP_PENDING,
SBI_HSM_HART_STATUS_SUSPEND_PENDING,
SBI_HSM_HART_STATUS_RESUME_PENDING,
};
enum sbi_ext_srst_fid {
SBI_EXT_SRST_RESET = 0,
};
enum sbi_srst_reset_type {
SBI_SRST_RESET_TYPE_SHUTDOWN = 0,
SBI_SRST_RESET_TYPE_COLD_REBOOT,
SBI_SRST_RESET_TYPE_WARM_REBOOT,
};
enum sbi_srst_reset_reason {
SBI_SRST_RESET_REASON_NONE = 0,
SBI_SRST_RESET_REASON_SYS_FAILURE,
};
#ifdef CONFIG_SBI_V01
@@ -118,5 +153,6 @@ void sbi_set_timer(uint64_t stime_value);
long sbi_get_spec_version(void);
int sbi_get_impl_id(void);
int sbi_probe_extension(int ext);
void sbi_srst_reset(unsigned long type, unsigned long reason);
#endif

View File

@@ -31,7 +31,6 @@ int riscv_fdt_copy_resv_mem_node(const void *src, void *dst)
fdt_addr_t addr;
fdt_size_t size;
int offset, node, err, rmem_offset;
bool nomap = true;
char basename[32] = {0};
int bname_len;
int max_len = sizeof(basename);
@@ -81,9 +80,7 @@ int riscv_fdt_copy_resv_mem_node(const void *src, void *dst)
log_err("failed to add reserved memory: %d\n", err);
return err;
}
if (!fdt_getprop(src, node, "no-map", NULL))
nomap = false;
if (nomap) {
if (fdt_getprop(src, node, "no-map", NULL)) {
rmem_offset = fdt_node_offset_by_phandle(dst, phandle);
fdt_setprop_empty(dst, rmem_offset, "no-map");
}

View File

@@ -108,6 +108,18 @@ int sbi_probe_extension(int extid)
return -ENOTSUPP;
}
/**
* sbi_srst_reset() - invoke system reset extension
*
* @type: type of reset
* @reason: reason for reset
*/
void sbi_srst_reset(unsigned long type, unsigned long reason)
{
sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET, type, reason,
0, 0, 0, 0);
}
#ifdef CONFIG_SBI_V01
/**

View File

@@ -29,21 +29,21 @@ static struct sbi_imp implementations[] = {
};
static struct sbi_ext extensions[] = {
{ 0x00000000, "sbi_set_timer" },
{ 0x00000001, "sbi_console_putchar" },
{ 0x00000002, "sbi_console_getchar" },
{ 0x00000003, "sbi_clear_ipi" },
{ 0x00000004, "sbi_send_ipi" },
{ 0x00000005, "sbi_remote_fence_i" },
{ 0x00000006, "sbi_remote_sfence_vma" },
{ 0x00000007, "sbi_remote_sfence_vma_asid" },
{ 0x00000008, "sbi_shutdown" },
{ 0x00000010, "SBI Base Functionality" },
{ 0x54494D45, "Timer Extension" },
{ 0x00735049, "IPI Extension" },
{ 0x52464E43, "RFENCE Extension" },
{ 0x0048534D, "Hart State Management Extension" },
{ 0x53525354, "System Reset Extension" },
{ SBI_EXT_0_1_SET_TIMER, "sbi_set_timer" },
{ SBI_EXT_0_1_CONSOLE_PUTCHAR, "sbi_console_putchar" },
{ SBI_EXT_0_1_CONSOLE_GETCHAR, "sbi_console_getchar" },
{ SBI_EXT_0_1_CLEAR_IPI, "sbi_clear_ipi" },
{ SBI_EXT_0_1_SEND_IPI, "sbi_send_ipi" },
{ SBI_EXT_0_1_REMOTE_FENCE_I, "sbi_remote_fence_i" },
{ SBI_EXT_0_1_REMOTE_SFENCE_VMA, "sbi_remote_sfence_vma" },
{ SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, "sbi_remote_sfence_vma_asid" },
{ SBI_EXT_0_1_SHUTDOWN, "sbi_shutdown" },
{ SBI_EXT_BASE, "SBI Base Functionality" },
{ SBI_EXT_TIME, "Timer Extension" },
{ SBI_EXT_IPI, "IPI Extension" },
{ SBI_EXT_RFENCE, "RFENCE Extension" },
{ SBI_EXT_HSM, "Hart State Management Extension" },
{ SBI_EXT_SRST, "System Reset Extension" },
};
static int do_sbi(struct cmd_tbl *cmdtp, int flag, int argc,

View File

@@ -684,7 +684,7 @@ ulong env_get_bootm_low(void)
#if defined(CONFIG_SYS_SDRAM_BASE)
return CONFIG_SYS_SDRAM_BASE;
#elif defined(CONFIG_ARM) || defined(CONFIG_MICROBLAZE)
#elif defined(CONFIG_ARM) || defined(CONFIG_MICROBLAZE) || defined(CONFIG_RISCV)
return gd->bd->bi_dram[0].start;
#else
return 0;

View File

@@ -15,3 +15,4 @@ CONFIG_CMD_NVEDIT_EFI=y
CONFIG_OF_PRIOR_STAGE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM_MTD=y
CONFIG_SYSRESET_SBI=y

View File

@@ -17,3 +17,4 @@ CONFIG_CMD_SBI=y
CONFIG_OF_PRIOR_STAGE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM_MTD=y
CONFIG_SYSRESET_SBI=y

View File

@@ -18,3 +18,4 @@ CONFIG_CMD_NVEDIT_EFI=y
CONFIG_OF_PRIOR_STAGE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM_MTD=y
CONFIG_SYSRESET_SBI=y

View File

@@ -18,3 +18,4 @@ CONFIG_CMD_SBI=y
CONFIG_OF_PRIOR_STAGE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_DM_MTD=y
CONFIG_SYSRESET_SBI=y

View File

@@ -709,6 +709,10 @@ TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in,
* Whether we swapped r and od while enforcing frequency limits
*/
bool swapped = false;
/*
* Whether the intermediate frequencies are out-of-spec
*/
bool out_of_spec;
u64 last_od = od;
u64 last_r = r;
@@ -767,76 +771,95 @@ TEST_STATIC int k210_pll_calc_config(u32 rate, u32 rate_in,
* aren't in spec, try swapping r and od. If everything is
* in-spec, calculate the relative error.
*/
while (true) {
again:
out_of_spec = false;
if (r > max_r) {
out_of_spec = true;
} else {
/*
* Whether the intermediate frequencies are out-of-spec
* There is no way to only divide once; we need
* to examine the frequency with and without the
* effect of od.
*/
bool out_of_spec = false;
u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r);
if (r > max_r) {
if (vco > 1750000000 || vco < 340000000)
out_of_spec = true;
} else {
/*
* There is no way to only divide once; we need
* to examine the frequency with and without the
* effect of od.
*/
u64 vco = DIV_ROUND_CLOSEST_ULL(rate_in * f, r);
}
if (vco > 1750000000 || vco < 340000000)
out_of_spec = true;
if (out_of_spec) {
u64 new_r, new_od;
if (!swapped) {
u64 tmp = r;
r = od;
od = tmp;
swapped = true;
goto again;
}
if (out_of_spec) {
if (!swapped) {
u64 tmp = r;
/*
* Try looking ahead to see if there are additional
* factors for the same product.
*/
if (i + 1 < ARRAY_SIZE(factors)) {
i++;
new_r = UNPACK_R(factors[i]);
new_od = UNPACK_OD(factors[i]);
if (r * od == new_r * new_od) {
r = new_r;
od = new_od;
swapped = false;
goto again;
}
i--;
}
r = od;
od = tmp;
swapped = true;
continue;
} else {
/*
* Try looking ahead to see if there are
* additional factors for the same
* product.
*/
if (i + 1 < ARRAY_SIZE(factors)) {
u64 new_r, new_od;
i++;
new_r = UNPACK_R(factors[i]);
new_od = UNPACK_OD(factors[i]);
if (r * od == new_r * new_od) {
r = new_r;
od = new_od;
swapped = false;
continue;
}
i--;
/*
* Try looking back to see if there is a worse ratio
* that we could try anyway
*/
while (i > 0) {
i--;
new_r = UNPACK_R(factors[i]);
new_od = UNPACK_OD(factors[i]);
/*
* Don't loop over factors for the same product
* to avoid getting stuck because of the above
* clause
*/
if (r * od != new_r * new_od) {
if (new_r * new_od > last_r * last_od) {
r = new_r;
od = new_od;
swapped = false;
goto again;
}
break;
}
}
error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
/* The lower 16 bits are spurious */
error = abs((error - BIT(32))) >> 16;
/* We ran out of things to try */
continue;
}
if (error < best_error) {
best->r = r;
best->f = f;
best->od = od;
best_error = error;
}
break;
error = DIV_ROUND_CLOSEST_ULL(f * inv_ratio, r * od);
/* The lower 16 bits are spurious */
error = abs((error - BIT(32))) >> 16;
if (error < best_error) {
best->r = r;
best->f = f;
best->od = od;
best_error = error;
}
} while (f < 64 && i + 1 < ARRAY_SIZE(factors) && error != 0);
log_debug("best error %lld\n", best_error);
if (best_error == S64_MAX)
return -EINVAL;
log_debug("best error %lld\n", best_error);
return 0;
}
@@ -849,9 +872,6 @@ static ulong k210_pll_set_rate(struct k210_clk_priv *priv, int id, ulong rate,
u32 reg;
ulong calc_rate;
if (rate_in < 0)
return rate_in;
err = k210_pll_calc_config(rate, rate_in, &config);
if (err)
return err;
@@ -895,7 +915,7 @@ static ulong k210_pll_get_rate(struct k210_clk_priv *priv, int id,
u64 r, f, od;
u32 reg = readl(priv->base + k210_plls[id].off);
if (rate_in < 0 || (reg & K210_PLL_BYPASS))
if (reg & K210_PLL_BYPASS)
return rate_in;
if (!(reg & K210_PLL_PWRD))
@@ -1029,6 +1049,8 @@ static ulong do_k210_clk_get_rate(struct k210_clk_priv *priv, int id)
parent = k210_clk_get_parent(priv, id);
parent_rate = do_k210_clk_get_rate(priv, parent);
if (IS_ERR_VALUE(parent_rate))
return parent_rate;
if (k210_clks[id].flags & K210_CLKF_PLL)
return k210_pll_get_rate(priv, k210_clks[id].pll, parent_rate);
@@ -1099,6 +1121,8 @@ static ulong k210_clk_set_rate(struct clk *clk, unsigned long rate)
parent = k210_clk_get_parent(priv, clk->id);
rate_in = do_k210_clk_get_rate(priv, parent);
if (IS_ERR_VALUE(rate_in))
return rate_in;
log_debug("id=%ld rate=%lu rate_in=%lu\n", clk->id, rate, rate_in);

View File

@@ -280,6 +280,14 @@ config DEBUG_EFI_CONSOLE
U-Boot when running on top of EFI (Extensive Firmware Interface).
This is a type of BIOS used by PCs.
config DEBUG_SBI_CONSOLE
bool "SBI"
depends on SBI_V01
help
Select this to enable a debug console which calls back to SBI to
output to the console. This can be useful for early debugging of
U-Boot when running on top of SBI (Supervisor Binary Interface).
config DEBUG_UART_S5P
bool "Samsung S5P"
depends on ARCH_EXYNOS || ARCH_S5PC1XX
@@ -442,6 +450,7 @@ endchoice
config DEBUG_UART_BASE
hex "Base address of UART"
depends on DEBUG_UART
default 0 if DEBUG_SBI_CONSOLE
default 0 if DEBUG_UART_SANDBOX
help
This is the base address of your UART for memory-mapped UARTs.
@@ -452,6 +461,7 @@ config DEBUG_UART_BASE
config DEBUG_UART_CLOCK
int "UART input clock"
depends on DEBUG_UART
default 0 if DEBUG_SBI_CONSOLE
default 0 if DEBUG_UART_SANDBOX
default 0 if DEBUG_MVEBU_A3700_UART
help

View File

@@ -36,6 +36,7 @@ obj-$(CONFIG_ATMEL_USART) += atmel_usart.o
obj-$(CONFIG_BCM6345_SERIAL) += serial_bcm6345.o
obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o
obj-$(CONFIG_CORTINA_UART) += serial_cortina.o
obj-$(CONFIG_DEBUG_SBI_CONSOLE) += serial_sbi.o
obj-$(CONFIG_EFI_APP) += serial_efi.o
obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
obj-$(CONFIG_MCFUART) += serial_mcf.o

View File

@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0+
#include <debug_uart.h>
#include <asm/sbi.h>
static inline void _debug_uart_init(void)
{
}
static inline void _debug_uart_putc(int c)
{
if (CONFIG_IS_ENABLED(RISCV_SMODE))
sbi_console_putchar(c);
}
DEBUG_UART_FUNCS

View File

@@ -85,6 +85,18 @@ config SYSRESET_PSCI
Enable PSCI SYSTEM_RESET function call. To use this, PSCI firmware
must be running on your system.
config SYSRESET_SBI
bool "Enable support for SBI System Reset"
depends on RISCV_SMODE && SBI_V02
select SYSRESET_CMD_POWEROFF if CMD_POWEROFF
help
Enable system reset and poweroff via the SBI system reset extension.
The extension was introduced in version 0.3 of the SBI specification.
If the SBI implementation provides the extension, is board specific.
The RISC-V platform specification mandates the extension for rich
operating system platforms.
config SYSRESET_SOCFPGA
bool "Enable support for Intel SOCFPGA family"
depends on ARCH_SOCFPGA && (TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10)

View File

@@ -13,6 +13,7 @@ obj-$(CONFIG_SYSRESET_MPC83XX) += sysreset_mpc83xx.o
obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o
obj-$(CONFIG_SYSRESET_OCTEON) += sysreset_octeon.o
obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
obj-$(CONFIG_SYSRESET_SBI) += sysreset_sbi.o
obj-$(CONFIG_SYSRESET_SOCFPGA) += sysreset_socfpga.o
obj-$(CONFIG_SYSRESET_SOCFPGA_SOC64) += sysreset_socfpga_soc64.o
obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o

View File

@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2021, Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <log.h>
#include <sysreset.h>
#include <asm/sbi.h>
static enum sbi_srst_reset_type reset_type_map[SYSRESET_COUNT] = {
[SYSRESET_WARM] = SBI_SRST_RESET_TYPE_WARM_REBOOT,
[SYSRESET_COLD] = SBI_SRST_RESET_TYPE_COLD_REBOOT,
[SYSRESET_POWER] = SBI_SRST_RESET_TYPE_COLD_REBOOT,
[SYSRESET_POWER_OFF] = SBI_SRST_RESET_TYPE_SHUTDOWN,
};
static int sbi_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
enum sbi_srst_reset_type reset_type;
reset_type = reset_type_map[type];
sbi_srst_reset(reset_type, SBI_SRST_RESET_REASON_NONE);
return -EINPROGRESS;
}
static int sbi_sysreset_probe(struct udevice *dev)
{
long have_reset;
have_reset = sbi_probe_extension(SBI_EXT_SRST);
if (have_reset)
return 0;
log_warning("SBI has no system reset extension\n");
return -ENOENT;
}
static struct sysreset_ops sbi_sysreset_ops = {
.request = sbi_sysreset_request,
};
U_BOOT_DRIVER(sbi_sysreset) = {
.name = "sbi-sysreset",
.id = UCLASS_SYSRESET,
.ops = &sbi_sysreset_ops,
.probe = sbi_sysreset_probe,
};

View File

@@ -69,27 +69,25 @@ static int dm_test_k210_pll(struct unit_test_state *uts)
&theirs));
ut_asserteq(-EINVAL, k210_pll_calc_config(1500000000, 20000000,
&theirs));
ut_asserteq(-EINVAL, k210_pll_calc_config(1750000000, 13300000,
&theirs));
/* Verify we get the same output with brute-force */
ut_assertok(dm_test_k210_pll_calc_config(390000000, 26000000, &ours));
ut_assertok(k210_pll_calc_config(390000000, 26000000, &theirs));
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
#define compare(rate, rate_in) do { \
ut_assertok(dm_test_k210_pll_calc_config(rate, rate_in, &ours)); \
ut_assertok(k210_pll_calc_config(rate, rate_in, &theirs)); \
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs)); \
} while (0)
ut_assertok(dm_test_k210_pll_calc_config(26000000, 390000000, &ours));
ut_assertok(k210_pll_calc_config(26000000, 390000000, &theirs));
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
ut_assertok(dm_test_k210_pll_calc_config(400000000, 26000000, &ours));
ut_assertok(k210_pll_calc_config(400000000, 26000000, &theirs));
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
ut_assertok(dm_test_k210_pll_calc_config(27000000, 26000000, &ours));
ut_assertok(k210_pll_calc_config(27000000, 26000000, &theirs));
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
ut_assertok(dm_test_k210_pll_calc_config(26000000, 27000000, &ours));
ut_assertok(k210_pll_calc_config(26000000, 27000000, &theirs));
ut_assertok(dm_test_k210_pll_compare(&ours, &theirs));
compare(390000000, 26000000);
compare(26000000, 390000000);
compare(400000000, 26000000);
compare(27000000, 26000000);
compare(26000000, 27000000);
compare(13300000 * 64, 13300000);
compare(21250000, 21250000 * 70);
compare(21250000, 1750000000);
compare(1750000000, 1750000000);
return 0;
}