[U-Boot] [PATCH 15/35] arm: socfpga: clock: Add code to read clock configuration
Dinh Nguyen
dinguyen at opensource.altera.com
Mon Sep 15 22:09:34 CEST 2014
On 09/15/2014 06:06 AM, Marek Vasut wrote:
> From: Pavel Machek <pavel at denx.de>
>
> Add the entire bulk of code to read out clock configuration from the SoCFPGA
> CPU registers. This is important for MMC, QSPI and UART drivers as otherwise
> they cannot determine the frequency of their upstream clock.
>
> Signed-off-by: Pavel Machek <pavel at denx.de>
> Signed-off-by: Marek Vasut <marex at denx.de>
> Cc: Chin Liang See <clsee at altera.com>
> Cc: Dinh Nguyen <dinguyen at altera.com>
> Cc: Albert Aribaud <albert.u.boot at aribaud.net>
> Cc: Tom Rini <trini at ti.com>
> Cc: Wolfgang Denk <wd at denx.de>
> Cc: Pavel Machek <pavel at denx.de>
> ---
> arch/arm/cpu/armv7/socfpga/clock_manager.c | 226 +++++++++++++++++++++-
> arch/arm/include/asm/arch-socfpga/clock_manager.h | 43 +++-
> include/configs/socfpga_cyclone5.h | 1 +
> 3 files changed, 267 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/socfpga/clock_manager.c b/arch/arm/cpu/armv7/socfpga/clock_manager.c
> index d032bbd..07cf74c 100644
> --- a/arch/arm/cpu/armv7/socfpga/clock_manager.c
> +++ b/arch/arm/cpu/armv7/socfpga/clock_manager.c
> @@ -8,8 +8,10 @@
> #include <asm/io.h>
> #include <asm/arch/clock_manager.h>
>
> +DECLARE_GLOBAL_DATA_PTR;
> +
> static const struct socfpga_clock_manager *clock_manager_base =
> - (void *)SOCFPGA_CLKMGR_ADDRESS;
> + (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS;
>
> #define CLKMGR_BYPASS_ENABLE 1
> #define CLKMGR_BYPASS_DISABLE 0
> @@ -358,3 +360,225 @@ void cm_basic_init(const cm_config_t *cfg)
> writel(~0, &clock_manager_base->per_pll.en);
> writel(~0, &clock_manager_base->sdr_pll.en);
> }
> +
> +unsigned long cm_get_mpu_clk_hz(void)
> +{
> + uint32_t reg, clock;
> +
> + /* get the main VCO clock */
> + reg = readl(&clock_manager_base->main_pll.vco);
> + clock = CONFIG_HPS_CLK_OSC1_HZ /
> + (CLKMGR_MAINPLLGRP_VCO_DENOM_GET(reg) + 1);
> + clock *= (CLKMGR_MAINPLLGRP_VCO_NUMER_GET(reg) + 1);
> +
> + /* get the MPU clock */
> + reg = readl(&clock_manager_base->altera.mpuclk);
> + clock /= (reg + 1);
> + reg = readl(&clock_manager_base->main_pll.mpuclk);
> + clock /= (reg + 1);
> + return clock;
> +}
> +
> +unsigned long cm_get_sdram_clk_hz(void)
> +{
> + uint32_t reg, clock = 0;
> +
> + /* identify SDRAM PLL clock source */
> + reg = readl(&clock_manager_base->sdr_pll.vco);
> + reg = CLKMGR_SDRPLLGRP_VCO_SSRC_GET(reg);
> + if (reg == CLKMGR_VCO_SSRC_EOSC1)
> + clock = CONFIG_HPS_CLK_OSC1_HZ;
> + else if (reg == CLKMGR_VCO_SSRC_EOSC2)
> + clock = CONFIG_HPS_CLK_OSC2_HZ;
> + else if (reg == CLKMGR_VCO_SSRC_F2S)
> + clock = CONFIG_HPS_CLK_F2S_SDR_REF_HZ;
> +
> + /* get the SDRAM VCO clock */
> + reg = readl(&clock_manager_base->sdr_pll.vco);
> + clock /= (CLKMGR_SDRPLLGRP_VCO_DENOM_GET(reg) + 1);
> + clock *= (CLKMGR_SDRPLLGRP_VCO_NUMER_GET(reg) + 1);
> +
> + /* get the SDRAM (DDR_DQS) clock */
> + reg = readl(&clock_manager_base->sdr_pll.ddrdqsclk);
> + reg = CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_GET(reg);
> + clock /= (reg + 1);
> +
> + return clock;
> +}
> +
> +unsigned int cm_get_l4_sp_clk_hz(void)
> +{
> + uint32_t reg, clock = 0;
> +
> + /* identify the source of L4 SP clock */
> + reg = readl(&clock_manager_base->main_pll.l4src);
> + reg = CLKMGR_MAINPLLGRP_L4SRC_L4SP_GET(reg);
> +
> + if (reg == CLKMGR_L4_SP_CLK_SRC_MAINPLL) {
> + /* get the main VCO clock */
> + reg = readl(&clock_manager_base->main_pll.vco);
> + clock = CONFIG_HPS_CLK_OSC1_HZ /
> + (CLKMGR_MAINPLLGRP_VCO_DENOM_GET(reg) + 1);
> + clock *= (CLKMGR_MAINPLLGRP_VCO_NUMER_GET(reg) + 1);
> +
> + /* get the clock prior L4 SP divider (main clk) */
> + reg = readl(&clock_manager_base->altera.mainclk);
> + clock /= (reg + 1);
> + reg = readl(&clock_manager_base->main_pll.mainclk);
> + clock /= (reg + 1);
> + } else if (reg == CLKMGR_L4_SP_CLK_SRC_PERPLL) {
> + /* identify PER PLL clock source */
> + reg = readl(&clock_manager_base->per_pll.vco);
> + reg = CLKMGR_PERPLLGRP_VCO_SSRC_GET(reg);
> + if (reg == CLKMGR_VCO_SSRC_EOSC1)
> + clock = CONFIG_HPS_CLK_OSC1_HZ;
> + else if (reg == CLKMGR_VCO_SSRC_EOSC2)
> + clock = CONFIG_HPS_CLK_OSC2_HZ;
> + else if (reg == CLKMGR_VCO_SSRC_F2S)
> + clock = CONFIG_HPS_CLK_F2S_PER_REF_HZ;
> +
> + /* get the PER VCO clock */
> + reg = readl(&clock_manager_base->per_pll.vco);
> + clock /= (CLKMGR_PERPLLGRP_VCO_DENOM_GET(reg) + 1);
> + clock *= (CLKMGR_PERPLLGRP_VCO_NUMER_GET(reg) + 1);
> +
> + /* get the clock prior L4 SP divider (periph_base_clk) */
> + reg = readl(&clock_manager_base->per_pll.perbaseclk);
> + clock /= (reg + 1);
> + }
> +
> + /* get the L4 SP clock which supplied to UART */
> + reg = readl(&clock_manager_base->main_pll.maindiv);
> + reg = CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_GET(reg);
> + clock = clock / (reg + 1);
This is not a +1. The l4 mp clock divider is structured like this:
0x0 = divide by 1
0x1 = divide by 2
0x2 = divide by 4
0x3 = divide by 8
0x4 = divide by 16
So it should be:
clock = clock / (1 << reg);
Dinh
More information about the U-Boot
mailing list