diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-05-31 13:59:47 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-05-31 15:20:33 +0200 |
commit | db42c079a0479c17add94e5fb5fb89db1dfa6799 (patch) | |
tree | 723eb41d04eddb021be998d57e8863806cc0d0a6 /c/src/lib/libbsp/arm/shared | |
parent | smp: Add ARM support (diff) | |
download | rtems-db42c079a0479c17add94e5fb5fb89db1dfa6799.tar.bz2 |
bsps/arm: Add SMP support
Diffstat (limited to 'c/src/lib/libbsp/arm/shared')
-rw-r--r-- | c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c | 71 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/shared/arm-gic-irq.c | 61 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h | 16 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h | 88 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/shared/include/arm-cp15-start.h | 6 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/shared/include/arm-gic-irq.h | 33 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/shared/start/start.S | 33 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/shared/startup/linkcmds.base | 8 |
8 files changed, 279 insertions, 37 deletions
diff --git a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c new file mode 100644 index 0000000000..b94bcec81c --- /dev/null +++ b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * 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 <assert.h> + +#include <rtems/bspsmp.h> + +#include <libcpu/arm-cp15.h> + +#include <bsp/irq.h> + +int bsp_smp_processor_id(void) +{ + return (int) arm_cortex_a9_get_multiprocessor_cpu_id(); +} + +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 max_cpu_count = arm_gic_irq_processor_count(); + uint32_t used_cpu_count = configured_cpu_count < max_cpu_count ? + configured_cpu_count : max_cpu_count; + + sc = rtems_interrupt_handler_install( + ARM_GIC_IRQ_SGI_0, + "IPI", + RTEMS_INTERRUPT_UNIQUE, + ipi_handler, + NULL + ); + assert(sc == RTEMS_SUCCESSFUL); + + return used_cpu_count; +} + +void bsp_smp_broadcast_interrupt(void) +{ + /* + * FIXME: This broadcasts the interrupt also to processors not used by RTEMS. + */ + rtems_status_code sc = arm_gic_irq_generate_software_irq( + ARM_GIC_IRQ_SGI_0, + ARM_GIC_IRQ_SOFTWARE_IRQ_TO_ALL_EXCEPT_SELF, + 0xff + ); +} + +void bsp_smp_interrupt_cpu(int cpu) +{ + rtems_status_code sc = arm_gic_irq_generate_software_irq( + ARM_GIC_IRQ_SGI_0, + ARM_GIC_IRQ_SOFTWARE_IRQ_TO_ALL_IN_LIST, + (uint8_t) (1U << cpu) + ); +} diff --git a/c/src/lib/libbsp/arm/shared/arm-gic-irq.c b/c/src/lib/libbsp/arm/shared/arm-gic-irq.c index 84d66aa0fb..ed2d389589 100644 --- a/c/src/lib/libbsp/arm/shared/arm-gic-irq.c +++ b/c/src/lib/libbsp/arm/shared/arm-gic-irq.c @@ -18,14 +18,12 @@ #include <libcpu/arm-cp15.h> -#include <bsp.h> #include <bsp/irq.h> #include <bsp/irq-generic.h> +#include <bsp/start.h> #define GIC_CPUIF ((volatile gic_cpuif *) BSP_ARM_GIC_CPUIF_BASE) -#define GIC_DIST ((volatile gic_dist *) BSP_ARM_GIC_DIST_BASE) - #define PRIORITY_DEFAULT 128 void bsp_interrupt_dispatch(void) @@ -51,7 +49,7 @@ rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector) rtems_status_code sc = RTEMS_SUCCESSFUL; if (bsp_interrupt_is_valid_vector(vector)) { - volatile gic_dist *dist = GIC_DIST; + volatile gic_dist *dist = ARM_GIC_DIST; gic_id_enable(dist, vector); } else { @@ -66,7 +64,7 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector) rtems_status_code sc = RTEMS_SUCCESSFUL; if (bsp_interrupt_is_valid_vector(vector)) { - volatile gic_dist *dist = GIC_DIST; + volatile gic_dist *dist = ARM_GIC_DIST; gic_id_disable(dist, vector); } else { @@ -89,10 +87,15 @@ static inline uint32_t get_id_count(volatile gic_dist *dist) rtems_status_code bsp_interrupt_facility_initialize(void) { volatile gic_cpuif *cpuif = GIC_CPUIF; - volatile gic_dist *dist = GIC_DIST; + volatile gic_dist *dist = ARM_GIC_DIST; uint32_t id_count = get_id_count(dist); uint32_t id; + arm_cp15_set_exception_handler( + ARM_EXCEPTION_IRQ, + _ARMV4_Exception_interrupt + ); + for (id = 0; id < id_count; ++id) { gic_id_set_priority(dist, id, PRIORITY_DEFAULT); } @@ -107,14 +110,25 @@ rtems_status_code bsp_interrupt_facility_initialize(void) dist->icddcr = GIC_DIST_ICDDCR_ENABLE; - arm_cp15_set_exception_handler( - ARM_EXCEPTION_IRQ, - _ARMV4_Exception_interrupt - ); - return RTEMS_SUCCESSFUL; } +#ifdef RTEMS_SMP +BSP_START_TEXT_SECTION void arm_gic_irq_initialize_secondary_cpu(void) +{ + volatile gic_cpuif *cpuif = GIC_CPUIF; + volatile gic_dist *dist = ARM_GIC_DIST; + + while ((dist->icddcr & GIC_DIST_ICDDCR_ENABLE) == 0) { + /* Wait */ + } + + cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff); + cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0); + cpuif->iccicr = GIC_CPUIF_ICCICR_ENABLE; +} +#endif + rtems_status_code arm_gic_irq_set_priority( rtems_vector_number vector, uint8_t priority @@ -123,7 +137,7 @@ rtems_status_code arm_gic_irq_set_priority( rtems_status_code sc = RTEMS_SUCCESSFUL; if (bsp_interrupt_is_valid_vector(vector)) { - volatile gic_dist *dist = GIC_DIST; + volatile gic_dist *dist = ARM_GIC_DIST; gic_id_set_priority(dist, vector, priority); } else { @@ -141,7 +155,7 @@ rtems_status_code arm_gic_irq_get_priority( rtems_status_code sc = RTEMS_SUCCESSFUL; if (bsp_interrupt_is_valid_vector(vector)) { - volatile gic_dist *dist = GIC_DIST; + volatile gic_dist *dist = ARM_GIC_DIST; *priority = gic_id_get_priority(dist, vector); } else { @@ -150,24 +164,3 @@ rtems_status_code arm_gic_irq_get_priority( return sc; } - -rtems_status_code arm_gic_irq_generate_software_irq( - rtems_vector_number vector, - arm_gic_irq_software_irq_target_filter filter, - uint8_t targets -) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - - if (vector < 16) { - volatile gic_dist *dist = GIC_DIST; - - dist->icdsgir = GIC_DIST_ICDSGIR_TARGET_LIST_FILTER(filter) - | GIC_DIST_ICDSGIR_CPU_TARGET_LIST(targets) - | GIC_DIST_ICDSGIR_SGIINTID(vector); - } else { - sc = RTEMS_INVALID_ID; - } - - return sc; -} diff --git a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h index 7d8f637bad..dc7fd758ed 100644 --- a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h +++ b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-regs.h @@ -19,7 +19,23 @@ typedef struct { uint32_t ctrl; +#define A9MPCORE_SCU_CTRL_SCU_EN BSP_BIT32(0) +#define A9MPCORE_SCU_CTRL_ADDR_FLT_EN BSP_BIT32(1) +#define A9MPCORE_SCU_CTRL_RAM_PAR_EN BSP_BIT32(2) +#define A9MPCORE_SCU_CTRL_SCU_SPEC_LINE_FILL_EN BSP_BIT32(3) +#define A9MPCORE_SCU_CTRL_FORCE_PORT_0_EN BSP_BIT32(4) +#define A9MPCORE_SCU_CTRL_SCU_STANDBY_EN BSP_BIT32(5) +#define A9MPCORE_SCU_CTRL_IC_STANDBY_EN BSP_BIT32(6) uint32_t cfg; +#define A9MPCORE_SCU_CFG_CPU_COUNT(val) BSP_FLD32(val, 0, 1) +#define A9MPCORE_SCU_CFG_CPU_COUNT_GET(reg) BSP_FLD32GET(reg, 0, 1) +#define A9MPCORE_SCU_CFG_CPU_COUNT_SET(reg, val) BSP_FLD32SET(reg, val, 0, 1) +#define A9MPCORE_SCU_CFG_SMP_MODE(val) BSP_FLD32(val, 4, 7) +#define A9MPCORE_SCU_CFG_SMP_MODE_GET(reg) BSP_FLD32GET(reg, 4, 7) +#define A9MPCORE_SCU_CFG_SMP_MODE_SET(reg, val) BSP_FLD32SET(reg, val, 4, 7) +#define A9MPCORE_SCU_CFG_TAG_RAM_SIZE(val) BSP_FLD32(val, 8, 15) +#define A9MPCORE_SCU_CFG_TAG_RAM_SIZE_GET(reg) BSP_FLD32GET(reg, 8, 15) +#define A9MPCORE_SCU_CFG_TAG_RAM_SIZE_SET(reg, val) BSP_FLD32SET(reg, val, 8, 15) uint32_t pwrst; uint32_t invss; uint32_t reserved_10[12]; diff --git a/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h new file mode 100644 index 0000000000..b42c549c91 --- /dev/null +++ b/c/src/lib/libbsp/arm/shared/include/arm-a9mpcore-start.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * 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. + */ + +#ifndef LIBBSP_ARM_SHARED_ARM_A9MPCORE_START_H +#define LIBBSP_ARM_SHARED_ARM_A9MPCORE_START_H + +#include <rtems/bspsmp.h> + +#include <libcpu/arm-cp15.h> + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/arm-a9mpcore-regs.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +BSP_START_TEXT_SECTION static inline uint32_t +arm_cp15_get_auxiliary_control(void); + +BSP_START_TEXT_SECTION static inline void +arm_cp15_set_auxiliary_control(uint32_t val); + +BSP_START_TEXT_SECTION static inline arm_a9mpcore_start_hook_0(void) +{ +#ifdef RTEMS_SMP + volatile a9mpcore_scu *scu = (volatile a9mpcore_scu *) BSP_ARM_A9MPCORE_SCU_BASE; + uint32_t cpu_id; + uint32_t actlr; + + /* Enable Snoop Control Unit (SCU) */ + scu->ctrl |= A9MPCORE_SCU_CTRL_SCU_EN; + + /* Enable cache coherency support for this processor */ + actlr = arm_cp15_get_auxiliary_control(); + actlr |= ARM_CORTEX_A9_ACTL_SMP; + arm_cp15_set_auxiliary_control(actlr); + + cpu_id = arm_cortex_a9_get_multiprocessor_cpu_id(); + if (cpu_id != 0) { + if (cpu_id < rtems_configuration_get_maximum_processors()) { + uint32_t ctrl; + + arm_gic_irq_initialize_secondary_cpu(); + + ctrl = arm_cp15_start_setup_mmu_and_cache( + 0, + ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_Z + ); + + arm_cp15_set_domain_access_control( + ARM_CP15_DAC_DOMAIN(ARM_MMU_DEFAULT_CLIENT_DOMAIN, ARM_CP15_DAC_CLIENT) + ); + + /* FIXME: Sharing the translation table between processors is brittle */ + arm_cp15_set_translation_table_base((uint32_t *) bsp_translation_table_base); + + ctrl |= ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_M; + arm_cp15_set_control(ctrl); + + rtems_smp_secondary_cpu_initialize(); + } else { + /* FIXME: Shutdown processor */ + while (1) { + __asm__ volatile ("wfi"); + } + } + } +#endif +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_ARM_SHARED_ARM_A9MPCORE_START_H */ diff --git a/c/src/lib/libbsp/arm/shared/include/arm-cp15-start.h b/c/src/lib/libbsp/arm/shared/include/arm-cp15-start.h index 6fb822667c..11efbcd400 100644 --- a/c/src/lib/libbsp/arm/shared/include/arm-cp15-start.h +++ b/c/src/lib/libbsp/arm/shared/include/arm-cp15-start.h @@ -41,6 +41,12 @@ arm_cp15_cache_invalidate(void); BSP_START_TEXT_SECTION static inline void arm_cp15_tlb_invalidate(void); +BSP_START_TEXT_SECTION static inline uint32_t +arm_cp15_get_multiprocessor_affinity(void); + +BSP_START_TEXT_SECTION static inline uint32_t +arm_cortex_a9_get_multiprocessor_cpu_id(void); + typedef struct { uint32_t begin; uint32_t end; diff --git a/c/src/lib/libbsp/arm/shared/include/arm-gic-irq.h b/c/src/lib/libbsp/arm/shared/include/arm-gic-irq.h index c45d3545d9..5c152a179e 100644 --- a/c/src/lib/libbsp/arm/shared/include/arm-gic-irq.h +++ b/c/src/lib/libbsp/arm/shared/include/arm-gic-irq.h @@ -15,7 +15,8 @@ #ifndef LIBBSP_ARM_SHARED_ARM_GIC_IRQ_H #define LIBBSP_ARM_SHARED_ARM_GIC_IRQ_H -#include <rtems.h> +#include <bsp.h> +#include <bsp/arm-gic.h> #ifdef __cplusplus extern "C" { @@ -37,6 +38,8 @@ extern "C" { #define ARM_GIC_IRQ_SGI_14 14 #define ARM_GIC_IRQ_SGI_15 15 +#define ARM_GIC_DIST ((volatile gic_dist *) BSP_ARM_GIC_DIST_BASE) + rtems_status_code arm_gic_irq_set_priority( rtems_vector_number vector, uint8_t priority @@ -53,11 +56,35 @@ typedef enum { ARM_GIC_IRQ_SOFTWARE_IRQ_TO_SELF } arm_gic_irq_software_irq_target_filter; -rtems_status_code arm_gic_irq_generate_software_irq( +static inline rtems_status_code arm_gic_irq_generate_software_irq( rtems_vector_number vector, arm_gic_irq_software_irq_target_filter filter, uint8_t targets -); +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (vector <= ARM_GIC_IRQ_SGI_15) { + volatile gic_dist *dist = ARM_GIC_DIST; + + dist->icdsgir = GIC_DIST_ICDSGIR_TARGET_LIST_FILTER(filter) + | GIC_DIST_ICDSGIR_CPU_TARGET_LIST(targets) + | GIC_DIST_ICDSGIR_SGIINTID(vector); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +static inline uint32_t arm_gic_irq_processor_count(void) +{ + volatile gic_dist *dist = ARM_GIC_DIST; + + return GIC_DIST_ICDICTR_CPU_NUMBER_GET(dist->icdictr) + 1; +} + +void arm_gic_irq_initialize_secondary_cpu(void); #ifdef __cplusplus } diff --git a/c/src/lib/libbsp/arm/shared/start/start.S b/c/src/lib/libbsp/arm/shared/start/start.S index e79a5fc503..7b59ab4857 100644 --- a/c/src/lib/libbsp/arm/shared/start/start.S +++ b/c/src/lib/libbsp/arm/shared/start/start.S @@ -31,6 +31,14 @@ .extern boot_card .extern bsp_start_hook_0 .extern bsp_start_hook_1 + .extern bsp_stack_irq_end + .extern bsp_stack_fiq_end + .extern bsp_stack_abt_end + .extern bsp_stack_und_end + .extern bsp_stack_svc_end +#ifdef RTEMS_SMP + .extern bsp_stack_all_size +#endif .extern _ARMV4_Exception_undef_default .extern _ARMV4_Exception_swi_default .extern _ARMV4_Exception_data_abort_default @@ -119,6 +127,16 @@ _start: * loader. */ +#ifdef RTEMS_SMP + /* Read MPIDR */ + mrc p15, 0, r0, c0, c0, 5 + + /* Calculate stack offset */ + and r0, #0xff + ldr r1, =bsp_stack_all_size + mul r1, r0 +#endif + /* * Set SVC mode, disable interrupts and enable ARM instructions. */ @@ -131,26 +149,41 @@ _start: mov r0, #(ARM_PSR_M_IRQ | ARM_PSR_I | ARM_PSR_F) msr cpsr, r0 ldr sp, =bsp_stack_irq_end +#ifdef RTEMS_SMP + add sp, r1 +#endif /* Enter FIQ mode and set up the FIQ stack pointer */ mov r0, #(ARM_PSR_M_FIQ | ARM_PSR_I | ARM_PSR_F) msr cpsr, r0 ldr sp, =bsp_stack_fiq_end +#ifdef RTEMS_SMP + add sp, r1 +#endif /* Enter ABT mode and set up the ABT stack pointer */ mov r0, #(ARM_PSR_M_ABT | ARM_PSR_I | ARM_PSR_F) msr cpsr, r0 ldr sp, =bsp_stack_abt_end +#ifdef RTEMS_SMP + add sp, r1 +#endif /* Enter UND mode and set up the UND stack pointer */ mov r0, #(ARM_PSR_M_UND | ARM_PSR_I | ARM_PSR_F) msr cpsr, r0 ldr sp, =bsp_stack_und_end +#ifdef RTEMS_SMP + add sp, r1 +#endif /* Enter SVC mode and set up the SVC stack pointer */ mov r0, #(ARM_PSR_M_SVC | ARM_PSR_I | ARM_PSR_F) msr cpsr, r0 ldr sp, =bsp_stack_svc_end +#ifdef RTEMS_SMP + add sp, r1 +#endif /* Stay in SVC mode */ diff --git a/c/src/lib/libbsp/arm/shared/startup/linkcmds.base b/c/src/lib/libbsp/arm/shared/startup/linkcmds.base index 27f5acb125..d1a73d009a 100644 --- a/c/src/lib/libbsp/arm/shared/startup/linkcmds.base +++ b/c/src/lib/libbsp/arm/shared/startup/linkcmds.base @@ -56,6 +56,10 @@ bsp_stack_und_size = ALIGN (bsp_stack_und_size, bsp_stack_align); bsp_stack_main_size = DEFINED (bsp_stack_main_size) ? bsp_stack_main_size : 0; bsp_stack_main_size = ALIGN (bsp_stack_main_size, bsp_stack_align); +bsp_stack_all_size = bsp_stack_abt_size + bsp_stack_fiq_size + bsp_stack_irq_size + bsp_stack_svc_size + bsp_stack_und_size + bsp_stack_main_size; + +bsp_processor_count = DEFINED (bsp_processor_count) ? bsp_processor_count : 1; + MEMORY { UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0 } @@ -324,6 +328,10 @@ SECTIONS { . = . + bsp_stack_main_size; bsp_stack_main_end = .; + bsp_stack_secondary_processors_begin = .; + . = . + (bsp_processor_count - 1) * bsp_stack_all_size; + bsp_stack_secondary_processors_end = .; + *(.bsp_vector) bsp_section_vector_end = .; |