mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-30 02:51:30 +02:00
In order to finish moving this symbol to Kconfig for all platforms, we need to do a few more things. First, for all platforms that define this to a function, introduce CONFIG_DYNAMIC_SYS_CLK_FREQ, similar to CONFIG_DYNAMIC_DDR_CLK_FREQ and populate clock_legacy.h. This entails also switching all users from CONFIG_SYS_CLK_FREQ to get_board_sys_clk() and updating a few preprocessor tests. With that done, all platforms that define a value here can be converted to Kconfig, and a fall-back of zero is sufficiently safe to use (and what is used today in cases where code may or may not have this available). Make sure that code which calls this function includes <clock_legacy.h> to get the prototype. Signed-off-by: Tom Rini <trini@konsulko.com>
97 lines
2.5 KiB
C
97 lines
2.5 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Cirrus Logic EP93xx PLL support.
|
|
*
|
|
* Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <clock_legacy.h>
|
|
#include <asm/arch/ep93xx.h>
|
|
#include <asm/io.h>
|
|
#include <div64.h>
|
|
|
|
/*
|
|
* get_board_sys_clk() should be defined as the input frequency of the PLL.
|
|
*
|
|
* get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of
|
|
* the specified bus in HZ.
|
|
*/
|
|
|
|
/*
|
|
* return the PLL output frequency
|
|
*
|
|
* PLL rate = get_board_sys_clk() * (X1FBD + 1) * (X2FBD + 1)
|
|
* / (X2IPD + 1) / 2^PS
|
|
*/
|
|
static ulong get_PLLCLK(uint32_t *pllreg)
|
|
{
|
|
uint8_t i;
|
|
const uint32_t clkset = readl(pllreg);
|
|
uint64_t rate = get_board_sys_clk();
|
|
rate *= ((clkset >> SYSCON_CLKSET_PLL_X1FBD1_SHIFT) & 0x1f) + 1;
|
|
rate *= ((clkset >> SYSCON_CLKSET_PLL_X2FBD2_SHIFT) & 0x3f) + 1;
|
|
do_div(rate, (clkset & 0x1f) + 1); /* X2IPD */
|
|
for (i = 0; i < ((clkset >> SYSCON_CLKSET_PLL_PS_SHIFT) & 3); i++)
|
|
rate >>= 1;
|
|
|
|
return (ulong)rate;
|
|
}
|
|
|
|
/* return FCLK frequency */
|
|
ulong get_FCLK(void)
|
|
{
|
|
const uint8_t fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
|
|
struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
|
|
|
|
const uint32_t clkset1 = readl(&syscon->clkset1);
|
|
const uint8_t fclk_div =
|
|
fclk_divisors[(clkset1 >> SYSCON_CLKSET1_FCLK_DIV_SHIFT) & 7];
|
|
const ulong fclk_rate = get_PLLCLK(&syscon->clkset1) / fclk_div;
|
|
|
|
return fclk_rate;
|
|
}
|
|
|
|
/* return HCLK frequency */
|
|
ulong get_HCLK(void)
|
|
{
|
|
const uint8_t hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
|
|
struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
|
|
|
|
const uint32_t clkset1 = readl(&syscon->clkset1);
|
|
const uint8_t hclk_div =
|
|
hclk_divisors[(clkset1 >> SYSCON_CLKSET1_HCLK_DIV_SHIFT) & 7];
|
|
const ulong hclk_rate = get_PLLCLK(&syscon->clkset1) / hclk_div;
|
|
|
|
return hclk_rate;
|
|
}
|
|
|
|
/* return PCLK frequency */
|
|
ulong get_PCLK(void)
|
|
{
|
|
const uint8_t pclk_divisors[] = { 1, 2, 4, 8 };
|
|
struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
|
|
|
|
const uint32_t clkset1 = readl(&syscon->clkset1);
|
|
const uint8_t pclk_div =
|
|
pclk_divisors[(clkset1 >> SYSCON_CLKSET1_PCLK_DIV_SHIFT) & 3];
|
|
const ulong pclk_rate = get_HCLK() / pclk_div;
|
|
|
|
return pclk_rate;
|
|
}
|
|
|
|
/* return UCLK frequency */
|
|
ulong get_UCLK(void)
|
|
{
|
|
struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
|
|
ulong uclk_rate;
|
|
|
|
const uint32_t value = readl(&syscon->pwrcnt);
|
|
if (value & SYSCON_PWRCNT_UART_BAUD)
|
|
uclk_rate = get_board_sys_clk();
|
|
else
|
|
uclk_rate = get_board_sys_clk() / 2;
|
|
|
|
return uclk_rate;
|
|
}
|