| /**************************************************************************** |
| * arch/arm/src/tms570/tms570_boot.c |
| * |
| * Copyright (C) 2015 Gregory Nutt. All rights reserved. |
| * Author: Gregory Nutt <gnutt@nuttx.org> |
| * |
| * This is primarily original code. However, some logic in this file was |
| * inspired/leveraged from TI's Project0 which has a compatible BSD license |
| * and credit should be given in any case: |
| * |
| * Copyright (c) 2012, Texas Instruments Incorporated |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * 3. Neither the name NuttX nor the names of its contributors may be |
| * used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
| * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
| * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| |
| #include <stdint.h> |
| #include <assert.h> |
| #include <debug.h> |
| |
| #include <arch/board/board.h> |
| |
| #include "chip.h" |
| #include "arm.h" |
| #include "sctlr.h" |
| #include "arm_internal.h" |
| |
| #include <nuttx/init.h> |
| |
| #include "hardware/tms570_sys.h" |
| #include "hardware/tms570_esm.h" |
| #include "hardware/tms570_pbist.h" |
| #include "tms570_clockconfig.h" |
| #include "tms570_selftest.h" |
| #include "tms570_gio.h" |
| #include "tms570_esm.h" |
| #include "tms570_boot.h" |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| #ifndef CONFIG_ARMV7R_MEMINIT |
| # error CONFIG_ARMV7R_MEMINIT is required by this architecture. |
| #endif |
| |
| #ifndef CONFIG_ARCH_LOWVECTORS |
| # error CONFIG_ARCH_LOWVECTORS is required by this architecture. |
| #endif |
| |
| /**************************************************************************** |
| * Public Data |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Private Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: tms570_event_export |
| * |
| * Description: |
| * Enable CPU Event Export by setting the X bit in the PMCR. In general, |
| * this bit enables the exporting of events to another debug device, such |
| * as a trace macrocell, over an event bus. |
| * |
| * For the TMS570, this allows the CPU to signal any single-bit or double |
| * -bit errors detected by its ECC logic for accesses to program flash or |
| * data RAM. |
| * |
| ****************************************************************************/ |
| |
| static inline void tms570_event_export(void) |
| { |
| cp15_pmu_pmcr(PMCR_X); |
| } |
| |
| /**************************************************************************** |
| * Name: tms570_check_reset |
| * |
| * Description: |
| * Assert if we go here through any mechanism other than a power-on reset. |
| * |
| ****************************************************************************/ |
| |
| static inline void tms570_check_reset(void) |
| { |
| #ifdef CONFIG_DEBUG_FEATURES |
| uint32_t regval; |
| |
| /* Read from the system exception status register to identify the cause of |
| * the CPU reset. |
| */ |
| |
| regval = getreg32(TMS570_SYS_ESR); |
| |
| /* Clear all reset status flags on normal reset */ |
| |
| regval = getreg32(TMS570_SYS_ESR); |
| putreg32(SYS_ESR_RSTALL, TMS570_SYS_ESR); |
| |
| /* Check for abnormal reset causes: Oscillator failures or watchdog |
| * timers. Ignore normal reset causes: External reset, software reset, CPU |
| * reset, power-on reset |
| * |
| * REVISIT: The reset cause is not used in the current design. But if you |
| * need to know the cause of the reset, here is where you would want to |
| * do that. |
| */ |
| |
| #if 0 |
| DEBUGASSERT((regval & SYS_ESR_FAILALL) == 0); |
| #else |
| UNUSED(regval); |
| #endif |
| |
| #else |
| /* Clear all reset status flags */ |
| |
| putreg32(SYS_ESR_RSTALL, TMS570_SYS_ESR); |
| #endif |
| } |
| |
| /**************************************************************************** |
| * Name: tms570_enable_ramecc |
| * |
| * Description: |
| * This function enables the CPU's ECC logic for accesses to B0TCM and |
| * B1TCM. |
| * |
| ****************************************************************************/ |
| |
| static inline void tms570_enable_ramecc(void) |
| { |
| uint32_t actlr = cp15_rdactlr(); |
| actlr |= 0x0c000000; |
| cp15_wractlr(actlr); |
| } |
| |
| /**************************************************************************** |
| * Name: tms570_memory_initialize |
| * |
| * Description: |
| * Perform memory initialization of selected RAMs |
| * |
| * This function uses the system module's hardware for auto-initialization |
| * of memories and their associated protection schemes. |
| * |
| ****************************************************************************/ |
| |
| static void tms570_memory_initialize(uint32_t ramset) |
| { |
| /* Enable Memory Hardware Initialization */ |
| |
| putreg32(SYS_MINITGCR_ENABLE, TMS570_SYS_MINITGCR); |
| |
| /* Enable Memory Hardware Initialization for selected RAM's */ |
| |
| putreg32(ramset, TMS570_SYS_MSIENA); |
| |
| /* Wait until Memory Hardware Initialization complete */ |
| |
| while ((getreg32(TMS570_SYS_MSTCGSTAT) & SYS_MSTCGSTAT_MINIDONE) == 0); |
| |
| /* Disable Memory Hardware Initialization */ |
| |
| putreg32(SYS_MINITGCR_DISABLE, TMS570_SYS_MINITGCR); |
| } |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: arm_boot |
| * |
| * Description: |
| * Complete boot operations started in arm_head.S |
| * |
| * Boot Sequence |
| * |
| * 1. The __start entry point in armv7-r/arm_head.S is invoked upon power- |
| * on reset. |
| * 2. __start prepares CPU for code execution. |
| * 3a. If CONFIG_ARMV7R_MEMINIT is not defined, then __start will prepare |
| * memory resources by calling arm_data_initialize() and will then |
| * branch this function. |
| * 3b. Otherwise, this function will be called without having initialized |
| * memory resources! We need to be very careful in this case. Here, |
| * this function will call tms570_boardinitialize() which, among other |
| * things, must initialize SDRAM memory. After initializatino of the |
| * memories, this function will call arm_data_initialize() to |
| * initialize the memory resources |
| * 4. This function will then branch to nx_start() to start the operating |
| * system. |
| * |
| ****************************************************************************/ |
| |
| void arm_boot(void) |
| { |
| #ifdef CONFIG_TMS570_SELFTEST |
| int check; |
| #endif /* CONFIG_TMS570_SELFTEST */ |
| |
| /* Enable CPU Event Export. |
| * |
| * This allows the CPU to signal any single-bit or double-bit errors |
| * detected by its ECC logic for accesses to program flash or data RAM. |
| */ |
| |
| tms570_event_export(); |
| |
| /* Verify that we got here via a power-up reset */ |
| |
| tms570_check_reset(); |
| |
| /* Check if there were ESM group3 errors during power-up. |
| * |
| * These could occur during eFuse auto-load or during reads from flash OTP |
| * during power-up. Device operation is not reliable and not recommended |
| * in this case. |
| * |
| * An ESM group3 error only drives the nERROR pin low. An external circuit |
| * that monitors the nERROR pin must take the appropriate action to ensure |
| * that the system is placed in a safe state, as determined by the |
| * application. |
| */ |
| |
| DEBUGASSERT(getreg32(TMS570_ESM_SR3) == 0); |
| |
| /* Initialize clocking to settings provided by board-specific logic */ |
| |
| tms570_clockconfig(); |
| |
| #ifdef CONFIG_TMS570_SELFTEST |
| /* Run a diagnostic check on the memory self-test controller. |
| * |
| * REVISIT: This is a destructive test. It will most likely clobber the |
| * current stack content and result in a failure if this function were to |
| * attempt to return. |
| */ |
| |
| tms570_memtest_selftest(); |
| |
| /* Run the memory selftest on CPU RAM. */ |
| |
| tms570_memtest_start(PBIST_RINFOL_ESRAM1_RAM); |
| check = tms570_memtest_complete(); |
| DEBUGASSERT(check == OK); |
| #endif /* CONFIG_TMS570_SELFTEST */ |
| |
| /* Initialize CPU RAM. */ |
| |
| tms570_memory_initialize(SYS_MSIENA_RAM); |
| |
| /* Enable ECC checking for TCRAM accesses. */ |
| |
| tms570_enable_ramecc(); |
| |
| #ifdef CONFIG_TMS570_SELFTEST |
| /* Perform PBIST on all dual-port memories */ |
| |
| tms570_memtest_start(PBIST_RINFOL_VIM_RAM |
| #ifdef CONFIG_TMS570_DCAN1 |
| | PBIST_RINFOL_DCAN1_RAM |
| #endif |
| #ifdef CONFIG_TMS570_DCAN2 |
| | PBIST_RINFOL_DCAN2_RAM |
| #endif |
| #ifdef CONFIG_TMS570_MIBASPI1 |
| | PBIST_RINFOL_MIBSPI1_RAM |
| #endif |
| #ifdef CONFIG_TMS570_MIBASPI1 |
| | PBIST_RINFOL_MIBADC_RAM |
| #endif |
| #ifdef CONFIG_TMS570_N2HET |
| | PBIST_RINFOL_N2HET_RAM |
| | PBIST_RINFOL_HET_TU_RAM |
| #endif |
| ); |
| |
| /* Test the CPU ECC mechanism for RAM accesses. */ |
| |
| tms570_cpuecc_selftest(); |
| |
| /* Wait for the memory test to complete */ |
| |
| check = tms570_memtest_complete(); |
| DEBUGASSERT(check == OK); |
| UNUSED(check); |
| #endif /* CONFIG_TMS570_SELFTEST */ |
| |
| #ifdef CONFIG_TMS570_MIBASPI1 |
| /* Release the MibSPI1 modules from local reset. |
| * |
| * This will cause the MibSPI1 RAMs to be initialized along with the |
| * parity memory. |
| */ |
| |
| putreg32(MIBSPI_GCR0_RESET, TMS570_MIBSPI_GCR0); |
| #endif |
| |
| /* Initialize all on-chip SRAMs except for MibSPIx RAMs. |
| * |
| * The MibSPIx modules have their own auto-initialization mechanism which |
| * is triggered as soon as the modules are brought out of local reset. |
| * |
| * The system module auto-init will hang on the MibSPI RAM if the module |
| * is still in local reset. |
| */ |
| |
| tms570_memory_initialize(SYS_MSIENA_VIM_RAM |
| #ifdef CONFIG_TMS570_N2HET |
| | SYS_MSIENA_N2HET_RAM | SYS_MSIENA_HTU_RAM |
| #endif |
| #ifdef CONFIG_TMS570_DCAN1 |
| | SYS_MSIENA_DCAN1_RAM |
| #endif |
| #ifdef CONFIG_TMS570_DCAN2 |
| | SYS_MSIENA_DCAN2_RAM |
| #endif |
| #ifdef CONFIG_TMS570_MIBADC |
| | SYS_MSIENA_MIBADC_RAM |
| #endif |
| ); |
| |
| #ifdef CONFIG_TMS570_SELFTEST |
| /* Test the parity protection mechanism for peripheral RAMs */ |
| |
| #warning Missing logic |
| #endif |
| |
| #ifdef CONFIG_TMS570_MIBASPI1 |
| /* Wait for MibSPI1 RAM to complete initialization */ |
| |
| #warning Missing logic |
| #endif |
| |
| /* Configure system response to error conditions */ |
| |
| tms570_esm_initialize(); |
| |
| /* Initialize the FPU */ |
| |
| arm_fpuconfig(); |
| |
| #ifdef CONFIG_ARMV7R_MEMINIT |
| /* Initialize the .bss and .data sections as well as RAM functions |
| * now after RAM has been initialized. |
| * |
| * NOTE that if SDRAM were supported, this call might have to be |
| * performed after returning from tms570_board_initialize() |
| */ |
| |
| arm_data_initialize(); |
| #endif |
| |
| /* Initialize GIO for use by board initialization logic */ |
| |
| tms570_gio_initialize(); |
| |
| /* Perform board-specific initialization, This must include: |
| * |
| * - Initialization of board-specific memory resources (e.g., SDRAM) |
| * - Configuration of board specific resources (GIOs, LEDs, etc). |
| * |
| * NOTE: We must use caution prior to this point to make sure that |
| * the logic does not access any global variables that might lie |
| * in SDRAM. |
| */ |
| |
| tms570_board_initialize(); |
| |
| /* Perform common, low-level chip initialization (might do nothing) */ |
| |
| tms570_lowsetup(); |
| |
| /* Then start NuttX */ |
| |
| nx_start(); |
| } |