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