summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_nwc_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_nwc_init.c')
-rw-r--r--FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_nwc_init.c397
1 files changed, 397 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_nwc_init.c b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_nwc_init.c
new file mode 100644
index 000000000..698cceffd
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/nwc/mss_nwc_init.c
@@ -0,0 +1,397 @@
+/*******************************************************************************
+ * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MPFS HAL Embedded Software
+ *
+ */
+
+/*******************************************************************************
+ * @file mss_nwc_init.c
+ * @author Microchip-FPGA Embedded Systems Solutions
+ * @brief north west corner, calls required startup code
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "mpfs_hal/mss_hal.h"
+#include "mss_nwc_init.h"
+#include "simulation.h"
+
+#ifdef DEBUG_DDR_INIT
+#include "drivers/mss/mss_mmuart/mss_uart.h"
+extern mss_uart_instance_t *g_debug_uart ;
+uint32_t setup_ddr_debug_port(mss_uart_instance_t * uart);
+#endif
+
+/*******************************************************************************
+ * Local Defines
+ */
+CFG_DDR_SGMII_PHY_TypeDef * const CFG_DDR_SGMII_PHY = ((CFG_DDR_SGMII_PHY_TypeDef *) CFG_DDR_SGMII_PHY_BASE);
+DDR_CSR_APB_TypeDef * const DDRCFG = ((DDR_CSR_APB_TypeDef *) DDRCFG_BASE);
+IOSCBCFG_TypeDef * const SCBCFG_REGS = (IOSCBCFG_TypeDef *)IOSCBCFG_BASE ;
+g5_mss_top_scb_regs_TypeDef * const SCB_REGS = (g5_mss_top_scb_regs_TypeDef *) SYSREGSCB_BASE;
+
+/*******************************************************************************
+ * Local functions
+ */
+void delay(uint32_t n);
+
+/*******************************************************************************
+ * extern defined functions
+ */
+#ifdef DEBUG_DDR_INIT
+uint32_t setup_ddr_debug_port(mss_uart_instance_t * uart);
+#endif
+
+/******************************************************************************
+ * Public Functions - API
+ ******************************************************************************/
+
+/**
+ * MSS_DDR_init_simulation(void)
+ * Flow when running through full chip simulation
+ *
+ * @return
+ */
+uint8_t mss_nwc_init(void)
+{
+ uint8_t error = 0U;
+
+#ifndef SIFIVE_HIFIVE_UNLEASHED
+
+#ifdef SIMULATION_TEST_FEEDBACK
+ /*
+ * set the test version- this is read in Simulation environment
+ * x.y.z
+ * byte[0] = z
+ * byte[1] = y
+ * byte[2] = x
+ */
+ SIM_FEEDBACK0(0x33333333);
+ SYSREG->TEMP0 = (0U << 16U) | (3U << 8U) | 3U;
+ SYSREG->TEMP0 = 0x44444444U;
+ SIM_FEEDBACK0(1);
+ SIM_FEEDBACK0(0x55555555);
+ SIM_FEEDBACK0(1);
+#endif
+ /*
+ * Assumptions:
+ * 1. We enter here shortly after start-up of E51 code by the system
+ * controller.
+ * 2. We are running on the E51 and all other cores are in wfi.
+ * 3. The MSS PLL will be set to use default internal clock of 80MH
+ * 4. MSS peripherals including the I/O are in the default power on state
+ *
+ *
+ * The following implements setting of
+ * external clock reference
+ * MSS PLL, SHMII PLL, SGMII PLL, MSS Mux's
+ * IO settings and IO MUX
+ * HSIO IO calibration options
+ * SGMII configuration
+ * DDR configuration
+ * Including SEG regs
+ * MPU setup
+ * PMP setup
+ * ABP Peripheral address setup (High/Low)
+ *
+ */
+
+ /*
+ * Set based on reference clock
+ */
+ set_RTC_divisor();
+
+ /*
+ * SCB access settings
+ * Bits 15:8 Sets how long SCB request is held active after SCB bus granted.
+ * Allows SCB bus master-ship to maintained across multiple SCB access
+ * cycles
+ * Bits 7:0 Set the timeout for an SCB access in CPU cycles.
+ */
+ SCBCFG_REGS->TIMER.TIMER = MSS_SCB_ACCESS_CONFIG;
+
+ /*
+ * Release APB reset & turn on dfi clock
+ *
+ * reserved bit 31:2
+ * reset bit 1 Asserts the APB reset to the MSS corner, is asserted at
+ * MSS reset.
+ * clock_on bit 0 Turns on the APB clock to the MSS Corner, is off at
+ * reset. Once corner blocks is configured the firmware
+ * may turn off the clock, but periodically should turn
+ * back on to allow refresh of TMR registers inside
+ * the corner block.
+ *
+ */
+ SYSREG->DFIAPB_CR = 0x00000001U;
+
+ /*
+ * Dynamic APB enables for slaves
+ * APB dynamic enables determine if we can write to the associated APB
+ * registers.
+ * ACB dynamic enables determine if we can write to the associated SCB
+ * registers.
+ *
+ * bit 31:22 Reserved
+ * bit 21 DYNEN_APB_DECODER_PRESETS
+ * bit 20 DYNEN_APB_BANKCNTL
+ * bit 19 DYNEN_APB_IO_CALIB
+ * bit 18 DYNEN_APB_CFM
+ * bit 17 DYNEN_APB_PLL1
+ * bit 16 DYNEN_APB_PLL0
+ * bit 15:13 Reserved
+ * bit 12 DYNEN_SCB_BANKCNTL
+ * bit 11 DYNEN_SCB_IO_CALIB
+ * bit 10 DYNEN_SCB_CFM
+ * bit 9 DYNEN_SCB_PLL1
+ * bit 8 DYNEN_SCB_PLL0
+ * bit 7:5 Reserved
+ * bit 4 Persist_DATA
+ * bit 3 CLKOUT
+ * bit 2 PERSIST_ADD_CMD
+ * bit 1 DATA_Lockdn
+ * bit 0 ADD_CMD_Lockdn
+ */
+ CFG_DDR_SGMII_PHY->DDRPHY_STARTUP.DDRPHY_STARTUP =\
+ (0x3FU << 16U) | (0x1FU << 8U);
+ /* Enable all dynamic enables
+ When in dynamic enable more, this allows:
+ 1. writing directly using SCB
+ 2. setting using RPC on a soft reset
+ */
+ CFG_DDR_SGMII_PHY->DYN_CNTL.DYN_CNTL = (0x01U<< 10U) | (0x7FU<<0U);
+
+ /*
+ * Configure IOMUX and I/O settings for bank 2 and 4
+ */
+ {
+#ifdef MSSIO_SUPPORT
+ error |= mssio_setup();
+#endif
+ }
+
+ /*************************************************************************/
+
+ /*
+ *
+ * In this step we enter Dynamic Enable mode.
+ * This is done by using the following sequence:
+ *
+ * Please note all dynamic enables must be enabled.
+ * If dynamic enables are not enabled, when flash valid is asserted, value
+ * of SCB registers will be immediately written to with default values
+ * rather than the RPC values.
+ *
+ * Dynamic Enable mode:
+ * Step 1:
+ * Make sure SCB dynamic enable bit is high
+ * step 2: Assert MSS core_up
+ * followed by delay
+ * step 3: Change dce[0,1,2] to 0x00
+ * followed by delay
+ * step 4: Assert flash valid
+ * followed by delay
+ * step 5: make sure all RPC registers are set to desired values
+ * (using mode and direct RPC writes to RPC)
+ * step 6: soft reset IP so SCB registers are written with RPC values.
+ * note: We will carry out step 5/6 later, once we have modified any
+ * RPC registers directly that may need tweaking or are not
+ * included in the mode write state machine, carried out in a
+ * previous step.
+ *
+ * Note 1: The SCB bus can be used to update/write new values to
+ * the SCB registers through the SCB bus interface while in Dynamic
+ * enable mode
+ * Note 2: The MSS top block assertion of core_up and flash_valid
+ * have no effect in themselves if MSS custom SCB register values
+ * if the custom SCB slaves are not being reset at the same time.
+ * If the custom SCB slaves are reset whilst core_up and
+ * flash_valid are high, then the SCB registers get asynchronously
+ * loaded with the values of their corresponding RPC bits. These
+ * values remain even after negation of reset but may be
+ * subsequently overwritten by SCB writes.
+ *
+ * reg MSS_LOW_POWER_CR
+ *
+ * bit 12 flash_valid Sets the value driven out on
+ * mss_flash_valid_out
+ * bit 11 core_up Sets the value driven out on
+ * mss_core_up_out
+ * bit 10:8 dce S Sets the value driven out on mss_dce_out
+ * unless G5C asserts its overrides
+ * bit 7 lp_stop_clocks_in Read back of lp_stop_clocks input
+ * bit 6 lp_stop_clocks_out Direct control of MSS Corner LP state
+ * control
+ * bit 5 p_pll_locked Direct control of MSS Corner
+ * LP state control
+ * bit 4 lp_state_bypass Direct control of MSS Corner LP
+ * state control
+ * bit 3 lp_state_persist
+ * bit 2 lp_state_op
+ * bit 1 lp_state_ip
+ * bit 0 lp_state_mss
+ *
+ * In order to re-flash/update the APB RPC register values into the
+ * registers of a specific SCB slave,the following sequence must be
+ * followed:
+ * 1) Embedded software running on E51 must force the mss_core_up and
+ * mss_flash valid must be high
+ * 2) Then do a soft reset of the specific SCB slave that will be
+ * re-flashed/updated.
+ *
+ * The APB RPC registers are used in the following ways to configure
+ * the MSS periphery
+ * 1) Load values to SCB registers.
+ * core_up" and "flash_valid" determines if the SCB registers get
+ * either:
+ * a. Reset to their hardware default
+ * (when core_up/flash_valis low)
+ * b. Loaded with the APB RPC register.
+ * (when core_up/flash_valid high)
+ * 2) IO configuration settings
+ * These are fed directly to the static configuration of IOA cells
+ * within the IOG lanes of the DDR and SGMII PHYs, as long as
+ * "core_up" and "flash_valid" are high.
+ * a. To avoid unwanted/intermediate states on IOs, the "core_up"
+ * and "flash_valid" should be initially 0 on MSS reset. This will
+ * select the safe hardware defaults. The RPC registers are written
+ * in the background and then simultaneously "flashed" as the new
+ * IO configuration by assertion of "core_up" and "flash_valid"
+ * being asserted.
+ * 3) Training IP settings
+ * These allow the direct control of the training IP via the APB
+ * registers.
+ *
+ * Notes:
+ * 1) When the MSS is reset, the SCB slaves won't take on the RPC
+ * values. They will be reset to their hardware default values.
+ *
+ * 2) Although RPC registers are writable in APB space,
+ * they only take effect on the SCB registers whenever there is a
+ * "virtual re-flash" operation, which involves performing
+ * a soft reset of an SCB slave (i.e. writing to the NV_MAP register
+ * bit in the SOFT_RESET register in the SCB slave).
+ * This mechanism would only be used if a full new configuration is to
+ * be applied to the full SCB slave and wouldn't be used, for example
+ * to change just a clock mux configuration.
+ *
+ * 3) To make configuration changes to individual registers, without
+ * "re-flashing" all registers in an MSS custom SCB slave, it is
+ * necessary to write directly to the SCB registers (via SCB space) in
+ * that slave, rather than writing RPC registers via APB space
+ *
+ */
+
+ /*
+ lp_state_mss :1;
+ lp_state_ip_mss :1;
+ lp_state_op_mss :1;
+ lp_state_persist_mss :1;
+ lp_state_bypass_mss :1;
+ lp_pll_locked_mss :1;
+ lp_stop_clocks_out_mss :1;
+ lp_stop_clocks_in_mss :1;
+ mss_dce :3;
+ mss_core_up :1;
+ mss_flash_valid :1;
+ mss_io_en :1;
+ */
+ /* DCE:111, CORE_UP:1, FLASH_VALID:0, mss_io_en:0 */
+ SCB_REGS->MSSIO_CONTROL_CR.MSSIO_CONTROL_CR =\
+ (0x07U<<8U)|(0x01U<<11U)|(0x00U<<12U)|(0x00U<<13U);
+ delay((uint32_t) 10U);
+ /* DCE:000, CORE_UP:1, FLASH_VALID:0, mss_io_en:0 */
+ SCB_REGS->MSSIO_CONTROL_CR.MSSIO_CONTROL_CR =\
+ (0x00U<<8U)|(0x01U<<11U)|(0x00U<<12U)|(0x00U<<13U);
+ delay((uint32_t) 10U);
+ /* DCE:000, CORE_UP:1, FLASH_VALID:1, mss_io_en:0 */
+ SCB_REGS->MSSIO_CONTROL_CR.MSSIO_CONTROL_CR =\
+ (0x00U<<8U)|(0x01U<<11U)|(0x01U<<12U)|(0x00U<<13U);
+ delay((uint32_t) 10U);
+ /* DCE:000, CORE_UP:1, FLASH_VALID:1, mss_io_en:1 */
+ SCB_REGS->MSSIO_CONTROL_CR.MSSIO_CONTROL_CR =\
+ (0x00U<<8U)|(0x01U<<11U)|(0x01U<<12U)|(0x01U<<13U);
+
+ /*
+ * Setup SGMII
+ * The SGMII set-upset configures the external clock reference so this must
+ * be called before configuring the MSS PLL
+ */
+ SIM_FEEDBACK0(2);
+ sgmii_setup();
+
+ /*
+ * Setup the MSS PLL
+ */
+ SIM_FEEDBACK0(3);
+ mss_pll_config();
+
+ {
+#ifdef DDR_SUPPORT
+#ifdef DEBUG_DDR_INIT
+ {
+ (void)setup_ddr_debug_port(g_debug_uart);
+ }
+#endif
+
+ uint32_t ddr_status;
+ ddr_status = ddr_state_machine(DDR_SS__INIT);
+
+ while((ddr_status & DDR_SETUP_DONE) != DDR_SETUP_DONE)
+ {
+ ddr_status = ddr_state_machine(DDR_SS_MONITOR);
+ }
+ if ((ddr_status & DDR_SETUP_FAIL) == DDR_SETUP_FAIL)
+ {
+ error |= (0x1U << 2U);
+ }
+ //todo: remove, just for sim test ddr_recalib_io_test();
+#endif
+ }
+
+#endif /* end of !define SIFIVE_HIFIVE_UNLEASHED */
+ SIM_FEEDBACK0(0x12345678U);
+ SIM_FEEDBACK0(error);
+ SIM_FEEDBACK0(0x87654321U);
+ return error;
+}
+
+
+/*-------------------------------------------------------------------------*//**
+ * delay()
+ * Not absolute. Dependency on current clk rate
+ * @param n Number of iterations to wait.
+ */
+void delay(uint32_t n)
+{
+ volatile uint32_t count = n;
+ while(count!=0U)
+ {
+ count--;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * mtime_delay()
+ * waits x microseconds
+ * Assumption 1 is we have ensured clock is 1MHz
+ * Assumption 2 is we have not setup tick timer when using this function. It is
+ * only used by the startup code
+ * @param microseconds microseconds to delay
+ */
+
+void mtime_delay(uint32_t microseconds)
+{
+ CLINT->MTIME = 0ULL;
+ volatile uint32_t count = 0ULL;
+
+ while(CLINT->MTIME < microseconds)
+ {
+ count++;
+ }
+ return;
+}