diff options
-rw-r--r-- | arch/arm/cpu/armv7/socfpga/clock_manager.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/arch/arm/cpu/armv7/socfpga/clock_manager.c b/arch/arm/cpu/armv7/socfpga/clock_manager.c index b91d16006b..8e4e556d89 100644 --- a/arch/arm/cpu/armv7/socfpga/clock_manager.c +++ b/arch/arm/cpu/armv7/socfpga/clock_manager.c @@ -46,10 +46,17 @@ unsigned long cm_qspi_clock; static inline void cm_wait_for_lock(uint32_t mask) { register uint32_t inter_val; + uint32_t retry = 0; do { inter_val = readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_INTER_ADDRESS) & mask; - } while (inter_val != mask); + if (inter_val == mask) + retry++; + else + retry = 0; + if (retry >= 10) + break; + } while (1); } /* function to poll in the fsm busy bit */ @@ -173,8 +180,37 @@ int cm_basic_init(const cm_config_t *cfg) CLKMGR_BYPASS_MAINPLL_SET(CLKMGR_BYPASS_ENUM_ENABLE)); /* - * Put all plls VCO registers back to reset value. - * Some code might have messed with them. + * Reset the SDR VCO register twice to overcome SDR PLL + * phase sync issue + */ + writel(CLKMGR_SDRPLLGRP_VCO_RESET_VALUE, + SOCFPGA_CLKMGR_ADDRESS + CLKMGR_SDRPLLGRP_VCO_ADDRESS); + + /* delay 5us */ + udelay(5); + + /* + * We made sure bgpwr down was assert for 5 us. Now deassert BG PWR DN + * with numerator and denominator. + */ + writel(CLKMGR_SDRPLLGRP_VCO_OUTRESET_SET(0) | + CLKMGR_SDRPLLGRP_VCO_OUTRESETALL_SET(0) | + cfg->sdram_vco_base | CLEAR_BGP_EN_PWRDN | + CLKMGR_SDRPLLGRP_VCO_REGEXTSEL_MASK, + (SOCFPGA_CLKMGR_ADDRESS + CLKMGR_SDRPLLGRP_VCO_ADDRESS)); + + /* delay 7us */ + udelay(7); + + /* Enable sdram pll vco */ + writel(CLKMGR_SDRPLLGRP_VCO_OUTRESET_SET(0) | + CLKMGR_SDRPLLGRP_VCO_OUTRESETALL_SET(0) | + cfg->sdram_vco_base | VCO_EN_BASE, + (SOCFPGA_CLKMGR_ADDRESS + CLKMGR_SDRPLLGRP_VCO_ADDRESS)); + + /* + * Now we reset for VCO include SDR VCO again. Put all plls VCO + * registers back to reset value. */ DEBUG_MEMORY writel(CLKMGR_MAINPLLGRP_VCO_RESET_VALUE, |