[PATCH 08/10] bsps/arm: basic BCM2836 SMP implementation.

2016-09-03 Thread pisa
From: Pavel Pisa 

---
 c/src/lib/libbsp/arm/raspberrypi/Makefile.am   |   3 +
 c/src/lib/libbsp/arm/raspberrypi/include/bsp.h |   3 +
 c/src/lib/libbsp/arm/raspberrypi/irq/irq.c |  18 +++
 c/src/lib/libbsp/arm/raspberrypi/startup/bspsmp.c  | 122 +
 .../libbsp/arm/raspberrypi/startup/bspstarthooks.c |  35 +-
 .../lib/libbsp/arm/raspberrypi/startup/linkcmds.in |   2 +-
 .../arm/raspberrypi/startup/mm_config_table.c  |   8 ++
 7 files changed, 187 insertions(+), 4 deletions(-)
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/startup/bspsmp.c

diff --git a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am 
b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am
index 01f4ad2..1a2f0aa 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am
+++ b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am
@@ -100,6 +100,9 @@ libbsp_a_SOURCES += ../../shared/bspreset_loop.c
 libbsp_a_SOURCES += startup/bspstart.c
 libbsp_a_SOURCES += startup/cmdline.c
 libbsp_a_SOURCES += startup/bspgetworkarea.c
+if HAS_SMP
+libbsp_a_SOURCES += startup/bspsmp.c
+endif
 
 # IRQ
 libbsp_a_SOURCES += ../shared/arm-cp15-set-exception-handler.c
diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/bsp.h 
b/c/src/lib/libbsp/arm/raspberrypi/include/bsp.h
index 5241979..ecd5b6a 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/include/bsp.h
+++ b/c/src/lib/libbsp/arm/raspberrypi/include/bsp.h
@@ -50,6 +50,9 @@ void  rpi_video_init(void);
 void  rpi_fb_outch  (char);
 int rpi_video_is_initialized(void);
 
+void rpi_ipi_initialize(void);
+void rpi_start_rtems_on_secondary_processor(void);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c 
b/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c
index e654d07..48f7810 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c
+++ b/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c
@@ -32,6 +32,11 @@
 #include 
 #include 
 
+#ifdef RTEMS_SMP
+#include 
+#include 
+#endif
+
 typedef struct {
   unsigned long enable_reg_addr;
   unsigned long disable_reg_addr;
@@ -97,6 +102,19 @@ void bsp_interrupt_dispatch(void)
 
   rtems_vector_number vector = 255;
 
+#ifdef RTEMS_SMP
+  uint32_t cpu_index_self = _SMP_Get_current_processor();
+  uint32_t local_source = BCM2835_REG(BCM2836_IRQ_SOURCE_REG(cpu_index_self));
+
+  if ( local_source & BCM2836_IRQ_SOURCE_MBOX3 ) {
+/* reset mailbox 3 contents to zero */
+BCM2835_REG(BCM2836_MAILBOX_3_READ_CLEAR_BASE + 0x10 * cpu_index_self) = 
0x;
+_SMP_Inter_processor_interrupt_handler();
+  }
+  if ( cpu_index_self != 0 )
+return;
+#endif /* RTEMS_SMP */
+
   pend = BCM2835_REG(BCM2835_IRQ_BASIC);
   if ( pend & BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS ) {
 pend_bit = ffs(pend) - 1;
diff --git a/c/src/lib/libbsp/arm/raspberrypi/startup/bspsmp.c 
b/c/src/lib/libbsp/arm/raspberrypi/startup/bspsmp.c
new file mode 100644
index 000..3f9fd6a
--- /dev/null
+++ b/c/src/lib/libbsp/arm/raspberrypi/startup/bspsmp.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016 Pavel Pisa 
+ *
+ * Czech Technical University in Prague
+ * Zikova 1903/4
+ * 166 36 Praha 6
+ * Czech Republic
+ *
+ * Reuses some ideas from Rohini Kulkarni 
+ * GSoC 2015 project and Altera Cyclone-V SMP code
+ * by embedded brains GmbH
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+bool _CPU_SMP_Start_processor( uint32_t cpu_index )
+{
+  bool started;
+  uint32_t cpu_index_self = _SMP_Get_current_processor();
+
+  if (cpu_index != cpu_index_self) {
+
+BCM2835_REG(BCM2836_MAILBOX_3_WRITE_SET_BASE + 0x10 * cpu_index) = 
(uint32_t)_start;
+
+/*
+ * Wait for secondary processor to complete its basic initialization so
+ * that we can enable the unified L2 cache.
+ */
+started = _Per_CPU_State_wait_for_non_initial_state(cpu_index, 0);
+  } else {
+started = false;
+  }
+
+  return started;
+}
+
+
+void rpi_ipi_initialize(void)
+{
+  uint32_t cpu_index_self = _SMP_Get_current_processor();
+
+  /*
+   * Includes support only for mailbox 3 interrupt.
+   * Further interrupt support has to be added. This will have to be integrated
+   * with existing interrupt support for Raspberry Pi
+   */
+
+  /* reset mailbox 3 contents to zero */
+  BCM2835_REG(BCM2836_MAILBOX_3_READ_CLEAR_BASE + 0x10 * cpu_index_self) = 
0x;
+
+  BCM2835_REG(BCM2836_MAILBOX_IRQ_CTRL(cpu_index_self)) =
+BCM2836_MAILBOX_IRQ_CTRL_MBOX3_IRQ;
+}
+
+void rpi_start_rtems_on_secondary_processor(void)
+{
+  uint32_t ctrl;
+
+  ctrl = arm_cp15_start_setup_mmu_and_cache(
+0,
+ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_Z
+  );
+
+  rpi_ipi_initialize();
+
+  arm_cp15_set_domain_access_control(
+ARM_CP15_DAC_DOMAIN(ARM_MMU_DEFAULT_CLIENT_DOMAIN, 

[PATCH 05/10] arm/raspberrypi: more definitions of BCM2836 core local peripherals.

2016-09-03 Thread pisa
From: Pavel Pisa 

---
 .../libbsp/arm/raspberrypi/include/raspberrypi.h   | 142 -
 1 file changed, 140 insertions(+), 2 deletions(-)

diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/raspberrypi.h 
b/c/src/lib/libbsp/arm/raspberrypi/include/raspberrypi.h
index 4cedc4c..2f42731 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/include/raspberrypi.h
+++ b/c/src/lib/libbsp/arm/raspberrypi/include/raspberrypi.h
@@ -347,6 +347,17 @@
 /** @} */
 
 /**
+ * @name Raspberry Pi 2 CPU Cores Local Peripherals
+ *
+ * @{
+ */
+
+#define BCM2836_CORE_LOCAL_PERIPH_BASE0x4000
+#define BCM2836_CORE_LOCAL_PERIPH_SIZE0x0004
+
+/** @} */
+
+/**
  * @name Raspberry Pi 2 Mailbox Register Defines
  *
  * @{
@@ -364,13 +375,140 @@
 /** @} */
 
 /**
+ * @name Raspberry Pi 2 Core Timer
+ *
+ * @{
+ */
+
+#define BCM2836_CORE_TIMER_CTRL   0x4000
+
+#define BCM2836_CORE_TIMER_CTRL_APB_CLK   0x0100
+#define BCM2836_CORE_TIMER_CTRL_INC_2 0x0200
+
+#define BCM2836_CORE_TIMER_PRESCALER  0x4008
+
+#define BCM2836_CORE_TIMER_LS32   0x401C
+#define BCM2836_CORE_TIMER_MS32   0x4020
+
+/** @} */
+
+/**
+ * @name Raspberry Pi 2 Local Timer
+ *
+ * @{
+ */
+
+#define BCM2836_LOCAL_TIMER_CTRL  0x4034
+
+#define BCM2836_LOCAL_TIMER_CTRL_IRQ_FLAG 0x8000
+#define BCM2836_LOCAL_TIMER_CTRL_IRQ_EN   0x2000
+#define BCM2836_LOCAL_TIMER_CTRL_TIMER_EN 0x1000
+#define BCM2836_LOCAL_TIMER_RELOAD0x0FFF
+
+#define BCM2836_LOCAL_TIMER_IRQ_RELOAD0x4038
+
+#define BCM2836_LOCAL_TIMER_IRQ_CLEAR 0x8000
+#define BCM2836_LOCAL_TIMER_RELOAD_NOW0x4000
+
+#define BCM2836_LOCAL_TIMER_IRQ_ROUTING   0x4024
+#define BCM2836_LOCAL_TIMER_ROU_CORE0_IRQ   0x00
+#define BCM2836_LOCAL_TIMER_ROU_CORE1_IRQ   0x01
+#define BCM2836_LOCAL_TIMER_ROU_CORE2_IRQ   0x02
+#define BCM2836_LOCAL_TIMER_ROU_CORE3_IRQ   0x03
+#define BCM2836_LOCAL_TIMER_ROU_CORE0_FIQ   0x04
+#define BCM2836_LOCAL_TIMER_ROU_CORE1_FIQ   0x05
+#define BCM2836_LOCAL_TIMER_ROU_CORE2_FIQ   0x06
+#define BCM2836_LOCAL_TIMER_ROU_CORE3_FIQ   0x07
+
+/** @} */
+
+/**
+ * @name Raspberry Pi 2 IRQ Routing
+ *
+ * @{
+ */
+
+#define BCM2836_GPU_IRQ_ROUTING   0x400C
+
+#define BCM2836_GPU_IRQ_ROU_GPU_IRQ_CORE0 0x
+#define BCM2836_GPU_IRQ_ROU_GPU_IRQ_CORE1 0x0001
+#define BCM2836_GPU_IRQ_ROU_GPU_IRQ_CORE2 0x0002
+#define BCM2836_GPU_IRQ_ROU_GPU_IRQ_CORE4 0x0003
+
+#define BCM2836_GPU_IRQ_ROU_GPU_FIQ_CORE0 0x
+#define BCM2836_GPU_IRQ_ROU_GPU_FIQ_CORE1 0x0004
+#define BCM2836_GPU_IRQ_ROU_GPU_FIQ_CORE2 0x0008
+#define BCM2836_GPU_IRQ_ROU_GPU_FIQ_CORE4 0x000C
+
+#define BCM2836_GPU_IRQ_ROU_GPU_FIQ_CORE4 0x000C
+
+
+/** @} */
+
+/**
  * @name Raspberry Pi 2 Interrupt Register Defines
  *
  * @{
  */
 
-#define BCM2836_MAILBOX_IRQ_CTRL_BASE 0x4050
-#define BCM2836_IRQ_SOURCE_REG_BASE 0x4060
+/* Timers interrupt control registers */
+#define BCM2836_CORE0_TIMER_IRQ_CTRL_BASE 0x4040
+#define BCM2836_CORE1_TIMER_IRQ_CTRL_BASE 0x4044
+#define BCM2836_CORE2_TIMER_IRQ_CTRL_BASE 0x4048
+#define BCM2836_CORE3_TIMER_IRQ_CTRL_BASE 0x404C
+
+#define BCM2836_CORE_TIMER_IRQ_CTRL(cpuidx) \
+  (BCM2836_CORE0_TIMER_IRQ_CTRL_BASE + 0x4 * (cpuidx))
+
+/*
+ * Where to route timer interrupt to, IRQ/FIQ
+ * Setting both the IRQ and FIQ bit gives an FIQ
+ */
+#define BCM2836_CORE_TIMER_IRQ_CTRL_TIMER0_IRQ  0x01
+#define BCM2836_CORE_TIMER_IRQ_CTRL_TIMER1_IRQ  0x02
+#define BCM2836_CORE_TIMER_IRQ_CTRL_TIMER2_IRQ  0x04
+#define BCM2836_CORE_TIMER_IRQ_CTRL_TIMER3_IRQ  0x08
+#define BCM2836_CORE_TIMER_IRQ_CTRL_TIMER0_FIQ  0x10
+#define BCM2836_CORE_TIMER_IRQ_CTRL_TIMER1_FIQ  0x20
+#define BCM2836_CORE_TIMER_IRQ_CTRL_TIMER2_FIQ  0x40
+#define BCM2836_CORE_TIMER_IRQ_CTRL_TIMER3_FIQ  0x80
+
+/* CPU mailbox registers */
+#define BCM2836_MAILBOX_IRQ_CTRL_BASE 0x4050
+#define BCM2836_MAILBOX_IRQ_CTRL(cpuidx) \
+  (BCM2836_MAILBOX_IRQ_CTRL_BASE + 0x4 * (cpuidx))
+/*
+ * Where to route mailbox interrupt to, IRQ/FIQ
+ * Setting both the IRQ and FIQ bit gives an FIQ
+ */
+#define BCM2836_MAILBOX_IRQ_CTRL_MBOX0_IRQ  0x01
+#define BCM2836_MAILBOX_IRQ_CTRL_MBOX1_IRQ  0x02
+#define BCM2836_MAILBOX_IRQ_CTRL_MBOX2_IRQ  0x04
+#define BCM2836_MAILBOX_IRQ_CTRL_MBOX3_IRQ  0x08
+#define BCM2836_MAILBOX_IRQ_CTRL_MBOX0_FIQ  0x10
+#define BCM2836_MAILBOX_IRQ_CTRL_MBOX1_FIQ  0x20
+#define BCM2836_MAILBOX_IRQ_CTRL_MBOX2_FIQ  0x40
+#define BCM2836_MAILBOX_IRQ_CTRL_MBOX3_FIQ  0x80
+
+#define BCM2836_IRQ_SOURCE_REG_BASE   0x4060
+#define BCM2836_IRQ_SOURCE_REG(cpuidx) \
+  (BCM2836_IRQ_SOURCE_REG_BASE + 0x4 * (cpuidx))
+
+#define BCM2836_FIQ_SOURCE_REG_BASE   0x4070
+#define BCM2836_FIQ_SOURCE_REG(cpuidx) \
+  (BCM2836_FIQ_SOURCE_REG_BASE + 0x4 * (cpuidx))
+
+#define BCM2836_IRQ_SOURCE_TIMER0 0x0001
+#define 

[PATCH 03/10] bsps/arm: reorganize CP15 code to allow clean and invalidate ARMv7 cache by level.

2016-09-03 Thread pisa
From: Pavel Pisa 

New function arm_cp15_cache_invalidate_level and arm_cp15_cache_clean_level
can be used to maintain single cache level (instruction or data).
---
 c/src/lib/libcpu/arm/shared/include/arm-cp15.h | 108 ++---
 1 file changed, 60 insertions(+), 48 deletions(-)

diff --git a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h 
b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
index 4e4cac4..7b27c1b 100644
--- a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
+++ b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
@@ -1083,6 +1083,35 @@ 
arm_cp15_data_cache_invalidate_line_by_set_and_way(uint32_t set_and_way)
 }
 
 ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_cache_invalidate_level(uint32_t level, uint32_t inst_data_fl)
+{
+  uint32_t ccsidr;
+  uint32_t line_power;
+  uint32_t associativity;
+  uint32_t way;
+  uint32_t way_shift;
+
+  ccsidr = arm_cp15_get_cache_size_id_for_level((level << 1) | inst_data_fl);
+
+  line_power = arm_ccsidr_get_line_power(ccsidr);
+  associativity = arm_ccsidr_get_associativity(ccsidr);
+  way_shift = __builtin_clz(associativity - 1);
+
+  for (way = 0; way < associativity; ++way) {
+uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
+uint32_t set;
+
+for (set = 0; set < num_sets; ++set) {
+  uint32_t set_way = (way << way_shift)
+| (set << line_power)
+| (level << 1);
+
+  arm_cp15_data_cache_invalidate_line_by_set_and_way(set_way);
+}
+  }
+}
+
+ARM_CP15_TEXT_SECTION static inline void
 arm_cp15_data_cache_invalidate_all_levels(void)
 {
   uint32_t clidr = arm_cp15_get_cache_level_id();
@@ -1094,30 +1123,7 @@ arm_cp15_data_cache_invalidate_all_levels(void)
 
 /* Check if this level has a data cache or unified cache */
 if (((ctype & (0x6)) == 2) || (ctype == 4)) {
-  uint32_t ccsidr;
-  uint32_t line_power;
-  uint32_t associativity;
-  uint32_t way;
-  uint32_t way_shift;
-
-  ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
-
-  line_power = arm_ccsidr_get_line_power(ccsidr);
-  associativity = arm_ccsidr_get_associativity(ccsidr);
-  way_shift = __builtin_clz(associativity - 1);
-
-  for (way = 0; way < associativity; ++way) {
-uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
-uint32_t set;
-
-for (set = 0; set < num_sets; ++set) {
-  uint32_t set_way = (way << way_shift)
-| (set << line_power)
-| (level << 1);
-
-  arm_cp15_data_cache_invalidate_line_by_set_and_way(set_way);
-}
-  }
+  arm_cp15_cache_invalidate_level(level, 0);
 }
   }
 }
@@ -1155,6 +1161,35 @@ arm_cp15_data_cache_clean_line_by_set_and_way(uint32_t 
set_and_way)
 }
 
 ARM_CP15_TEXT_SECTION static inline void
+arm_cp15_data_cache_clean_level(uint32_t level)
+{
+  uint32_t ccsidr;
+  uint32_t line_power;
+  uint32_t associativity;
+  uint32_t way;
+  uint32_t way_shift;
+
+  ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
+
+  line_power = arm_ccsidr_get_line_power(ccsidr);
+  associativity = arm_ccsidr_get_associativity(ccsidr);
+  way_shift = __builtin_clz(associativity - 1);
+
+  for (way = 0; way < associativity; ++way) {
+uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
+uint32_t set;
+
+for (set = 0; set < num_sets; ++set) {
+  uint32_t set_way = (way << way_shift)
+| (set << line_power)
+| (level << 1);
+
+  arm_cp15_data_cache_clean_line_by_set_and_way(set_way);
+}
+  }
+}
+
+ARM_CP15_TEXT_SECTION static inline void
 arm_cp15_data_cache_clean_all_levels(void)
 {
   uint32_t clidr = arm_cp15_get_cache_level_id();
@@ -1166,30 +1201,7 @@ arm_cp15_data_cache_clean_all_levels(void)
 
 /* Check if this level has a data cache or unified cache */
 if (((ctype & (0x6)) == 2) || (ctype == 4)) {
-  uint32_t ccsidr;
-  uint32_t line_power;
-  uint32_t associativity;
-  uint32_t way;
-  uint32_t way_shift;
-
-  ccsidr = arm_cp15_get_cache_size_id_for_level(level << 1);
-
-  line_power = arm_ccsidr_get_line_power(ccsidr);
-  associativity = arm_ccsidr_get_associativity(ccsidr);
-  way_shift = __builtin_clz(associativity - 1);
-
-  for (way = 0; way < associativity; ++way) {
-uint32_t num_sets = arm_ccsidr_get_num_sets(ccsidr);
-uint32_t set;
-
-for (set = 0; set < num_sets; ++set) {
-  uint32_t set_way = (way << way_shift)
-| (set << line_power)
-| (level << 1);
-
-  arm_cp15_data_cache_clean_line_by_set_and_way(set_way);
-}
-  }
+  arm_cp15_data_cache_clean_level(level);
 }
   }
 }
-- 
1.9.1

___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel


[PATCH 10/10] arm/raspberrypi: use GPU/system timer as clock source.

2016-09-03 Thread pisa
From: Pavel Pisa 

It has advantage that it is designed as free-running counter
with compare registers and can easily serve for for both
timecounter and tick interrupt.
---
 c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c | 98 ++-
 1 file changed, 62 insertions(+), 36 deletions(-)

diff --git a/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c 
b/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c
index 4ce795f..72c85b1 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c
+++ b/c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c
@@ -10,6 +10,7 @@
  * BCM2835 Clock driver
  *
  * Copyright (c) 2013 Alan Cudmore
+ * Copyright (c) 2016 Pavel Pisa
  *
  *  The license and distribution terms for this file may be
  *  found in the file LICENSE in this distribution or at
@@ -21,71 +22,96 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 
 /* This is defined in ../../../shared/clockdrv_shell.h */
 void Clock_isr(rtems_irq_hdl_param arg);
 
+static struct timecounter raspberrypi_tc;
+
+static uint32_t raspberrypi_clock_get_timecount(struct timecounter *tc)
+{
+  return BCM2835_REG(BCM2835_GPU_TIMER_CLO);
+}
+
 static void raspberrypi_clock_at_tick(void)
 {
-   BCM2835_REG(BCM2835_TIMER_CLI) = 0;
+  uint32_t act_val;
+  uint32_t next_cmp = BCM2835_REG(BCM2835_GPU_TIMER_C3);
+  next_cmp += rtems_configuration_get_microseconds_per_tick();
+  BCM2835_REG(BCM2835_GPU_TIMER_C3) = next_cmp;
+  act_val = BCM2835_REG(BCM2835_GPU_TIMER_CLO);
+
+  /*
+   * Clear interrupt only if there is time left to the next tick.
+   * If time of the next tick has already passed then interrupt
+   * request stays active and fires immediately after current tick
+   * processing is finished.
+   */
+  if ((int32_t)(next_cmp - act_val) > 0)
+BCM2835_REG(BCM2835_GPU_TIMER_CS) = BCM2835_GPU_TIMER_CS_M3;
 }
 
-static void raspberrypi_clock_handler_install(void)
+static void raspberrypi_clock_handler_install_isr(
+  rtems_isr_entry clock_isr
+)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
 
-  sc = rtems_interrupt_handler_install(
-BCM2835_IRQ_ID_TIMER_0,
-"Clock",
-RTEMS_INTERRUPT_UNIQUE,
-(rtems_interrupt_handler) Clock_isr,
-NULL
-  );
-  if (sc != RTEMS_SUCCESSFUL) {
+  if (clock_isr != NULL) {
+sc = rtems_interrupt_handler_install(
+  BCM2835_IRQ_ID_GPU_TIMER_M3,
+  "Clock",
+  RTEMS_INTERRUPT_UNIQUE,
+  (rtems_interrupt_handler) clock_isr,
+  NULL
+);
+  } else {
+/* Remove interrupt handler */
+sc = rtems_interrupt_handler_remove(
+  BCM2835_IRQ_ID_GPU_TIMER_M3,
+  (rtems_interrupt_handler) Clock_isr,
+  NULL
+);
+  }
+  if ( sc != RTEMS_SUCCESSFUL ) {
 rtems_fatal_error_occurred(0xdeadbeef);
   }
 }
 
-static void raspberrypi_clock_initialize(void)
+static void raspberrypi_clock_initialize_hardware(void)
 {
-   BCM2835_REG(BCM2835_TIMER_CTL) = 0x003E;
-   BCM2835_REG(BCM2835_TIMER_LOD) =
-rtems_configuration_get_microseconds_per_tick() - 1;
-   BCM2835_REG(BCM2835_TIMER_RLD) =
-rtems_configuration_get_microseconds_per_tick() - 1;
-   BCM2835_REG(BCM2835_TIMER_DIV) = BCM2835_TIMER_PRESCALE;
-   BCM2835_REG(BCM2835_TIMER_CLI) = 0;
-   BCM2835_REG(BCM2835_TIMER_CTL) = 0x003E00A2;
+  uint32_t next_cmp = BCM2835_REG(BCM2835_GPU_TIMER_CLO);
+  next_cmp += rtems_configuration_get_microseconds_per_tick();
+  BCM2835_REG(BCM2835_GPU_TIMER_C3) = next_cmp;
+  BCM2835_REG(BCM2835_GPU_TIMER_CS) = BCM2835_GPU_TIMER_CS_M3;
+
+  raspberrypi_tc.tc_get_timecount = raspberrypi_clock_get_timecount;
+  raspberrypi_tc.tc_counter_mask = 0x;
+  raspberrypi_tc.tc_frequency = 100; /* 1 MHz */
+  raspberrypi_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install(_tc);
 }
 
 static void raspberrypi_clock_cleanup(void)
 {
-  rtems_status_code sc = RTEMS_SUCCESSFUL;
-
-  /* Remove interrupt handler */
-  sc = rtems_interrupt_handler_remove(
-BCM2835_IRQ_ID_TIMER_0,
-(rtems_interrupt_handler) Clock_isr,
-NULL
-  );
-  if (sc != RTEMS_SUCCESSFUL) {
-rtems_fatal_error_occurred(0xdeadbeef);
-  }
+  bsp_interrupt_vector_disable(BCM2835_IRQ_ID_GPU_TIMER_M3);
 }
 
 #define Clock_driver_support_at_tick() raspberrypi_clock_at_tick()
 
-#define Clock_driver_support_initialize_hardware() 
raspberrypi_clock_initialize()
+#define Clock_driver_support_initialize_hardware() 
raspberrypi_clock_initialize_hardware()
 
-#define Clock_driver_support_install_isr(isr, old_isr) \
+#define Clock_driver_support_shutdown_hardware() raspberrypi_clock_cleanup()
+
+#define Clock_driver_support_install_isr(clock_isr, old_isr) \
   do { \
-raspberrypi_clock_handler_install();   \
+raspberrypi_clock_handler_install_isr(clock_isr);  \
 old_isr = NULL;\
   } while (0)
 
-#define Clock_driver_support_shutdown_hardware() raspberrypi_clock_cleanup()
-

[PATCH 07/10] arm/raspberrypi: propagate number of configured CPUs into linker script.

2016-09-03 Thread pisa
From: Pavel Pisa 

---
 c/src/lib/libbsp/arm/raspberrypi/configure.ac| 14 ++
 c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds.in |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/c/src/lib/libbsp/arm/raspberrypi/configure.ac 
b/c/src/lib/libbsp/arm/raspberrypi/configure.ac
index 48bd62c..b772d6e 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/configure.ac
+++ b/c/src/lib/libbsp/arm/raspberrypi/configure.ac
@@ -40,6 +40,20 @@ RTEMS_BSPOPTS_SET([BSP_IS_RPI2],[*],[0])
 RTEMS_BSPOPTS_HELP([BSP_IS_RPI2],[Set if the BSP variant is Raspberry Pi 2.])
 AM_CONDITIONAL(RTEMS_RPI2,[test "$BSP_IS_RPI2" = "1"])
 
+# Hom many CPUs are used?
+RASPBERRYPI_CPUS="1"
+RTEMS_CHECK_SMP
+AM_CONDITIONAL(HAS_SMP,[test "$rtems_cv_HAS_SMP" = "yes"])
+AS_IF([test "$rtems_cv_HAS_SMP" = "yes"],
+  [RASPBERRYPI_CPUS="4"])
+
+AC_DEFUN([RASPBERRYPI_LINKCMD],[
+AC_ARG_VAR([$1],[$2; default $3])dnl
+[$1]=[$]{[$1]:-[$3]}
+])
+
+RASPBERRYPI_LINKCMD([RASPBERRYPI_CPUS],[Number of active 
cores],[${RASPBERRYPI_CPUS}])
+
 RTEMS_BSP_CLEANUP_OPTIONS(0, 0)
 
 AC_CONFIG_FILES([
diff --git a/c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds.in 
b/c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds.in
index fc72b5c..d88c6d7 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds.in
+++ b/c/src/lib/libbsp/arm/raspberrypi/startup/linkcmds.in
@@ -41,6 +41,8 @@ MEMORY {
 RAM(AIW) : ORIGIN = 0x8000, LENGTH = 128M - 32k
 }
 
+bsp_processor_count = DEFINED (bsp_processor_count) ? bsp_processor_count : 
@RASPBERRYPI_CPUS@;
+
 REGION_ALIAS ("REGION_START", RAM);
 REGION_ALIAS ("REGION_VECTOR", VECTOR_RAM);
 REGION_ALIAS ("REGION_TEXT", RAM);
-- 
1.9.1

___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel


[PATCH 02/10] bsps/arm: remove lock in arm_cp15_set_translation_table_entries().

2016-09-03 Thread pisa
From: Pavel Pisa 

Protection by rtems_interrupt_disable() is incompatible with SMP build.
Actual page table entries manipulation function does not need locking
and disabling cache and can be run concurrently even on multiple
CPUs as long as changes do not modify same region. If the function
is called from more threads/CPUs to modify same region with different
mapping options concurrently then there is problem at another level
of virtual address space management  and has to be solved by mutex
or other locking at that level.
---
 c/src/lib/libbsp/arm/shared/arm-cp15-set-ttb-entries.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/c/src/lib/libbsp/arm/shared/arm-cp15-set-ttb-entries.c 
b/c/src/lib/libbsp/arm/shared/arm-cp15-set-ttb-entries.c
index f650009..c2be0f5 100644
--- a/c/src/lib/libbsp/arm/shared/arm-cp15-set-ttb-entries.c
+++ b/c/src/lib/libbsp/arm/shared/arm-cp15-set-ttb-entries.c
@@ -85,13 +85,5 @@ uint32_t arm_cp15_set_translation_table_entries(
   uint32_t section_flags
 )
 {
-  rtems_interrupt_level level;
-  uint32_t section_flags_of_first_entry;
-
-  rtems_interrupt_disable(level);
-  section_flags_of_first_entry =
-set_translation_table_entries(begin, end, section_flags);
-  rtems_interrupt_enable(level);
-
-  return section_flags_of_first_entry;
+  return set_translation_table_entries(begin, end, section_flags);
 }
-- 
1.9.1

___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel


[PATCH 01/10] bsps/arm: use defines for cache type register format field.

2016-09-03 Thread pisa
From: Pavel Pisa 

The change documents meaning of codes and opens
well defined way to use cache type format for cache
examination/debugging outside of arm-cp15.h file.
---
 c/src/lib/libcpu/arm/shared/include/arm-cp15.h | 39 --
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h 
b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
index a27e50d..4e4cac4 100644
--- a/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
+++ b/c/src/lib/libcpu/arm/shared/include/arm-cp15.h
@@ -211,6 +211,20 @@ extern "C" {
 /** @} */
 
 /**
+ * @name CTR, Cache Type Register Defines
+ *
+ * The format can be obtained from CP15 by call
+ * arm_cp15_cache_type_get_format(arm_cp15_get_cache_type());
+ *
+ * @{
+ */
+
+#define ARM_CP15_CACHE_TYPE_FORMAT_ARMV6 0
+#define ARM_CP15_CACHE_TYPE_FORMAT_ARMV7 4
+
+/** @} */
+
+/**
  * @name CCSIDR, Cache Size ID Register Defines
  *
  * @{
@@ -685,18 +699,25 @@ arm_cp15_get_cache_type(void)
   return val;
 }
 
+/* Extract format version from cache type CTR */
+ARM_CP15_TEXT_SECTION static inline int
+arm_cp15_cache_type_get_format(uint32_t ct)
+{
+  return (ct >> 29) & 0x7U;
+}
+
 /* Read size of smallest cache line of all instruction/data caches controlled 
by the processor */
 ARM_CP15_TEXT_SECTION static inline uint32_t
 arm_cp15_get_min_cache_line_size(void)
 {
   uint32_t mcls = 0;
   uint32_t ct = arm_cp15_get_cache_type();
-  uint32_t format = (ct >> 29) & 0x7U;
+  uint32_t format = arm_cp15_cache_type_get_format(ct);
 
-  if (format == 0x4) {
+  if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
 /* ARMv7 format */
 mcls = (1U << (ct & 0xf)) * 4;
-  } else if (format == 0x0) {
+  } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
 /* ARMv6 format */
 uint32_t mask = (1U << 12) - 1;
 uint32_t dcls = (ct >> 12) & mask;
@@ -714,12 +735,12 @@ arm_cp15_get_data_cache_line_size(void)
 {
   uint32_t mcls = 0;
   uint32_t ct = arm_cp15_get_cache_type();
-  uint32_t format = (ct >> 29) & 0x7U;
+  uint32_t format = arm_cp15_cache_type_get_format(ct);
 
-  if (format == 0x4) {
+  if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
 /* ARMv7 format */
 mcls = (1U << ((ct & 0xf) >> 16)) * 4;
-  } else if (format == 0x0) {
+  } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
 /* ARMv6 format */
 uint32_t mask = (1U << 12) - 1;
 mcls = (ct >> 12) & mask;
@@ -734,12 +755,12 @@ arm_cp15_get_instruction_cache_line_size(void)
 {
   uint32_t mcls = 0;
   uint32_t ct = arm_cp15_get_cache_type();
-  uint32_t format = (ct >> 29) & 0x7U;
+  uint32_t format = arm_cp15_cache_type_get_format(ct);
 
-  if (format == 0x4) {
+  if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV7) {
 /* ARMv7 format */
 mcls = (1U << (ct & 0xf)) * 4;
-  } else if (format == 0x0) {
+  } else if (format == ARM_CP15_CACHE_TYPE_FORMAT_ARMV6) {
 /* ARMv6 format */
 uint32_t mask = (1U << 12) - 1;
 mcls = ct & mask;;
-- 
1.9.1

___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel


[PATCH 00/10] Raspberry Pi 2 (BCM2836) SMP support

2016-09-03 Thread pisa
From: Pavel Pisa 

The series implements Raspberry Pi 2 (BCM2836) SMP support.

The first two patches modify ARM Cortex-A common CP15 support
to expose clean by level cache operations to the BSP code.
Clean and invalidation of L1 cache is required when the secondary
CPU is booted. But the secondary CPU must not trash content
of shared cache levels because primary CPU is already running
from it.

Next patches provides basic SMP implementation.
BCM2836 core mailboxes are used to implement inter-processor
interrupts.

The last two patches change reimplement clock driver to
use GPU/system timer instead of ARM timer because original
approach has been incompatible with SMP support.
SMP support requires timecounter source and it implemented
easier from GPU/system timer which is based on free-running
counter.

Pavel Pisa (9):
  bsps/arm: use defines for cache type register format field.
  bsps/arm: remove lock in arm_cp15_set_translation_table_entries().
  bsps/arm: reorganize CP15 code to allow clean and invalidate ARMv7
cache by level.
  arm/raspberrypi: more definitions of BCM2836 core local peripherals.
  arm/raspberrypi: rename linkcmds to linkcmds.in to allow their
configure processing.
  arm/raspberrypi: propagate number of configured CPUs into linker
script.
  bsps/arm: basic BCM2836 SMP implementation.
  arm/raspberrypi: correct and extend definitions for GPU timer.
  arm/raspberrypi: use GPU/system timer as clock source.

Rohini Kulkarni (1):
  arm/raspberrypi: include definitions of BCM2836 SMP mailboxes.

 c/src/lib/libbsp/arm/raspberrypi/Makefile.am   |   5 +-
 c/src/lib/libbsp/arm/raspberrypi/clock/clockdrv.c  |  98 +++
 c/src/lib/libbsp/arm/raspberrypi/configure.ac  |  19 ++-
 c/src/lib/libbsp/arm/raspberrypi/include/bsp.h |   3 +
 c/src/lib/libbsp/arm/raspberrypi/include/irq.h |   5 +
 .../libbsp/arm/raspberrypi/include/raspberrypi.h   | 182 -
 c/src/lib/libbsp/arm/raspberrypi/irq/irq.c |  18 ++
 c/src/lib/libbsp/arm/raspberrypi/startup/bspsmp.c  | 122 ++
 .../libbsp/arm/raspberrypi/startup/bspstarthooks.c |  35 +++-
 .../raspberrypi/startup/{linkcmds => linkcmds.in}  |   4 +-
 .../arm/raspberrypi/startup/mm_config_table.c  |   8 +
 .../libbsp/arm/shared/arm-cp15-set-ttb-entries.c   |  10 +-
 c/src/lib/libcpu/arm/shared/include/arm-cp15.h | 147 ++---
 13 files changed, 539 insertions(+), 117 deletions(-)
 create mode 100644 c/src/lib/libbsp/arm/raspberrypi/startup/bspsmp.c
 rename c/src/lib/libbsp/arm/raspberrypi/startup/{linkcmds => linkcmds.in} (95%)

-- 
1.9.1

___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel