]> git.sur5r.net Git - freertos/blob
04134b86e597f73c11b279544fab8e3059426610
[freertos] /
1 /*******************************************************************************\r
2  * (c) Copyright 2012-2013 Microsemi SoC Products Group. All rights reserved.\r
3  * \r
4  *  SmartFusion2 CMSIS system initialization.\r
5  *\r
6  * SVN $Revision: 5280 $\r
7  * SVN $Date: 2013-03-22 20:51:50 +0000 (Fri, 22 Mar 2013) $\r
8  */\r
9 #include "m2sxxx.h"\r
10 #include "../drivers_config/sys_config/sys_config.h"\r
11 #include "sys_init_cfg_types.h"\r
12 \r
13 /*------------------------------------------------------------------------------\r
14   Silicon revisions.\r
15  */\r
16 #define UNKNOWN_SILICON_REV     0\r
17 #define M2S050_REV_A_SILICON    1\r
18 #define M2S050_REV_B_SILICON    2\r
19 \r
20 /*------------------------------------------------------------------------------\r
21  * \r
22  */\r
23 void mscc_post_hw_cfg_init(void);\r
24 \r
25 /*------------------------------------------------------------------------------\r
26  * System registers of interest.\r
27  */\r
28 /*\r
29  * MSSDDR_FACC1_CR register masks:\r
30  */\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
35 \r
36 /*\r
37  * MSSDDR_PLL_STATUS register masks:\r
38  */\r
39 #define FAB_PLL_LOCK_MASK   0x00000001u\r
40 #define MPLL_LOCK_MASK      0x00000002u\r
41 \r
42 /*\r
43  * MSSDDR_PLL_STATUS_HIGH_CR register masks:\r
44  */\r
45 #define FACC_PLL_BYPASS_MASK    0x00000001u\r
46 \r
47 /*------------------------------------------------------------------------------\r
48  * Standard CMSIS global variables.\r
49  */\r
50 uint32_t SystemCoreClock = MSS_SYS_M3_CLK_FREQ;         /*!< System Clock Frequency (Core Clock) */\r
51 \r
52 /*------------------------------------------------------------------------------\r
53  * SmartFusion2 specific clocks.\r
54  */\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
61 \r
62 /*------------------------------------------------------------------------------\r
63  * System configuration tables generated by Libero.\r
64  */\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
68 #endif\r
69 \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
73 #endif\r
74 \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
76 \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
79 #endif\r
80 \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
83 #endif\r
84 \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
87 #endif\r
88 \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
91 #endif\r
92 \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
94 \r
95 /*------------------------------------------------------------------------------\r
96  * Local functions:\r
97  */\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
101 \r
102 #if (MSS_SYS_FACC_INIT_BY_CORTEX == 1)\r
103 static void complete_clock_config(void);\r
104 #endif\r
105 \r
106 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX\r
107 static void configure_serdes_intf(void);\r
108 #endif\r
109 \r
110 #if (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX)\r
111 static void config_ddr_subsys\r
112 (\r
113     const ddr_subsys_cfg_t * p_ddr_subsys_cfg,\r
114     DDRCore_TypeDef * p_ddr_subsys_regs\r
115 );\r
116 #endif\r
117 \r
118 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX\r
119 static void config_by_addr_value\r
120 (\r
121     const cfg_addr_value_pair_t * p_addr_value_pair,\r
122     uint32_t nb_of_cfg_pairs\r
123 );\r
124 #endif\r
125 \r
126 static uint32_t get_rcosc_25_50mhz_frequency(void);\r
127 static void set_clock_frequency_globals(uint32_t fclk);\r
128 \r
129 /***************************************************************************//**\r
130  * See system_m2sxxx.h for details.\r
131  */\r
132 void SystemInit(void)\r
133 {\r
134     /*\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
138      */\r
139 #if (MSS_SYS_FACC_INIT_BY_CORTEX == 1)\r
140     complete_clock_config();\r
141 #endif\r
142 \r
143     silicon_workarounds();\r
144     \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
149      */\r
150     SCB->CCR |= SCB_CCR_STKALIGN_Msk;\r
151     \r
152     /*--------------------------------------------------------------------------\r
153      * MDDR configuration\r
154      */\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
157 #endif\r
158 \r
159     /*--------------------------------------------------------------------------\r
160      * MDDR configuration\r
161      */\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
164 #endif\r
165 \r
166     /*--------------------------------------------------------------------------\r
167      * SERDES interfaces configuration.\r
168      */\r
169 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX\r
170     configure_serdes_intf();\r
171 #endif\r
172 \r
173     /*--------------------------------------------------------------------------\r
174      * Call user defined configuration function.\r
175      */\r
176     mscc_post_hw_cfg_init();\r
177     \r
178     /*--------------------------------------------------------------------------\r
179      * Synchronize with CoreSF2Reset controlling resets from the fabric.\r
180      */\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
185     {\r
186         ;   /* Wait for INIT_DONE from CoreSF2Reset. */\r
187     }\r
188 #endif\r
189 }\r
190 \r
191 /***************************************************************************//**\r
192  * SystemCoreClockUpdate()\r
193  */\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
198 \r
199 #define FACC_STANDBY_SHIFT      6u\r
200 #define FACC_STANDBY_SEL_MASK   0x00000007u\r
201 \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
206 \r
207 void SystemCoreClockUpdate(void)\r
208 {\r
209 #if 1\r
210     uint32_t controller_pll_init;\r
211     uint32_t clk_src;\r
212 \r
213     controller_pll_init = SYSREG->MSSDDR_FACC1_CR & CONTROLLER_PLL_INIT_MASK;\r
214     \r
215     if(0u == controller_pll_init)\r
216     {\r
217         /* Normal operations. */\r
218         uint32_t global_mux_sel;\r
219         \r
220         global_mux_sel = SYSREG->MSSDDR_FACC1_CR & FACC_GLMUX_SEL_MASK;\r
221         if(0u == global_mux_sel)\r
222         {\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
231         }\r
232         else\r
233         {\r
234             /* MSS clocked from standby clock. */\r
235             const uint8_t standby_clock_lut[8] = { RCOSC_25_50MHZ_CLK_SRC,\r
236                                                    CLK_XTAL_CLK_SRC,\r
237                                                    RCOSC_25_50MHZ_CLK_SRC,\r
238                                                    CLK_XTAL_CLK_SRC,\r
239                                                    RCOSC_1_MHZ_CLK_SRC,\r
240                                                    RCOSC_1_MHZ_CLK_SRC,\r
241                                                    CCC2ASCI_CLK_SRC,\r
242                                                    CCC2ASCI_CLK_SRC };\r
243             \r
244             uint32_t standby_sel;\r
245             uint8_t clock_source;\r
246             \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
250             {\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
254                 break;\r
255                 \r
256                 case CLK_XTAL_CLK_SRC:\r
257                     set_clock_frequency_globals(FREQ_32KHZ);\r
258                 break;\r
259                 \r
260                 case RCOSC_1_MHZ_CLK_SRC:\r
261                     set_clock_frequency_globals(FREQ_1MHZ);\r
262                 break;\r
263                 \r
264                 case CCC2ASCI_CLK_SRC:\r
265                     /* Fall through. */\r
266                 default:\r
267                     set_clock_frequency_globals(FREQ_1MHZ);\r
268                 break;\r
269             }   \r
270         }\r
271     }\r
272     else\r
273     {\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
277     }\r
278     \r
279 #else\r
280     /*\r
281      * Reset the clock frequency global variables to the values delected in the\r
282      * Libero flow.\r
283      */\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
291 #endif\r
292 }\r
293 \r
294 /***************************************************************************//**\r
295  * Find out frequency generated by the 25_50mhz RC osciallator.\r
296  */\r
297 static uint32_t get_rcosc_25_50mhz_frequency(void)\r
298 {\r
299     uint32_t rcosc_div2;\r
300     uint32_t rcosc_frequency;\r
301     \r
302     rcosc_div2 = SYSREG->MSSDDR_PLL_STATUS & RCOSC_DIV2_MASK;\r
303     if(0u == rcosc_div2)\r
304     {\r
305         /* 25_50mhz oscillator is configured for 25 MHz operations. */\r
306         rcosc_frequency = FREQ_25MHZ;\r
307     }\r
308     else\r
309     {\r
310         /* 25_50mhz oscillator is configured for 50 MHz operations. */\r
311         rcosc_frequency = FREQ_50MHZ;\r
312     }\r
313     \r
314     return rcosc_frequency;\r
315 }\r
316 \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
321         - SystemCoreClock\r
322         - g_FrequencyPCLK0\r
323         - g_FrequencyPCLK1\r
324         - g_FrequencyPCLK2\r
325         - g_FrequencyFIC0\r
326         - g_FrequencyFIC1\r
327         - g_FrequencyFIC64\r
328  */\r
329 static void set_clock_frequency_globals(uint32_t standby_clk)\r
330 {\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
338 }\r
339 \r
340 /***************************************************************************//**\r
341  * Write 16-bit configuration values into 32-bit word aligned registers.\r
342  */\r
343 #if (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX)\r
344 static void copy_cfg16_to_regs\r
345 (\r
346     volatile uint32_t * p_regs,\r
347     const uint16_t * p_cfg,\r
348     uint32_t nb_16bit_words\r
349 )\r
350 {\r
351     uint32_t inc;\r
352     \r
353     for(inc = 0u; inc < nb_16bit_words; ++inc)\r
354     {\r
355         p_regs[inc] = p_cfg[inc];\r
356     }\r
357 }\r
358 #endif\r
359 \r
360 /***************************************************************************//**\r
361  * Configure peripheral using register address and register value pairs.\r
362  */\r
363 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX\r
364 static void config_by_addr_value\r
365 (\r
366     const cfg_addr_value_pair_t * p_addr_value_pair,\r
367     uint32_t nb_of_cfg_pairs\r
368 )\r
369 {\r
370     uint32_t inc;\r
371     \r
372     for(inc = 0u; inc < nb_of_cfg_pairs; ++inc)\r
373     {\r
374         *p_addr_value_pair[inc].p_reg = p_addr_value_pair[inc].value;\r
375     }\r
376 }\r
377 #endif\r
378 \r
379 /***************************************************************************//**\r
380  * DDR subsystem configuration.\r
381  */\r
382 #if (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX)\r
383 \r
384 #define NB_OF_DDRC_REGS_TO_CONFIG       57u\r
385 #define NB_OF_DDR_PHY_REGS_TO_CONFIG    65u\r
386 \r
387 static void config_ddr_subsys\r
388 (\r
389     const ddr_subsys_cfg_t * p_ddr_subsys_cfg,\r
390     DDRCore_TypeDef * p_ddr_subsys_regs\r
391 )\r
392 {\r
393     volatile uint32_t * p_regs;\r
394     const uint16_t * p_cfg;\r
395     \r
396     /*--------------------------------------------------------------------------\r
397      * Configure DDR controller part of the MDDR subsystem.\r
398      */\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
401 \r
402     copy_cfg16_to_regs(p_regs, p_cfg, NB_OF_DDRC_REGS_TO_CONFIG);\r
403     \r
404     /*--------------------------------------------------------------------------\r
405      * Configure DDR PHY.\r
406      */\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
409 \r
410     copy_cfg16_to_regs(p_regs, p_cfg, NB_OF_DDR_PHY_REGS_TO_CONFIG);\r
411     \r
412     /*--------------------------------------------------------------------------\r
413      * Configure DDR FIC.\r
414      */\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
426 \r
427     /*--------------------------------------------------------------------------\r
428      * Enable DDR.\r
429      */\r
430     p_ddr_subsys_regs->ddrc.DYN_SOFT_RESET_CR = 0x01u;\r
431     \r
432     while(0x0000u == p_ddr_subsys_regs->ddrc.DDRC_SR)\r
433     {\r
434         ;\r
435     }        \r
436 }\r
437 \r
438 #endif\r
439 \r
440 /***************************************************************************//**\r
441  * Configure SERDES interfaces.\r
442  */\r
443 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX\r
444 \r
445 static void configure_serdes_intf(void)\r
446 {\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
449 #endif\r
450 \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
453 #endif\r
454 \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
457 #endif\r
458 \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
461 #endif\r
462 }\r
463 \r
464 #endif\r
465 \r
466 /*------------------------------------------------------------------------------\r
467   Retrieve silicon revision from system registers.\r
468  */\r
469 static uint32_t get_silicon_revision(void)\r
470 {\r
471     uint32_t silicon_revision;\r
472     uint32_t device_version;\r
473     \r
474     device_version = SYSREG->DEVICE_VERSION;\r
475     switch(device_version)\r
476     {\r
477         case 0x0000F802:\r
478             silicon_revision = M2S050_REV_A_SILICON;\r
479             break;\r
480             \r
481         case 0x0001F802:\r
482             silicon_revision = M2S050_REV_B_SILICON;\r
483             break;\r
484             \r
485         default:\r
486             silicon_revision = UNKNOWN_SILICON_REV;\r
487             break;\r
488     }\r
489     \r
490     return silicon_revision;\r
491 }\r
492 \r
493 /*------------------------------------------------------------------------------\r
494   Workarounds for various silicon versions.\r
495  */\r
496 static void silicon_workarounds(void)\r
497 {\r
498     uint32_t silicon_revision;\r
499     \r
500     silicon_revision = get_silicon_revision();\r
501     \r
502     switch(silicon_revision)\r
503     {\r
504         case M2S050_REV_A_SILICON:\r
505             m2s050_rev_a_workarounds();\r
506             break;\r
507             \r
508         case M2S050_REV_B_SILICON:\r
509             /* Fall through. */\r
510         case UNKNOWN_SILICON_REV:\r
511             /* Fall through. */\r
512         default:\r
513             break;\r
514     }\r
515 }\r
516 \r
517 /*------------------------------------------------------------------------------\r
518   Silicon workarounds for M2S050 rev A.\r
519  */\r
520 static void m2s050_rev_a_workarounds(void)\r
521 {\r
522     /*--------------------------------------------------------------------------\r
523      * Work around a couple of silicon issues:\r
524      */\r
525     /* DDR_CLK_EN <- 1 */\r
526     SYSREG->MSSDDR_FACC1_CR |= (uint32_t)1 << DDR_CLK_EN_SHIFT;\r
527     \r
528     /* CONTROLLER_PLL_INIT <- 0 */\r
529     SYSREG->MSSDDR_FACC1_CR = SYSREG->MSSDDR_FACC1_CR & ~CONTROLLER_PLL_INIT_MASK;\r
530 }\r
531 \r
532 /*------------------------------------------------------------------------------\r
533   Complete clock configuration if requested by Libero.\r
534  */\r
535 #if (MSS_SYS_FACC_INIT_BY_CORTEX == 1)\r
536 static void complete_clock_config(void)\r
537 {\r
538     uint32_t pll_locked;\r
539     \r
540     /* Wait for fabric PLL to lock. */\r
541     do {\r
542         pll_locked = SYSREG->MSSDDR_PLL_STATUS & FAB_PLL_LOCK_MASK;\r
543     } while(!pll_locked);\r
544     \r
545     /* Negate MPLL bypass. */\r
546     SYSREG->MSSDDR_PLL_STATUS_HIGH_CR &= ~FACC_PLL_BYPASS_MASK;\r
547     \r
548     /* Wait for MPLL to lock. */\r
549     do {\r
550         pll_locked = SYSREG->MSSDDR_PLL_STATUS & MPLL_LOCK_MASK;\r
551     } while(!pll_locked);\r
552     \r
553     /* Switch FACC from standby to run mode. */\r
554     SYSREG->MSSDDR_FACC1_CR &= ~FACC_GLMUX_SEL_MASK;\r
555 \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
558 }\r
559 #endif\r
560 \r