1 /*******************************************************************************
2  * (c) Copyright 2012-2013 Microsemi SoC Products Group. All rights reserved.
3  *
4  *  SmartFusion2 CMSIS system initialization.
5  *
6  * SVN $Revision: 7375 $
7  * SVN $Date: 2015-05-01 14:57:40 +0100 (Fri, 01 May 2015) $
8  */
9 #include "m2sxxx.h"
10 #if MSCC_NO_RELATIVE_PATHS
11 #include "sys_config.h"
12 #else
13 #include "sys_config.h"
14 #endif
15 #include "sys_init_cfg_types.h"
16 /*------------------------------------------------------------------------------
17   Silicon revisions.
18  */
19 #define UNKNOWN_SILICON_REV     0
20 #define M2S050_REV_A_SILICON    1
21 #define M2S050_REV_B_SILICON    2
22 
23 /*------------------------------------------------------------------------------
24  * CoreConfigP IP block version.
25  */
26 #define CORE_CONFIGP_V7_0   0x00070000u
27 
28 /*------------------------------------------------------------------------------
29  *
30  */
31 void mscc_post_hw_cfg_init(void);
32 
33 /*------------------------------------------------------------------------------
34  * CoreConfigP/CoreConfigP register bits
35  */
36 #define CONFIG_1_DONE   1u
37 #define CONFIG_2_DONE   2u
38 
39 #define INIT_DONE_MASK      0x00000001u
40 #define SDIF_RELEASED_MASK  0x00000002u
41 
42 /*------------------------------------------------------------------------------
43  * System registers of interest.
44  */
45 /*
46  * MSSDDR_FACC1_CR register masks:
47  */
48 #define DDR_CLK_EN_SHIFT    8u
49 #define FACC_GLMUX_SEL_MASK         0x00001000u
50 #define CONTROLLER_PLL_INIT_MASK    0x04000000u
51 #define RCOSC_DIV2_MASK             0x00000004u
52 
53 /*
54  * MSSDDR_PLL_STATUS register masks:
55  */
56 #define FAB_PLL_LOCK_MASK   0x00000001u
57 #define MPLL_LOCK_MASK      0x00000002u
58 
59 /*
60  * MSSDDR_PLL_STATUS_HIGH_CR register masks:
61  */
62 #define FACC_PLL_BYPASS_MASK    0x00000001u
63 
64 /*------------------------------------------------------------------------------
65  * Standard CMSIS global variables.
66  */
67 uint32_t SystemCoreClock = MSS_SYS_M3_CLK_FREQ;         /*!< System Clock Frequency (Core Clock) */
68 
69 /*------------------------------------------------------------------------------
70  * SmartFusion2 specific clocks.
71  */
72 uint32_t g_FrequencyPCLK0 = MSS_SYS_APB_0_CLK_FREQ;     /*!< Clock frequency of APB bus 0. */
73 uint32_t g_FrequencyPCLK1 = MSS_SYS_APB_1_CLK_FREQ;     /*!< Clock frequency of APB bus 1. */
74 uint32_t g_FrequencyPCLK2 = MSS_SYS_APB_2_CLK_FREQ;     /*!< Clock frequency of APB bus 2. */
75 uint32_t g_FrequencyFIC0 = MSS_SYS_FIC_0_CLK_FREQ;      /*!< Clock frequecny of FPGA fabric interface controller 1. */
76 uint32_t g_FrequencyFIC1 = MSS_SYS_FIC_1_CLK_FREQ;      /*!< Clock frequecny of FPGA fabric inteface controller 2. */
77 uint32_t g_FrequencyFIC64 = MSS_SYS_FIC64_CLK_FREQ;     /*!< Clock frequecny of 64-bit FPGA fabric interface controller. */
78 
79 /*------------------------------------------------------------------------------
80  * System configuration tables generated by Libero.
81  */
82 #if MSS_SYS_MDDR_CONFIG_BY_CORTEX
83 extern MDDR_TypeDef * const g_m2s_mddr_addr;
84 extern const ddr_subsys_cfg_t g_m2s_mddr_subsys_config;
85 #endif
86 
87 #if MSS_SYS_FDDR_CONFIG_BY_CORTEX
88 extern FDDR_TypeDef * const g_m2s_fddr_addr;
89 extern const ddr_subsys_cfg_t g_m2s_fddr_subsys_config;
90 #endif
91 
92 #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)
93 
94 #if MSS_SYS_SERDES_0_CONFIG_BY_CORTEX
95 extern const cfg_addr_value_pair_t g_m2s_serdes_0_config[SERDES_0_CFG_NB_OF_PAIRS];
96 #endif
97 
98 #if MSS_SYS_SERDES_1_CONFIG_BY_CORTEX
99 extern const cfg_addr_value_pair_t g_m2s_serdes_1_config[SERDES_1_CFG_NB_OF_PAIRS];
100 #endif
101 
102 #if MSS_SYS_SERDES_2_CONFIG_BY_CORTEX
103 extern const cfg_addr_value_pair_t g_m2s_serdes_2_config[SERDES_2_CFG_NB_OF_PAIRS];
104 #endif
105 
106 #if MSS_SYS_SERDES_3_CONFIG_BY_CORTEX
107 extern const cfg_addr_value_pair_t g_m2s_serdes_3_config[SERDES_3_CFG_NB_OF_PAIRS];
108 #endif
109 
110 #define MSS_SYS_CORESF2RESET_USED  (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX || MSS_SYS_SERDES_CONFIG_BY_CORTEX)
111 
112 /*==============================================================================
113  * List of PCIe lanes on which PMA_READY must be polled. Allows only polling PMA
114  * READY on the first lane of a PCIe link regardless of the number of lanes used
115  * or whether lane reversal is used.
116  */
117 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
118 
119 #define CONFIG_REG_LANE_SEL_LANE_0      0x00000100U
120 #define CONFIG_REG_LANE_SEL_LANE_1      0x00000200U
121 #define CONFIG_REG_LANE_SEL_LANE_2      0x00000400U
122 #define CONFIG_REG_LANE_SEL_LANE_3      0x00000800U
123 
124 #define CONFIG_REG_LANE_SEL_MASK    (CONFIG_REG_LANE_SEL_LANE_0 | \
125                                      CONFIG_REG_LANE_SEL_LANE_1 | \
126                                      CONFIG_REG_LANE_SEL_LANE_2 | \
127                                      CONFIG_REG_LANE_SEL_LANE_3)
128 
129 #define FIRST_PCIE_CTRL             1U
130 #define SECOND_PCIE_CTRL            2U
131 
132 typedef struct pma_poll_info
133 {
134     SERDESIF_TypeDef *      serdes;
135     SERDES_TypeDef * const  lane;
136     uint16_t                config_reg_lane_sel;
137     uint16_t                pcie_ctrl_id;           /* distinguish between first and second PCIe controller on M2S090. */
138 } pma_poll_info_t;
139 
140 /*------------------------------------------------------------------------------
141  * SERDES0: list of PMA to poll as part of PCIe configuration. This list only
142  * handles the first PCIe controller of SERDES0.
143  */
144 static const pma_poll_info_t g_serdes0_pcie_lane_cfg_lut[] =
145 {
146   #if defined(SERDESIF_0_PCIE_LANE_PMA_STATUS_LANE_0)
147     {
148         SERDES0,                    /* SERDESIF_TypeDef * serdes */
149         &SERDES0->lane[0],          /* SERDES_TypeDef * const lane */
150         CONFIG_REG_LANE_SEL_LANE_0, /* uint16_t config_reg_lane_sel */
151         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
152     },
153   #endif
154 
155   #if defined(SERDESIF_0_PCIE_LANE_PMA_STATUS_LANE_1)
156     {
157         SERDES0,                    /* SERDESIF_TypeDef * serdes */
158         &SERDES0->lane[1],          /* SERDES_TypeDef * const lane */
159         CONFIG_REG_LANE_SEL_LANE_1, /* uint16_t config_reg_lane_sel */
160         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
161     },
162   #endif
163 
164   #if defined(SERDESIF_0_PCIE_LANE_PMA_STATUS_LANE_2)
165     {
166         SERDES0,                    /* SERDESIF_TypeDef * serdes */
167         &SERDES0->lane[2],          /* SERDES_TypeDef * const lane */
168         CONFIG_REG_LANE_SEL_LANE_2, /* uint16_t config_reg_lane_sel */
169         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
170     },
171   #endif
172 
173   #if defined(SERDESIF_0_PCIE_LANE_PMA_STATUS_LANE_3)
174     {
175         SERDES0,                    /* SERDESIF_TypeDef * serdes */
176         &SERDES0->lane[3],          /* SERDES_TypeDef * const lane */
177         CONFIG_REG_LANE_SEL_LANE_3, /* uint16_t config_reg_lane_sel */
178         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
179     },
180   #endif
181 
182     {
183         (SERDESIF_TypeDef *)0,      /* SERDESIF_TypeDef * serdes */
184         (SERDES_TypeDef *)0,        /* SERDES_TypeDef * const lane */
185         0,                          /* uint16_t config_reg_lane_sel */
186         0                           /* uint16_t pcie_ctrl_id */
187     }
188 };
189 
190 /*------------------------------------------------------------------------------
191  * SERDES1: list of PMA to poll as part of PCIe configuration. This list handles
192  * both SERDES1 first PCIe controller and the M2S090 SERDES0 second PCIe
193  * controller.
194  */
195 static const pma_poll_info_t g_serdes1_pcie_lane_cfg_lut[] =
196 {
197   #if defined(SERDESIF_1_PCIE_LANE_PMA_STATUS_LANE_0)
198     {
199         SERDES1,                    /* SERDESIF_TypeDef * serdes */
200         &SERDES1->lane[0],          /* SERDES_TypeDef * const lane */
201         CONFIG_REG_LANE_SEL_LANE_0, /* uint16_t config_reg_lane_sel */
202         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
203     },
204   #endif
205 
206   #if defined(SERDESIF_1_PCIE_LANE_PMA_STATUS_LANE_1)
207     {
208         SERDES1,                    /* SERDESIF_TypeDef * serdes */
209         &SERDES1->lane[1],          /* SERDES_TypeDef * const lane */
210         CONFIG_REG_LANE_SEL_LANE_1, /* uint16_t config_reg_lane_sel */
211         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
212     },
213   #endif
214 
215   #if defined(SERDESIF_1_PCIE_LANE_PMA_STATUS_LANE_2)
216     {
217         SERDES1,                    /* SERDESIF_TypeDef * serdes */
218         &SERDES1->lane[2],          /* SERDES_TypeDef * const lane */
219         CONFIG_REG_LANE_SEL_LANE_2, /* uint16_t config_reg_lane_sel */
220         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
221     },
222   #endif
223 
224   #if defined(SERDESIF_1_PCIE_LANE_PMA_STATUS_LANE_3)
225     {
226         SERDES1,                    /* SERDESIF_TypeDef * serdes */
227         &SERDES1->lane[3],          /* SERDES_TypeDef * const lane */
228         CONFIG_REG_LANE_SEL_LANE_3, /* uint16_t config_reg_lane_sel */
229         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
230     },
231   #endif
232   #if defined(SERDESIF_0_PCIE_1_LANE_PMA_STATUS_LANE_0)
233     {
234         SERDES0,                    /* SERDESIF_TypeDef * serdes */
235         &SERDES0->lane[0],          /* SERDES_TypeDef * const lane */
236         CONFIG_REG_LANE_SEL_LANE_0, /* uint16_t config_reg_lane_sel */
237         SECOND_PCIE_CTRL            /* uint16_t pcie_ctrl_id */
238     },
239   #endif
240 
241   #if defined(SERDESIF_0_PCIE_1_LANE_PMA_STATUS_LANE_1)
242     {
243         SERDES0,                    /* SERDESIF_TypeDef * serdes */
244         &SERDES0->lane[1],          /* SERDES_TypeDef * const lane */
245         CONFIG_REG_LANE_SEL_LANE_1, /* uint16_t config_reg_lane_sel */
246         SECOND_PCIE_CTRL            /* uint16_t pcie_ctrl_id */
247     },
248   #endif
249 
250   #if defined(SERDESIF_0_PCIE_1_LANE_PMA_STATUS_LANE_2)
251     {
252         SERDES0,                    /* SERDESIF_TypeDef * serdes */
253         &SERDES0->lane[2],          /* SERDES_TypeDef * const lane */
254         CONFIG_REG_LANE_SEL_LANE_2, /* uint16_t config_reg_lane_sel */
255         SECOND_PCIE_CTRL            /* uint16_t pcie_ctrl_id */
256     },
257   #endif
258 
259   #if defined(SERDESIF_0_PCIE_1_LANE_PMA_STATUS_LANE_3)
260     {
261         SERDES0,                    /* SERDESIF_TypeDef * serdes */
262         &SERDES0->lane[3],          /* SERDES_TypeDef * const lane */
263         CONFIG_REG_LANE_SEL_LANE_3, /* uint16_t config_reg_lane_sel */
264         SECOND_PCIE_CTRL            /* uint16_t pcie_ctrl_id */
265     },
266   #endif
267     {
268         (SERDESIF_TypeDef *)0,      /* SERDESIF_TypeDef * serdes */
269         (SERDES_TypeDef *)0,        /* SERDES_TypeDef * const lane */
270         0,                          /* uint16_t config_reg_lane_sel */
271         0                           /* uint16_t pcie_ctrl_id */
272     }
273 };
274 
275 /*------------------------------------------------------------------------------
276  * SERDES2: list of PMA to poll as part of PCIe configuration.
277  */
278 static const pma_poll_info_t g_serdes2_pcie_lane_cfg_lut[] =
279 {
280   #if defined(SERDESIF_2_PCIE_LANE_PMA_STATUS_LANE_0)
281     {
282         SERDES2,                     /* SERDESIF_TypeDef * serdes */
283         &SERDES2->lane[0],          /* SERDES_TypeDef * const lane */
284         CONFIG_REG_LANE_SEL_LANE_0, /* uint16_t config_reg_lane_sel */
285         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
286     },
287   #endif
288 
289   #if defined(SERDESIF_2_PCIE_LANE_PMA_STATUS_LANE_1)
290     {
291         SERDES2,                    /* SERDESIF_TypeDef * serdes */
292         &SERDES2->lane[1],          /* SERDES_TypeDef * const lane */
293         CONFIG_REG_LANE_SEL_LANE_1, /* uint16_t config_reg_lane_sel */
294         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
295     },
296   #endif
297 
298   #if defined(SERDESIF_2_PCIE_LANE_PMA_STATUS_LANE_2)
299     {
300         SERDES2,                    /* SERDESIF_TypeDef * serdes */
301         &SERDES2->lane[2],          /* SERDES_TypeDef * const lane */
302         CONFIG_REG_LANE_SEL_LANE_2, /* uint16_t config_reg_lane_sel */
303         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
304     },
305   #endif
306 
307   #if defined(SERDESIF_2_PCIE_LANE_PMA_STATUS_LANE_3)
308     {
309         SERDES2,                    /* SERDESIF_TypeDef * serdes */
310         &SERDES2->lane[3],          /* SERDES_TypeDef * const lane */
311         CONFIG_REG_LANE_SEL_LANE_3, /* uint16_t config_reg_lane_sel */
312         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
313     },
314   #endif
315 
316     {
317         (SERDESIF_TypeDef *)0,      /* SERDESIF_TypeDef * serdes */
318         (SERDES_TypeDef *)0,        /* SERDES_TypeDef * const lane */
319         0,                          /* uint16_t config_reg_lane_sel */
320         0                           /* uint16_t pcie_ctrl_id */
321     }
322 };
323 
324 /*------------------------------------------------------------------------------
325  * SERDES3: list of PMA to poll as part of PCIe configuration.
326  */
327 static const pma_poll_info_t g_serdes3_pcie_lane_cfg_lut[] =
328 {
329   #if defined(SERDESIF_3_PCIE_LANE_PMA_STATUS_LANE_0)
330     {
331         SERDES3,                    /* SERDESIF_TypeDef * serdes */
332         &SERDES3->lane[0],          /* SERDES_TypeDef * const lane */
333         CONFIG_REG_LANE_SEL_LANE_0, /* uint16_t config_reg_lane_sel */
334         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
335     },
336   #endif
337 
338   #if defined(SERDESIF_3_PCIE_LANE_PMA_STATUS_LANE_1)
339     {
340         SERDES3,                    /* SERDESIF_TypeDef * serdes */
341         &SERDES3->lane[1],          /* SERDES_TypeDef * const lane */
342         CONFIG_REG_LANE_SEL_LANE_1, /* uint16_t config_reg_lane_sel */
343         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
344     },
345   #endif
346 
347   #if defined(SERDESIF_3_PCIE_LANE_PMA_STATUS_LANE_2)
348     {
349         SERDES3,                    /* SERDESIF_TypeDef * serdes */
350         &SERDES3->lane[2],          /* SERDES_TypeDef * const lane */
351         CONFIG_REG_LANE_SEL_LANE_2, /* uint16_t config_reg_lane_sel */
352         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
353     },
354   #endif
355 
356   #if defined(SERDESIF_3_PCIE_LANE_PMA_STATUS_LANE_3)
357     {
358         SERDES3,                    /* SERDESIF_TypeDef * serdes */
359         &SERDES3->lane[3],          /* SERDES_TypeDef * const lane */
360         CONFIG_REG_LANE_SEL_LANE_3, /* uint16_t config_reg_lane_sel */
361         FIRST_PCIE_CTRL             /* uint16_t pcie_ctrl_id */
362     },
363   #endif
364 
365     {
366         (SERDESIF_TypeDef *)0,      /* SERDESIF_TypeDef * serdes */
367         (SERDES_TypeDef *)0,        /* SERDES_TypeDef * const lane */
368         0,                          /* uint16_t config_reg_lane_sel */
369         0                           /* uint16_t pcie_ctrl_id */
370     }
371 };
372 
373 /*------------------------------------------------------------------------------
374  * Master lookup table for all SERDES PCIe configuration.
375  */
376 static const pma_poll_info_t * const g_pcie_lane_cfg_lut[] =
377 {
378     g_serdes0_pcie_lane_cfg_lut,
379     g_serdes1_pcie_lane_cfg_lut,
380     g_serdes2_pcie_lane_cfg_lut,
381     g_serdes3_pcie_lane_cfg_lut
382 };
383 
384 #endif
385 
386 /*------------------------------------------------------------------------------
387  * Local functions:
388  */
389 static uint32_t get_silicon_revision(void);
390 static void silicon_workarounds(void);
391 static void m2s050_rev_a_workarounds(void);
392 
393 #if (MSS_SYS_FACC_INIT_BY_CORTEX == 1)
394 static void complete_clock_config(void);
395 #endif
396 
397 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
398 static void configure_serdes_intf(void);
399 static void configure_pcie_intf(void);
400 
401 static void configure_pcie_block
402 (
403     const cfg_addr_value_pair_t * p_addr_value_pair,
404     uint32_t nb_of_cfg_pairs,
405     uint32_t serdes_id
406 );
407 #endif
408 
409 #if (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX)
410 static void config_ddr_subsys
411 (
412     const ddr_subsys_cfg_t * p_ddr_subsys_cfg,
413     DDRCore_TypeDef * p_ddr_subsys_regs
414 );
415 #endif
416 
417 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
418 static void config_by_addr_value
419 (
420     const cfg_addr_value_pair_t * p_addr_value_pair,
421     uint32_t nb_of_cfg_pairs
422 );
423 #endif
424 
425 static uint32_t get_rcosc_25_50mhz_frequency(void);
426 static void set_clock_frequency_globals(uint32_t fclk);
427 
428 /***************************************************************************//**
429  * See system_m2sxxx.h for details.
430  */
SystemInit(void)431 void SystemInit(void)
432 {
433 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
434     uint32_t sdif_released;
435 #endif
436 #if MSS_SYS_CORESF2RESET_USED
437     uint32_t init_done;
438 #endif
439 
440 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
441     uint32_t core_cfg_version;
442 
443     core_cfg_version = CORE_SF2_CFG->IP_VERSION_SR;
444 #endif
445 
446     /*
447      * Do not make use of global variables or make any asumptions regarding
448      * memory content if modifying this function. The memory content has not been
449      * initialised by the time this function is called by the start-up code.
450      */
451 #if (MSS_SYS_FACC_INIT_BY_CORTEX == 1)
452     complete_clock_config();
453 #endif
454 
455     silicon_workarounds();
456 
457     /*--------------------------------------------------------------------------
458      * Set STKALIGN to ensure exception stacking starts on 8 bytes address
459      * boundary. This ensures compliance with the "Procedure Call Standards for
460      * the ARM Architecture" (AAPCS).
461      */
462     SCB->CCR |= SCB_CCR_STKALIGN_Msk;
463 
464     /*--------------------------------------------------------------------------
465      * MDDR configuration
466      */
467 #if MSS_SYS_MDDR_CONFIG_BY_CORTEX
468     if(0u == SYSREG->DDR_CR)
469     {
470         /*
471          * We only configure the MDDR memory controller if MDDR is not remapped
472          * to address 0x00000000. If MDDR is remapped to 0x00000000 then we are
473          * probably executing this code from MDDR in a debugging session and
474          * attempting to reconfigure the MDDR memory controller will cause the
475          * Cortex-M3 to crash.
476          */
477         config_ddr_subsys(&g_m2s_mddr_subsys_config, &g_m2s_mddr_addr->core);
478     }
479 #endif
480 
481     /*--------------------------------------------------------------------------
482      * FDDR configuration
483      */
484 #if MSS_SYS_FDDR_CONFIG_BY_CORTEX
485     config_ddr_subsys(&g_m2s_fddr_subsys_config, &g_m2s_fddr_addr->core);
486 #endif
487 
488     /*--------------------------------------------------------------------------
489      * Call user defined configuration function.
490      */
491     mscc_post_hw_cfg_init();
492 
493     /*--------------------------------------------------------------------------
494      * SERDES interfaces configuration.
495      */
496 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
497     configure_serdes_intf();
498 
499     if(core_cfg_version >= CORE_CONFIGP_V7_0)
500     {
501         CORE_SF2_CFG->CONFIG_DONE = CONFIG_1_DONE;
502 
503         /* Poll for SDIF_RELEASED. */
504         do
505         {
506             sdif_released = CORE_SF2_CFG->INIT_DONE & SDIF_RELEASED_MASK;
507         } while (0u == sdif_released);
508     }
509 
510     configure_pcie_intf();
511 #endif
512 
513     /*--------------------------------------------------------------------------
514      * Synchronize with CoreSF2Reset controlling resets from the fabric.
515      */
516 #if MSS_SYS_CORESF2RESET_USED
517     /*
518      * Negate FPGA_SOFTRESET to de-assert MSS_RESET_N_M2F in the fabric. We must
519      * do this here because this signal is only deasserted by the System
520      * Controller on a power-on reset. Other types of reset such as a watchdog
521      * reset would result in the FPGA fabric being held in reset and getting
522      * stuck waiting for the CoreSF2Config INIT_DONE to become asserted.
523      */
524     SYSREG->SOFT_RST_CR &= ~SYSREG_FPGA_SOFTRESET_MASK;
525 
526     /*
527      * Signal to CoreSF2Reset that peripheral configuration registers have been
528      * written.
529      */
530     CORE_SF2_CFG->CONFIG_DONE |= (CONFIG_1_DONE | CONFIG_2_DONE);
531 
532     /* Wait for INIT_DONE from CoreSF2Reset. */
533     do
534     {
535         init_done = CORE_SF2_CFG->INIT_DONE & INIT_DONE_MASK;
536     } while (0u == init_done);
537 #endif
538 }
539 
540 /***************************************************************************//**
541  * SystemCoreClockUpdate()
542  */
543 #define RCOSC_25_50MHZ_CLK_SRC  0u
544 #define CLK_XTAL_CLK_SRC        1u
545 #define RCOSC_1_MHZ_CLK_SRC     2u
546 #define CCC2ASCI_CLK_SRC        3u
547 
548 #define FACC_STANDBY_SHIFT      6u
549 #define FACC_STANDBY_SEL_MASK   0x00000007u
550 
551 #define FREQ_32KHZ   32768u
552 #define FREQ_1MHZ    1000000u
553 #define FREQ_25MHZ   25000000u
554 #define FREQ_50MHZ   50000000u
555 
SystemCoreClockUpdate(void)556 void SystemCoreClockUpdate(void)
557 {
558     uint32_t controller_pll_init;
559     uint32_t clk_src;
560 
561     controller_pll_init = SYSREG->MSSDDR_FACC1_CR & CONTROLLER_PLL_INIT_MASK;
562 
563     if(0u == controller_pll_init)
564     {
565         /* Normal operations. */
566         uint32_t global_mux_sel;
567 
568         global_mux_sel = SYSREG->MSSDDR_FACC1_CR & FACC_GLMUX_SEL_MASK;
569         if(0u == global_mux_sel)
570         {
571             /* MSS clocked from MSS PLL. Use Libero flow defines. */
572             SystemCoreClock = MSS_SYS_M3_CLK_FREQ;
573             g_FrequencyPCLK0 = MSS_SYS_APB_0_CLK_FREQ;
574             g_FrequencyPCLK1 = MSS_SYS_APB_1_CLK_FREQ;
575             g_FrequencyPCLK2 = MSS_SYS_APB_2_CLK_FREQ;
576             g_FrequencyFIC0 = MSS_SYS_FIC_0_CLK_FREQ;
577             g_FrequencyFIC1 = MSS_SYS_FIC_1_CLK_FREQ;
578             g_FrequencyFIC64 = MSS_SYS_FIC64_CLK_FREQ;
579         }
580         else
581         {
582             /* MSS clocked from standby clock. */
583             const uint8_t standby_clock_lut[8] = { RCOSC_25_50MHZ_CLK_SRC,
584                                                    CLK_XTAL_CLK_SRC,
585                                                    RCOSC_25_50MHZ_CLK_SRC,
586                                                    CLK_XTAL_CLK_SRC,
587                                                    RCOSC_1_MHZ_CLK_SRC,
588                                                    RCOSC_1_MHZ_CLK_SRC,
589                                                    CCC2ASCI_CLK_SRC,
590                                                    CCC2ASCI_CLK_SRC };
591 
592             uint32_t standby_sel;
593             uint8_t clock_source;
594 
595             standby_sel = (SYSREG->MSSDDR_FACC2_CR >> FACC_STANDBY_SHIFT) & FACC_STANDBY_SEL_MASK;
596             clock_source = standby_clock_lut[standby_sel];
597             switch(clock_source)
598             {
599                 case RCOSC_25_50MHZ_CLK_SRC:
600                     clk_src = get_rcosc_25_50mhz_frequency();
601                     set_clock_frequency_globals(clk_src);
602                 break;
603 
604                 case CLK_XTAL_CLK_SRC:
605                     set_clock_frequency_globals(FREQ_32KHZ);
606                 break;
607 
608                 case RCOSC_1_MHZ_CLK_SRC:
609                     set_clock_frequency_globals(FREQ_1MHZ);
610                 break;
611 
612                 case CCC2ASCI_CLK_SRC:
613                     /* Fall through. */
614                 default:
615                     set_clock_frequency_globals(FREQ_1MHZ);
616                 break;
617             }
618         }
619     }
620     else
621     {
622         /* PLL initialization mode. Running from 25/50MHZ RC oscillator. */
623         clk_src = get_rcosc_25_50mhz_frequency();
624         set_clock_frequency_globals(clk_src);
625     }
626 }
627 
628 /***************************************************************************//**
629  * Find out frequency generated by the 25_50mhz RC osciallator.
630  */
get_rcosc_25_50mhz_frequency(void)631 static uint32_t get_rcosc_25_50mhz_frequency(void)
632 {
633     uint32_t rcosc_div2;
634     uint32_t rcosc_frequency;
635 
636     rcosc_div2 = SYSREG->MSSDDR_PLL_STATUS & RCOSC_DIV2_MASK;
637     if(0u == rcosc_div2)
638     {
639         /* 25_50mhz oscillator is configured for 25 MHz operations. */
640         rcosc_frequency = FREQ_25MHZ;
641     }
642     else
643     {
644         /* 25_50mhz oscillator is configured for 50 MHz operations. */
645         rcosc_frequency = FREQ_50MHZ;
646     }
647 
648     return rcosc_frequency;
649 }
650 
651 /***************************************************************************//**
652    Set the value of the clock frequency global variables based on the value of
653    standby_clk passed as parameter.
654    The following global variables are set by this function:
655         - SystemCoreClock
656         - g_FrequencyPCLK0
657         - g_FrequencyPCLK1
658         - g_FrequencyPCLK2
659         - g_FrequencyFIC0
660         - g_FrequencyFIC1
661         - g_FrequencyFIC64
662  */
set_clock_frequency_globals(uint32_t standby_clk)663 static void set_clock_frequency_globals(uint32_t standby_clk)
664 {
665     SystemCoreClock = standby_clk;
666     g_FrequencyPCLK0 = standby_clk;
667     g_FrequencyPCLK1 = standby_clk;
668     g_FrequencyPCLK2 = MSS_SYS_APB_2_CLK_FREQ;
669     g_FrequencyFIC0 = standby_clk;
670     g_FrequencyFIC1 = standby_clk;
671     g_FrequencyFIC64 = standby_clk;
672 }
673 
674 /***************************************************************************//**
675  * Write 16-bit configuration values into 32-bit word aligned registers.
676  */
677 #if (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX)
copy_cfg16_to_regs(volatile uint32_t * p_regs,const uint16_t * p_cfg,uint32_t nb_16bit_words)678 static void copy_cfg16_to_regs
679 (
680     volatile uint32_t * p_regs,
681     const uint16_t * p_cfg,
682     uint32_t nb_16bit_words
683 )
684 {
685     uint32_t inc;
686 
687     for(inc = 0u; inc < nb_16bit_words; ++inc)
688     {
689         p_regs[inc] = p_cfg[inc];
690     }
691 }
692 #endif
693 
694 /***************************************************************************//**
695  * Configure peripheral using register address and register value pairs.
696  */
697 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
config_by_addr_value(const cfg_addr_value_pair_t * p_addr_value_pair,uint32_t nb_of_cfg_pairs)698 static void config_by_addr_value
699 (
700     const cfg_addr_value_pair_t * p_addr_value_pair,
701     uint32_t nb_of_cfg_pairs
702 )
703 {
704     uint32_t inc;
705 
706     for(inc = 0u; inc < nb_of_cfg_pairs; ++inc)
707     {
708         *p_addr_value_pair[inc].p_reg = p_addr_value_pair[inc].value;
709     }
710 }
711 #endif
712 
713 /***************************************************************************//**
714  * DDR subsystem configuration.
715  */
716 #if (MSS_SYS_MDDR_CONFIG_BY_CORTEX || MSS_SYS_FDDR_CONFIG_BY_CORTEX)
717 
718 #define NB_OF_DDRC_REGS_TO_CONFIG       57u
719 #define NB_OF_DDR_PHY_REGS_TO_CONFIG    65u
720 
config_ddr_subsys(const ddr_subsys_cfg_t * p_ddr_subsys_cfg,DDRCore_TypeDef * p_ddr_subsys_regs)721 static void config_ddr_subsys
722 (
723     const ddr_subsys_cfg_t * p_ddr_subsys_cfg,
724     DDRCore_TypeDef * p_ddr_subsys_regs
725 )
726 {
727     volatile uint32_t * p_regs;
728     const uint16_t * p_cfg;
729 
730     /*--------------------------------------------------------------------------
731      * Configure DDR controller part of the MDDR subsystem.
732      */
733     p_cfg = &p_ddr_subsys_cfg->ddrc.DYN_SOFT_RESET_CR;
734     p_regs = &p_ddr_subsys_regs->ddrc.DYN_SOFT_RESET_CR;
735 
736     copy_cfg16_to_regs(p_regs, p_cfg, NB_OF_DDRC_REGS_TO_CONFIG);
737 
738     /*--------------------------------------------------------------------------
739      * Configure DDR PHY.
740      */
741     p_cfg = &p_ddr_subsys_cfg->phy.LOOPBACK_TEST_CR;
742     p_regs = &p_ddr_subsys_regs->phy.LOOPBACK_TEST_CR;
743 
744     copy_cfg16_to_regs(p_regs, p_cfg, NB_OF_DDR_PHY_REGS_TO_CONFIG);
745 
746     /*--------------------------------------------------------------------------
747      * Configure DDR FIC.
748      */
749     p_ddr_subsys_regs->fic.NB_ADDR_CR = p_ddr_subsys_cfg->fic.NB_ADDR_CR;
750     p_ddr_subsys_regs->fic.NBRWB_SIZE_CR = p_ddr_subsys_cfg->fic.NBRWB_SIZE_CR;
751     p_ddr_subsys_regs->fic.WB_TIMEOUT_CR = p_ddr_subsys_cfg->fic.WB_TIMEOUT_CR;
752     p_ddr_subsys_regs->fic.HPD_SW_RW_EN_CR = p_ddr_subsys_cfg->fic.HPD_SW_RW_EN_CR;
753     p_ddr_subsys_regs->fic.HPD_SW_RW_INVAL_CR = p_ddr_subsys_cfg->fic.HPD_SW_RW_INVAL_CR;
754     p_ddr_subsys_regs->fic.SW_WR_ERCLR_CR = p_ddr_subsys_cfg->fic.SW_WR_ERCLR_CR;
755     p_ddr_subsys_regs->fic.ERR_INT_ENABLE_CR = p_ddr_subsys_cfg->fic.ERR_INT_ENABLE_CR;
756     p_ddr_subsys_regs->fic.NUM_AHB_MASTERS_CR = p_ddr_subsys_cfg->fic.NUM_AHB_MASTERS_CR;
757     p_ddr_subsys_regs->fic.LOCK_TIMEOUTVAL_CR[0] = p_ddr_subsys_cfg->fic.LOCK_TIMEOUTVAL_1_CR;
758     p_ddr_subsys_regs->fic.LOCK_TIMEOUTVAL_CR[1] = p_ddr_subsys_cfg->fic.LOCK_TIMEOUTVAL_2_CR;
759     p_ddr_subsys_regs->fic.LOCK_TIMEOUT_EN_CR = p_ddr_subsys_cfg->fic.LOCK_TIMEOUT_EN_CR;
760 
761     /*--------------------------------------------------------------------------
762      * Enable DDR.
763      */
764     p_ddr_subsys_regs->ddrc.DYN_SOFT_RESET_CR = 0x01u;
765 
766     while(0x0000u == p_ddr_subsys_regs->ddrc.DDRC_SR)
767     {
768         ;
769     }
770 }
771 
772 #endif
773 
774 /***************************************************************************//**
775  * Configure SERDES interfaces.
776  */
777 #if MSS_SYS_SERDES_CONFIG_BY_CORTEX
778 
configure_serdes_intf(void)779 static void configure_serdes_intf(void)
780 {
781   #if MSS_SYS_SERDES_0_CONFIG_BY_CORTEX
782     config_by_addr_value(g_m2s_serdes_0_config, SERDES_0_CFG_NB_OF_PAIRS);
783   #endif
784 
785   #if MSS_SYS_SERDES_1_CONFIG_BY_CORTEX
786     config_by_addr_value(g_m2s_serdes_1_config, SERDES_1_CFG_NB_OF_PAIRS);
787   #endif
788 
789   #if MSS_SYS_SERDES_2_CONFIG_BY_CORTEX
790     config_by_addr_value(g_m2s_serdes_2_config, SERDES_2_CFG_NB_OF_PAIRS);
791   #endif
792 
793   #if MSS_SYS_SERDES_3_CONFIG_BY_CORTEX
794     config_by_addr_value(g_m2s_serdes_3_config, SERDES_3_CFG_NB_OF_PAIRS);
795   #endif
796 }
797 
798 /***************************************************************************//**
799  * Configure PCIe interfaces.
800  */
configure_pcie_intf(void)801 static void configure_pcie_intf(void)
802 {
803   #if MSS_SYS_SERDES_0_CONFIG_BY_CORTEX
804     configure_pcie_block(g_m2s_serdes_0_config, SERDES_0_CFG_NB_OF_PAIRS, 0u);
805   #endif
806 
807   #if MSS_SYS_SERDES_1_CONFIG_BY_CORTEX
808     configure_pcie_block(g_m2s_serdes_1_config, SERDES_1_CFG_NB_OF_PAIRS, 1u);
809   #endif
810 
811   #if MSS_SYS_SERDES_2_CONFIG_BY_CORTEX
812     configure_pcie_block(g_m2s_serdes_2_config, SERDES_2_CFG_NB_OF_PAIRS, 2u);
813   #endif
814 
815   #if MSS_SYS_SERDES_3_CONFIG_BY_CORTEX
816     configure_pcie_block(g_m2s_serdes_3_config, SERDES_3_CFG_NB_OF_PAIRS, 3u);
817   #endif
818 }
819 
820 /*------------------------------------------------------------------------------
821   Configure one individual PCIe block.
822  */
configure_pcie_block(const cfg_addr_value_pair_t * p_addr_value_pair,uint32_t nb_of_cfg_pairs,uint32_t serdes_id)823 static void configure_pcie_block
824 (
825     const cfg_addr_value_pair_t * p_addr_value_pair,
826     uint32_t nb_of_cfg_pairs,
827     uint32_t serdes_id
828 )
829 {
830     uint32_t inc;
831 
832     const uint32_t PMA_READY_MASK = 0x00000080u;
833     const uint32_t PCIE_CTRL_REG_LENGTH = 0x1000u;
834     const uint32_t PCIE_CTLR_SOFTRESET_MASK = 0x00000001;
835     const uint32_t PCIE2_CTLR_SOFTRESET_MASK = 0x00000040;
836 
837     SERDESIF_TypeDef * const serdes_lut[4] =
838     {
839         SERDES0, SERDES1, SERDES2, SERDES3
840     };
841 
842     const uint32_t pcie_ctrl_top_addr_lut[4] =
843     {
844         SERDES0_CFG_BASE + PCIE_CTRL_REG_LENGTH,
845         SERDES1_CFG_BASE + PCIE_CTRL_REG_LENGTH,
846         SERDES2_CFG_BASE + PCIE_CTRL_REG_LENGTH,
847         SERDES3_CFG_BASE + PCIE_CTRL_REG_LENGTH
848     };
849 
850     /*
851      * Poll for PMA_READY.
852      */
853     inc = 0U;
854     while(g_pcie_lane_cfg_lut[serdes_id][inc].config_reg_lane_sel != 0)
855     {
856         uint32_t pma_ready;
857         uint32_t config_phy_mode_1;
858 
859         /* select lane */
860         config_phy_mode_1 = g_pcie_lane_cfg_lut[serdes_id][inc].serdes->sys_regs.CONFIG_PHY_MODE_1;
861         config_phy_mode_1 &= ~CONFIG_REG_LANE_SEL_MASK;
862         config_phy_mode_1 |= (uint32_t)g_pcie_lane_cfg_lut[serdes_id][inc].config_reg_lane_sel;
863         g_pcie_lane_cfg_lut[serdes_id][inc].serdes->sys_regs.CONFIG_PHY_MODE_1 = config_phy_mode_1;
864 
865         /* Wait for PMA to become ready. */
866         do
867         {
868             pma_ready = g_pcie_lane_cfg_lut[serdes_id][inc].lane->PMA_STATUS & PMA_READY_MASK;
869         }
870         while (0u == pma_ready);
871         ++inc;
872     }
873 
874     /*
875      * Configure the PCIe controller registers.
876      */
877     for(inc = 0u; inc < nb_of_cfg_pairs; ++inc)
878     {
879         uint32_t reg_addr;
880 
881         reg_addr = (uint32_t)p_addr_value_pair[inc].p_reg;
882 
883         if(reg_addr < pcie_ctrl_top_addr_lut[serdes_id])
884         {
885             *p_addr_value_pair[inc].p_reg = p_addr_value_pair[inc].value;
886         }
887     }
888 
889     /*
890      * Issue a soft-reset to the PCIe controller
891      */
892     inc = 0U;
893     while(g_pcie_lane_cfg_lut[serdes_id][inc].config_reg_lane_sel != 0)
894     {
895         if(FIRST_PCIE_CTRL == g_pcie_lane_cfg_lut[serdes_id][inc].pcie_ctrl_id)
896         {
897             serdes_lut[serdes_id]->sys_regs.SERDESIF_SOFT_RESET &= ~PCIE_CTLR_SOFTRESET_MASK;
898             serdes_lut[serdes_id]->sys_regs.SERDESIF_SOFT_RESET |= PCIE_CTLR_SOFTRESET_MASK;
899         }
900         else
901         {
902             serdes_lut[serdes_id]->sys_regs.SERDESIF_SOFT_RESET &= ~PCIE2_CTLR_SOFTRESET_MASK;
903             serdes_lut[serdes_id]->sys_regs.SERDESIF_SOFT_RESET |= PCIE2_CTLR_SOFTRESET_MASK;
904         }
905         ++inc;
906     }
907 }
908 
909 #endif
910 
911 /*------------------------------------------------------------------------------
912   Retrieve silicon revision from system registers.
913  */
get_silicon_revision(void)914 static uint32_t get_silicon_revision(void)
915 {
916     uint32_t silicon_revision;
917     uint32_t device_version;
918 
919     device_version = SYSREG->DEVICE_VERSION;
920     switch(device_version)
921     {
922         case 0x0000F802:
923             silicon_revision = M2S050_REV_A_SILICON;
924             break;
925 
926         case 0x0001F802:
927             silicon_revision = M2S050_REV_B_SILICON;
928             break;
929 
930         default:
931             silicon_revision = UNKNOWN_SILICON_REV;
932             break;
933     }
934 
935     return silicon_revision;
936 }
937 
938 /*------------------------------------------------------------------------------
939   Workarounds for various silicon versions.
940  */
silicon_workarounds(void)941 static void silicon_workarounds(void)
942 {
943     uint32_t silicon_revision;
944 
945     silicon_revision = get_silicon_revision();
946 
947     switch(silicon_revision)
948     {
949         case M2S050_REV_A_SILICON:
950             m2s050_rev_a_workarounds();
951             break;
952 
953         case M2S050_REV_B_SILICON:
954             /* Fall through. */
955         case UNKNOWN_SILICON_REV:
956             /* Fall through. */
957         default:
958             break;
959     }
960 }
961 
962 /*------------------------------------------------------------------------------
963   Silicon workarounds for M2S050 rev A.
964  */
m2s050_rev_a_workarounds(void)965 static void m2s050_rev_a_workarounds(void)
966 {
967     /*--------------------------------------------------------------------------
968      * Work around a couple of silicon issues:
969      */
970     /* DDR_CLK_EN <- 1 */
971     SYSREG->MSSDDR_FACC1_CR |= (uint32_t)1 << DDR_CLK_EN_SHIFT;
972 
973     /* CONTROLLER_PLL_INIT <- 0 */
974     SYSREG->MSSDDR_FACC1_CR = SYSREG->MSSDDR_FACC1_CR & ~CONTROLLER_PLL_INIT_MASK;
975 }
976 
977 /*------------------------------------------------------------------------------
978   Complete clock configuration if requested by Libero.
979  */
980 #if (MSS_SYS_FACC_INIT_BY_CORTEX == 1)
complete_clock_config(void)981 static void complete_clock_config(void)
982 {
983     uint32_t pll_locked;
984 
985     /* Wait for fabric PLL to lock. */
986     do {
987         pll_locked = SYSREG->MSSDDR_PLL_STATUS & FAB_PLL_LOCK_MASK;
988     } while(!pll_locked);
989 
990     /* Negate MPLL bypass. */
991     SYSREG->MSSDDR_PLL_STATUS_HIGH_CR &= ~FACC_PLL_BYPASS_MASK;
992 
993     /* Wait for MPLL to lock. */
994     do {
995         pll_locked = SYSREG->MSSDDR_PLL_STATUS & MPLL_LOCK_MASK;
996     } while(!pll_locked);
997 
998     /* Switch FACC from standby to run mode. */
999     SYSREG->MSSDDR_FACC1_CR &= ~FACC_GLMUX_SEL_MASK;
1000 
1001     /* Negate FPGA_SOFTRESET to de-assert MSS_RESET_N_M2F in the fabric */
1002     SYSREG->SOFT_RST_CR &= ~SYSREG_FPGA_SOFTRESET_MASK;
1003 }
1004 #endif
1005 
1006