1 /*******************************************************************************
2 * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * MPFS HAL Embedded Software
7 *
8 */
9
10 /*******************************************************************************
11 * @file mss_nwc_init.c
12 * @author Microchip-FPGA Embedded Systems Solutions
13 * @brief north west corner, calls required startup code
14 *
15 */
16
17 #include <string.h>
18 #include <stdio.h>
19 #include "mpfs_hal/mss_hal.h"
20 #include "mss_nwc_init.h"
21 #include "simulation.h"
22
23 #ifdef DEBUG_DDR_INIT
24 #include "drivers/mss/mss_mmuart/mss_uart.h"
25 extern mss_uart_instance_t *g_debug_uart ;
26 uint32_t setup_ddr_debug_port(mss_uart_instance_t * uart);
27 #endif
28
29 /*******************************************************************************
30 * Local Defines
31 */
32 CFG_DDR_SGMII_PHY_TypeDef * const CFG_DDR_SGMII_PHY = ((CFG_DDR_SGMII_PHY_TypeDef *) CFG_DDR_SGMII_PHY_BASE);
33 DDR_CSR_APB_TypeDef * const DDRCFG = ((DDR_CSR_APB_TypeDef *) DDRCFG_BASE);
34 IOSCBCFG_TypeDef * const SCBCFG_REGS = (IOSCBCFG_TypeDef *)IOSCBCFG_BASE ;
35 g5_mss_top_scb_regs_TypeDef * const SCB_REGS = (g5_mss_top_scb_regs_TypeDef *) SYSREGSCB_BASE;
36
37 /*******************************************************************************
38 * Local functions
39 */
40 void delay(uint32_t n);
41
42 /*******************************************************************************
43 * extern defined functions
44 */
45 #ifdef DEBUG_DDR_INIT
46 uint32_t setup_ddr_debug_port(mss_uart_instance_t * uart);
47 #endif
48
49 /******************************************************************************
50 * Public Functions - API
51 ******************************************************************************/
52
53 /**
54 * MSS_DDR_init_simulation(void)
55 * Flow when running through full chip simulation
56 *
57 * @return
58 */
mss_nwc_init(void)59 uint8_t mss_nwc_init(void)
60 {
61 uint8_t error = 0U;
62
63 #ifndef SIFIVE_HIFIVE_UNLEASHED
64
65 #ifdef SIMULATION_TEST_FEEDBACK
66 /*
67 * set the test version- this is read in Simulation environment
68 * x.y.z
69 * byte[0] = z
70 * byte[1] = y
71 * byte[2] = x
72 */
73 SIM_FEEDBACK0(0x33333333);
74 SYSREG->TEMP0 = (0U << 16U) | (3U << 8U) | 3U;
75 SYSREG->TEMP0 = 0x44444444U;
76 SIM_FEEDBACK0(1);
77 SIM_FEEDBACK0(0x55555555);
78 SIM_FEEDBACK0(1);
79 #endif
80 /*
81 * Assumptions:
82 * 1. We enter here shortly after start-up of E51 code by the system
83 * controller.
84 * 2. We are running on the E51 and all other cores are in wfi.
85 * 3. The MSS PLL will be set to use default internal clock of 80MH
86 * 4. MSS peripherals including the I/O are in the default power on state
87 *
88 *
89 * The following implements setting of
90 * external clock reference
91 * MSS PLL, SHMII PLL, SGMII PLL, MSS Mux's
92 * IO settings and IO MUX
93 * HSIO IO calibration options
94 * SGMII configuration
95 * DDR configuration
96 * Including SEG regs
97 * MPU setup
98 * PMP setup
99 * ABP Peripheral address setup (High/Low)
100 *
101 */
102
103 /*
104 * Set based on reference clock
105 */
106 set_RTC_divisor();
107
108 /*
109 * SCB access settings
110 * Bits 15:8 Sets how long SCB request is held active after SCB bus granted.
111 * Allows SCB bus master-ship to maintained across multiple SCB access
112 * cycles
113 * Bits 7:0 Set the timeout for an SCB access in CPU cycles.
114 */
115 SCBCFG_REGS->TIMER.TIMER = MSS_SCB_ACCESS_CONFIG;
116
117 /*
118 * Release APB reset & turn on dfi clock
119 *
120 * reserved bit 31:2
121 * reset bit 1 Asserts the APB reset to the MSS corner, is asserted at
122 * MSS reset.
123 * clock_on bit 0 Turns on the APB clock to the MSS Corner, is off at
124 * reset. Once corner blocks is configured the firmware
125 * may turn off the clock, but periodically should turn
126 * back on to allow refresh of TMR registers inside
127 * the corner block.
128 *
129 */
130 SYSREG->DFIAPB_CR = 0x00000001U;
131
132 /*
133 * Dynamic APB enables for slaves
134 * APB dynamic enables determine if we can write to the associated APB
135 * registers.
136 * ACB dynamic enables determine if we can write to the associated SCB
137 * registers.
138 *
139 * bit 31:22 Reserved
140 * bit 21 DYNEN_APB_DECODER_PRESETS
141 * bit 20 DYNEN_APB_BANKCNTL
142 * bit 19 DYNEN_APB_IO_CALIB
143 * bit 18 DYNEN_APB_CFM
144 * bit 17 DYNEN_APB_PLL1
145 * bit 16 DYNEN_APB_PLL0
146 * bit 15:13 Reserved
147 * bit 12 DYNEN_SCB_BANKCNTL
148 * bit 11 DYNEN_SCB_IO_CALIB
149 * bit 10 DYNEN_SCB_CFM
150 * bit 9 DYNEN_SCB_PLL1
151 * bit 8 DYNEN_SCB_PLL0
152 * bit 7:5 Reserved
153 * bit 4 Persist_DATA
154 * bit 3 CLKOUT
155 * bit 2 PERSIST_ADD_CMD
156 * bit 1 DATA_Lockdn
157 * bit 0 ADD_CMD_Lockdn
158 */
159 CFG_DDR_SGMII_PHY->DDRPHY_STARTUP.DDRPHY_STARTUP =\
160 (0x3FU << 16U) | (0x1FU << 8U);
161 /* Enable all dynamic enables
162 When in dynamic enable more, this allows:
163 1. writing directly using SCB
164 2. setting using RPC on a soft reset
165 */
166 CFG_DDR_SGMII_PHY->DYN_CNTL.DYN_CNTL = (0x01U<< 10U) | (0x7FU<<0U);
167
168 /*
169 * Configure IOMUX and I/O settings for bank 2 and 4
170 */
171 {
172 #ifdef MSSIO_SUPPORT
173 error |= mssio_setup();
174 #endif
175 }
176
177 /*************************************************************************/
178
179 /*
180 *
181 * In this step we enter Dynamic Enable mode.
182 * This is done by using the following sequence:
183 *
184 * Please note all dynamic enables must be enabled.
185 * If dynamic enables are not enabled, when flash valid is asserted, value
186 * of SCB registers will be immediately written to with default values
187 * rather than the RPC values.
188 *
189 * Dynamic Enable mode:
190 * Step 1:
191 * Make sure SCB dynamic enable bit is high
192 * step 2: Assert MSS core_up
193 * followed by delay
194 * step 3: Change dce[0,1,2] to 0x00
195 * followed by delay
196 * step 4: Assert flash valid
197 * followed by delay
198 * step 5: make sure all RPC registers are set to desired values
199 * (using mode and direct RPC writes to RPC)
200 * step 6: soft reset IP so SCB registers are written with RPC values.
201 * note: We will carry out step 5/6 later, once we have modified any
202 * RPC registers directly that may need tweaking or are not
203 * included in the mode write state machine, carried out in a
204 * previous step.
205 *
206 * Note 1: The SCB bus can be used to update/write new values to
207 * the SCB registers through the SCB bus interface while in Dynamic
208 * enable mode
209 * Note 2: The MSS top block assertion of core_up and flash_valid
210 * have no effect in themselves if MSS custom SCB register values
211 * if the custom SCB slaves are not being reset at the same time.
212 * If the custom SCB slaves are reset whilst core_up and
213 * flash_valid are high, then the SCB registers get asynchronously
214 * loaded with the values of their corresponding RPC bits. These
215 * values remain even after negation of reset but may be
216 * subsequently overwritten by SCB writes.
217 *
218 * reg MSS_LOW_POWER_CR
219 *
220 * bit 12 flash_valid Sets the value driven out on
221 * mss_flash_valid_out
222 * bit 11 core_up Sets the value driven out on
223 * mss_core_up_out
224 * bit 10:8 dce S Sets the value driven out on mss_dce_out
225 * unless G5C asserts its overrides
226 * bit 7 lp_stop_clocks_in Read back of lp_stop_clocks input
227 * bit 6 lp_stop_clocks_out Direct control of MSS Corner LP state
228 * control
229 * bit 5 p_pll_locked Direct control of MSS Corner
230 * LP state control
231 * bit 4 lp_state_bypass Direct control of MSS Corner LP
232 * state control
233 * bit 3 lp_state_persist
234 * bit 2 lp_state_op
235 * bit 1 lp_state_ip
236 * bit 0 lp_state_mss
237 *
238 * In order to re-flash/update the APB RPC register values into the
239 * registers of a specific SCB slave,the following sequence must be
240 * followed:
241 * 1) Embedded software running on E51 must force the mss_core_up and
242 * mss_flash valid must be high
243 * 2) Then do a soft reset of the specific SCB slave that will be
244 * re-flashed/updated.
245 *
246 * The APB RPC registers are used in the following ways to configure
247 * the MSS periphery
248 * 1) Load values to SCB registers.
249 * core_up" and "flash_valid" determines if the SCB registers get
250 * either:
251 * a. Reset to their hardware default
252 * (when core_up/flash_valis low)
253 * b. Loaded with the APB RPC register.
254 * (when core_up/flash_valid high)
255 * 2) IO configuration settings
256 * These are fed directly to the static configuration of IOA cells
257 * within the IOG lanes of the DDR and SGMII PHYs, as long as
258 * "core_up" and "flash_valid" are high.
259 * a. To avoid unwanted/intermediate states on IOs, the "core_up"
260 * and "flash_valid" should be initially 0 on MSS reset. This will
261 * select the safe hardware defaults. The RPC registers are written
262 * in the background and then simultaneously "flashed" as the new
263 * IO configuration by assertion of "core_up" and "flash_valid"
264 * being asserted.
265 * 3) Training IP settings
266 * These allow the direct control of the training IP via the APB
267 * registers.
268 *
269 * Notes:
270 * 1) When the MSS is reset, the SCB slaves won't take on the RPC
271 * values. They will be reset to their hardware default values.
272 *
273 * 2) Although RPC registers are writable in APB space,
274 * they only take effect on the SCB registers whenever there is a
275 * "virtual re-flash" operation, which involves performing
276 * a soft reset of an SCB slave (i.e. writing to the NV_MAP register
277 * bit in the SOFT_RESET register in the SCB slave).
278 * This mechanism would only be used if a full new configuration is to
279 * be applied to the full SCB slave and wouldn't be used, for example
280 * to change just a clock mux configuration.
281 *
282 * 3) To make configuration changes to individual registers, without
283 * "re-flashing" all registers in an MSS custom SCB slave, it is
284 * necessary to write directly to the SCB registers (via SCB space) in
285 * that slave, rather than writing RPC registers via APB space
286 *
287 */
288
289 /*
290 lp_state_mss :1;
291 lp_state_ip_mss :1;
292 lp_state_op_mss :1;
293 lp_state_persist_mss :1;
294 lp_state_bypass_mss :1;
295 lp_pll_locked_mss :1;
296 lp_stop_clocks_out_mss :1;
297 lp_stop_clocks_in_mss :1;
298 mss_dce :3;
299 mss_core_up :1;
300 mss_flash_valid :1;
301 mss_io_en :1;
302 */
303 /* DCE:111, CORE_UP:1, FLASH_VALID:0, mss_io_en:0 */
304 SCB_REGS->MSSIO_CONTROL_CR.MSSIO_CONTROL_CR =\
305 (0x07U<<8U)|(0x01U<<11U)|(0x00U<<12U)|(0x00U<<13U);
306 delay((uint32_t) 10U);
307 /* DCE:000, CORE_UP:1, FLASH_VALID:0, mss_io_en:0 */
308 SCB_REGS->MSSIO_CONTROL_CR.MSSIO_CONTROL_CR =\
309 (0x00U<<8U)|(0x01U<<11U)|(0x00U<<12U)|(0x00U<<13U);
310 delay((uint32_t) 10U);
311 /* DCE:000, CORE_UP:1, FLASH_VALID:1, mss_io_en:0 */
312 SCB_REGS->MSSIO_CONTROL_CR.MSSIO_CONTROL_CR =\
313 (0x00U<<8U)|(0x01U<<11U)|(0x01U<<12U)|(0x00U<<13U);
314 delay((uint32_t) 10U);
315 /* DCE:000, CORE_UP:1, FLASH_VALID:1, mss_io_en:1 */
316 SCB_REGS->MSSIO_CONTROL_CR.MSSIO_CONTROL_CR =\
317 (0x00U<<8U)|(0x01U<<11U)|(0x01U<<12U)|(0x01U<<13U);
318
319 /*
320 * Setup SGMII
321 * The SGMII set-upset configures the external clock reference so this must
322 * be called before configuring the MSS PLL
323 */
324 SIM_FEEDBACK0(2);
325 sgmii_setup();
326
327 /*
328 * Setup the MSS PLL
329 */
330 SIM_FEEDBACK0(3);
331 mss_pll_config();
332
333 {
334 #ifdef DDR_SUPPORT
335 #ifdef DEBUG_DDR_INIT
336 {
337 (void)setup_ddr_debug_port(g_debug_uart);
338 }
339 #endif
340
341 uint32_t ddr_status;
342 ddr_status = ddr_state_machine(DDR_SS__INIT);
343
344 while((ddr_status & DDR_SETUP_DONE) != DDR_SETUP_DONE)
345 {
346 ddr_status = ddr_state_machine(DDR_SS_MONITOR);
347 }
348 if ((ddr_status & DDR_SETUP_FAIL) == DDR_SETUP_FAIL)
349 {
350 error |= (0x1U << 2U);
351 }
352 //todo: remove, just for sim test ddr_recalib_io_test();
353 #endif
354 }
355
356 #endif /* end of !define SIFIVE_HIFIVE_UNLEASHED */
357 SIM_FEEDBACK0(0x12345678U);
358 SIM_FEEDBACK0(error);
359 SIM_FEEDBACK0(0x87654321U);
360 return error;
361 }
362
363
364 /*-------------------------------------------------------------------------*//**
365 * delay()
366 * Not absolute. Dependency on current clk rate
367 * @param n Number of iterations to wait.
368 */
delay(uint32_t n)369 void delay(uint32_t n)
370 {
371 volatile uint32_t count = n;
372 while(count!=0U)
373 {
374 count--;
375 }
376 }
377
378 /*-------------------------------------------------------------------------*//**
379 * mtime_delay()
380 * waits x microseconds
381 * Assumption 1 is we have ensured clock is 1MHz
382 * Assumption 2 is we have not setup tick timer when using this function. It is
383 * only used by the startup code
384 * @param microseconds microseconds to delay
385 */
386
mtime_delay(uint32_t microseconds)387 void mtime_delay(uint32_t microseconds)
388 {
389 CLINT->MTIME = 0ULL;
390 volatile uint32_t count = 0ULL;
391
392 while(CLINT->MTIME < microseconds)
393 {
394 count++;
395 }
396 return;
397 }
398