
On 09/15/2014 06:06 AM, Marek Vasut wrote:
From: Pavel Machek pavel@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@denx.de Signed-off-by: Marek Vasut marex@denx.de Cc: Chin Liang See clsee@altera.com Cc: Dinh Nguyen dinguyen@altera.com Cc: Albert Aribaud albert.u.boot@aribaud.net Cc: Tom Rini trini@ti.com Cc: Wolfgang Denk wd@denx.de Cc: Pavel Machek pavel@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