1 /*******************************************************************************
\r
2 * (c) Copyright 2012-2013 Microsemi SoC Products Group. All rights reserved.
\r
4 * SmartFusion2 CMSIS system initialization.
\r
6 * SVN $Revision: 5280 $
\r
7 * SVN $Date: 2013-03-22 20:51:50 +0000 (Fri, 22 Mar 2013) $
\r
10 #include "../drivers_config/sys_config/sys_config.h"
\r
11 #include "sys_init_cfg_types.h"
\r
13 /*------------------------------------------------------------------------------
\r
16 #define UNKNOWN_SILICON_REV 0
\r
17 #define M2S050_REV_A_SILICON 1
\r
18 #define M2S050_REV_B_SILICON 2
\r
20 /*------------------------------------------------------------------------------
\r
23 void mscc_post_hw_cfg_init(void);
\r
25 /*------------------------------------------------------------------------------
\r
26 * System registers of interest.
\r
29 * MSSDDR_FACC1_CR register masks:
\r
31 #define DDR_CLK_EN_SHIFT 8u
\r
32 #define FACC_GLMUX_SEL_MASK 0x00001000u
\r
33 #define CONTROLLER_PLL_INIT_MASK 0x04000000u
\r
34 #define RCOSC_DIV2_MASK 0x00000004u
\r
37 * MSSDDR_PLL_STATUS register masks:
\r
39 #define FAB_PLL_LOCK_MASK 0x00000001u
\r
40 #define MPLL_LOCK_MASK 0x00000002u
\r
43 * MSSDDR_PLL_STATUS_HIGH_CR register masks:
\r
45 #define FACC_PLL_BYPASS_MASK 0x00000001u
\r
47 /*------------------------------------------------------------------------------
\r
48 * Standard CMSIS global variables.
\r
50 uint32_t SystemCoreClock = MSS_SYS_M3_CLK_FREQ; /*!< System Clock Frequency (Core Clock) */
\r
52 /*------------------------------------------------------------------------------
\r
53 * SmartFusion2 specific clocks.
\r
55 uint32_t g_FrequencyPCLK0 = MSS_SYS_APB_0_CLK_FREQ; /*!< Clock frequency of APB bus 0. */
\r
56 uint32_t g_FrequencyPCLK1 = MSS_SYS_APB_1_CLK_FREQ; /*!< Clock frequency of APB bus 1. */
\r
57 uint32_t g_FrequencyPCLK2 = MSS_SYS_APB_2_CLK_FREQ; /*!< Clock frequency of APB bus 2. */
\r
58 uint32_t g_FrequencyFIC0 = MSS_SYS_FIC_0_CLK_FREQ; /*!< Clock frequecny of FPGA fabric interface controller 1. */
\r
59 uint32_t g_FrequencyFIC1 = MSS_SYS_FIC_1_CLK_FREQ; /*!< Clock frequecny of FPGA fabric inteface controller 2. */
\r
60 uint32_t g_FrequencyFIC64 = MSS_SYS_FIC64_CLK_FREQ; /*!< Clock frequecny of 64-bit FPGA fabric interface controller. */
\r
62 /*------------------------------------------------------------------------------
\r
63 * System configuration tables generated by Libero.
\r
65 #if MSS_SYS_MDDR_CONFIG_BY_CORTEX
\r
66 extern MDDR_TypeDef * const g_m2s_mddr_addr;
\r
67 extern const ddr_subsys_cfg_t g_m2s_mddr_subsys_config;
\r
70 #if MSS_SYS_FDDR_CONFIG_BY_CORTEX
\r
71 extern FDDR_TypeDef * const g_m2s_fddr_addr;
\r
72 extern const ddr_subsys_cfg_t g_m2s_fddr_subsys_config;
\r
75 #define MSS_SYS_SERDES_CONFIG_BY_CORTEX (MSS_SYS_SERDES_0_CONFIG_BY_CORTEX || MSS_SYS_SERDES_1_CONFIG_BY_CORTEX || MSS_SYS_SERDES_2_CONFIG_BY_CORTEX || MSS_SYS_SERDES_3_CONFIG_BY_CORTEX)
\r
77 #if MSS_SYS_SERDES_0_CONFIG_BY_CORTEX
\r
78 extern const cfg_addr_value_pair_t g_m2s_serdes_0_config[SERDES_0_CFG_NB_OF_PAIRS];
\r
81 #if MSS_SYS_SERDES_1_CONFIG_BY_CORTEX
\r
82 extern const cfg_addr_value_pair_t g_m2s_serdes_1_config[SERDES_1_CFG_NB_OF_PAIRS];
\r
85 #if MSS_SYS_SERDES_2_CONFIG_BY_CORTEX
\r
86 extern const cfg_addr_value_pair_t g_m2s_serdes_2_config[SERDES_2_CFG_NB_OF_PAIRS];
\r
89 #if MSS_SYS_SERDES_3_CONFIG_BY_CORTEX
\r
90 extern const cfg_addr_value_pair_t g_m2s_serdes_3_config[SERDES_3_CFG_NB_OF_PAIRS];
\r
93 #define MSS_SYS_CORESF2RESET_USED (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX || MSS_SYS_SERDES_CONFIG_BY_CORTEX)
\r
95 /*------------------------------------------------------------------------------
\r
98 static uint32_t get_silicon_revision(void);
\r
99 static void silicon_workarounds(void);
\r
100 static void m2s050_rev_a_workarounds(void);
\r
102 #if (MSS_SYS_FACC_INIT_BY_CORTEX == 1)
\r
103 static void complete_clock_config(void);
\r
106 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
\r
107 static void configure_serdes_intf(void);
\r
110 #if (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX)
\r
111 static void config_ddr_subsys
\r
113 const ddr_subsys_cfg_t * p_ddr_subsys_cfg,
\r
114 DDRCore_TypeDef * p_ddr_subsys_regs
\r
118 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
\r
119 static void config_by_addr_value
\r
121 const cfg_addr_value_pair_t * p_addr_value_pair,
\r
122 uint32_t nb_of_cfg_pairs
\r
126 static uint32_t get_rcosc_25_50mhz_frequency(void);
\r
127 static void set_clock_frequency_globals(uint32_t fclk);
\r
129 /***************************************************************************//**
\r
130 * See system_m2sxxx.h for details.
\r
132 void SystemInit(void)
\r
135 * Do not make use of global variables or make any asumptions regarding
\r
136 * memory content if modifying this function. The memory content has not been
\r
137 * initialised by the time this function is called by the start-up code.
\r
139 #if (MSS_SYS_FACC_INIT_BY_CORTEX == 1)
\r
140 complete_clock_config();
\r
143 silicon_workarounds();
\r
145 /*--------------------------------------------------------------------------
\r
146 * Set STKALIGN to ensure exception stacking starts on 8 bytes address
\r
147 * boundary. This ensures compliance with the "Procedure Call Standards for
\r
148 * the ARM Architecture" (AAPCS).
\r
150 SCB->CCR |= SCB_CCR_STKALIGN_Msk;
\r
152 /*--------------------------------------------------------------------------
\r
153 * MDDR configuration
\r
155 #if MSS_SYS_MDDR_CONFIG_BY_CORTEX
\r
156 config_ddr_subsys(&g_m2s_mddr_subsys_config, &g_m2s_mddr_addr->core);
\r
159 /*--------------------------------------------------------------------------
\r
160 * MDDR configuration
\r
162 #if MSS_SYS_FDDR_CONFIG_BY_CORTEX
\r
163 config_ddr_subsys(&g_m2s_fddr_subsys_config, &g_m2s_fddr_addr->core);
\r
166 /*--------------------------------------------------------------------------
\r
167 * SERDES interfaces configuration.
\r
169 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
\r
170 configure_serdes_intf();
\r
173 /*--------------------------------------------------------------------------
\r
174 * Call user defined configuration function.
\r
176 mscc_post_hw_cfg_init();
\r
178 /*--------------------------------------------------------------------------
\r
179 * Synchronize with CoreSF2Reset controlling resets from the fabric.
\r
181 #if MSS_SYS_CORESF2RESET_USED
\r
182 CORE_SF2_CFG->CONFIG_DONE = 1u; /* Signal to CoreSF2Reset that peripheral
\r
183 configuration registers have been written.*/
\r
184 while(!CORE_SF2_CFG->INIT_DONE)
\r
186 ; /* Wait for INIT_DONE from CoreSF2Reset. */
\r
191 /***************************************************************************//**
\r
192 * SystemCoreClockUpdate()
\r
194 #define RCOSC_25_50MHZ_CLK_SRC 0u
\r
195 #define CLK_XTAL_CLK_SRC 1u
\r
196 #define RCOSC_1_MHZ_CLK_SRC 2u
\r
197 #define CCC2ASCI_CLK_SRC 3u
\r
199 #define FACC_STANDBY_SHIFT 6u
\r
200 #define FACC_STANDBY_SEL_MASK 0x00000007u
\r
202 #define FREQ_32KHZ 32768u
\r
203 #define FREQ_1MHZ 1000000u
\r
204 #define FREQ_25MHZ 25000000u
\r
205 #define FREQ_50MHZ 50000000u
\r
207 void SystemCoreClockUpdate(void)
\r
210 uint32_t controller_pll_init;
\r
213 controller_pll_init = SYSREG->MSSDDR_FACC1_CR & CONTROLLER_PLL_INIT_MASK;
\r
215 if(0u == controller_pll_init)
\r
217 /* Normal operations. */
\r
218 uint32_t global_mux_sel;
\r
220 global_mux_sel = SYSREG->MSSDDR_FACC1_CR & FACC_GLMUX_SEL_MASK;
\r
221 if(0u == global_mux_sel)
\r
223 /* MSS clocked from MSS PLL. Use Libero flow defines. */
\r
224 SystemCoreClock = MSS_SYS_M3_CLK_FREQ;
\r
225 g_FrequencyPCLK0 = MSS_SYS_APB_0_CLK_FREQ;
\r
226 g_FrequencyPCLK1 = MSS_SYS_APB_1_CLK_FREQ;
\r
227 g_FrequencyPCLK2 = MSS_SYS_APB_2_CLK_FREQ;
\r
228 g_FrequencyFIC0 = MSS_SYS_FIC_0_CLK_FREQ;
\r
229 g_FrequencyFIC1 = MSS_SYS_FIC_1_CLK_FREQ;
\r
230 g_FrequencyFIC64 = MSS_SYS_FIC64_CLK_FREQ;
\r
234 /* MSS clocked from standby clock. */
\r
235 const uint8_t standby_clock_lut[8] = { RCOSC_25_50MHZ_CLK_SRC,
\r
237 RCOSC_25_50MHZ_CLK_SRC,
\r
239 RCOSC_1_MHZ_CLK_SRC,
\r
240 RCOSC_1_MHZ_CLK_SRC,
\r
242 CCC2ASCI_CLK_SRC };
\r
244 uint32_t standby_sel;
\r
245 uint8_t clock_source;
\r
247 standby_sel = (SYSREG->MSSDDR_FACC2_CR >> FACC_STANDBY_SHIFT) & FACC_STANDBY_SEL_MASK;
\r
248 clock_source = standby_clock_lut[standby_sel];
\r
249 switch(clock_source)
\r
251 case RCOSC_25_50MHZ_CLK_SRC:
\r
252 clk_src = get_rcosc_25_50mhz_frequency();
\r
253 set_clock_frequency_globals(clk_src);
\r
256 case CLK_XTAL_CLK_SRC:
\r
257 set_clock_frequency_globals(FREQ_32KHZ);
\r
260 case RCOSC_1_MHZ_CLK_SRC:
\r
261 set_clock_frequency_globals(FREQ_1MHZ);
\r
264 case CCC2ASCI_CLK_SRC:
\r
265 /* Fall through. */
\r
267 set_clock_frequency_globals(FREQ_1MHZ);
\r
274 /* PLL initialization mode. Running from 25/50MHZ RC oscillator. */
\r
275 clk_src = get_rcosc_25_50mhz_frequency();
\r
276 set_clock_frequency_globals(clk_src);
\r
281 * Reset the clock frequency global variables to the values delected in the
\r
284 SystemCoreClock = MSS_SYS_M3_CLK_FREQ;
\r
285 g_FrequencyPCLK0 = MSS_SYS_APB_0_CLK_FREQ;
\r
286 g_FrequencyPCLK1 = MSS_SYS_APB_1_CLK_FREQ;
\r
287 g_FrequencyPCLK2 = MSS_SYS_APB_2_CLK_FREQ;
\r
288 g_FrequencyFIC0 = MSS_SYS_FIC_0_CLK_FREQ;
\r
289 g_FrequencyFIC1 = MSS_SYS_FIC_1_CLK_FREQ;
\r
290 g_FrequencyFIC64 = MSS_SYS_FIC64_CLK_FREQ;
\r
294 /***************************************************************************//**
\r
295 * Find out frequency generated by the 25_50mhz RC osciallator.
\r
297 static uint32_t get_rcosc_25_50mhz_frequency(void)
\r
299 uint32_t rcosc_div2;
\r
300 uint32_t rcosc_frequency;
\r
302 rcosc_div2 = SYSREG->MSSDDR_PLL_STATUS & RCOSC_DIV2_MASK;
\r
303 if(0u == rcosc_div2)
\r
305 /* 25_50mhz oscillator is configured for 25 MHz operations. */
\r
306 rcosc_frequency = FREQ_25MHZ;
\r
310 /* 25_50mhz oscillator is configured for 50 MHz operations. */
\r
311 rcosc_frequency = FREQ_50MHZ;
\r
314 return rcosc_frequency;
\r
317 /***************************************************************************//**
\r
318 Set the value of the clock frequency global variables based on the value of
\r
319 standby_clk passed as parameter.
\r
320 The following global variables are set by this function:
\r
329 static void set_clock_frequency_globals(uint32_t standby_clk)
\r
331 SystemCoreClock = standby_clk;
\r
332 g_FrequencyPCLK0 = standby_clk;
\r
333 g_FrequencyPCLK1 = standby_clk;
\r
334 g_FrequencyPCLK2 = MSS_SYS_APB_2_CLK_FREQ;
\r
335 g_FrequencyFIC0 = standby_clk;
\r
336 g_FrequencyFIC1 = standby_clk;
\r
337 g_FrequencyFIC64 = standby_clk;
\r
340 /***************************************************************************//**
\r
341 * Write 16-bit configuration values into 32-bit word aligned registers.
\r
343 #if (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX)
\r
344 static void copy_cfg16_to_regs
\r
346 volatile uint32_t * p_regs,
\r
347 const uint16_t * p_cfg,
\r
348 uint32_t nb_16bit_words
\r
353 for(inc = 0u; inc < nb_16bit_words; ++inc)
\r
355 p_regs[inc] = p_cfg[inc];
\r
360 /***************************************************************************//**
\r
361 * Configure peripheral using register address and register value pairs.
\r
363 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
\r
364 static void config_by_addr_value
\r
366 const cfg_addr_value_pair_t * p_addr_value_pair,
\r
367 uint32_t nb_of_cfg_pairs
\r
372 for(inc = 0u; inc < nb_of_cfg_pairs; ++inc)
\r
374 *p_addr_value_pair[inc].p_reg = p_addr_value_pair[inc].value;
\r
379 /***************************************************************************//**
\r
380 * DDR subsystem configuration.
\r
382 #if (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX)
\r
384 #define NB_OF_DDRC_REGS_TO_CONFIG 57u
\r
385 #define NB_OF_DDR_PHY_REGS_TO_CONFIG 65u
\r
387 static void config_ddr_subsys
\r
389 const ddr_subsys_cfg_t * p_ddr_subsys_cfg,
\r
390 DDRCore_TypeDef * p_ddr_subsys_regs
\r
393 volatile uint32_t * p_regs;
\r
394 const uint16_t * p_cfg;
\r
396 /*--------------------------------------------------------------------------
\r
397 * Configure DDR controller part of the MDDR subsystem.
\r
399 p_cfg = &p_ddr_subsys_cfg->ddrc.DYN_SOFT_RESET_CR;
\r
400 p_regs = &p_ddr_subsys_regs->ddrc.DYN_SOFT_RESET_CR;
\r
402 copy_cfg16_to_regs(p_regs, p_cfg, NB_OF_DDRC_REGS_TO_CONFIG);
\r
404 /*--------------------------------------------------------------------------
\r
405 * Configure DDR PHY.
\r
407 p_cfg = &p_ddr_subsys_cfg->phy.LOOPBACK_TEST_CR;
\r
408 p_regs = &p_ddr_subsys_regs->phy.LOOPBACK_TEST_CR;
\r
410 copy_cfg16_to_regs(p_regs, p_cfg, NB_OF_DDR_PHY_REGS_TO_CONFIG);
\r
412 /*--------------------------------------------------------------------------
\r
413 * Configure DDR FIC.
\r
415 p_ddr_subsys_regs->fic.NB_ADDR_CR = p_ddr_subsys_cfg->fic.NB_ADDR_CR;
\r
416 p_ddr_subsys_regs->fic.NBRWB_SIZE_CR = p_ddr_subsys_cfg->fic.NBRWB_SIZE_CR;
\r
417 p_ddr_subsys_regs->fic.WB_TIMEOUT_CR = p_ddr_subsys_cfg->fic.WB_TIMEOUT_CR;
\r
418 p_ddr_subsys_regs->fic.HPD_SW_RW_EN_CR = p_ddr_subsys_cfg->fic.HPD_SW_RW_EN_CR;
\r
419 p_ddr_subsys_regs->fic.HPD_SW_RW_INVAL_CR = p_ddr_subsys_cfg->fic.HPD_SW_RW_INVAL_CR;
\r
420 p_ddr_subsys_regs->fic.SW_WR_ERCLR_CR = p_ddr_subsys_cfg->fic.SW_WR_ERCLR_CR;
\r
421 p_ddr_subsys_regs->fic.ERR_INT_ENABLE_CR = p_ddr_subsys_cfg->fic.ERR_INT_ENABLE_CR;
\r
422 p_ddr_subsys_regs->fic.NUM_AHB_MASTERS_CR = p_ddr_subsys_cfg->fic.NUM_AHB_MASTERS_CR;
\r
423 p_ddr_subsys_regs->fic.LOCK_TIMEOUTVAL_CR[0] = p_ddr_subsys_cfg->fic.LOCK_TIMEOUTVAL_1_CR;
\r
424 p_ddr_subsys_regs->fic.LOCK_TIMEOUTVAL_CR[1] = p_ddr_subsys_cfg->fic.LOCK_TIMEOUTVAL_2_CR;
\r
425 p_ddr_subsys_regs->fic.LOCK_TIMEOUT_EN_CR = p_ddr_subsys_cfg->fic.LOCK_TIMEOUT_EN_CR;
\r
427 /*--------------------------------------------------------------------------
\r
430 p_ddr_subsys_regs->ddrc.DYN_SOFT_RESET_CR = 0x01u;
\r
432 while(0x0000u == p_ddr_subsys_regs->ddrc.DDRC_SR)
\r
440 /***************************************************************************//**
\r
441 * Configure SERDES interfaces.
\r
443 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
\r
445 static void configure_serdes_intf(void)
\r
447 #if MSS_SYS_SERDES_0_CONFIG_BY_CORTEX
\r
448 config_by_addr_value(g_m2s_serdes_0_config, SERDES_0_CFG_NB_OF_PAIRS);
\r
451 #if MSS_SYS_SERDES_1_CONFIG_BY_CORTEX
\r
452 config_by_addr_value(g_m2s_serdes_1_config, SERDES_1_CFG_NB_OF_PAIRS);
\r
455 #if MSS_SYS_SERDES_2_CONFIG_BY_CORTEX
\r
456 config_by_addr_value(g_m2s_serdes_2_config, SERDES_2_CFG_NB_OF_PAIRS);
\r
459 #if MSS_SYS_SERDES_3_CONFIG_BY_CORTEX
\r
460 config_by_addr_value(g_m2s_serdes_3_config, SERDES_3_CFG_NB_OF_PAIRS);
\r
466 /*------------------------------------------------------------------------------
\r
467 Retrieve silicon revision from system registers.
\r
469 static uint32_t get_silicon_revision(void)
\r
471 uint32_t silicon_revision;
\r
472 uint32_t device_version;
\r
474 device_version = SYSREG->DEVICE_VERSION;
\r
475 switch(device_version)
\r
478 silicon_revision = M2S050_REV_A_SILICON;
\r
482 silicon_revision = M2S050_REV_B_SILICON;
\r
486 silicon_revision = UNKNOWN_SILICON_REV;
\r
490 return silicon_revision;
\r
493 /*------------------------------------------------------------------------------
\r
494 Workarounds for various silicon versions.
\r
496 static void silicon_workarounds(void)
\r
498 uint32_t silicon_revision;
\r
500 silicon_revision = get_silicon_revision();
\r
502 switch(silicon_revision)
\r
504 case M2S050_REV_A_SILICON:
\r
505 m2s050_rev_a_workarounds();
\r
508 case M2S050_REV_B_SILICON:
\r
509 /* Fall through. */
\r
510 case UNKNOWN_SILICON_REV:
\r
511 /* Fall through. */
\r
517 /*------------------------------------------------------------------------------
\r
518 Silicon workarounds for M2S050 rev A.
\r
520 static void m2s050_rev_a_workarounds(void)
\r
522 /*--------------------------------------------------------------------------
\r
523 * Work around a couple of silicon issues:
\r
525 /* DDR_CLK_EN <- 1 */
\r
526 SYSREG->MSSDDR_FACC1_CR |= (uint32_t)1 << DDR_CLK_EN_SHIFT;
\r
528 /* CONTROLLER_PLL_INIT <- 0 */
\r
529 SYSREG->MSSDDR_FACC1_CR = SYSREG->MSSDDR_FACC1_CR & ~CONTROLLER_PLL_INIT_MASK;
\r
532 /*------------------------------------------------------------------------------
\r
533 Complete clock configuration if requested by Libero.
\r
535 #if (MSS_SYS_FACC_INIT_BY_CORTEX == 1)
\r
536 static void complete_clock_config(void)
\r
538 uint32_t pll_locked;
\r
540 /* Wait for fabric PLL to lock. */
\r
542 pll_locked = SYSREG->MSSDDR_PLL_STATUS & FAB_PLL_LOCK_MASK;
\r
543 } while(!pll_locked);
\r
545 /* Negate MPLL bypass. */
\r
546 SYSREG->MSSDDR_PLL_STATUS_HIGH_CR &= ~FACC_PLL_BYPASS_MASK;
\r
548 /* Wait for MPLL to lock. */
\r
550 pll_locked = SYSREG->MSSDDR_PLL_STATUS & MPLL_LOCK_MASK;
\r
551 } while(!pll_locked);
\r
553 /* Switch FACC from standby to run mode. */
\r
554 SYSREG->MSSDDR_FACC1_CR &= ~FACC_GLMUX_SEL_MASK;
\r
556 /* Negate FPGA_SOFTRESET to de-assert MSS_RESET_N_M2F in the fabric */
\r
557 SYSREG->SOFT_RST_CR &= ~SYSREG_FPGA_SOFTRESET_MASK;
\r