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