>From bfa21dcbacbcb36531f22f8a636aeda7af9a1fb8 Mon Sep 17 00:00:00 2001
From: Jiri Gaisler <j...@gaisler.se>
Date: Sat, 5 Jan 2019 15:35:56 +0100
Subject: [PATCH 5/5] Add bsp riscv/grlib

---
 bsps/riscv/grlib/clock/clockdrv.c             | 203 +++++++++
 bsps/riscv/grlib/config/grlib.cfg             |   9 +
 bsps/riscv/grlib/console/console.c            | 162 ++++++++
 bsps/riscv/grlib/console/printk_support.c     | 126 ++++++
 bsps/riscv/grlib/headers.am                   |  16 +
 bsps/riscv/grlib/include/amba.h               | 143 +++++++
 bsps/riscv/grlib/include/bsp.h                |  68 ++++
 bsps/riscv/grlib/include/bsp/irq.h            |  73 ++++
 bsps/riscv/grlib/include/bsp/riscv.h          |  57 +++
 bsps/riscv/grlib/include/dev/serial/htif.h    |  54 +++
 bsps/riscv/grlib/include/tm27.h               |   1 +
 bsps/riscv/grlib/irq/irq.c                    | 145 +++++++
 bsps/riscv/grlib/start/amba.c                 | 115 ++++++
 bsps/riscv/grlib/start/bsp_fatal_halt.c       |  34 ++
 bsps/riscv/grlib/start/bsp_specs              |   9 +
 bsps/riscv/grlib/start/bspsmp.c               |  98 +++++
 bsps/riscv/grlib/start/bspstart.c             |  71 ++++
 bsps/riscv/grlib/start/linkcmds.base          | 385 ++++++++++++++++++
 bsps/riscv/grlib/start/linkcmds.in            |  46 +++
 bsps/riscv/grlib/start/start.S                | 142 +++++++
 bsps/riscv/riscv/clock/clockdrv.c             |   5 +
 c/src/lib/libbsp/riscv/acinclude.m4           |   2 +
 c/src/lib/libbsp/riscv/grlib/Makefile.am      |  70 ++++
 c/src/lib/libbsp/riscv/grlib/configure.ac     |  68 ++++
 .../score/cpu/riscv/include/rtems/score/cpu.h |   5 +-
 25 files changed, 2103 insertions(+), 4 deletions(-)
 create mode 100644 bsps/riscv/grlib/clock/clockdrv.c
 create mode 100644 bsps/riscv/grlib/config/grlib.cfg
 create mode 100644 bsps/riscv/grlib/console/console.c
 create mode 100644 bsps/riscv/grlib/console/printk_support.c
 create mode 100644 bsps/riscv/grlib/headers.am
 create mode 100644 bsps/riscv/grlib/include/amba.h
 create mode 100644 bsps/riscv/grlib/include/bsp.h
 create mode 100644 bsps/riscv/grlib/include/bsp/irq.h
 create mode 100644 bsps/riscv/grlib/include/bsp/riscv.h
 create mode 100644 bsps/riscv/grlib/include/dev/serial/htif.h
 create mode 100644 bsps/riscv/grlib/include/tm27.h
 create mode 100644 bsps/riscv/grlib/irq/irq.c
 create mode 100644 bsps/riscv/grlib/start/amba.c
 create mode 100644 bsps/riscv/grlib/start/bsp_fatal_halt.c
 create mode 100644 bsps/riscv/grlib/start/bsp_specs
 create mode 100644 bsps/riscv/grlib/start/bspsmp.c
 create mode 100644 bsps/riscv/grlib/start/bspstart.c
 create mode 100644 bsps/riscv/grlib/start/linkcmds.base
 create mode 100644 bsps/riscv/grlib/start/linkcmds.in
 create mode 100644 bsps/riscv/grlib/start/start.S
 create mode 100644 c/src/lib/libbsp/riscv/grlib/Makefile.am
 create mode 100644 c/src/lib/libbsp/riscv/grlib/configure.ac

diff --git a/bsps/riscv/grlib/clock/clockdrv.c b/bsps/riscv/grlib/clock/clockdrv.c
new file mode 100644
index 0000000000..a1868137c1
--- /dev/null
+++ b/bsps/riscv/grlib/clock/clockdrv.c
@@ -0,0 +1,203 @@
+/*
+ *  Clock Tick Device Driver
+ *
+ *  This routine initializes LEON timer 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 <bsp/riscv.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/grlib/config/grlib.cfg b/bsps/riscv/grlib/config/grlib.cfg
new file mode 100644
index 0000000000..bd4a0cacbe
--- /dev/null
+++ b/bsps/riscv/grlib/config/grlib.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/grlib/console/console.c b/bsps/riscv/grlib/console/console.c
new file mode 100644
index 0000000000..e767180242
--- /dev/null
+++ b/bsps/riscv/grlib/console/console.c
@@ -0,0 +1,162 @@
+/*
+ *  This file contains the TTY driver for the serial ports on the LEON.
+ *
+ *  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 make/custom/grlib.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/grlib/console/printk_support.c b/bsps/riscv/grlib/console/printk_support.c
new file mode 100644
index 0000000000..9a83c429b8
--- /dev/null
+++ b/bsps/riscv/grlib/console/printk_support.c
@@ -0,0 +1,126 @@
+/*
+ *  This file contains the TTY driver for the serial ports on the LEON.
+ *
+ *  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 */
+    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/grlib/headers.am b/bsps/riscv/grlib/headers.am
new file mode 100644
index 0000000000..416cc89dc9
--- /dev/null
+++ b/bsps/riscv/grlib/headers.am
@@ -0,0 +1,16 @@
+## This file was generated by "./boostrap -H".
+
+include_HEADERS =
+include_HEADERS += ../../../../../../bsps/riscv/grlib/include/amba.h
+include_HEADERS += ../../../../../../bsps/riscv/grlib/include/bsp.h
+include_HEADERS += include/bspopts.h
+include_HEADERS += ../../../../../../bsps/riscv/grlib/include/tm27.h
+
+include_bspdir = $(includedir)/bsp
+include_bsp_HEADERS =
+include_bsp_HEADERS += ../../../../../../bsps/riscv/grlib/include/bsp/irq.h
+include_bsp_HEADERS += ../../../../../../bsps/riscv/grlib/include/bsp/riscv.h
+
+include_dev_serialdir = $(includedir)/dev/serial
+include_dev_serial_HEADERS =
+include_dev_serial_HEADERS += ../../../../../../bsps/riscv/grlib/include/dev/serial/htif.h
diff --git a/bsps/riscv/grlib/include/amba.h b/bsps/riscv/grlib/include/amba.h
new file mode 100644
index 0000000000..e1c5c00464
--- /dev/null
+++ b/bsps/riscv/grlib/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/grlib/include/bsp.h b/bsps/riscv/grlib/include/bsp.h
new file mode 100644
index 0000000000..9c930c3f3c
--- /dev/null
+++ b/bsps/riscv/grlib/include/bsp.h
@@ -0,0 +1,68 @@
+/*
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham Almatary <hes...@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_GENERIC_H
+#define LIBBSP_RISCV_GENERIC_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
+
+#define BSP_FDT_IS_SUPPORTED
+
+/* 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_GENERIC_H */
diff --git a/bsps/riscv/grlib/include/bsp/irq.h b/bsps/riscv/grlib/include/bsp/irq.h
new file mode 100644
index 0000000000..cf88443740
--- /dev/null
+++ b/bsps/riscv/grlib/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 <hes...@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_GENERIC_RISCV_IRQ_H
+#define LIBBSP_GENERIC_RISCV_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_GENERIC_RISCV_IRQ_H */
diff --git a/bsps/riscv/grlib/include/bsp/riscv.h b/bsps/riscv/grlib/include/bsp/riscv.h
new file mode 100644
index 0000000000..374d5f7a77
--- /dev/null
+++ b/bsps/riscv/grlib/include/bsp/riscv.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef BSP_RISCV_H
+#define BSP_RISCV_H
+
+#include <bsp.h>
+
+#include <rtems/score/cpuimpl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern volatile RISCV_CLINT_regs *riscv_clint;
+
+void *riscv_fdt_get_address(const void *fdt, int node);
+
+#ifdef RTEMS_SMP
+extern uint32_t riscv_hart_count;
+#else
+#define riscv_hart_count 1
+#endif
+
+uint32_t riscv_get_hart_index_by_phandle(uint32_t phandle);
+
+#if RISCV_ENABLE_HTIF_SUPPORT != 0
+void htif_poweroff(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BSP_RISCV_H */
diff --git a/bsps/riscv/grlib/include/dev/serial/htif.h b/bsps/riscv/grlib/include/dev/serial/htif.h
new file mode 100644
index 0000000000..b0d83652b7
--- /dev/null
+++ b/bsps/riscv/grlib/include/dev/serial/htif.h
@@ -0,0 +1,54 @@
+/*
+ * 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 <rtems/termiostypes.h>
+
+#ifndef DEV_SERIAL_HTIF_H
+#define DEV_SERIAL_HTIF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct {
+  rtems_termios_device_context base;
+} htif_console_context;
+
+void htif_console_context_init(
+  rtems_termios_device_context *base,
+  int device_tree_node
+);
+
+void htif_console_putchar(rtems_termios_device_context *base, char c);
+
+int htif_console_getchar(rtems_termios_device_context *base);
+
+const rtems_termios_device_handler htif_console_handler;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* DEV_SERIAL_HTIF_H */
diff --git a/bsps/riscv/grlib/include/tm27.h b/bsps/riscv/grlib/include/tm27.h
new file mode 100644
index 0000000000..0dfa7bf628
--- /dev/null
+++ b/bsps/riscv/grlib/include/tm27.h
@@ -0,0 +1 @@
+#include <rtems/tm27-default.h>
diff --git a/bsps/riscv/grlib/irq/irq.c b/bsps/riscv/grlib/irq/irq.c
new file mode 100644
index 0000000000..8686fc6798
--- /dev/null
+++ b/bsps/riscv/grlib/irq/irq.c
@@ -0,0 +1,145 @@
+/**
+ * @file
+ *
+ * @ingroup riscv_interrupt
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ * Copyright (c) 2018 embedded brains GmbH
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham Almatary <hes...@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 <bsp/riscv.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/grlib/start/amba.c b/bsps/riscv/grlib/start/amba.c
new file mode 100644
index 0000000000..182f659d69
--- /dev/null
+++ b/bsps/riscv/grlib/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/grlib/start/bsp_fatal_halt.c b/bsps/riscv/grlib/start/bsp_fatal_halt.c
new file mode 100644
index 0000000000..3f9ff49ae4
--- /dev/null
+++ b/bsps/riscv/grlib/start/bsp_fatal_halt.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham Almatary <hes...@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/riscv.h>
+
+void _CPU_Fatal_halt(uint32_t source, uint32_t error)
+{
+    asm ("ecall");
+}
diff --git a/bsps/riscv/grlib/start/bsp_specs b/bsps/riscv/grlib/start/bsp_specs
new file mode 100644
index 0000000000..87638cc027
--- /dev/null
+++ b/bsps/riscv/grlib/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/grlib/start/bspsmp.c b/bsps/riscv/grlib/start/bspsmp.c
new file mode 100644
index 0000000000..5ad3ce7ae1
--- /dev/null
+++ b/bsps/riscv/grlib/start/bspsmp.c
@@ -0,0 +1,98 @@
+/*
+ * 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 <bsp/riscv.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/grlib/start/bspstart.c b/bsps/riscv/grlib/start/bspstart.c
new file mode 100644
index 0000000000..2a8631818c
--- /dev/null
+++ b/bsps/riscv/grlib/start/bspstart.c
@@ -0,0 +1,71 @@
+/*
+ * 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 <bsp/riscv.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/grlib/start/linkcmds.base b/bsps/riscv/grlib/start/linkcmds.base
new file mode 100644
index 0000000000..7d889ab38c
--- /dev/null
+++ b/bsps/riscv/grlib/start/linkcmds.base
@@ -0,0 +1,385 @@
+/* Copyright (C) 2014-2018 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+/*
+ * Copyright (c) 2018 embedded brains GmbH.
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham ALMatary <hmka...@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.
+ */
+
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
+STARTUP(start.o)
+
+bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1;
+bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1;
+
+MEMORY {
+	UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0
+}
+
+SECTIONS {
+	.start : ALIGN_WITH_INPUT {
+		bsp_section_start_begin = .;
+		KEEP (*(.bsp_start_text))
+		KEEP (*(.bsp_start_data))
+		bsp_section_start_end = .;
+	} > REGION_START AT > REGION_START
+	bsp_section_start_size = bsp_section_start_end - bsp_section_start_begin;
+
+	.text : ALIGN_WITH_INPUT {
+		bsp_section_text_begin = .;
+		*(.text.unlikely .text.*_unlikely .text.unlikely.*)
+		*(.text.exit .text.exit.*)
+		*(.text.startup .text.startup.*)
+		*(.text.hot .text.hot.*)
+		*(.text .stub .text.* .gnu.linkonce.t.*)
+		/* .gnu.warning sections are handled specially by elf32.em.	*/
+		*(.gnu.warning)
+	} > REGION_TEXT AT > REGION_TEXT_LOAD
+	.init : ALIGN_WITH_INPUT {
+		KEEP (*(SORT_NONE(.init)))
+	} > REGION_TEXT AT > REGION_TEXT_LOAD
+	.fini : ALIGN_WITH_INPUT {
+		KEEP (*(SORT_NONE(.fini)))
+		bsp_section_text_end = .;
+	} > REGION_TEXT AT > REGION_TEXT_LOAD
+	bsp_section_text_size = bsp_section_text_end - bsp_section_text_begin;
+	bsp_section_text_load_begin = LOADADDR (.text);
+	bsp_section_text_load_end = bsp_section_text_load_begin + bsp_section_text_size;
+
+	.robarrier : ALIGN_WITH_INPUT {
+		. = ALIGN (bsp_section_robarrier_align);
+	} > REGION_RODATA AT > REGION_RODATA
+
+	.rodata : ALIGN_WITH_INPUT {
+		bsp_section_rodata_begin = .;
+		*(.rodata .rodata.* .gnu.linkonce.r.*)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.rodata1 : ALIGN_WITH_INPUT {
+		*(.rodata1)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.sdata2 : ALIGN_WITH_INPUT {
+		*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.sbss2 : ALIGN_WITH_INPUT {
+		*(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.eh_frame_hdr : ALIGN_WITH_INPUT {
+		*(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.eh_frame : ALIGN_WITH_INPUT {
+		KEEP (*(.eh_frame)) *(.eh_frame.*)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.gcc_except_table : ALIGN_WITH_INPUT {
+		*(.gcc_except_table .gcc_except_table.*)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.gnu_extab : ALIGN_WITH_INPUT {
+		*(.gnu_extab*)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.tdata : ALIGN_WITH_INPUT {
+		_TLS_Data_begin = .;
+		*(.tdata .tdata.* .gnu.linkonce.td.*)
+		_TLS_Data_end = .;
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.tbss : ALIGN_WITH_INPUT {
+		_TLS_BSS_begin = .;
+		*(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
+		_TLS_BSS_end = .;
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	_TLS_Data_size = _TLS_Data_end - _TLS_Data_begin;
+	_TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin;
+	_TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin;
+	_TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin;
+	_TLS_Size = _TLS_BSS_end - _TLS_Data_begin;
+	_TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss));
+	.preinit_array : ALIGN_WITH_INPUT {
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP (*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.init_array : ALIGN_WITH_INPUT {
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+		KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+		PROVIDE_HIDDEN (__init_array_end = .);
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.fini_array : ALIGN_WITH_INPUT {
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+		KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.ctors : ALIGN_WITH_INPUT {
+		/* gcc uses crtbegin.o to find the start of
+			 the constructors, so we make sure it is
+			 first.	Because this is a wildcard, it
+			 doesn't matter if the user does not
+			 actually link against crtbegin.o; the
+			 linker won't look for a file to match a
+			 wildcard.	The wildcard also means that it
+			 doesn't matter which directory crtbegin.o
+			 is in.	*/
+		KEEP (*crtbegin.o(.ctors))
+		KEEP (*crtbegin?.o(.ctors))
+		/* We don't want to include the .ctor section from
+			 the crtend.o file until after the sorted ctors.
+			 The .ctor section from the crtend file contains the
+			 end of ctors marker and it must be last */
+		KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+		KEEP (*(SORT(.ctors.*)))
+		KEEP (*(.ctors))
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.dtors : ALIGN_WITH_INPUT {
+		KEEP (*crtbegin.o(.dtors))
+		KEEP (*crtbegin?.o(.dtors))
+		KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+		KEEP (*(SORT(.dtors.*)))
+		KEEP (*(.dtors))
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.data.rel.ro : ALIGN_WITH_INPUT {
+		*(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*)
+		*(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.jcr : ALIGN_WITH_INPUT {
+		KEEP (*(.jcr))
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.interp : ALIGN_WITH_INPUT {
+		*(.interp)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.note.gnu.build-id : { *(.note.gnu.build-id)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.hash : ALIGN_WITH_INPUT {
+		*(.hash)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.gnu.hash : ALIGN_WITH_INPUT {
+		*(.gnu.hash)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.dynsym : ALIGN_WITH_INPUT {
+		*(.dynsym)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.dynstr : ALIGN_WITH_INPUT {
+		*(.dynstr)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.gnu.version : ALIGN_WITH_INPUT {
+		*(.gnu.version)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.gnu.version_d : ALIGN_WITH_INPUT {
+		*(.gnu.version_d)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.gnu.version_r : ALIGN_WITH_INPUT {
+		*(.gnu.version_r)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.rela.dyn : ALIGN_WITH_INPUT {
+		*(.rela.init)
+		*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+		*(.rela.fini)
+		*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+		*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+		*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+		*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+		*(.rela.ctors)
+		*(.rela.dtors)
+		*(.rela.got)
+		*(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
+		*(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
+		*(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
+		*(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
+		*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+		PROVIDE_HIDDEN (__rela_iplt_start = .);
+		*(.rela.iplt)
+		PROVIDE_HIDDEN (__rela_iplt_end = .);
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.rela.plt : ALIGN_WITH_INPUT {
+			*(.rela.plt)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.plt : ALIGN_WITH_INPUT {
+		*(.plt)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.iplt : ALIGN_WITH_INPUT {
+		*(.iplt)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.dynamic : ALIGN_WITH_INPUT {
+		*(.dynamic)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.tm_clone_table : ALIGN_WITH_INPUT {
+		*(.tm_clone_table)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.got : ALIGN_WITH_INPUT {
+		*(.got.plt) *(.igot.plt) *(.got) *(.igot)
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	.rtemsroset : ALIGN_WITH_INPUT {
+		/* Special FreeBSD linker set sections */
+		__start_set_sysctl_set = .;
+		*(set_sysctl_*);
+		__stop_set_sysctl_set = .;
+		*(set_domain_*);
+		*(set_pseudo_*);
+
+		KEEP (*(SORT(.rtemsroset.*)))
+		bsp_section_rodata_end = .;
+	} > REGION_RODATA AT > REGION_RODATA_LOAD
+	bsp_section_rodata_size = bsp_section_rodata_end - bsp_section_rodata_begin;
+	bsp_section_rodata_load_begin = LOADADDR (.rodata);
+	bsp_section_rodata_load_end = bsp_section_rodata_load_begin + bsp_section_rodata_size;
+
+	.rwbarrier : ALIGN_WITH_INPUT {
+		. = ALIGN (bsp_section_rwbarrier_align);
+	} > REGION_DATA AT > REGION_DATA
+
+	.fast_text : ALIGN_WITH_INPUT {
+		bsp_section_fast_text_begin = .;
+		*(.bsp_fast_text)
+		bsp_section_fast_text_end = .;
+	} > REGION_FAST_TEXT AT > REGION_FAST_TEXT_LOAD
+	bsp_section_fast_text_size = bsp_section_fast_text_end - bsp_section_fast_text_begin;
+	bsp_section_fast_text_load_begin = LOADADDR (.fast_text);
+	bsp_section_fast_text_load_end = bsp_section_fast_text_load_begin + bsp_section_fast_text_size;
+
+	.fast_data : ALIGN_WITH_INPUT {
+		bsp_section_fast_data_begin = .;
+		*(.bsp_fast_data)
+		bsp_section_fast_data_end = .;
+	} > REGION_FAST_DATA AT > REGION_FAST_DATA_LOAD
+	bsp_section_fast_data_size = bsp_section_fast_data_end - bsp_section_fast_data_begin;
+	bsp_section_fast_data_load_begin = LOADADDR (.fast_data);
+	bsp_section_fast_data_load_end = bsp_section_fast_data_load_begin + bsp_section_fast_data_size;
+
+	.data : ALIGN_WITH_INPUT {
+		bsp_section_data_begin = .;
+		*(.data .data.* .gnu.linkonce.d.*)
+		SORT(CONSTRUCTORS)
+	} > REGION_DATA AT > REGION_DATA_LOAD
+	.data1 : ALIGN_WITH_INPUT {
+		*(.data1)
+	} > REGION_DATA AT > REGION_DATA_LOAD
+	.rtemsrwset : ALIGN_WITH_INPUT {
+		KEEP (*(SORT(.rtemsrwset.*)))
+	} > REGION_DATA AT > REGION_DATA_LOAD
+	.htif ALIGN(4096) : ALIGN_WITH_INPUT {
+		*(.htif)
+	} > REGION_DATA AT > REGION_DATA_LOAD
+	.sdata : ALIGN_WITH_INPUT {
+		__global_pointer$ = . + 0x800;
+		*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)
+		*(.sdata .sdata.* .gnu.linkonce.s.*)
+		bsp_section_data_end = .;
+	} > REGION_DATA AT > REGION_DATA_LOAD
+	bsp_section_data_size = bsp_section_data_end - bsp_section_data_begin;
+	bsp_section_data_load_begin = LOADADDR (.data);
+	bsp_section_data_load_end = bsp_section_data_load_begin + bsp_section_data_size;
+
+	.sbss : ALIGN_WITH_INPUT {
+		bsp_section_bss_begin = .;
+		*(.dynsbss)
+		*(.sbss .sbss.* .gnu.linkonce.sb.*)
+		*(.scommon)
+	} > REGION_DATA AT > REGION_DATA
+	.bss : ALIGN_WITH_INPUT {
+		*(.dynbss)
+		*(.bss .bss.* .gnu.linkonce.b.*)
+		*(COMMON)
+		bsp_section_bss_end = .;
+	} > REGION_DATA AT > REGION_DATA
+	bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_begin;
+
+	.rtemsstack (NOLOAD) : ALIGN_WITH_INPUT {
+		bsp_section_rtemsstack_begin = .;
+		*(SORT(.rtemsstack.*))
+		bsp_section_rtemsstack_end = .;
+	} > REGION_RTEMSSTACK AT > REGION_RTEMSSTACK
+	bsp_section_rtemsstack_size = bsp_section_rtemsstack_end - bsp_section_rtemsstack_begin;
+
+	.work : ALIGN_WITH_INPUT {
+		/*
+		 * The work section will occupy the remaining REGION_WORK region and
+		 * contains the RTEMS work space and heap.
+		 */
+		bsp_section_work_begin = .;
+		. += ORIGIN (REGION_WORK) + LENGTH (REGION_WORK) - ABSOLUTE (.);
+		bsp_section_work_end = .;
+	} > REGION_WORK AT > REGION_WORK
+	bsp_section_work_size = bsp_section_work_end - bsp_section_work_begin;
+
+	/* FIXME */
+	RamBase = ORIGIN (REGION_WORK);
+	RamSize = LENGTH (REGION_WORK);
+	WorkAreaBase = bsp_section_work_begin;
+	HeapSize = 0;
+
+	/* Stabs debugging sections.	*/
+	.stab					0 : { *(.stab) }
+	.stabstr			 0 : { *(.stabstr) }
+	.stab.excl		 0 : { *(.stab.excl) }
+	.stab.exclstr	0 : { *(.stab.exclstr) }
+	.stab.index		0 : { *(.stab.index) }
+	.stab.indexstr 0 : { *(.stab.indexstr) }
+	.comment			 0 : { *(.comment) }
+	/* DWARF debug sections.
+		 Symbols in the DWARF debugging sections are relative to the beginning
+		 of the section so we begin them at 0.	*/
+	/* DWARF 1 */
+	.debug					0 : { *(.debug) }
+	.line					 0 : { *(.line) }
+	/* GNU DWARF 1 extensions */
+	.debug_srcinfo	0 : { *(.debug_srcinfo) }
+	.debug_sfnames	0 : { *(.debug_sfnames) }
+	/* DWARF 1.1 and DWARF 2 */
+	.debug_aranges	0 : { *(.debug_aranges) }
+	.debug_pubnames 0 : { *(.debug_pubnames) }
+	/* DWARF 2 */
+	.debug_info		 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+	.debug_abbrev	 0 : { *(.debug_abbrev) }
+	.debug_line		 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+	.debug_frame		0 : { *(.debug_frame) }
+	.debug_str			0 : { *(.debug_str) }
+	.debug_loc			0 : { *(.debug_loc) }
+	.debug_macinfo	0 : { *(.debug_macinfo) }
+	/* SGI/MIPS DWARF 2 extensions */
+	.debug_weaknames 0 : { *(.debug_weaknames) }
+	.debug_funcnames 0 : { *(.debug_funcnames) }
+	.debug_typenames 0 : { *(.debug_typenames) }
+	.debug_varnames	0 : { *(.debug_varnames) }
+	/* DWARF 3 */
+	.debug_pubtypes 0 : { *(.debug_pubtypes) }
+	.debug_ranges	 0 : { *(.debug_ranges) }
+	/* DWARF Extension.	*/
+	.debug_macro		0 : { *(.debug_macro) }
+	.debug_addr		 0 : { *(.debug_addr) }
+	.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+	/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+
+	/*
+	 * This is a RTEMS specific section to catch all unexpected input
+	 * sections.  In case you get an error like
+	 *   "section `.unexpected_sections' will not fit in region
+	 *   `UNEXPECTED_SECTIONS'"
+	 * you have to figure out the offending input section and add it to the
+	 * appropriate output section definition above.
+	 */
+	.unexpected_sections : { *(*) } > UNEXPECTED_SECTIONS
+}
diff --git a/bsps/riscv/grlib/start/linkcmds.in b/bsps/riscv/grlib/start/linkcmds.in
new file mode 100644
index 0000000000..80e2f5ef90
--- /dev/null
+++ b/bsps/riscv/grlib/start/linkcmds.in
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 University of York.
+ * Hesham ALMatary <hmka...@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/grlib/start/start.S b/bsps/riscv/grlib/start/start.S
new file mode 100644
index 0000000000..2d83e7e236
--- /dev/null
+++ b/bsps/riscv/grlib/start/start.S
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH
+
+ * Copyright (c) 2015 University of York.
+ * Hesham Almatary <hes...@alumni.york.ac.uk>
+ *
+ * Copyright (c) 2013, The Regents of the University of California (Regents).
+ * All Rights Reserved.
+ *
+ * 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 <rtems/asm.h>
+#include <rtems/score/percpu.h>
+#include <rtems/score/riscv-utility.h>
+#include <bsp/linker-symbols.h>
+#include <bspopts.h>
+
+PUBLIC(_start)
+
+	.section	.bsp_start_text, "wax", @progbits
+	.align	2
+
+TYPE_FUNC(_start)
+SYM(_start):
+	/* Load global pointer */
+	.option	push
+	.option	norelax
+	LADDR	gp, __global_pointer$
+	.option	pop
+
+	/* Init FPU */
+#ifdef __riscv_flen
+	li	t0, MSTATUS_FS
+	csrs	mstatus, t0
+	csrw	fcsr, zero
+#endif
+
+	/* Set exception handler */
+	LADDR	t0, _RISCV_Exception_handler
+	csrw	mtvec, t0
+
+	/* Load stack pointer and branch to secondary processor start if necessary */
+#ifdef RTEMS_SMP
+	LADDR	sp, _ISR_Stack_area_begin
+	LADDR	t2, _ISR_Stack_size
+	csrr	s0, mhartid
+	LADDR	t0, _Per_CPU_Information
+	slli	t1, s0, PER_CPU_CONTROL_SIZE_LOG2
+	add	s1, t0, t1
+	csrw	mscratch, s1
+	bnez	s0, .Lstart_on_secondary_processor
+	add	sp, sp, t2
+#else
+	LADDR	sp, _ISR_Stack_area_end
+#endif
+
+	/* Clear .bss */
+	LADDR	a0, bsp_section_bss_begin
+	li	a1, 0
+	LADDR	a2, bsp_section_bss_size
+	call	memset
+
+#ifdef RTEMS_SMP
+	/* Give go to secondary processors */
+	LADDR	t0, .Lsecondary_processor_go
+	fence	iorw,ow
+	amoswap.w	zero, zero, 0(t0)
+#endif
+
+	li	a0, 0
+	j	boot_card
+
+#ifdef RTEMS_SMP
+
+.Lstart_on_secondary_processor:
+
+	/* Adjust stack pointer */
+#ifdef __riscv_mul
+	addi	t0, s0, 1
+	mul	t2, t2, t0
+#else
+	mv	t0, s0
+	mv	t3, t2
+
+.Ladd_more:
+
+	add	t2, t2, t3
+	addi	t0, t0, -1
+	bnez	t0, .Ladd_more
+#endif
+	add	sp, sp, t2
+
+	/* Wait for go issued by the boot processor (mhartid == 0) */
+	LADDR	t0, .Lsecondary_processor_go
+
+.Lwait_for_go_again:
+
+	lw	t1, 0(t0)
+	fence	iorw, iorw
+	bnez	t1, .Lwait_for_go_again
+
+	mv	a0, s1
+	call	bsp_start_on_secondary_processor
+
+#if __riscv_xlen == 32
+	.align	2
+#elif __riscv_xlen == 64
+	.align	3
+#endif
+
+.Lsecondary_processor_go:
+
+	/*
+	 * These are ebreak instructions, just in case we end up here executing
+	 * code.
+	 */
+	.word	0x00100073
+#if __riscv_xlen == 64
+	.word	0x00100073
+#endif
+
+#endif /* RTEMS_SMP */
diff --git a/bsps/riscv/riscv/clock/clockdrv.c b/bsps/riscv/riscv/clock/clockdrv.c
index 30a894f384..7e6034d4d1 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/c/src/lib/libbsp/riscv/acinclude.m4 b/c/src/lib/libbsp/riscv/acinclude.m4
index d8b3319b08..0b3c6e293d 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
+  grlib )
+    AC_CONFIG_SUBDIRS([grlib]);;
   riscv )
     AC_CONFIG_SUBDIRS([riscv]);;
   *)
diff --git a/c/src/lib/libbsp/riscv/grlib/Makefile.am b/c/src/lib/libbsp/riscv/grlib/Makefile.am
new file mode 100644
index 0000000000..23593d744f
--- /dev/null
+++ b/c/src/lib/libbsp/riscv/grlib/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/grlib/start/bsp_specs
+
+###############################################################################
+#                  Header                                                     #
+###############################################################################
+
+###############################################################################
+#                  Data                                                       #
+###############################################################################
+
+start.$(OBJEXT): ../../../../../../bsps/riscv/grlib/start/start.S
+	$(CPPASCOMPILE) -o $@ -c $<
+project_lib_DATA = start.$(OBJEXT)
+
+project_lib_DATA += linkcmds
+project_lib_DATA += ../../../../../../bsps/riscv/grlib/start/linkcmds.base
+
+###############################################################################
+#                  LibBSP                                                     #
+###############################################################################
+
+project_lib_LIBRARIES = librtemsbsp.a
+
+# Startup
+librtemsbsp_a_SOURCES = ../../../../../../bsps/shared/start/bspreset-empty.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/grlib/start/bspstart.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/grlib/start/bsp_fatal_halt.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/grlib/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/grlib/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/grlib/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/grlib/console/console.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/grlib/console/printk_support.c
+
+if HAS_SMP
+librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/grlib/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/grlib/headers.am
diff --git a/c/src/lib/libbsp/riscv/grlib/configure.ac b/c/src/lib/libbsp/riscv/grlib/configure.ac
new file mode 100644
index 0000000000..d0b23ebafe
--- /dev/null
+++ b/c/src/lib/libbsp/riscv/grlib/configure.ac
@@ -0,0 +1,68 @@
+##
+#
+# @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_START_COPY_FDT_FROM_U_BOOT],[*],[1])
+RTEMS_BSPOPTS_HELP([BSP_START_COPY_FDT_FROM_U_BOOT],[copy the U-Boot provided FDT to an internal storage])
+
+RTEMS_BSPOPTS_SET([BSP_FDT_BLOB_SIZE_MAX],[*],[65536])
+RTEMS_BSPOPTS_HELP([BSP_FDT_BLOB_SIZE_MAX],[maximum size of the FDT blob in bytes])
+
+RTEMS_BSPOPTS_SET([BSP_FDT_BLOB_READ_ONLY],[*],[1])
+RTEMS_BSPOPTS_HELP([BSP_FDT_BLOB_READ_ONLY],[place the FDT blob into the read-only data area])
+
+RTEMS_BSPOPTS_SET([BSP_FDT_BLOB_COPY_TO_READ_ONLY_LOAD_AREA],[*],[1])
+RTEMS_BSPOPTS_HELP([BSP_FDT_BLOB_COPY_TO_READ_ONLY_LOAD_AREA],[copy the FDT blob into the read-only load area via bsp_fdt_copy()])
+
+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_BSPOPTS_SET([RISCV_ENABLE_HTIF_SUPPORT],[*],[])
+RTEMS_BSPOPTS_HELP([RISCV_ENABLE_HTIF_SUPPORT],[enables the HTIF support if defined to a non-zero value, otherwise it is disabled (disabled by default)])
+
+RTEMS_BSPOPTS_SET([RISCV_CONSOLE_MAX_NS16550_DEVICES],[*],[2])
+RTEMS_BSPOPTS_HELP([RISCV_CONSOLE_MAX_NS16550_DEVICES],[maximum number of NS16550 devices supported by the console driver (2 by default)])
+
+RTEMS_BSP_CLEANUP_OPTIONS
+
+case "${RTEMS_BSP}" in
+  rv64*medany)
+    RISCV_RAM_REGION_BEGIN_DEFAULT=0x80000000
+    ;;
+  rv64*)
+    RISCV_RAM_REGION_BEGIN_DEFAULT=0x70000000
+    ;;
+  *)
+    RISCV_RAM_REGION_BEGIN_DEFAULT=0x40000000
+    ;;
+esac
+
+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 0x70000000 for 64-bit with -mcmodel=medlow and 0x80000000 for all other)],[${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/grlib/start/linkcmds.in
+])
+AC_OUTPUT
diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
index fb358e167c..db46032df2 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,
-- 
2.17.1

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

Reply via email to