From bd39add8fafc01d9a469beba89a97557a2fd1125 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 31 May 2013 10:08:43 +0200 Subject: bsp/qoriq: Add SMP support --- c/src/lib/libbsp/powerpc/qoriq/Makefile.am | 4 + c/src/lib/libbsp/powerpc/qoriq/configure.ac | 3 + c/src/lib/libbsp/powerpc/qoriq/include/bsp.h | 6 +- c/src/lib/libbsp/powerpc/qoriq/start/start.S | 54 ++++++- .../lib/libbsp/powerpc/qoriq/startup/mmu-config.c | 14 +- c/src/lib/libbsp/powerpc/qoriq/startup/smp.c | 179 +++++++++++++++++++++ 6 files changed, 252 insertions(+), 8 deletions(-) create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/smp.c (limited to 'c') diff --git a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am index 54fc5477ed..4a541af910 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am +++ b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am @@ -125,5 +125,9 @@ libbsp_a_SOURCES += network/network.c \ libbsp_a_LIBADD += ../../../libcpu/@RTEMS_CPU@/tsec.rel endif +if HAS_SMP +libbsp_a_SOURCES += startup/smp.c +endif + include $(srcdir)/preinstall.am include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/qoriq/configure.ac b/c/src/lib/libbsp/powerpc/qoriq/configure.ac index 0fbc13488f..3e690720a6 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/configure.ac +++ b/c/src/lib/libbsp/powerpc/qoriq/configure.ac @@ -97,6 +97,9 @@ RTEMS_BSPOPTS_HELP([QORIQ_CLOCK_TIMER],[global timer used for system clock, 0..3 RTEMS_CHECK_NETWORKING AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes") +RTEMS_CHECK_SMP +AM_CONDITIONAL(HAS_SMP,[test "$rtems_cv_HAS_SMP" = "yes"]) + RTEMS_BSP_CLEANUP_OPTIONS(0, 0) RTEMS_PPC_EXCEPTIONS RTEMS_BSP_LINKCMDS diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/bsp.h b/c/src/lib/libbsp/powerpc/qoriq/include/bsp.h index 70dc7477d4..44d6cc3ec5 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/include/bsp.h +++ b/c/src/lib/libbsp/powerpc/qoriq/include/bsp.h @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * Copyright (c) 2010-2013 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * @@ -59,6 +59,8 @@ int qoriq_if_intercom_attach_detach( #define RTEMS_BSP_NETWORK_DRIVER_NAME3 "tsec3" #define RTEMS_BSP_NETWORK_DRIVER_NAME4 "intercom1" +void qoriq_secondary_cpu_initialize(void); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/start/start.S b/c/src/lib/libbsp/powerpc/qoriq/start/start.S index c4debf55c7..7d74bd1424 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/start/start.S +++ b/c/src/lib/libbsp/powerpc/qoriq/start/start.S @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2010-2012 embedded brains GmbH. All rights reserved. + * Copyright (c) 2010-2013 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * @@ -32,6 +32,7 @@ #define UBOOT_BOARD_INFO r15 .globl _start + .globl _start_core_1 .globl bsp_exc_vector_base .section ".bsp_start_text", "ax" @@ -169,6 +170,55 @@ copy: beqlr b memcpy +_start_core_1: + + /* Reset time base */ + li r0, 0 + mtspr TBWU, r0 + mtspr TBWL, r0 + + /* Get start stack */ + subi r1, r3, 16 + + /* Initial MMU setup */ + bl qoriq_tlb1_ts_0_only + li r3, SCRATCH_TLB + li r4, FSL_EIS_MAS1_TS + li r5, FSL_EIS_MAS2_I + li r6, FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW | FSL_EIS_MAS3_SX + li r7, 0 + li r8, 11 + bl qoriq_tlb1_write + + /* MSR initialization */ + LWI INITIAL_MSR, QORIQ_INITIAL_MSR + ori r0, INITIAL_MSR, MSR_IS | MSR_DS + mtmsr r0 + + /* SPEFSCR initialization */ + LWI r0, QORIQ_INITIAL_SPEFSCR + mtspr FSL_EIS_SPEFSCR, r0 + + /* Initialize start stack */ + li r0, 0 + stw r0, 0(r1) + + /* Configure MMU */ + li r3, FIRST_TLB + li r4, SCRATCH_TLB + bl qoriq_mmu_config + mtmsr INITIAL_MSR + li r3, SCRATCH_TLB + bl qoriq_tlb1_invalidate + + /* Set small-data anchors */ + LA r2, _SDA2_BASE_ + LA r13, _SDA_BASE_ + + b qoriq_secondary_cpu_initialize + + b twiddle + /* Exception vector prologues area */ .section ".bsp_start_text", "ax" .align 4 diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c index 3bcf17a7ba..01055da6f3 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c @@ -7,10 +7,10 @@ */ /* - * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * Copyright (c) 2011-2013 embedded brains GmbH. All rights reserved. * * embedded brains GmbH - * Obere Lagerstr. 30 + * Dornierstr. 4 * 82178 Puchheim * Germany * @@ -20,7 +20,7 @@ * http://www.rtems.com/license/LICENSE. */ -#include +#include #include #include #include @@ -49,10 +49,16 @@ typedef struct { .mas3 = FSL_EIS_MAS3_SR \ } +#ifdef RTEMS_SMP + #define ENTRY_RW_MAS2 FSL_EIS_MAS2_M +#else + #define ENTRY_RW_MAS2 0 +#endif + #define ENTRY_RW(b, s) { \ .begin = (uint32_t) b, \ .size = (uint32_t) s, \ - .mas2 = 0, \ + .mas2 = ENTRY_RW_MAS2, \ .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \ } diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c b/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c new file mode 100644 index 0000000000..24d6a9b8f7 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +LINKER_SYMBOL(bsp_exc_vector_base); + +void _start_core_1(void); + +#define CORE_COUNT 2 + +#define ONE_CORE(core) (1 << (core)) + +#define ALL_CORES ((1 << CORE_COUNT) - 1) + +#define IPI_INDEX 0 + +#define TLB_BEGIN 8 + +#define TLB_END 16 + +#define TLB_COUNT (TLB_END - TLB_BEGIN) + +int bsp_smp_processor_id(void) +{ + return (int) ppc_processor_id(); +} + +/* + * These values can be obtained with the debugger or a look into the + * U-Boot sources (arch/powerpc/cpu/mpc85xx/release.S). + */ +#if 1 + #define BOOT_BEGIN 0x1fff0000 + #define BOOT_LAST 0x1fffffff + #define SPIN_TABLE (BOOT_BEGIN + 0xf2a0) +#else + #define BOOT_BEGIN 0x3fff0000 + #define BOOT_LAST 0x3fffffff + #define SPIN_TABLE (BOOT_BEGIN + 0xf240) +#endif + +#define TLB_BEGIN 8 + +#define TLB_END 16 + +#define TLB_COUNT (TLB_END - TLB_BEGIN) + +typedef struct { + uint32_t addr_upper; + uint32_t addr_lower; + uint32_t r3_upper; + uint32_t r3_lower; + uint32_t reserved; + uint32_t pir; + uint32_t r6_upper; + uint32_t r6_lower; +} uboot_spin_table; + +static uint32_t initial_core_1_stack[4096 / sizeof(uint32_t)]; + +static void mmu_config_undo(void) +{ + int i = 0; + + for (i = TLB_BEGIN; i < TLB_END; ++i) { + qoriq_tlb1_invalidate(i); + } +} + +static void release_core_1(void) +{ + uboot_spin_table *spin_table = (uboot_spin_table *) SPIN_TABLE; + qoriq_mmu_context mmu_context; + + qoriq_mmu_context_init(&mmu_context); + qoriq_mmu_add(&mmu_context, BOOT_BEGIN, BOOT_LAST, 0, 0, FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW); + qoriq_mmu_partition(&mmu_context, TLB_COUNT); + qoriq_mmu_write_to_tlb1(&mmu_context, TLB_BEGIN); + + spin_table->pir = 1; + spin_table->r3_lower = (uint32_t) _Per_CPU_Information[1].interrupt_stack_high; + spin_table->addr_upper = 0; + rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table)); + ppc_synchronize_data(); + spin_table->addr_lower = (uint32_t) _start_core_1; + rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table)); + + mmu_config_undo(); +} + +void qoriq_secondary_cpu_initialize(void) +{ + /* Disable decrementer */ + PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS(BOOKE_TCR, BOOKE_TCR_DIE); + + /* Initialize exception handler */ + ppc_exc_vector_base = (uint32_t) bsp_exc_vector_base; + ppc_exc_initialize( + PPC_INTERRUPT_DISABLE_MASK_DEFAULT, + (uintptr_t) _Per_CPU_Information[1].interrupt_stack_low, + rtems_configuration_get_interrupt_stack_size() + ); + + /* Now it is possible to make the code execute only */ + qoriq_mmu_change_perm( + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SX, + FSL_EIS_MAS3_SX, + FSL_EIS_MAS3_SR + ); + + /* Initialize interrupt support */ + bsp_interrupt_facility_initialize(); + + bsp_interrupt_vector_enable(QORIQ_IRQ_IPI_0); + + rtems_smp_secondary_cpu_initialize(); +} + +static void ipi_handler(void *arg) +{ + rtems_smp_process_interrupt(); +} + +uint32_t bsp_smp_initialize(uint32_t configured_cpu_count) +{ + rtems_status_code sc; + uint32_t cores = configured_cpu_count < CORE_COUNT ? + configured_cpu_count : CORE_COUNT; + + sc = rtems_interrupt_handler_install( + QORIQ_IRQ_IPI_0, + "IPI", + RTEMS_INTERRUPT_UNIQUE, + ipi_handler, + NULL + ); + assert(sc == RTEMS_SUCCESSFUL); + + if (cores > 1) { + release_core_1(); + } + + return cores; +} + +void bsp_smp_broadcast_interrupt(void) +{ + uint32_t self = ppc_processor_id(); + qoriq.pic.per_cpu [self].ipidr [IPI_INDEX].reg = ALL_CORES; +} + +void bsp_smp_interrupt_cpu(int core) +{ + uint32_t self = ppc_processor_id(); + qoriq.pic.per_cpu [self].ipidr [IPI_INDEX].reg = ONE_CORE(core); +} -- cgit v1.2.3