diff --git a/arch/arm/src/imx6/chip/imx_memorymap.h b/arch/arm/src/imx6/chip/imx_memorymap.h index c91fb924e09..87625af7908 100644 --- a/arch/arm/src/imx6/chip/imx_memorymap.h +++ b/arch/arm/src/imx6/chip/imx_memorymap.h @@ -897,7 +897,7 @@ * 0x80000000-0xefffffff: Undefined (1.75 GB) * * That is the offset where the main L2 page tables will be positioned. This - * corresponds to page table offsets 0x000002000 up to 0x000003c00. That + * corresponds to page table offsets 0x00002000 up to 0x00003c00. That * is 1792 entries, each mapping 4KB of address for a total of 7MB of virtual * address space) * @@ -917,7 +917,21 @@ * the address space. */ +#define INTERCPU_L2_PAGES 1 /* Pages allowed for inter-processor communications */ + #ifndef CONFIG_ARCH_LOWVECTORS + /* Memory map + * VIRTUAL ADDRESS RANGE L1 PG TABLE L2 PG TABLE DESCRIPTION + * START END OFFSET SIZE + * ---------- ---------- ------------ ---------------------------- + * 0x80000000 0x803fffff 0x000002000 0x000000400 Vectors (1MiB) + * 0x80100000 0x806fffff 0x000002400 0x000001800 Paging (6MiB) + * + * If SMP is enabled, then INTERCPU_L2_PAGES pages are taken from the end + * of the Paging L2 page table to hold non-cacheable, inter-processor + * communication data. + */ + /* Vector L2 page table offset/size */ # define VECTOR_L2_OFFSET 0x000002000 @@ -933,16 +947,44 @@ # define VECTOR_L2_END_PADDR (VECTOR_L2_PBASE + VECTOR_L2_SIZE) # define VECTOR_L2_END_VADDR (VECTOR_L2_VBASE + VECTOR_L2_SIZE) - /* Paging L2 page table offset/size */ +# ifdef CONFIG_SMP + /* Paging L2 page table offset/size */ -# define PGTABLE_L2_OFFSET 0x000002400 -# define PGTABLE_L2_SIZE 0x000001800 +# define PGTABLE_L2_OFFSET 0x000002400 +# define PGTABLE_L2_SIZE (0x000001800 - 4*INTERCPU_L2_PAGES) + +# else + /* Paging L2 page table offset/size */ + +# define PGTABLE_L2_OFFSET 0x000002400 +# define PGTABLE_L2_SIZE 0x000001800 +# endif #else - /* Paging L2 page table offset/size */ + /* Memory map + * VIRTUAL ADDRESS RANGE L1 PG TABLE L2 PG TABLE DESCRIPTION + * START END OFFSET SIZE + * ---------- ---------- ------------ ---------------------------- + * 0x80000000 0x806fffff 0x000002000 0x000001c00 Paging (7MiB) + * + * If SMP is enabled, then INTERCPU_L2_PAGES pages are taken from the end + * of the Paging L2 page table to hold non-cacheable, inter-processor + * communication data. + */ + +# ifdef CONFIG_SMP + /* Paging L2 page table offset/size */ + +# define PGTABLE_L2_OFFSET 0x000002000 +# define PGTABLE_L2_SIZE (0x000001c00 - 4*INTERCPU_L2_PAGES) + +# else + /* Paging L2 page table offset/size */ + +# define PGTABLE_L2_OFFSET 0x000002000 +# define PGTABLE_L2_SIZE 0x000001c00 +# endif -# define PGTABLE_L2_OFFSET 0x000002000 -# define PGTABLE_L2_SIZE 0x000001c00 #endif /* Paging L2 page table base addresses @@ -959,6 +1001,17 @@ #define PGTABLE_L2_END_PADDR (PGTABLE_L2_PBASE + PGTABLE_L2_SIZE) #define PGTABLE_L2_END_VADDR (PGTABLE_L2_VBASE + PGTABLE_L2_SIZE) +#ifdef CONFIG_SMP +/* Non-cached inter-processor communication data */ + +# define INTERCPU_L2_OFFSET (PGTABLE_L2_OFFSET + PGTABLE_L2_SIZE) +# define INTERCPU_L2_SIZE (4*INTERCPU_L2_PAGES) + +/* Inter-processor communications L2 page table virtual base addresse */ + +# define INTERCPU_L2_VBASE (PGTABLE_BASE_VADDR + INTERCPU_L2_OFFSET) +#endif + /* Base address of the interrupt vector table. * * IMX_VECTOR_PADDR - Unmapped, physical address of vector table in SRAM @@ -974,19 +1027,35 @@ */ #ifdef CONFIG_ARCH_LOWVECTORS /* Vectors located at 0x0000:0000 */ - - /* Vectors will always lie at the beginnin of OCRAM */ +/* Vectors will always lie at the beginning of OCRAM */ # define IMX_VECTOR_PADDR IMX_OCRAM_PBASE # define IMX_VECTOR_VSRAM IMX_OCRAM_VBASE # define IMX_VECTOR_VADDR 0x00000000 +#ifdef CONFIG_SMP +/* Inter-processor communications */ + +# define INTERCPU_PADDR (IMX_VECTOR_PADDR + VECTOR_TABLE_SIZE) +# define INTERCPU_VADDR (INTERCPU_L2_VBASE << 18) +# define INTERCPU_SIZE (INTERCPU_L2_PAGES << 12) +# define INTERCPU_VSRAM (IMX_VECTOR_VSRAM + VECTOR_TABLE_SIZE) +#endif + #else /* Vectors located at 0xffff:0000 -- this probably does not work */ # define IMX_VECTOR_PADDR (IMX_OCRAM_PBASE + IMX_OCRAM_SIZE - VECTOR_TABLE_SIZE) # define IMX_VECTOR_VSRAM (IMX_OCRAM_VBASE + IMX_OCRAM_SIZE - VECTOR_TABLE_SIZE) # define IMX_VECTOR_VADDR 0xffff0000 +#ifdef CONFIG_SMP +/* Inter-processor communications */ + +# define INTERCPU_PADDR (IMX_VECTOR_PADDR - INTERCPU_L2_SIZE) +# define INTERCPU_VADDR (INTERCPU_L2_VBASE << 18) +# define INTERCPU_SIZE (INTERCPU_L2_PAGES << 12) +# define INTERCPU_VSRAM (IMX_VECTOR_VSRAM - INTERCPU_L2_SIZE) +#endif #endif /************************************************************************************ diff --git a/arch/arm/src/imx6/imx_boot.c b/arch/arm/src/imx6/imx_boot.c index edfd5304a14..b4c36b9540e 100644 --- a/arch/arm/src/imx6/imx_boot.c +++ b/arch/arm/src/imx6/imx_boot.c @@ -224,6 +224,46 @@ static void imx_vectormapping(void) # define imx_vectormapping() #endif +/**************************************************************************** + * Name: imx_intercpu_mapping + * + * Description: + * Setup a special mapping for the non-cached, inter-cpu communications + * area. + * + ****************************************************************************/ + +#ifndef CONFIG_SMP +static void imx_intercpu_mapping(void) +{ + uint32_t intercpu_paddr = INTERCPU_PADDR & PTE_SMALL_PADDR_MASK; + uint32_t intercpu_vaddr = INTERCPU_VADDR & PTE_SMALL_PADDR_MASK; + uint32_t end_paddr = INTERCPU_PADDR + INTERCPU_SIZE; + + /* We want to keep the inter-cpu region in on-chip RAM (OCRAM). The + * i.MX6 has 256Kb of OCRAM positioned at physical address 0x0090:0000. + */ + + while (intercpu_paddr < end_paddr) + { + mmu_l2_setentry(INTERCPU_L2_VBASE, intercpu_paddr, intercpu_vaddr, + MMU_L2_INTERCPUFLAGS); + intercpu_paddr += 4096; + intercpu_vaddr += 4096; + } + + /* Now set the level 1 descriptor to refer to the level 2 page table. */ + + mmu_l1_setentry(VECTOR_L2_PBASE & PMD_PTE_PADDR_MASK, + INTERCPU_VADDR & PMD_PTE_PADDR_MASK, + MMU_L1_PGTABFLAGS); +} +#else + /* No inter-cpu communications area */ + +# define imx_intercpu_mapping() +#endif + /**************************************************************************** * Name: imx_copyvectorblock * @@ -414,6 +454,15 @@ void arm_boot(void) imx_vectormapping(); imx_lowputc('B'); +#ifdef CONFIG_SMP + /* Provide a special mapping for the OCRAM interrupt vector positioned in + * high memory. + */ + + imx_intercpu_mapping(); + imx_lowputc('C'); +#endif + #ifdef CONFIG_ARCH_RAMFUNCS /* Copy any necessary code sections from FLASH to RAM. The correct * destination in OCRAM is given by _sramfuncs and _eramfuncs. The @@ -426,14 +475,14 @@ void arm_boot(void) *dest++ = *src++; } - imx_lowputc('C'); + imx_lowputc('D'); /* Flush the copied RAM functions into physical RAM so that will * be available when fetched into the I-Cache. */ arch_clean_dcache((uintptr_t)&_sramfuncs, (uintptr_t)&_eramfuncs) - imx_lowputc('D'); + imx_lowputc('E'); #endif /* Setup up vector block. _vector_start and _vector_end are exported from @@ -441,23 +490,23 @@ void arm_boot(void) */ imx_copyvectorblock(); - imx_lowputc('E'); + imx_lowputc('F'); /* Disable the watchdog timer */ imx_wdtdisable(); - imx_lowputc('F'); + imx_lowputc('G'); /* Initialize clocking to settings provided by board-specific logic */ imx_clockconfig(); - imx_lowputc('G'); + imx_lowputc('H'); #ifdef CONFIG_ARCH_FPU /* Initialize the FPU */ arm_fpuconfig(); - imx_lowputc('H'); + imx_lowputc('I'); #endif /* Perform board-specific initialization, This must include: @@ -471,7 +520,7 @@ void arm_boot(void) */ imx_board_initialize(); - imx_lowputc('I'); + imx_lowputc('J'); #ifdef NEED_SDRAM_REMAPPING /* SDRAM was configured in a temporary state to support low-level @@ -480,7 +529,7 @@ void arm_boot(void) */ imx_remap(); - imx_lowputc('J'); + imx_lowputc('K'); #endif #ifdef CONFIG_BOOT_SDRAM_DATA @@ -489,13 +538,13 @@ void arm_boot(void) */ arm_data_initialize(); - imx_lowputc('K'); + imx_lowputc('L'); #endif /* Perform common, low-level chip initialization (might do nothing) */ imx_lowsetup(); - imx_lowputc('L'); + imx_lowputc('M'); #ifdef USE_EARLYSERIALINIT /* Perform early serial initialization if we are going to use the serial @@ -503,7 +552,7 @@ void arm_boot(void) */ imx_earlyserialinit(); - imx_lowputc('M'); + imx_lowputc('N'); #endif /* Now we can enable all other CPUs. The enabled CPUs will start execution @@ -512,6 +561,6 @@ void arm_boot(void) */ imx_cpu_enable(); - imx_lowputc('N'); + imx_lowputc('O'); imx_lowputc('\n'); }