[rtems commit] riscv: add griscv bsp

Sebastian Huber sebh at rtems.org
Tue Jan 22 11:53:19 UTC 2019


Module:    rtems
Branch:    master
Commit:    d3d4e77c4218377d9aad9a3ac5d71461274bbc1e
Changeset: http://git.rtems.org/rtems/commit/?id=d3d4e77c4218377d9aad9a3ac5d71461274bbc1e

Author:    Jiri Gaisler <jiri at gaisler.se>
Date:      Fri Jan 18 12:37:55 2019 +0100

riscv: add griscv bsp

Update #3678.

---

 bsps/riscv/griscv/clock/clockdrv.c               | 202 +++++++++++++++++++++++
 bsps/riscv/griscv/config/griscv.cfg              |   9 +
 bsps/riscv/griscv/console/console.c              | 162 ++++++++++++++++++
 bsps/riscv/griscv/console/printk_support.c       | 126 ++++++++++++++
 bsps/riscv/griscv/headers.am                     |  11 ++
 bsps/riscv/griscv/include/amba.h                 | 143 ++++++++++++++++
 bsps/riscv/griscv/include/bsp.h                  |  66 ++++++++
 bsps/riscv/griscv/include/bsp/irq.h              |  73 ++++++++
 bsps/riscv/griscv/include/tm27.h                 |   1 +
 bsps/riscv/griscv/irq/irq.c                      | 144 ++++++++++++++++
 bsps/riscv/griscv/start/amba.c                   | 115 +++++++++++++
 bsps/riscv/griscv/start/bsp_fatal_halt.c         |  36 ++++
 bsps/riscv/griscv/start/bsp_specs                |   9 +
 bsps/riscv/griscv/start/bspsmp.c                 |  97 +++++++++++
 bsps/riscv/griscv/start/bspstart.c               |  70 ++++++++
 bsps/riscv/griscv/start/linkcmds.in              |  46 ++++++
 bsps/riscv/riscv/clock/clockdrv.c                |   5 +
 bsps/riscv/{riscv => shared}/start/linkcmds.base |   0
 bsps/riscv/{riscv => shared}/start/start.S       |   0
 c/src/lib/libbsp/riscv/acinclude.m4              |   2 +
 c/src/lib/libbsp/riscv/griscv/Makefile.am        |  70 ++++++++
 c/src/lib/libbsp/riscv/griscv/configure.ac       |  40 +++++
 c/src/lib/libbsp/riscv/riscv/Makefile.am         |   4 +-
 cpukit/score/cpu/riscv/include/rtems/score/cpu.h |   5 +-
 24 files changed, 1430 insertions(+), 6 deletions(-)

diff --git a/bsps/riscv/griscv/clock/clockdrv.c b/bsps/riscv/griscv/clock/clockdrv.c
new file mode 100644
index 0000000..47ed6b3
--- /dev/null
+++ b/bsps/riscv/griscv/clock/clockdrv.c
@@ -0,0 +1,202 @@
+/*
+ *  Clock Tick Device Driver
+ *
+ *  This routine initializes GRLIB gptimer 1 which used for the clock tick.
+ *
+ *  The tick frequency is directly programmed to the configured number of
+ *  microseconds per tick.
+ *
+ *  COPYRIGHT (c) 1989-2006.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  Modified for GRLIB BSP.
+ *  COPYRIGHT (c) 2004.
+ *  Gaisler Research.
+ *
+ *  Copyright (c) 2014, 2018 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 <bsp.h>
+#include <amba.h>
+#include <bsp/irq.h>
+#include <bspopts.h>
+#include <bsp/fatal.h>
+#include <rtems/rtems/intr.h>
+#include <grlib/ambapp.h>
+#include <rtems/score/profiling.h>
+#include <rtems/timecounter.h>
+#include <rtems/score/cpuimpl.h>
+#include <rtems/score/riscv-utility.h>
+
+volatile uint32_t _RISCV_Counter_register;
+
+/* The GRLIB BSP Timer driver can rely on the Driver Manager if the
+ * DrvMgr is initialized during startup. Otherwise the classic driver
+ * must be used.
+ *
+ * The DrvMgr Clock driver is located in the shared/timer directory
+ */
+#ifndef RTEMS_DRVMGR_STARTUP
+
+/* GRLIB Timer system interrupt number */
+static int clkirq;
+
+static void (*grlib_tc_tick)(void);
+
+static struct timecounter grlib_tc;
+
+#ifdef RTEMS_PROFILING
+#define IRQMP_TIMESTAMP_S1_S2 ((1U << 25) | (1U << 26))
+
+static void grlib_tc_tick_irqmp_timestamp(void)
+{
+  volatile struct irqmp_timestamp_regs *irqmp_ts =
+    &GRLIB_IrqCtrl_Regs->timestamp[0];
+  unsigned int first = irqmp_ts->assertion;
+  unsigned int second = irqmp_ts->counter;
+
+  irqmp_ts->control |= IRQMP_TIMESTAMP_S1_S2;
+
+  _Profiling_Update_max_interrupt_delay(_Per_CPU_Get(), second - first);
+
+  rtems_timecounter_tick();
+}
+#endif
+
+static void grlib_tc_tick_irqmp_timestamp_init(void)
+{
+#ifdef RTEMS_PROFILING
+  /*
+   * Ignore the first clock interrupt, since it contains the sequential system
+   * initialization time.  Do the timestamp initialization on the fly.
+   */
+
+#ifdef RTEMS_SMP
+  static Atomic_Uint counter = ATOMIC_INITIALIZER_UINT(0);
+
+  bool done =
+    _Atomic_Fetch_add_uint(&counter, 1, ATOMIC_ORDER_RELAXED)
+      == rtems_get_processor_count() - 1;
+#else
+  bool done = true;
+#endif
+
+  volatile struct irqmp_timestamp_regs *irqmp_ts =
+    &GRLIB_IrqCtrl_Regs->timestamp[0];
+  unsigned int ks = 1U << 5;
+
+  irqmp_ts->control = ks | IRQMP_TIMESTAMP_S1_S2 | (unsigned int) clkirq;
+
+  if (done) {
+    grlib_tc_tick = grlib_tc_tick_irqmp_timestamp;
+  }
+#endif
+
+  rtems_timecounter_tick();
+}
+
+static void grlib_tc_do_tick(void)
+{
+  (*grlib_tc_tick)();
+}
+
+#define Adjust_clkirq_for_node() do { clkirq += GRLIB_CLOCK_INDEX; } while(0)
+
+#define Clock_driver_support_find_timer() \
+  do { \
+    /* Assume timer found during BSP initialization */ \
+    if (GRLIB_Timer_Regs) { \
+      clkirq = (GRLIB_Timer_Regs->cfg & 0xf8) >> 3; \
+      \
+      Adjust_clkirq_for_node(); \
+    } \
+  } while (0)
+
+#define Clock_driver_support_install_isr( _new ) \
+  bsp_clock_handler_install(_new)
+
+static void bsp_clock_handler_install(rtems_isr *new)
+{
+  rtems_status_code sc;
+
+  sc = rtems_interrupt_handler_install(
+    clkirq,
+    "Clock",
+    RTEMS_INTERRUPT_UNIQUE,
+    new,
+    NULL
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    rtems_fatal(RTEMS_FATAL_SOURCE_BSP, LEON3_FATAL_CLOCK_INITIALIZATION);
+  }
+}
+
+#define Clock_driver_support_set_interrupt_affinity(online_processors) \
+  bsp_interrupt_set_affinity(clkirq, online_processors)
+
+uint32_t _CPU_Counter_frequency( void )
+{
+  return grlib_up_counter_frequency();
+}
+
+
+static uint32_t _RISCV_Get_timecount_csr(struct timecounter *tc)
+{
+  return read_csr(time);
+}
+
+static void grlib_clock_initialize(void)
+{
+  volatile struct gptimer_regs *gpt;
+  struct timecounter *tc;
+
+  gpt = GRLIB_Timer_Regs;
+  tc = &grlib_tc;
+
+  gpt->timer[GRLIB_CLOCK_INDEX].reload =
+    rtems_configuration_get_microseconds_per_tick() - 1;
+  gpt->timer[GRLIB_CLOCK_INDEX].ctrl =
+    GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_RS |
+      GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_IE;
+
+    /* Use the RISCV time register as up-counter */
+  tc->tc_get_timecount = _RISCV_Get_timecount_csr;
+  tc->tc_frequency = grlib_up_counter_frequency();
+
+#ifdef RTEMS_PROFILING
+  volatile struct irqmp_timestamp_regs *irqmp_ts =
+    &GRLIB_IrqCtrl_Regs->timestamp[0];
+
+    if (!grlib_irqmp_has_timestamp(irqmp_ts)) {
+      bsp_fatal(GRLIB_FATAL_CLOCK_NO_IRQMP_TIMESTAMP_SUPPORT);
+    }
+#endif
+
+  grlib_tc_tick = grlib_tc_tick_irqmp_timestamp_init;
+
+  tc->tc_counter_mask = 0xffffffff;
+  tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+  rtems_timecounter_install(tc);
+}
+
+CPU_Counter_ticks _CPU_Counter_read( void )
+{
+  unsigned long timec;
+
+  __asm__ volatile ( "csrr %0, time" : "=&r" ( timec ) );
+
+  return timec;
+}
+
+#define Clock_driver_support_initialize_hardware() \
+  grlib_clock_initialize()
+
+#define Clock_driver_timecounter_tick() grlib_tc_do_tick()
+
+#include "../../../shared/dev/clock/clockimpl.h"
+
+#endif
diff --git a/bsps/riscv/griscv/config/griscv.cfg b/bsps/riscv/griscv/config/griscv.cfg
new file mode 100644
index 0000000..bd4a0ca
--- /dev/null
+++ b/bsps/riscv/griscv/config/griscv.cfg
@@ -0,0 +1,9 @@
+include $(RTEMS_ROOT)/make/custom/default.cfg
+
+RTEMS_CPU = riscv
+
+CPU_CFLAGS = -march=rv32imafc -mabi=ilp32f
+
+LDFLAGS = -Wl,--gc-sections
+
+CFLAGS_OPTIMIZE_V ?= -O2 -g -ffunction-sections -fdata-sections
diff --git a/bsps/riscv/griscv/console/console.c b/bsps/riscv/griscv/console/console.c
new file mode 100644
index 0000000..582b4c8
--- /dev/null
+++ b/bsps/riscv/griscv/console/console.c
@@ -0,0 +1,162 @@
+/*
+ *  This file contains the TTY driver for the GRLIB APBUART
+ *
+ *  This driver uses the termios pseudo driver.
+ *
+ *  COPYRIGHT (c) 1989-1998.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  Modified for GRLIB BSP.
+ *  COPYRIGHT (c) 2004.
+ *  Gaisler Research.
+ *
+ *  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.
+ */
+
+/* Define CONSOLE_USE_INTERRUPTS to enable APBUART interrupt handling instead
+ * of polling mode.
+ *
+ * Note that it is not possible to use the interrupt mode of the driver
+ * together with the "old" APBUART and -u to GRMON. However the new
+ * APBUART core (from GRLIB 1.0.17-b2710) has the GRMON debug bit and can 
+ * handle interrupts.
+ *
+ * NOTE: This can be defined in the griscv.cfg file.
+ */
+
+#include <bsp.h>
+#include <bsp/fatal.h>
+#include <amba.h>
+#include <grlib/ambapp.h>
+#include <grlib/apbuart_termios.h>
+#include <rtems/console.h>
+#include <string.h>
+
+/* The GRLIB BSP UART driver can rely on the Driver Manager if the
+ * DrvMgr is initialized during startup. Otherwise the classic driver
+ * must be used.
+ *
+ * The DrvMgr APBUART driver is located in the shared/uart directory
+ */
+#ifndef RTEMS_DRVMGR_STARTUP
+
+int syscon_uart_index __attribute__((weak)) = 0;
+
+/* body is in debugputs.c */
+static struct apbuart_context apbuarts[BSP_NUMBER_OF_TERMIOS_PORTS];
+static int uarts = 0;
+
+static rtems_termios_device_context *grlib_console_get_context(int index)
+{
+  struct apbuart_context *uart = &apbuarts[index];
+
+  rtems_termios_device_context_initialize(&uart->base, "APBUART");
+
+  return &uart->base;
+}
+
+/* AMBA PP find routine. Extract AMBA PnP information into data structure. */
+static int find_matching_apbuart(struct ambapp_dev *dev, int index, void *arg)
+{
+  struct ambapp_apb_info *apb = (struct ambapp_apb_info *)dev->devinfo;
+
+  /* Extract needed information of one APBUART */
+  apbuarts[uarts].regs = (struct apbuart_regs *)apb->start;
+  apbuarts[uarts].irq = apb->irq;
+  /* Get APBUART core frequency, it is assumed that it is the same
+   * as Bus frequency where the UART is situated
+   */
+  apbuarts[uarts].freq_hz = ambapp_freq_get(&ambapp_plb, dev);
+  uarts++;
+
+  if (uarts >= BSP_NUMBER_OF_TERMIOS_PORTS)
+    return 1; /* Satisfied number of UARTs, stop search */
+  else
+    return 0; /* Continue searching for more UARTs */
+}
+
+/* Find all UARTs */
+static void grlib_console_scan_uarts(void)
+{
+  memset(apbuarts, 0, sizeof(apbuarts));
+
+  /* Find APBUART cores */
+  ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS), VENDOR_GAISLER,
+                  GAISLER_APBUART, find_matching_apbuart, NULL);
+}
+
+rtems_device_driver console_initialize(
+  rtems_device_major_number  major,
+  rtems_device_minor_number  minor,
+  void                      *arg
+)
+{
+  const rtems_termios_device_handler *handler =
+#if CONSOLE_USE_INTERRUPTS
+    &apbuart_handler_interrupt;
+#else
+    &apbuart_handler_polled;
+#endif
+  rtems_status_code status;
+  int i;
+  char console_name[16];
+
+  rtems_termios_initialize();
+
+  /* Find UARTs */
+  grlib_console_scan_uarts();
+
+  /* Update syscon_uart_index to index used as /dev/console
+   * Let user select System console by setting syscon_uart_index. If the
+   * BSP is to provide the default UART (syscon_uart_index==0):
+   *   non-MP: APBUART[0] is system console
+   *   MP: LEON CPU index select UART
+   */
+  if (syscon_uart_index == 0) {
+#if defined(RTEMS_MULTIPROCESSING)
+    syscon_uart_index = GRLIB_Cpu_Index;
+#else
+    syscon_uart_index = 0;
+#endif
+  } else {
+    syscon_uart_index = syscon_uart_index - 1; /* User selected sys-console */
+  }
+
+  /*  Register Device Names
+   *
+   *  0 /dev/console   - APBUART[USER-SELECTED, DEFAULT=APBUART[0]]
+   *  1 /dev/console_a - APBUART[0] (by default not present because is console)
+   *  2 /dev/console_b - APBUART[1]
+   *  ...
+   *
+   * On a MP system one should not open UARTs that other OS instances use.
+   */
+  if (syscon_uart_index < uarts) {
+    status = rtems_termios_device_install(
+      CONSOLE_DEVICE_NAME,
+      handler,
+      NULL,
+      grlib_console_get_context(syscon_uart_index)
+    );
+    if (status != RTEMS_SUCCESSFUL)
+      bsp_fatal(LEON3_FATAL_CONSOLE_REGISTER_DEV);
+  }
+  strcpy(console_name,"/dev/console_a");
+  for (i = 0; i < uarts; i++) {
+    if (i == syscon_uart_index)
+      continue; /* skip UART that is registered as /dev/console */
+    console_name[13] = 'a' + i;
+    rtems_termios_device_install(
+      console_name,
+      handler,
+      NULL,
+      grlib_console_get_context(i)
+    );
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+#endif
diff --git a/bsps/riscv/griscv/console/printk_support.c b/bsps/riscv/griscv/console/printk_support.c
new file mode 100644
index 0000000..f8c1469
--- /dev/null
+++ b/bsps/riscv/griscv/console/printk_support.c
@@ -0,0 +1,126 @@
+/*
+ *  This file contains the TTY driver for the GRLIb APBUART
+ *
+ *  This driver uses the termios pseudo driver.
+ *
+ *  COPYRIGHT (c) 1989-1999.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  Modified for GRLIB BSP.
+ *  COPYRIGHT (c) 2011.
+ *  Aeroflex Gaisler.
+ *
+ *  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 <bsp.h>
+#include <amba.h>
+#include <rtems/libio.h>
+#include <rtems/sysinit.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <grlib/apbuart.h>
+#include <grlib/ambapp.h>
+
+int grlib_debug_uart_index __attribute__((weak)) = 0;
+struct apbuart_regs *grlib_debug_uart = NULL;
+
+/* Before UART driver has registered (or when no UART is available), calls to
+ * printk that gets to bsp_out_char() will be filling data into the
+ * pre_printk_dbgbuf[] buffer, hopefully the buffer can help debugging the
+ * early BSP boot.. At least the last printk() will be caught.
+ *
+static char pre_printk_dbgbuf[32] = {0};
+static int pre_printk_pos = 0;
+ */
+
+/* Initialize the BSP system debug console layer. It will scan AMBA Plu&Play
+ * for a debug APBUART and enable RX/TX for that UART.
+ */
+static void bsp_debug_uart_init(void)
+{
+  int i;
+  struct ambapp_dev *adev;
+  struct ambapp_apb_info *apb;
+
+  /* Update grlib_debug_uart_index to index used as debug console. Let user
+   * select Debug console by setting grlib_debug_uart_index. If the BSP is to
+   * provide the default UART (grlib_debug_uart_index==0):
+   *   non-MP: APBUART[0] is debug console
+   *   MP: LEON CPU index select UART
+   */
+  if (grlib_debug_uart_index == 0) {
+#if defined(RTEMS_MULTIPROCESSING)
+    grlib_debug_uart_index = GRLIB_Cpu_Index;
+#else
+    grlib_debug_uart_index = 0;
+#endif
+  } else {
+    grlib_debug_uart_index--; /* User selected dbg-console */
+  }
+
+  /* Find APBUART core for System Debug Console */
+  i = grlib_debug_uart_index;
+  adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
+                                 VENDOR_GAISLER, GAISLER_APBUART,
+                                 ambapp_find_by_idx, (void *)&i);
+  if (adev) {
+    /* Found a matching debug console, initialize debug uart if present
+     * for printk
+     */
+    apb = (struct ambapp_apb_info *)adev->devinfo;
+    grlib_debug_uart = (struct apbuart_regs *)apb->start;
+    grlib_debug_uart->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
+    grlib_debug_uart->status = 0;
+  }
+}
+
+RTEMS_SYSINIT_ITEM(
+  bsp_debug_uart_init,
+  RTEMS_SYSINIT_BSP_START,
+  RTEMS_SYSINIT_ORDER_FOURTH
+);
+
+/* putchar/getchar for printk */
+static void bsp_out_char(char c)
+{
+  if (grlib_debug_uart == NULL) {
+    /* Try to assign standard UART address to debug driver to pass some tests */
+    grlib_debug_uart = (struct apbuart_regs *) 0x80000100;
+    grlib_debug_uart->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
+    grlib_debug_uart->status = 0;
+    /* Local debug buffer when UART driver has not registered */
+    /*
+    pre_printk_dbgbuf[pre_printk_pos++] = c;
+    pre_printk_pos = pre_printk_pos & (sizeof(pre_printk_dbgbuf)-1);
+    return;
+    */
+  }
+
+  apbuart_outbyte_polled(grlib_debug_uart, c, 1, 1);
+}
+
+/*
+ *  To support printk
+ */
+
+#include <rtems/bspIo.h>
+
+BSP_output_char_function_type BSP_output_char = bsp_out_char;
+
+static int bsp_in_char(void)
+{
+  int tmp;
+
+  if (grlib_debug_uart == NULL)
+    return EOF;
+
+  while ((tmp = apbuart_inbyte_nonblocking(grlib_debug_uart)) < 0)
+    ;
+  return tmp;
+}
+
+BSP_polling_getchar_function_type BSP_poll_char = bsp_in_char;
diff --git a/bsps/riscv/griscv/headers.am b/bsps/riscv/griscv/headers.am
new file mode 100644
index 0000000..f351d7c
--- /dev/null
+++ b/bsps/riscv/griscv/headers.am
@@ -0,0 +1,11 @@
+## This file was generated by "./boostrap -H".
+
+include_HEADERS =
+include_HEADERS += ../../../../../../bsps/riscv/griscv/include/amba.h
+include_HEADERS += ../../../../../../bsps/riscv/griscv/include/bsp.h
+include_HEADERS += include/bspopts.h
+include_HEADERS += ../../../../../../bsps/riscv/griscv/include/tm27.h
+
+include_bspdir = $(includedir)/bsp
+include_bsp_HEADERS =
+include_bsp_HEADERS += ../../../../../../bsps/riscv/griscv/include/bsp/irq.h
diff --git a/bsps/riscv/griscv/include/amba.h b/bsps/riscv/griscv/include/amba.h
new file mode 100644
index 0000000..e1c5c00
--- /dev/null
+++ b/bsps/riscv/griscv/include/amba.h
@@ -0,0 +1,143 @@
+/**
+ * @file
+ * @defgroup amba AMBA Driver Handler
+ * @ingroup sparc_leon3
+ * @brief AMBA Plag & Play Bus Driver Macros
+ */
+
+/*
+ *  AMBA Plag & Play Bus Driver Macros
+ *
+ *  Macros used for AMBA Plug & Play bus scanning
+ *
+ *  COPYRIGHT (c) 2004.
+ *  Gaisler Research
+ *
+ *  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.
+ */
+
+#ifndef __AMBA_H__
+#define __AMBA_H__
+
+#ifndef GRLIB_IO_AREA
+#define GRLIB_IO_AREA 0xfff00000
+#endif
+
+#define GRLIB_CONF_AREA 0xff000
+#define GRLIB_AHB_SLAVE_CONF_AREA (1 << 11)
+
+#define GRLIB_AHB_CONF_WORDS 8
+#define GRLIB_APB_CONF_WORDS 2
+#define GRLIB_AHB_MASTERS 64
+#define GRLIB_AHB_SLAVES 64
+#define GRLIB_APB_SLAVES 16
+
+#if defined(RTEMS_MULTIPROCESSING)
+  #define GRLIB_CLOCK_INDEX \
+   (rtems_configuration_get_user_multiprocessing_table() ? GRLIB_Cpu_Index : 0)
+#else
+  #define GRLIB_CLOCK_INDEX 0
+#endif
+
+#if defined(RTEMS_SMP)
+#define GRLIB_COUNTER_GPTIMER_INDEX (GRLIB_CLOCK_INDEX + 1)
+#else
+#define GRLIB_COUNTER_GPTIMER_INDEX GRLIB_CLOCK_INDEX
+#endif
+
+#define GRLIB_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER 1000000
+
+#define GRLIB_IRQMPSTATUS_CPUNR     28
+
+#include <grlib/ambapp.h>
+#include <grlib/grlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The AMBA Plug&Play info of the bus that the cpu sits on */
+extern struct ambapp_bus ambapp_plb;
+
+extern uint32_t GRLIB_Cpu_Index;
+extern const unsigned char GRLIB_mp_irq;
+
+extern volatile struct irqmp_regs *GRLIB_IrqCtrl_Regs;
+extern struct ambapp_dev *GRLIB_IrqCtrl_Adev;
+extern int GRLIB_IrqCtrl_EIrq;
+extern volatile struct gptimer_regs *GRLIB_Timer_Regs;
+extern struct ambapp_dev *GRLIB_Timer_Adev;
+void gptimer_initialize(void);
+void irqmp_initialize(void);
+
+static inline uint32_t grlib_up_counter_frequency(void)
+{
+  /*
+   * For simplicity, assume that the interrupt controller uses the processor
+   * clock.  This is at least true on the GR740.
+   */
+  return ambapp_freq_get(&ambapp_plb, GRLIB_IrqCtrl_Adev);
+}
+
+extern rtems_interrupt_lock GRLIB_IrqCtrl_Lock;
+
+
+static inline uint32_t grlib_get_cpu_count(
+  volatile struct irqmp_regs *irqmp
+)
+{
+  uint32_t mpstat = irqmp->mpstat;
+
+  return ((mpstat >> GRLIB_IRQMPSTATUS_CPUNR) & 0xf)  + 1;
+}
+
+#define GRLIB_IRQCTRL_ACQUIRE( _lock_context ) \
+  rtems_interrupt_lock_acquire( &GRLIB_IrqCtrl_Lock, _lock_context )
+
+#define GRLIB_IRQCTRL_RELEASE( _lock_context ) \
+  rtems_interrupt_lock_release( &GRLIB_IrqCtrl_Lock, _lock_context )
+
+#define GRLIB_Cpu_Unmask_interrupt( _source, _cpu ) \
+  do { \
+    rtems_interrupt_lock_context _lock_context; \
+    GRLIB_IRQCTRL_ACQUIRE( &_lock_context ); \
+    GRLIB_IrqCtrl_Regs->mask[_cpu]  |= (1U << (_source)); \
+    GRLIB_IRQCTRL_RELEASE( &_lock_context ); \
+  } while (0)
+
+#define GRLIB_Cpu_Mask_interrupt( _source, _cpu ) \
+  do { \
+    rtems_interrupt_lock_context _lock_context; \
+    GRLIB_IRQCTRL_ACQUIRE( &_lock_context ); \
+     GRLIB_IrqCtrl_Regs->mask[_cpu]  &= ~(1U << (_source)); \
+    GRLIB_IRQCTRL_RELEASE( &_lock_context ); \
+  } while (0)
+
+#define GRLIB_Enable_interrupt_broadcast( _source ) \
+  do { \
+    rtems_interrupt_lock_context _lock_context; \
+    uint32_t _mask = 1U << ( _source ); \
+    GRLIB_IRQCTRL_ACQUIRE( &_lock_context ); \
+    GRLIB_IrqCtrl_Regs->bcast |= _mask; \
+    GRLIB_IRQCTRL_RELEASE( &_lock_context ); \
+  } while (0)
+
+#define GRLIB_Disable_interrupt_broadcast( _source ) \
+  do { \
+    rtems_interrupt_lock_context _lock_context; \
+    uint32_t _mask = 1U << ( _source ); \
+    GRLIB_IRQCTRL_ACQUIRE( &_lock_context ); \
+    GRLIB_IrqCtrl_Regs->bcast &= ~_mask; \
+    GRLIB_IRQCTRL_RELEASE( &_lock_context ); \
+  } while (0)
+
+#define BSP_Cpu_Is_interrupt_masked( _source, _cpu ) \
+     (!(GRLIB_IrqCtrl_Regs->mask[_cpu] & (1U << (_source))))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __AMBA_H__ */
diff --git a/bsps/riscv/griscv/include/bsp.h b/bsps/riscv/griscv/include/bsp.h
new file mode 100644
index 0000000..185bd5b
--- /dev/null
+++ b/bsps/riscv/griscv/include/bsp.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham Almatary <hesham at alumni.york.ac.uk>
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LIBBSP_RISCV_GRISCV_H
+#define LIBBSP_RISCV_GRISCV_H
+
+#include <rtems.h>
+#include <rtems/clockdrv.h>
+#include <rtems/console.h>
+#include <rtems/irq-extension.h>
+
+#include <bspopts.h>
+#include <bsp/default-initial-extension.h>
+
+#include <rtems/devnull.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BSP_FEATURE_IRQ_EXTENSION
+
+/* Maximum supported APBUARTs by BSP */
+#define BSP_NUMBER_OF_TERMIOS_PORTS 8
+
+/* Make sure maximum number of consoles fit in filesystem */
+#define BSP_MAXIMUM_DEVICES 8
+
+/* GRLIB driver functions */
+
+extern void BSP_shared_interrupt_mask(int irq);
+extern void BSP_shared_interrupt_clear(int irq);
+extern void BSP_shared_interrupt_unmask(int irq);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBBSP_RISCV_GRISCV_H */
diff --git a/bsps/riscv/griscv/include/bsp/irq.h b/bsps/riscv/griscv/include/bsp/irq.h
new file mode 100644
index 0000000..cd6f159
--- /dev/null
+++ b/bsps/riscv/griscv/include/bsp/irq.h
@@ -0,0 +1,73 @@
+/**
+ * @file
+ *
+ * @ingroup RISCV_IRQ
+ *
+ * @brief Interrupt definitions.
+ */
+
+/*
+ * Copyright (c) 2018 embedded brains GmbH
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham Almatary <hesham at alumni.york.ac.uk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef LIBBSP_RISCV_GRISCV_IRQ_H
+#define LIBBSP_RISCV_GRISCV_IRQ_H
+
+#ifndef ASM
+
+#include <bsp.h>
+#include <rtems/irq.h>
+#include <rtems/irq-extension.h>
+#include <rtems/score/processormask.h>
+
+#define RISCV_INTERRUPT_VECTOR_SOFTWARE 0
+
+#define RISCV_INTERRUPT_VECTOR_TIMER 1
+
+#define RISCV_INTERRUPT_VECTOR_EXTERNAL(x) ((x) + 2)
+
+#define RISCV_INTERRUPT_VECTOR_IS_EXTERNAL(x) ((x) >= 2)
+
+#define RISCV_INTERRUPT_VECTOR_EXTERNAL_TO_INDEX(x) ((x) - 2)
+
+#define BSP_INTERRUPT_VECTOR_MIN 0
+
+#define BSP_INTERRUPT_VECTOR_MAX RISCV_INTERRUPT_VECTOR_EXTERNAL(RISCV_MAXIMUM_EXTERNAL_INTERRUPTS - 1)
+
+void bsp_interrupt_set_affinity(
+  rtems_vector_number vector,
+  const Processor_mask *affinity
+);
+
+void bsp_interrupt_get_affinity(
+  rtems_vector_number vector,
+  Processor_mask *affinity
+);
+
+#endif /* ASM */
+
+#endif /* LIBBSP_RISCV_GRISCV_IRQ_H */
diff --git a/bsps/riscv/griscv/include/tm27.h b/bsps/riscv/griscv/include/tm27.h
new file mode 100644
index 0000000..0dfa7bf
--- /dev/null
+++ b/bsps/riscv/griscv/include/tm27.h
@@ -0,0 +1 @@
+#include <rtems/tm27-default.h>
diff --git a/bsps/riscv/griscv/irq/irq.c b/bsps/riscv/griscv/irq/irq.c
new file mode 100644
index 0000000..721cd98
--- /dev/null
+++ b/bsps/riscv/griscv/irq/irq.c
@@ -0,0 +1,144 @@
+/**
+ * @file
+ *
+ * @ingroup riscv_interrupt
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ * Copyright (c) 2018 embedded brains GmbH
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham Almatary <hesham at alumni.york.ac.uk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <bsp/irq.h>
+#include <bsp/fatal.h>
+#include <bsp/irq-generic.h>
+#include <amba.h>
+
+#include <rtems/score/percpu.h>
+#include <rtems/score/riscv-utility.h>
+#include <rtems/score/smpimpl.h>
+
+rtems_interrupt_lock GRLIB_IrqCtrl_Lock;
+
+#if defined(RTEMS_SMP)
+/* Interrupt to CPU map. Default to CPU0 since in BSS. */
+const unsigned char GRLIB_irq_to_cpu[32] __attribute__((weak));
+
+/* On SMP use map table above relative to SMP Boot CPU (normally CPU0) */
+static inline int bsp_irq_cpu(int irq)
+{
+  /* protect from bad user configuration, default to boot cpu */
+  if (rtems_configuration_get_maximum_processors() <= GRLIB_irq_to_cpu[irq])
+    return GRLIB_Cpu_Index;
+  else
+    return GRLIB_Cpu_Index + GRLIB_irq_to_cpu[irq];
+}
+#else
+/* when not SMP the local CPU is returned */
+static inline int bsp_irq_cpu(int irq)
+{
+  return read_csr(mhartid);
+}
+#endif
+
+void _RISCV_Interrupt_dispatch(uintptr_t mcause, Per_CPU_Control *cpu_self)
+{
+  if (mcause & 0x80000000) {
+
+    bsp_interrupt_handler_dispatch(mcause & 0xf);
+
+  } else {
+    bsp_fatal(RISCV_FATAL_UNEXPECTED_INTERRUPT_EXCEPTION);
+  }
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+
+  /*
+   * External M-mode interrupts on secondary processors are enabled in
+   * bsp_start_on_secondary_processor().
+   */
+  set_csr(mie, MIP_MEIP);
+
+  return RTEMS_SUCCESSFUL;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+  int irq = (int)vector;
+  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+  GRLIB_Cpu_Unmask_interrupt(irq, bsp_irq_cpu(irq));
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+  int irq = (int)vector;
+  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+  GRLIB_Cpu_Mask_interrupt(irq, bsp_irq_cpu(irq));
+}
+
+void bsp_interrupt_get_affinity(
+  rtems_vector_number vector,
+  Processor_mask *affinity
+)
+{
+  uint32_t cpu_count = rtems_get_processor_count();
+  uint32_t cpu_index;
+
+  _Processor_mask_Zero(affinity);
+
+  for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
+    if (!BSP_Cpu_Is_interrupt_masked(vector, cpu_index)) {
+      _Processor_mask_Set(affinity, cpu_index);
+    }
+  }
+}
+
+void bsp_interrupt_set_affinity(
+  rtems_vector_number vector,
+  const Processor_mask *affinity
+)
+{
+  uint32_t unmasked = 0;
+  uint32_t cpu_count = rtems_get_processor_count();
+  uint32_t cpu_index;
+
+  for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
+    if (_Processor_mask_Is_set(affinity, cpu_index)) {
+      GRLIB_Cpu_Unmask_interrupt(vector, cpu_index);
+      ++unmasked;
+    }
+  }
+
+  if (unmasked > 1) {
+    GRLIB_Enable_interrupt_broadcast(vector);
+  } else {
+    GRLIB_Disable_interrupt_broadcast(vector);
+  }
+}
diff --git a/bsps/riscv/griscv/start/amba.c b/bsps/riscv/griscv/start/amba.c
new file mode 100644
index 0000000..182f659
--- /dev/null
+++ b/bsps/riscv/griscv/start/amba.c
@@ -0,0 +1,115 @@
+
+/*
+ *  Find and initialize irqmp and gptimer.
+ *  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 <bsp.h>
+#include <bsp/fatal.h>
+#include <amba.h>
+
+rtems_interrupt_lock GRLIB_IrqCtrl_Lock =
+  RTEMS_INTERRUPT_LOCK_INITIALIZER("GRLIB IrqCtrl");
+
+/* Pointers to Interrupt Controller configuration registers */
+volatile struct irqmp_regs *GRLIB_IrqCtrl_Regs;
+struct ambapp_dev *GRLIB_IrqCtrl_Adev;
+
+/* GRLIB extended IRQ controller IRQ number */
+int GRLIB_IrqCtrl_EIrq = -1;
+
+/* Initialize Extended Interrupt controller */
+static void grlib_ext_irq_init(void)
+{
+  if ( (GRLIB_IrqCtrl_Regs->mpstat >> 16) & 0xf ) {
+    /* Extended IRQ controller available */
+    GRLIB_IrqCtrl_EIrq = (GRLIB_IrqCtrl_Regs->mpstat >> 16) & 0xf;
+  }
+}
+
+/*
+ *  irqmp_initialize
+ *
+ *  Probes for IRQMP and initialises necessary registers.
+ *
+ */
+
+void irqmp_initialize(void)
+{
+  int icsel;
+  struct ambapp_dev *adev;
+
+  /* Find GRLIB Interrupt controller */
+  adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
+                                 VENDOR_GAISLER, GAISLER_IRQMP,
+                                 ambapp_find_by_idx, NULL);
+  if (adev != NULL) {
+
+    GRLIB_IrqCtrl_Regs = (volatile struct irqmp_regs *)DEV_TO_APB(adev)->start;
+    GRLIB_IrqCtrl_Adev = adev;
+    if ((GRLIB_IrqCtrl_Regs->ampctrl >> 28) > 0) {
+    /* IRQ Controller has support for multiple IRQ Controllers, each
+     * CPU can be routed to different Controllers, we find out which
+     * controller by looking at the IRQCTRL Select Register for this CPU.
+     * Each Controller is located at a 4KByte offset.
+     */
+      icsel = GRLIB_IrqCtrl_Regs->icsel[GRLIB_Cpu_Index/8];
+      icsel = (icsel >> ((7 - (GRLIB_Cpu_Index & 0x7)) * 4)) & 0xf;
+      GRLIB_IrqCtrl_Regs += icsel;
+    }
+    GRLIB_IrqCtrl_Regs->mask[GRLIB_Cpu_Index] = 0;
+    GRLIB_IrqCtrl_Regs->force[GRLIB_Cpu_Index] = 0;
+    GRLIB_IrqCtrl_Regs->iclear = 0xffffffff;
+
+  /* Init Extended IRQ controller if available */
+    grlib_ext_irq_init();
+
+  }
+
+}
+
+
+/* GPTIMER */
+
+unsigned int grlib_timer_prescaler __attribute__((weak)) = 0;
+int grlib_timer_core_index __attribute__((weak)) = 0;
+
+volatile struct gptimer_regs *GRLIB_Timer_Regs;
+struct ambapp_dev *GRLIB_Timer_Adev;
+
+/*
+ *  gptimer_initialize
+ *
+ */
+
+void gptimer_initialize(void)
+{
+  struct ambapp_dev *adev;
+
+  /* find GP Timer */
+  adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
+                                 VENDOR_GAISLER, GAISLER_GPTIMER,
+                                 ambapp_find_by_idx, &grlib_timer_core_index);
+  if (adev) {
+    GRLIB_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start;
+    GRLIB_Timer_Adev = adev;
+
+    /* Register AMBA Bus Frequency */
+    ambapp_freq_init(
+      &ambapp_plb,
+      GRLIB_Timer_Adev,
+      (GRLIB_Timer_Regs->scaler_reload + 1)
+        * GRLIB_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER
+    );
+    /* Set user prescaler configuration. Use this to increase accuracy of timer
+     * and accociated services like cpucounter.
+     * Note that minimum value is the number of timer instances present in
+     * GRTIMER/GPTIMER hardware. See HW manual.
+     */
+    if (grlib_timer_prescaler)
+      GRLIB_Timer_Regs->scaler_reload = grlib_timer_prescaler;
+  }
+
+}
diff --git a/bsps/riscv/griscv/start/bsp_fatal_halt.c b/bsps/riscv/griscv/start/bsp_fatal_halt.c
new file mode 100644
index 0000000..ced328e
--- /dev/null
+++ b/bsps/riscv/griscv/start/bsp_fatal_halt.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham Almatary <hesham at alumni.york.ac.uk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <bsp.h>
+
+void _CPU_Fatal_halt(uint32_t source, uint32_t error)
+{
+    /* ecall is currently used to halt the griscv cpu */
+    asm ("ecall");
+    for(;;);
+}
diff --git a/bsps/riscv/griscv/start/bsp_specs b/bsps/riscv/griscv/start/bsp_specs
new file mode 100644
index 0000000..87638cc
--- /dev/null
+++ b/bsps/riscv/griscv/start/bsp_specs
@@ -0,0 +1,9 @@
+%rename endfile old_endfile
+%rename startfile old_startfile
+
+*startfile:
+%{!qrtems: %(old_startfile)} \
+%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}}
+
+*endfile:
+%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s}
diff --git a/bsps/riscv/griscv/start/bspsmp.c b/bsps/riscv/griscv/start/bspsmp.c
new file mode 100644
index 0000000..df826f8
--- /dev/null
+++ b/bsps/riscv/griscv/start/bspsmp.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <bsp/bootcard.h>
+#include <bsp/irq.h>
+#include <amba.h>
+
+#include <rtems/score/riscv-utility.h>
+#include <rtems/score/smpimpl.h>
+
+static rtems_isr bsp_inter_processor_interrupt( void *v )
+{
+  _SMP_Inter_processor_interrupt_handler(_Per_CPU_Get());
+}
+
+void bsp_start_on_secondary_processor(Per_CPU_Control *cpu_self)
+{
+  uint32_t cpu_index_self;
+
+  cpu_index_self = _Per_CPU_Get_index(cpu_self);
+  GRLIB_IrqCtrl_Regs->mask[cpu_index_self] |= 1U << GRLIB_mp_irq;
+
+  if (
+    cpu_index_self < rtems_configuration_get_maximum_processors()
+      && _SMP_Should_start_processor(cpu_index_self)
+  ) {
+    set_csr(mie, MIP_MEIP);
+    _SMP_Start_multitasking_on_secondary_processor(cpu_self);
+  } else {
+    _CPU_Thread_Idle_body(0);
+  }
+}
+
+uint32_t _CPU_SMP_Initialize(void)
+{
+  if ( rtems_configuration_get_maximum_processors() > 1 ) {
+    GRLIB_Cpu_Unmask_interrupt(GRLIB_mp_irq, _CPU_SMP_Get_current_processor());
+
+    rtems_interrupt_handler_install(
+      GRLIB_mp_irq,
+      "IPI",
+      RTEMS_INTERRUPT_SHARED,
+      bsp_inter_processor_interrupt,
+      NULL
+    );
+
+  }
+
+  return grlib_get_cpu_count(GRLIB_IrqCtrl_Regs);
+}
+
+bool _CPU_SMP_Start_processor(uint32_t cpu_index)
+{
+  GRLIB_IrqCtrl_Regs->mpstat = 1U << cpu_index;
+
+  return true;
+}
+
+void _CPU_SMP_Finalize_initialization(uint32_t cpu_count)
+{
+  (void) cpu_count;
+//  set_csr(mie, MIP_MSIP);
+}
+
+void _CPU_SMP_Prepare_start_multitasking(void)
+{
+  /* Do nothing */
+}
+
+void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
+{
+ 
+  GRLIB_IrqCtrl_Regs->force[target_processor_index] = 1 << GRLIB_mp_irq;
+
+}
diff --git a/bsps/riscv/griscv/start/bspstart.c b/bsps/riscv/griscv/start/bspstart.c
new file mode 100644
index 0000000..dd83c80
--- /dev/null
+++ b/bsps/riscv/griscv/start/bspstart.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <bsp/bootcard.h>
+#include <bsp/fatal.h>
+#include <bsp/irq-generic.h>
+
+#include <amba.h>
+#include <rtems/sysinit.h>
+
+#if defined(RTEMS_SMP) || defined(RTEMS_MULTIPROCESSING)
+/* Irq used by shared memory driver and for inter-processor interrupts.
+ * Can be overridden by being defined in the application.
+ */
+const unsigned char GRLIB_mp_irq __attribute__((weak)) = 14;
+#endif
+
+uint32_t GRLIB_Cpu_Index = 0;
+
+#ifdef RTEMS_SMP
+uint32_t riscv_hart_count = 1;
+/* Index of the boot CPU. Set by the first CPU at boot to its CPU ID. */
+int GRLIB_Boot_Cpu = -1;
+#endif
+
+void bsp_start(void)
+{
+  bsp_interrupt_initialize();
+#ifdef RTEMS_SMP
+  GRLIB_Cpu_Index = _CPU_SMP_Get_current_processor();
+#endif
+}
+
+void amba_initialize(void);
+struct ambapp_bus ambapp_plb;
+
+void amba_initialize(void)
+{
+  ambapp_scan(&ambapp_plb, GRLIB_IO_AREA, NULL, NULL);
+  gptimer_initialize();
+  irqmp_initialize();
+}
+
+RTEMS_SYSINIT_ITEM(
+  amba_initialize,
+  RTEMS_SYSINIT_BSP_START,
+  RTEMS_SYSINIT_ORDER_FIRST
+);
diff --git a/bsps/riscv/griscv/start/linkcmds.in b/bsps/riscv/griscv/start/linkcmds.in
new file mode 100644
index 0000000..80e2f5e
--- /dev/null
+++ b/bsps/riscv/griscv/start/linkcmds.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 University of York.
+ * Hesham ALMatary <hmka501 at york.ac.uk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+MEMORY
+{
+  RAM    : ORIGIN = @RISCV_RAM_REGION_BEGIN@, LENGTH = @RISCV_RAM_REGION_SIZE@
+}
+
+REGION_ALIAS ("REGION_START", RAM);
+REGION_ALIAS ("REGION_TEXT", RAM);
+REGION_ALIAS ("REGION_TEXT_LOAD", RAM);
+REGION_ALIAS ("REGION_FAST_TEXT", RAM);
+REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM);
+REGION_ALIAS ("REGION_RODATA", RAM);
+REGION_ALIAS ("REGION_RODATA_LOAD", RAM);
+REGION_ALIAS ("REGION_DATA", RAM);
+REGION_ALIAS ("REGION_DATA_LOAD", RAM);
+REGION_ALIAS ("REGION_FAST_DATA", RAM);
+REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM);
+REGION_ALIAS ("REGION_RTEMSSTACK", RAM);
+REGION_ALIAS ("REGION_WORK", RAM);
+
+INCLUDE linkcmds.base
diff --git a/bsps/riscv/riscv/clock/clockdrv.c b/bsps/riscv/riscv/clock/clockdrv.c
index 30a894f..7e6034d 100644
--- a/bsps/riscv/riscv/clock/clockdrv.c
+++ b/bsps/riscv/riscv/clock/clockdrv.c
@@ -189,6 +189,11 @@ uint32_t _CPU_Counter_frequency( void )
   return riscv_clock_get_timebase_frequency(bsp_fdt_get());
 }
 
+CPU_Counter_ticks _CPU_Counter_read( void )
+{
+  return *_RISCV_Counter;
+}
+
 RTEMS_SYSINIT_ITEM(
   riscv_counter_initialize,
   RTEMS_SYSINIT_CPU_COUNTER,
diff --git a/bsps/riscv/riscv/start/linkcmds.base b/bsps/riscv/shared/start/linkcmds.base
similarity index 100%
rename from bsps/riscv/riscv/start/linkcmds.base
rename to bsps/riscv/shared/start/linkcmds.base
diff --git a/bsps/riscv/riscv/start/start.S b/bsps/riscv/shared/start/start.S
similarity index 100%
rename from bsps/riscv/riscv/start/start.S
rename to bsps/riscv/shared/start/start.S
diff --git a/c/src/lib/libbsp/riscv/acinclude.m4 b/c/src/lib/libbsp/riscv/acinclude.m4
index d8b3319..db1a210 100644
--- a/c/src/lib/libbsp/riscv/acinclude.m4
+++ b/c/src/lib/libbsp/riscv/acinclude.m4
@@ -2,6 +2,8 @@
 AC_DEFUN([RTEMS_CHECK_BSPDIR],
 [
   case "$1" in
+  griscv )
+    AC_CONFIG_SUBDIRS([griscv]);;
   riscv )
     AC_CONFIG_SUBDIRS([riscv]);;
   *)
diff --git a/c/src/lib/libbsp/riscv/griscv/Makefile.am b/c/src/lib/libbsp/riscv/griscv/Makefile.am
new file mode 100644
index 0000000..4077dde
--- /dev/null
+++ b/c/src/lib/libbsp/riscv/griscv/Makefile.am
@@ -0,0 +1,70 @@
+##
+#
+# @brief Makefile of LibBSP for the RISCV/Spike simulator.
+#
+#
+ACLOCAL_AMFLAGS = -I ../../../../aclocal
+
+include $(top_srcdir)/../../../../automake/compile.am
+include $(top_srcdir)/../../bsp.am
+
+dist_project_lib_DATA = ../../../../../../bsps/riscv/griscv/start/bsp_specs
+
+###############################################################################
+#                  Header                                                     #
+###############################################################################
+
+###############################################################################
+#                  Data                                                       #
+###############################################################################
+
+start.$(OBJEXT): ../../../../../../bsps/riscv/shared/start/start.S
+	$(CPPASCOMPILE) -o $@ -c $<
+project_lib_DATA = start.$(OBJEXT)
+
+project_lib_DATA += linkcmds
+project_lib_DATA += ../../../../../../bsps/riscv/shared/start/linkcmds.base
+
+###############################################################################
+#                  LibBSP                                                     #
+###############################################################################
+
+project_lib_LIBRARIES = librtemsbsp.a
+
+# Startup
+librtemsbsp_a_SOURCES = ../../../../../../bsps/shared/start/bspreset-empty.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/start/bspstart.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/start/bsp_fatal_halt.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/start/amba.c
+
+# Shared
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspfatal-default.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/getentropy/getentropy-cpucounter.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspgetworkarea-default.c
+
+# clock
+librtemsbsp_a_SOURCES +=../../../../../../bsps/riscv/griscv/clock/clockdrv.c
+
+# Timer
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/btimer/btimer-stub.c
+
+# IRQ
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/irq/irq.c
+
+# Cache
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c
+
+# Console
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/console/console.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/console/printk_support.c
+
+if HAS_SMP
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/start/bspsmp.c
+endif
+
+include $(srcdir)/../../../../../../bsps/shared/irq-sources.am
+include $(srcdir)/../../../../../../bsps/shared/grlib-sources.am
+include $(srcdir)/../../../../../../bsps/shared/shared-sources.am
+include $(srcdir)/../../../../../../bsps/riscv/griscv/headers.am
diff --git a/c/src/lib/libbsp/riscv/griscv/configure.ac b/c/src/lib/libbsp/riscv/griscv/configure.ac
new file mode 100644
index 0000000..ed5694c
--- /dev/null
+++ b/c/src/lib/libbsp/riscv/griscv/configure.ac
@@ -0,0 +1,40 @@
+##
+#
+# @file
+#
+# @brief Configure script of LibBSP for riscv BSP.
+#
+
+AC_PREREQ([2.69])
+AC_INIT([rtems-c-src-lib-libbsp-riscv],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla])
+RTEMS_TOP(../../../../../..)
+RTEMS_SOURCE_TOP
+RTEMS_BUILD_TOP
+
+RTEMS_CANONICAL_TARGET_CPU
+AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.12.2])
+RTEMS_BSP_CONFIGURE
+
+RTEMS_BSPOPTS_SET([BSP_CONSOLE_BAUD],[*],[115200])
+RTEMS_BSPOPTS_HELP([BSP_CONSOLE_BAUD],[default baud for console driver devices (default 115200)])
+
+RTEMS_BSPOPTS_SET([RISCV_MAXIMUM_EXTERNAL_INTERRUPTS],[*],[64])
+RTEMS_BSPOPTS_HELP([RISCV_MAXIMUM_EXTERNAL_INTERRUPTS],[maximum number of external interrupts supported by the BSP (default 64)])
+
+RTEMS_BSP_CLEANUP_OPTIONS
+
+RISCV_RAM_REGION_BEGIN_DEFAULT=0x40000000
+
+AC_DEFUN([RISCV_LINKCMD],[
+AC_ARG_VAR([$1],[$2])dnl
+[$1]=[$]{[$1]:-[$3]}
+])
+
+RISCV_LINKCMD([RISCV_RAM_REGION_BEGIN],[begin of the RAM region for linker command file (default is 0x40000000)],[${RISCV_RAM_REGION_BEGIN_DEFAULT}])
+RISCV_LINKCMD([RISCV_RAM_REGION_SIZE],[size of the RAM region for linker command file (default 16MiB)],[0x01000000])
+
+AC_CONFIG_FILES([
+Makefile
+linkcmds:../../../../../../bsps/riscv/griscv/start/linkcmds.in
+])
+AC_OUTPUT
diff --git a/c/src/lib/libbsp/riscv/riscv/Makefile.am b/c/src/lib/libbsp/riscv/riscv/Makefile.am
index b8a034c..34bedf8 100644
--- a/c/src/lib/libbsp/riscv/riscv/Makefile.am
+++ b/c/src/lib/libbsp/riscv/riscv/Makefile.am
@@ -18,12 +18,12 @@ dist_project_lib_DATA = ../../../../../../bsps/riscv/riscv/start/bsp_specs
 #                  Data                                                       #
 ###############################################################################
 
-start.$(OBJEXT): ../../../../../../bsps/riscv/riscv/start/start.S
+start.$(OBJEXT): ../../../../../../bsps/riscv/shared/start/start.S
 	$(CPPASCOMPILE) -o $@ -c $<
 project_lib_DATA = start.$(OBJEXT)
 
 project_lib_DATA += linkcmds
-project_lib_DATA += ../../../../../../bsps/riscv/riscv/start/linkcmds.base
+project_lib_DATA += ../../../../../../bsps/riscv/shared/start/linkcmds.base
 
 ###############################################################################
 #                  LibBSP                                                     #
diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
index fb358e1..db46032 100644
--- a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
+++ b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
@@ -439,10 +439,7 @@ uint32_t _CPU_Counter_frequency( void );
 
 extern volatile uint32_t * const _RISCV_Counter;
 
-static inline CPU_Counter_ticks _CPU_Counter_read( void )
-{
-  return *_RISCV_Counter;
-}
+CPU_Counter_ticks _CPU_Counter_read( void );
 
 static inline CPU_Counter_ticks _CPU_Counter_difference(
   CPU_Counter_ticks second,



More information about the vc mailing list