aboutsummaryrefslogtreecommitdiffstats
path: root/src/atsam/same70_sysinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/atsam/same70_sysinit.c')
-rw-r--r--src/atsam/same70_sysinit.c87
1 files changed, 82 insertions, 5 deletions
diff --git a/src/atsam/same70_sysinit.c b/src/atsam/same70_sysinit.c
index 4cb5f48c..d2b6ecb4 100644
--- a/src/atsam/same70_sysinit.c
+++ b/src/atsam/same70_sysinit.c
@@ -1,5 +1,6 @@
// This code is from lib/sam4e/gcc/system_sam4e.c and modified for the SAM E70
+#include <string.h> // memset
#include "internal.h"
/* Clock Settings (300MHz) */
@@ -9,13 +10,17 @@
| CKGR_PLLAR_PLLACOUNT(0x3fU) \
| CKGR_PLLAR_DIVA_BYPASS)
#define SYS_BOARD_MCKR (PMC_MCKR_MDIV_PCK_DIV2 | PMC_MCKR_CSS_PLLA_CLK)
+#define RST_PARAMS ((0xA5 << RSTC_CR_KEY_Pos) | RSTC_CR_PROCRST)
+#define GPNVM_TCM_MASK ((1 << 7) | (1 << 8))
/* Key to unlock MOR register */
#define SYS_CKGR_MOR_KEY_VALUE CKGR_MOR_KEY(0x37)
-uint32_t SystemCoreClock = CHIP_FREQ_MAINCK_RC_12MHZ;
+extern uint32_t _text_size;
+extern uint32_t _dtcm_bss_start, _dtcm_bss_end;
-void SystemInit( void )
+void
+SystemInit( void )
{
/* Set FWS according to SYS_BOARD_MCKR configuration */
EFC->EEFC_FMR = EEFC_FMR_FWS(6) | EEFC_FMR_CLOE;
@@ -66,12 +71,84 @@ void SystemInit( void )
{
}
- SystemCoreClock = CHIP_FREQ_CPU_MAX;
-
- // Configure PCK6 for TC use
+ /* Configure PCK6 for TC use */
PMC->PMC_PCK[6] = PMC_PCK_CSS_MCK | PMC_PCK_PRES(2);
while ( !(PMC->PMC_SR & PMC_SR_PCKRDY6) )
{
}
PMC->PMC_SCER |= PMC_SCER_PCK6;
+
+ /* Check Tightly Coupled Memory (TCM) bits. */
+ EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_GGPB);
+ while ((EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
+ ;
+ if ((EFC->EEFC_FRR & GPNVM_TCM_MASK) != GPNVM_TCM_MASK)
+ {
+ /* Configure TCM sizes to 128KiB (set GPNVM7 and GPNVM8). */
+ EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SGPB
+ | EEFC_FCR_FARG(7));
+ while ((EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
+ ;
+ EFC->EEFC_FCR = (EEFC_FCR_FKEY_PASSWD| EEFC_FCR_FCMD_SGPB
+ | EEFC_FCR_FARG(8));
+ while ((EFC->EEFC_FSR & EEFC_FSR_FRDY) == 0)
+ ;
+ /* Reboot required, but bits are set now and we will not
+ * return down this path. */
+ __DSB();
+ __ISB();
+ RSTC->RSTC_CR = RST_PARAMS;
+ for (;;)
+ ;
+ }
+
+ /* Clear Data Tightly Coupled Memory (DTCM) bss segment - this has to happen
+ * after we check that the DTCM is enabled. */
+ memset(&_dtcm_bss_start, 0, (&_dtcm_bss_end - &_dtcm_bss_start) * 4);
+
+ /* DMA copy flash to Instruction Tightly Coupled Memory (ITCM). Just use
+ * channel 0 since we have not done anything yet. */
+ enable_pclock(ID_XDMAC);
+ /* Clear pending interrupts. */
+ (void)REG_XDMAC_CIS0;
+ REG_XDMAC_CSA0 = CONFIG_ARMCM_ITCM_FLASH_MIRROR_START;
+ REG_XDMAC_CDA0 = CONFIG_FLASH_APPLICATION_ADDRESS;
+ REG_XDMAC_CUBC0 = XDMAC_CUBC_UBLEN((int)&_text_size);
+
+ REG_XDMAC_CC0 =
+ XDMAC_CC_TYPE_MEM_TRAN | XDMAC_CC_MBSIZE_SINGLE |
+ XDMAC_CC_CSIZE_CHK_1 | XDMAC_CC_DWIDTH_WORD |
+ XDMAC_CC_SAM_INCREMENTED_AM | XDMAC_CC_DAM_INCREMENTED_AM |
+ XDMAC_CC_SIF_AHB_IF1 | XDMAC_CC_DIF_AHB_IF0;
+
+ REG_XDMAC_CNDA0 = 0;
+ REG_XDMAC_CNDC0 = 0;
+ REG_XDMAC_CBC0 = 0;
+ REG_XDMAC_CDS_MSP0 = 0;
+ REG_XDMAC_CSUS0 = 0;
+ REG_XDMAC_CDUS0 = 0;
+
+ REG_XDMAC_CIE0 = XDMAC_CIE_BIE;
+
+ __DSB();
+ __ISB();
+ XDMAC->XDMAC_GE = XDMAC_GE_EN0;
+ while ( XDMAC->XDMAC_GS & XDMAC_GS_ST0 )
+ ;
+
+ while ( !(REG_XDMAC_CIS0 & XDMAC_CIS_BIS) )
+ ;
+
+ /* Enable ITCM. DTCM is enabled by default. */
+ __DSB();
+ __ISB();
+ SCB->ITCMCR = (SCB_ITCMCR_EN_Msk | SCB_ITCMCR_RMW_Msk
+ | SCB_ITCMCR_RETEN_Msk);
+ __DSB();
+ __ISB();
+
+ /* Use data cache rather than DTCM for two reasons:
+ * 1. It is hard to flash this device with GPNVM bits enabled.
+ * 2. It is about as fast. */
+ SCB_EnableDCache();
}