mirror of
https://github.com/apache/nuttx.git
synced 2026-10-10 07:40:27 +00:00
arch/arm/imxrt: Add M7 DTCM/ITCM ECC initialization for imxrt118x
Add support for Cortex-M33 code to initialize the M7 TCM memories before releasing it to run. The TCM has ECC, which needs to be initialized before the memory is usable for M7. Specifically, the TCM needs to be initialized sequentially in 64-bit writes. Use eDMA4 for this; this is the same mechanism which the NXP MCUXpresso SDK code does. Split imxrt118x_release_cm7() into imxrt118x_prepare_cm7() and imxrt118x_start_cm7(). The TCM ECC initialization is done in imxrt118x_prepare_cm7(), after the M7 has been released from reset and before the M7 is started. Also reset M7_CFG[TCM_SIZE] to the default 256 KiB ITCM / 256 KiB DTCM layout. Co-Authored-By: Jukka Laitinen <jukka.laitinen@tii.ae> Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
This commit is contained in:
parent
59faf7ed2b
commit
3a5d5e08d5
4 changed files with 152 additions and 5 deletions
|
|
@ -36,7 +36,10 @@
|
|||
#include "arm_internal.h"
|
||||
#include "imxrt118x_ele.h"
|
||||
#include "imxrt118x_start_cm7.h"
|
||||
#include "imxrt_edma.h"
|
||||
#include "hardware/imxrt_ccm.h"
|
||||
#include "imxrt_clockconfig_ver3.h"
|
||||
#include "hardware/rt118x/imxrt118x_edma.h"
|
||||
#include "hardware/rt117x/imxrt117x_dcdc.h"
|
||||
#include "hardware/rt118x/imxrt118x_anadig.h"
|
||||
#include "hardware/rt118x/imxrt118x_blkctrl.h"
|
||||
|
|
@ -50,6 +53,21 @@
|
|||
#define CCM_M7_ROOT_CONFIG (CCM_CR_CTRL_MUX_SRCSEL(2) | \
|
||||
CCM_CR_CTRL_DIV(1))
|
||||
|
||||
extern char _sitcm_m7[];
|
||||
extern char _eitcm_m7[];
|
||||
extern char _sdtcm_m7[];
|
||||
extern char _edtcm_m7[];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Zero fill pattern for the M7 TCM ECC initialization. It lives in flash
|
||||
* (.rodata), which is readable by eDMA4 and guaranteed to be zero.
|
||||
*/
|
||||
|
||||
static const uint64_t g_m7_tcm_fill aligned_data(8) = 0;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -169,15 +187,115 @@ static int prepare_m7_power(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt118x_initialize_m7_tcm_ecc
|
||||
*
|
||||
* Description:
|
||||
* Initialize the M7 ITCM and DTCM ECC using eDMA before starting the M7.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int imxrt118x_initialize_m7_tcm_ecc(void)
|
||||
{
|
||||
const uintptr_t starts[] =
|
||||
{
|
||||
(uintptr_t)_sitcm_m7,
|
||||
(uintptr_t)_sdtcm_m7
|
||||
};
|
||||
|
||||
const uintptr_t ends[] =
|
||||
{
|
||||
(uintptr_t)_eitcm_m7,
|
||||
(uintptr_t)_edtcm_m7
|
||||
};
|
||||
|
||||
uintptr_t tcd = IMXRT_EDMA_TCD(IMXRT_DMA4_BASE, 0);
|
||||
unsigned int i;
|
||||
|
||||
/* The bootloader only needs this focused eDMA4 write to initialize the
|
||||
* M7 TCM ECC; it does not need to initialize the full NuttX DMA subsystem.
|
||||
*/
|
||||
|
||||
/* Run eDMA4 from WAKEUP_AXI at SYS_PLL3_OUT / 2 (240 MHz). */
|
||||
|
||||
if (imxrt_ccm_configure_root_clock(CCM_CR_WAKEUP_AXI,
|
||||
SYS_PLL3_OUT, 2) < 0 ||
|
||||
imxrt_ccm_gate_on(CCM_LPCG_EDMA4, true) < 0)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(starts) / sizeof(starts[0]); i++)
|
||||
{
|
||||
/* Clear stale DONE and error status. Hardware requests and the error
|
||||
* interrupt stay disabled; the transfer is started by software and
|
||||
* completion is polled.
|
||||
*/
|
||||
|
||||
putreg32(EDMA_CH_CSR_DONE, tcd + IMXRT_EDMA_CH_CSR_OFFSET);
|
||||
putreg32(EDMA_CH_ES_ERR, tcd + IMXRT_EDMA_CH_ES_OFFSET);
|
||||
|
||||
/* Fill the whole region with 64-bit zero writes. */
|
||||
|
||||
putreg32((uintptr_t)&g_m7_tcm_fill,
|
||||
tcd + IMXRT_EDMA_TCD_SADDR_OFFSET);
|
||||
putreg32(starts[i], tcd + IMXRT_EDMA_TCD_DADDR_OFFSET);
|
||||
putreg32(ends[i] - starts[i], tcd + IMXRT_EDMA_TCD_NBYTES_OFFSET);
|
||||
putreg16(EDMA_TCD_ATTR_DSIZE(EDMA_64BIT) |
|
||||
EDMA_TCD_ATTR_SSIZE(EDMA_64BIT),
|
||||
tcd + IMXRT_EDMA_TCD_ATTR_OFFSET);
|
||||
|
||||
/* Keep re-reading the same zero source; step the destination by one
|
||||
* 64-bit write.
|
||||
*/
|
||||
|
||||
putreg16(0, tcd + IMXRT_EDMA_TCD_SOFF_OFFSET);
|
||||
putreg16(sizeof(g_m7_tcm_fill), tcd + IMXRT_EDMA_TCD_DOFF_OFFSET);
|
||||
|
||||
/* One major loop iteration; the whole region is in NBYTES. */
|
||||
|
||||
putreg16(1, tcd + IMXRT_EDMA_TCD_CITER_OFFSET);
|
||||
putreg16(1, tcd + IMXRT_EDMA_TCD_BITER_OFFSET);
|
||||
|
||||
/* No destination address adjustment or scatter/gather chain. */
|
||||
|
||||
putreg32(0, tcd + IMXRT_EDMA_TCD_DLAST_SGA_OFFSET);
|
||||
|
||||
/* Launch the transfer by software request. */
|
||||
|
||||
putreg16(EDMA_TCD_CSR_START | EDMA_TCD_CSR_DREQ,
|
||||
tcd + IMXRT_EDMA_TCD_CSR_OFFSET);
|
||||
|
||||
/* An error does not set DONE, so poll for both. */
|
||||
|
||||
while ((getreg32(tcd + IMXRT_EDMA_CH_CSR_OFFSET) &
|
||||
EDMA_CH_CSR_DONE) == 0)
|
||||
{
|
||||
if ((getreg32(tcd + IMXRT_EDMA_CH_ES_OFFSET) &
|
||||
EDMA_CH_ES_ERR) != 0)
|
||||
{
|
||||
/* Clear error and return */
|
||||
|
||||
putreg32(EDMA_CH_ES_ERR, tcd + IMXRT_EDMA_CH_ES_OFFSET);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
putreg32(EDMA_CH_CSR_DONE, tcd + IMXRT_EDMA_CH_CSR_OFFSET);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt118x_release_cm7
|
||||
* Name: imxrt118x_prepare_cm7
|
||||
****************************************************************************/
|
||||
|
||||
int imxrt118x_release_cm7(uintptr_t vtor)
|
||||
int imxrt118x_prepare_cm7(uintptr_t vtor)
|
||||
{
|
||||
uint32_t cfg;
|
||||
int ret;
|
||||
|
|
@ -206,7 +324,8 @@ int imxrt118x_release_cm7(uintptr_t vtor)
|
|||
/* Program the M7 initial VTOR and force its clocks on. */
|
||||
|
||||
cfg = getreg32(IMXRT_AON_M7_CFG);
|
||||
cfg = (cfg & ~AON_M7_CFG_INITVTOR_MASK) |
|
||||
cfg = (cfg & ~(AON_M7_CFG_TCM_SIZE_MASK |
|
||||
AON_M7_CFG_INITVTOR_MASK)) |
|
||||
AON_M7_CFG_INITVTOR(vtor >> AON_M7_CFG_INITVTOR_SHIFT) |
|
||||
AON_M7_CFG_HCLK_FORCE_ON |
|
||||
AON_M7_CFG_CORECLK_FORCE_ON;
|
||||
|
|
@ -224,6 +343,21 @@ int imxrt118x_release_cm7(uintptr_t vtor)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = imxrt118x_initialize_m7_tcm_ecc();
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt118x_start_cm7
|
||||
****************************************************************************/
|
||||
|
||||
int imxrt118x_start_cm7(void)
|
||||
{
|
||||
/* Kick the M7 by toggling its clock around WAIT deassertion.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
int imxrt118x_release_cm7(uintptr_t vtor);
|
||||
int imxrt118x_prepare_cm7(uintptr_t vtor);
|
||||
int imxrt118x_start_cm7(void);
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_IMXRT_IMXRT118X_START_CM7_H */
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ MEMORY
|
|||
flash (rx) : ORIGIN = 0x28000000, LENGTH = 512K /* FlexSPI XIP window reserved for the M33 image */
|
||||
systcm (rwx): ORIGIN = 0x20000000, LENGTH = 128K /* CM33 private System TCM */
|
||||
ocram2 (rw) : ORIGIN = 0x20500000, LENGTH = 16K /* OCRAM2 (DMA/TRDC accessible); USB DMA buffers only */
|
||||
itcm_m7 (rw): ORIGIN = 0x303c0000, LENGTH = 256K /* M7 ITCM alias, accessible to M33 eDMA */
|
||||
dtcm_m7 (rw): ORIGIN = 0x30400000, LENGTH = 256K /* M7 DTCM alias, accessible to M33 eDMA */
|
||||
}
|
||||
|
||||
OUTPUT_ARCH(arm)
|
||||
|
|
@ -180,6 +182,11 @@ SECTIONS
|
|||
_boot_loadaddr = ORIGIN(flash);
|
||||
_boot_size = LENGTH(flash);
|
||||
_ram_size = LENGTH(systcm);
|
||||
|
||||
_sitcm_m7 = ORIGIN(itcm_m7);
|
||||
_eitcm_m7 = ORIGIN(itcm_m7) + LENGTH(itcm_m7);
|
||||
_sdtcm_m7 = ORIGIN(dtcm_m7);
|
||||
_edtcm_m7 = ORIGIN(dtcm_m7) + LENGTH(dtcm_m7);
|
||||
}
|
||||
|
||||
/* The M7 image starts at 0x2808_0000. Fail the link rather than silently
|
||||
|
|
|
|||
|
|
@ -61,7 +61,12 @@ int bootloader_main(int argc, char *argv[])
|
|||
up_disable_irq(IMXRT_IRQ_LPUART1);
|
||||
irq_detach(IMXRT_IRQ_LPUART1);
|
||||
|
||||
if (imxrt118x_release_cm7(M7_ENTRY) < 0)
|
||||
if (imxrt118x_prepare_cm7(M7_ENTRY) < 0)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (imxrt118x_start_cm7() < 0)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue