summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/qoriq/startup
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/powerpc/qoriq/startup')
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c194
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c18
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_t2080rdb36
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_t4240rdb7
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c6
-rw-r--r--c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c26
6 files changed, 198 insertions, 89 deletions
diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c b/c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c
index c60230a8f4..80764fec2c 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/bspsmp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2013-2015 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -12,14 +12,13 @@
* http://www.rtems.org/license/LICENSE.
*/
-#include <assert.h>
-
#include <rtems/score/smpimpl.h>
#include <libcpu/powerpc-utility.h>
#include <bsp.h>
#include <bsp/mmu.h>
+#include <bsp/fatal.h>
#include <bsp/qoriq.h>
#include <bsp/vectors.h>
#include <bsp/bootcard.h>
@@ -28,19 +27,17 @@
LINKER_SYMBOL(bsp_exc_vector_base);
-void _start_core_1(void);
-
-#define CORE_COUNT 2
-
-#define ONE_CORE(core) (1 << (core))
+#if QORIQ_THREAD_COUNT > 1
+void _start_thread(void);
+#endif
-#define ALL_CORES ((1 << CORE_COUNT) - 1)
+void _start_secondary_processor(void);
#define IPI_INDEX 0
-#define TLB_BEGIN 8
+#define TLB_BEGIN (3 * QORIQ_TLB1_ENTRY_COUNT / 4)
-#define TLB_END 16
+#define TLB_END QORIQ_TLB1_ENTRY_COUNT
#define TLB_COUNT (TLB_END - TLB_BEGIN)
@@ -48,84 +45,76 @@ void _start_core_1(void);
* 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)
+#define BOOT_BEGIN U_BOOT_BOOT_PAGE_BEGIN
+#define BOOT_LAST U_BOOT_BOOT_PAGE_LAST
+#define SPIN_TABLE (BOOT_BEGIN + U_BOOT_BOOT_PAGE_SPIN_OFFSET)
typedef struct {
uint32_t addr_upper;
uint32_t addr_lower;
uint32_t r3_upper;
uint32_t r3_lower;
- uint32_t reserved;
+ uint32_t reserved_0;
uint32_t pir;
uint32_t r6_upper;
uint32_t r6_lower;
+ uint32_t reserved_1[8];
} uboot_spin_table;
-static uint32_t initial_core_1_stack[4096 / sizeof(uint32_t)];
-
-static void mmu_config_undo(void)
+#if QORIQ_THREAD_COUNT > 1
+static bool is_started_by_u_boot(uint32_t cpu_index)
{
- int i = 0;
-
- for (i = TLB_BEGIN; i < TLB_END; ++i) {
- qoriq_tlb1_invalidate(i);
- }
+ return cpu_index % QORIQ_THREAD_COUNT == 0;
}
-static void release_core_1(void)
+void qoriq_start_thread(void)
{
- const Per_CPU_Control *second_cpu = _Per_CPU_Get_by_index(1);
- 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,
- 0
+ const Per_CPU_Control *cpu_self = _Per_CPU_Get();
+
+ ppc_exc_initialize_interrupt_stack(
+ (uintptr_t) cpu_self->interrupt_stack_low,
+ rtems_configuration_get_interrupt_stack_size()
);
- 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) second_cpu->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));
+ bsp_interrupt_facility_initialize();
- mmu_config_undo();
+ _SMP_Start_multitasking_on_secondary_processor();
}
+#endif
-void bsp_start_on_secondary_processor(void)
+static void start_thread_if_necessary(uint32_t cpu_index_self)
{
- const Per_CPU_Control *second_cpu = _Per_CPU_Get_by_index(1);
+#if QORIQ_THREAD_COUNT > 1
+ uint32_t i;
+
+ for (i = 1; i < QORIQ_THREAD_COUNT; ++i) {
+ uint32_t cpu_index_next = cpu_index_self + i;
+
+ if (
+ is_started_by_u_boot(cpu_index_self)
+ && cpu_index_next < rtems_configuration_get_maximum_processors()
+ && _SMP_Should_start_processor(cpu_index_next)
+ ) {
+ /* Thread Initial Next Instruction Address (INIA) */
+ PPC_SET_THREAD_MGMT_REGISTER(321, (uint32_t) _start_thread);
+
+ /* Thread Initial Machine State (IMSR) */
+ PPC_SET_THREAD_MGMT_REGISTER(289, QORIQ_INITIAL_MSR);
+
+ /* Thread Enable Set (TENS) */
+ PPC_SET_SPECIAL_PURPOSE_REGISTER(438, 1U << i);
+ }
+ }
+#endif
+}
- /* Disable decrementer */
- PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS(BOOKE_TCR, BOOKE_TCR_DIE);
+void bsp_start_on_secondary_processor(void)
+{
+ uint32_t cpu_index_self = _SMP_Get_current_processor();
+ const Per_CPU_Control *cpu_self = _Per_CPU_Get_by_index(cpu_index_self);
- /* Initialize exception handler */
ppc_exc_initialize_with_vector_base(
- (uintptr_t) second_cpu->interrupt_stack_low,
+ (uintptr_t) cpu_self->interrupt_stack_low,
rtems_configuration_get_interrupt_stack_size(),
bsp_exc_vector_base
);
@@ -137,10 +126,9 @@ void bsp_start_on_secondary_processor(void)
FSL_EIS_MAS3_SR
);
- /* Initialize interrupt support */
bsp_interrupt_facility_initialize();
- bsp_interrupt_vector_enable(QORIQ_IRQ_IPI_0);
+ start_thread_if_necessary(cpu_index_self);
_SMP_Start_multitasking_on_secondary_processor();
}
@@ -152,20 +140,78 @@ static void bsp_inter_processor_interrupt(void *arg)
uint32_t _CPU_SMP_Initialize(void)
{
- return CORE_COUNT;
+ if (rtems_configuration_get_maximum_processors() > 0) {
+ 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,
+ 0
+ );
+ qoriq_mmu_partition(&mmu_context, TLB_COUNT);
+ qoriq_mmu_write_to_tlb1(&mmu_context, TLB_BEGIN);
+ }
+
+ start_thread_if_necessary(0);
+
+ return QORIQ_CPU_COUNT;
+}
+
+static void release_processor(uboot_spin_table *spin_table, uint32_t cpu_index)
+{
+ const Per_CPU_Control *cpu = _Per_CPU_Get_by_index(cpu_index);
+
+ spin_table->pir = cpu_index;
+ spin_table->r3_lower = (uint32_t) cpu->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_secondary_processor;
+ rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table));
}
bool _CPU_SMP_Start_processor(uint32_t cpu_index)
{
- (void) cpu_index;
+#if QORIQ_THREAD_COUNT > 1
+ if (is_started_by_u_boot(cpu_index)) {
+ uboot_spin_table *spin_table =
+ &((uboot_spin_table *) SPIN_TABLE)[cpu_index / 2 - 1];
- release_core_1();
+ release_processor(spin_table, cpu_index);
+
+ return true;
+ } else {
+ return _SMP_Should_start_processor(cpu_index - 1);
+ }
+#else
+ uboot_spin_table *spin_table = (uboot_spin_table *) SPIN_TABLE;
+
+ release_processor(spin_table, cpu_index);
return true;
+#endif
+}
+
+static void mmu_config_undo(void)
+{
+ int i;
+
+ for (i = TLB_BEGIN; i < TLB_END; ++i) {
+ qoriq_tlb1_invalidate(i);
+ }
}
void _CPU_SMP_Finalize_initialization(uint32_t cpu_count)
{
+ if (rtems_configuration_get_maximum_processors() > 0) {
+ mmu_config_undo();
+ }
+
if (cpu_count > 1) {
rtems_status_code sc;
@@ -176,13 +222,13 @@ void _CPU_SMP_Finalize_initialization(uint32_t cpu_count)
bsp_inter_processor_interrupt,
NULL
);
- assert(sc == RTEMS_SUCCESSFUL);
+ if (sc != RTEMS_SUCCESSFUL) {
+ bsp_fatal(QORIQ_FATAL_SMP_IPI_HANDLER_INSTALL);
+ }
}
}
void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
{
- uint32_t self = ppc_processor_id();
- qoriq.pic.per_cpu [self].ipidr [IPI_INDEX].reg =
- ONE_CORE(target_processor_index);
+ qoriq.pic.ipidr [IPI_INDEX].reg = 1U << target_processor_index;
}
diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c
index 364d8af875..9784cbe943 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c
@@ -87,8 +87,9 @@ void bsp_start(void)
/* Initialize some device driver parameters */
#ifdef HAS_UBOOT
- BSP_bus_frequency = bsp_uboot_board_info.bi_busfreq;
- bsp_clicks_per_usec = bsp_uboot_board_info.bi_busfreq / 8000000;
+ BSP_bus_frequency = bsp_uboot_board_info.bi_busfreq
+ / QORIQ_BUS_CLOCK_DIVIDER;
+ bsp_clicks_per_usec = BSP_bus_frequency / 8000000;
rtems_counter_initialize_converter(bsp_uboot_board_info.bi_intfreq);
#endif /* HAS_UBOOT */
@@ -108,14 +109,15 @@ void bsp_start(void)
ctx->clock = BSP_bus_frequency;
#ifdef HAS_UBOOT
- ctx->initial_baud = bsp_uboot_board_info.bi_baudrate;
+ #ifdef U_BOOT_GENERIC_BOARD_INFO
+ ctx->initial_baud = 115200;
+ #else
+ ctx->initial_baud = bsp_uboot_board_info.bi_baudrate;
+ #endif
#endif
}
}
- /* Disable decrementer */
- PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS(BOOKE_TCR, BOOKE_TCR_DIE);
-
/* Initialize exception handler */
ppc_exc_initialize_with_vector_base(
(uintptr_t) bsp_section_work_begin,
@@ -134,5 +136,9 @@ void bsp_start(void)
bsp_interrupt_initialize();
/* Disable boot page translation */
+#if QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT)
+ qoriq.lcc.bstar &= ~LCC_BSTAR_EN;
+#else
qoriq.lcc.bptr &= ~BPTR_EN;
+#endif
}
diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_t2080rdb b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_t2080rdb
new file mode 100644
index 0000000000..951a0ee684
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_t2080rdb
@@ -0,0 +1,36 @@
+/**
+ * @file
+ *
+ * Memory map for T2080RDB.
+ */
+
+MEMORY {
+ LOW : ORIGIN = 0x4000, LENGTH = 16M - 16k
+ HIGH : ORIGIN = 0x1000000, LENGTH = 2048M - 16M
+ EMPTY : ORIGIN = 0x0, LENGTH = 0
+}
+
+REGION_ALIAS ("REGION_START", LOW);
+REGION_ALIAS ("REGION_FAST_TEXT", LOW);
+REGION_ALIAS ("REGION_FAST_TEXT_LOAD", LOW);
+REGION_ALIAS ("REGION_TEXT", LOW);
+REGION_ALIAS ("REGION_TEXT_LOAD", LOW);
+REGION_ALIAS ("REGION_RODATA", HIGH);
+REGION_ALIAS ("REGION_RODATA_LOAD", LOW);
+REGION_ALIAS ("REGION_FAST_DATA", HIGH);
+REGION_ALIAS ("REGION_FAST_DATA_LOAD", LOW);
+REGION_ALIAS ("REGION_DATA", HIGH);
+REGION_ALIAS ("REGION_DATA_LOAD", LOW);
+REGION_ALIAS ("REGION_BSS", HIGH);
+REGION_ALIAS ("REGION_RWEXTRA", HIGH);
+REGION_ALIAS ("REGION_WORK", HIGH);
+REGION_ALIAS ("REGION_STACK", HIGH);
+REGION_ALIAS ("REGION_NOCACHE", EMPTY);
+REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY);
+REGION_ALIAS ("REGION_NVRAM", EMPTY);
+
+bsp_section_robarrier_align = 0x1000000;
+bsp_section_rwbarrier_align = 0x1000000;
+qoriq = 0xfe000000;
+
+INCLUDE linkcmds.base
diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_t4240rdb b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_t4240rdb
new file mode 100644
index 0000000000..b2f38b789c
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_t4240rdb
@@ -0,0 +1,7 @@
+/**
+ * @file
+ *
+ * Memory map for T4240RDB.
+ */
+
+INCLUDE linkcmds.qoriq_t2080rdb
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 2d81125d90..5b759fbbe1 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2011-2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011-2015 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -105,7 +105,7 @@ void TEXT qoriq_mmu_config(int first_tlb, int scratch_tlb)
qoriq_mmu_context_init(&context);
- for (i = 0; i < 16; ++i) {
+ for (i = 0; i < QORIQ_TLB1_ENTRY_COUNT; ++i) {
if (i != scratch_tlb) {
qoriq_tlb1_invalidate(i);
}
@@ -126,6 +126,6 @@ void TEXT qoriq_mmu_config(int first_tlb, int scratch_tlb)
}
}
- qoriq_mmu_partition(&context, 8);
+ qoriq_mmu_partition(&context, (3 * QORIQ_TLB1_ENTRY_COUNT) / 4);
qoriq_mmu_write_to_tlb1(&context, first_tlb);
}
diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c
index 0e52f0ab32..e2a0188c80 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c
@@ -7,10 +7,10 @@
*/
/*
- * Copyright (c) 2011 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011-2015 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
@@ -40,6 +40,21 @@ static uint32_t TEXT power_of_two(uint32_t val)
return power;
}
+static uint32_t TEXT max_power_of_two(uint32_t val)
+{
+ uint32_t test_power = QORIQ_MMU_MIN_POWER;
+ uint32_t power = test_power;
+ uint32_t max = 1U << test_power;
+
+ do {
+ power = test_power;
+ max <<= QORIQ_MMU_POWER_STEP;
+ test_power += QORIQ_MMU_POWER_STEP;
+ } while (test_power <= QORIQ_MMU_MAX_POWER && max <= val);
+
+ return power;
+}
+
void TEXT qoriq_mmu_context_init(qoriq_mmu_context *self)
{
int *cur = (int *) self;
@@ -150,7 +165,7 @@ static void TEXT align(qoriq_mmu_context *self, uint32_t alignment)
static bool TEXT is_full(qoriq_mmu_context *self)
{
- return self->count >= QORIQ_MMU_ENTRY_COUNT;
+ return self->count >= QORIQ_TLB1_ENTRY_COUNT;
}
static void TEXT append(qoriq_mmu_context *self, const qoriq_mmu_entry *new_entry)
@@ -208,9 +223,8 @@ static bool TEXT split(qoriq_mmu_context *self, qoriq_mmu_entry *cur)
uint32_t end = cur->last + 1;
uint32_t size = end - begin;
uint32_t begin_power = power_of_two(begin);
- uint32_t end_power = power_of_two(end);
- uint32_t size_power = power_of_two(size);
- uint32_t power = min(begin_power, min(end_power, size_power));
+ uint32_t size_power = max_power_of_two(size);
+ uint32_t power = min(begin_power, size_power);
uint32_t split_size = power < 32 ? (1U << power) : 0;
uint32_t split_pos = begin + split_size;