[PATCH v3 8/8] riscv: add griscv bsp
Jiri Gaisler
jiri at gaisler.se
Fri Jan 18 19:43:01 UTC 2019
---
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 +
.../{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 +-
.../score/cpu/riscv/include/rtems/score/cpu.h | 5 +-
24 files changed, 1430 insertions(+), 6 deletions(-)
create mode 100644 bsps/riscv/griscv/clock/clockdrv.c
create mode 100644 bsps/riscv/griscv/config/griscv.cfg
create mode 100644 bsps/riscv/griscv/console/console.c
create mode 100644 bsps/riscv/griscv/console/printk_support.c
create mode 100644 bsps/riscv/griscv/headers.am
create mode 100644 bsps/riscv/griscv/include/amba.h
create mode 100644 bsps/riscv/griscv/include/bsp.h
create mode 100644 bsps/riscv/griscv/include/bsp/irq.h
create mode 100644 bsps/riscv/griscv/include/tm27.h
create mode 100644 bsps/riscv/griscv/irq/irq.c
create mode 100644 bsps/riscv/griscv/start/amba.c
create mode 100644 bsps/riscv/griscv/start/bsp_fatal_halt.c
create mode 100644 bsps/riscv/griscv/start/bsp_specs
create mode 100644 bsps/riscv/griscv/start/bspsmp.c
create mode 100644 bsps/riscv/griscv/start/bspstart.c
create mode 100644 bsps/riscv/griscv/start/linkcmds.in
rename bsps/riscv/{riscv => shared}/start/linkcmds.base (100%)
rename bsps/riscv/{riscv => shared}/start/start.S (100%)
create mode 100644 c/src/lib/libbsp/riscv/griscv/Makefile.am
create mode 100644 c/src/lib/libbsp/riscv/griscv/configure.ac
diff --git a/bsps/riscv/griscv/clock/clockdrv.c b/bsps/riscv/griscv/clock/clockdrv.c
new file mode 100644
index 0000000000..47ed6b305d
--- /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 0000000000..bd4a0cacbe
--- /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 0000000000..582b4c81b8
--- /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 0000000000..f8c14692c1
--- /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 0000000000..f351d7c12b
--- /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 0000000000..e1c5c00464
--- /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 0000000000..a926bab707
--- /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_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
+
+/* 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/griscv/include/bsp/irq.h b/bsps/riscv/griscv/include/bsp/irq.h
new file mode 100644
index 0000000000..cf88443740
--- /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_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/griscv/include/tm27.h b/bsps/riscv/griscv/include/tm27.h
new file mode 100644
index 0000000000..0dfa7bf628
--- /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 0000000000..721cd98ffe
--- /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 0000000000..182f659d69
--- /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 0000000000..ced328ea0f
--- /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 0000000000..87638cc027
--- /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 0000000000..df826f8217
--- /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 0000000000..dd83c80818
--- /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 0000000000..80e2f5ef90
--- /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 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/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 d8b3319b08..db1a210fd4 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 0000000000..4077ddebd2
--- /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 0000000000..ed5694c763
--- /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 b8a034ccde..34bedf844f 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 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
More information about the devel
mailing list