From 51dde8b98faf94da540624b9c7bb7fffa69daee9 Mon Sep 17 00:00:00 2001
From: Bunnaroath Sou <bsou@sifive.com>
Date: Wed, 6 Mar 2019 13:23:03 -0800
Subject: Add E76, S76 arty targets for all 19.2 CoreIPs release

---
 bsp/coreip-s76-arty/README.md   |  16 ++
 bsp/coreip-s76-arty/design.dts  | 215 ++++++++++++++++++
 bsp/coreip-s76-arty/metal.h     | 492 ++++++++++++++++++++++++++++++++++++++++
 bsp/coreip-s76-arty/metal.lds   | 225 ++++++++++++++++++
 bsp/coreip-s76-arty/openocd.cfg |  30 +++
 bsp/coreip-s76-arty/settings.mk |   2 +
 6 files changed, 980 insertions(+)
 create mode 100644 bsp/coreip-s76-arty/README.md
 create mode 100644 bsp/coreip-s76-arty/design.dts
 create mode 100644 bsp/coreip-s76-arty/metal.h
 create mode 100644 bsp/coreip-s76-arty/metal.lds
 create mode 100644 bsp/coreip-s76-arty/openocd.cfg
 create mode 100644 bsp/coreip-s76-arty/settings.mk

(limited to 'bsp/coreip-s76-arty')

diff --git a/bsp/coreip-s76-arty/README.md b/bsp/coreip-s76-arty/README.md
new file mode 100644
index 0000000..67be221
--- /dev/null
+++ b/bsp/coreip-s76-arty/README.md
@@ -0,0 +1,16 @@
+The SiFive S76 Standard Core is a high-performance 64-bit embedded processor which is fully-compliant with the RISC-V ISA.
+
+The S76 is ideal for latency-sensitive applications in domains such as storage and networking that require 64-bit memory addressability (e.g. In-storage Compute, Edge Compute, 5G Modems, Object storage etc.)
+
+This FPGA core target is ideal for makers and hobbyists to develop running application software building on top of freedom-metal libraries. The target supports:
+
+- 1 hart with RV64IMAFDC core
+- 4 hardware breakpoints
+- Physical Memory Protection with 8 regions
+- 16 local interrupts signal that can be connected to off core complex devices
+- Up to 127 PLIC interrupt signals that can be connected to off core complex devices, with 7 priority levels
+- GPIO memory with 16 interrupt lines
+- SPI memory with 1 interrupt line
+- Serial port with 1 interrupt line
+- 4 RGB LEDS
+- 4 Buttons and 4 Switches
diff --git a/bsp/coreip-s76-arty/design.dts b/bsp/coreip-s76-arty/design.dts
new file mode 100644
index 0000000..f43d9c5
--- /dev/null
+++ b/bsp/coreip-s76-arty/design.dts
@@ -0,0 +1,215 @@
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "SiFive,FS760G-dev", "fs710-dev", "sifive-dev";
+	model = "SiFive,FS760G";
+	L21: aliases {
+		serial0 = &L13;
+	};
+	L16: chosen {
+                stdout-path = "/soc/serial@20000000:115200";
+                metal,entry = <&L14 0x400000>;
+	};
+	L20: cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		L6: cpu@0 {
+			clock-frequency = <0>;
+			compatible = "sifive,bullet0", "riscv";
+			d-cache-block-size = <64>;
+			d-cache-sets = <128>;
+			d-cache-size = <32768>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <128>;
+			i-cache-size = <32768>;
+			next-level-cache = <&L14 &L15>;
+			reg = <0x0>;
+			riscv,isa = "rv64imafdc";
+			status = "okay";
+			timebase-frequency = <1000000>;
+                        hardware-exec-breakpoint-count = <4>;
+			L4: interrupt-controller {
+				#interrupt-cells = <1>;
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+			};
+		};
+	};
+	L15: memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>;
+	};
+	L19: soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "SiFive,FS760G-soc", "fs710-soc", "sifive-soc", "simple-bus";
+		ranges;
+		L2: clint@2000000 {
+			compatible = "riscv,clint0";
+			interrupts-extended = <&L4 3 &L4 7>;
+			reg = <0x2000000 0x10000>;
+			reg-names = "control";
+		};
+		L3: debug-controller@0 {
+			compatible = "sifive,debug-013", "riscv,debug-013";
+			interrupts-extended = <&L4 65535>;
+			reg = <0x0 0x1000>;
+			reg-names = "control";
+		};
+		L0: error-device@3000 {
+			compatible = "sifive,error0";
+			reg = <0x3000 0x1000>;
+		};
+		L10: global-external-interrupts {
+                        compatible = "sifive,global-external-interrupts0";
+			interrupt-parent = <&L1>;
+			interrupts = <21 22 23 24>;
+		};
+		L17: gpio@10060000 {
+			#gpio-cells = <2>;
+			#interrupt-cells = <2>;
+			compatible = "sifive,gpio0", "sifive,gpio1";
+			gpio-controller;
+			interrupt-controller;
+			interrupt-parent = <&L1>;
+			interrupts = <27 28 29 30>;
+			reg = <0x10060000 0x1000>;
+			reg-names = "control";
+		};
+		L7: gpio@20002000 {
+			#gpio-cells = <2>;
+			#interrupt-cells = <2>;
+			compatible = "sifive,gpio0", "sifive,gpio1";
+			gpio-controller;
+			interrupt-controller;
+			interrupt-parent = <&L1>;
+			interrupts = <1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16>;
+			reg = <0x20002000 0x1000>;
+			reg-names = "control";
+		};
+		L1: interrupt-controller@c000000 {
+			#interrupt-cells = <1>;
+			compatible = "riscv,plic0";
+			interrupt-controller;
+			interrupts-extended = <&L4 11>;
+			reg = <0xc000000 0x4000000>;
+			reg-names = "control";
+			riscv,max-priority = <7>;
+			riscv,ndev = <30>;
+		};
+		L8: pwm@20005000 {
+			compatible = "sifive,pwm0";
+			interrupt-parent = <&L1>;
+			interrupts = <17 18 19 20>;
+			reg = <0x20005000 0x1000>;
+			reg-names = "control";
+		};
+		L11: rom@1000 {
+			compatible = "sifive,modeselect0";
+			reg = <0x1000 0x1000>;
+			reg-names = "mem";
+		};
+		L13: serial@20000000 {
+			clocks = <&L12>;
+			compatible = "sifive,uart0";
+			interrupt-parent = <&L1>;
+			interrupts = <25>;
+			reg = <0x20000000 0x1000>;
+			reg-names = "control";
+		};
+		L14: spi@20004000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&L12>;
+			compatible = "sifive,spi0";
+			interrupt-parent = <&L1>;
+			interrupts = <26>;
+			reg = <0x20004000 0x1000 0x40000000 0x20000000>;
+			reg-names = "control", "mem";
+		};
+               	led@0red {
+                       	compatible = "sifive,gpio-leds";
+                       	label = "LD0red";
+                       	gpios = <&L17 0>;
+                       	linux,default-trigger = "none";
+               	};
+                led@0green {
+                       	compatible = "sifive,gpio-leds";
+                        label = "LD0green";
+                        gpios = <&L17 1>;
+                        linux,default-trigger = "none";
+                };
+                led@0blue {
+                     	compatible = "sifive,gpio-leds";
+                        label = "LD0blue";
+                        gpios = <&L17 2>;
+                        linux,default-trigger = "none";
+                };
+                button@0 {
+                       	compatible = "sifive,gpio-buttons";
+                        label = "BTN0";
+                        gpios = <&L17 4>;
+                        interrupts-extended = <&L10 0>;
+                        linux,code = "none";
+                };
+                button@1 {
+                       	compatible = "sifive,gpio-buttons";
+                        label = "BTN1";
+                        gpios = <&L17 5>;
+                        interrupts-extended = <&L10 1>;
+                        linux,code = "none";
+                };
+                button@2 {
+                       	compatible = "sifive,gpio-buttons";
+                        label = "BTN2";
+                        gpios = <&L17 6>;
+                        interrupts-extended = <&L10 2>;
+                        linux,code = "none";
+                };
+                button@3 {
+                       	compatible = "sifive,gpio-buttons";
+                        label = "BTN3";
+                        gpios = <&L17 7>;
+                        interrupts-extended = <&L10 3>;
+                        linux,code = "none";
+                };
+                switch@0 {
+                        compatible = "sifive,gpio-switches";
+                        label = "SW0";
+                        interrupts-extended = <&L10 0>;
+                        linux,code = "none";
+                };
+                switch@1 {
+                        compatible = "sifive,gpio-switches";
+                        label = "SW1";
+                        interrupts-extended = <&L10 1>;
+                        linux,code = "none";
+                };
+                switch@2 {
+                        compatible = "sifive,gpio-switches";
+                        label = "SW2";
+                        interrupts-extended = <&L10 2>;
+                        linux,code = "none";
+                };
+                switch@3 {
+                        compatible = "sifive,gpio-switches";
+                        label = "SW3";
+                        interrupts-extended = <&L10 3>;
+                        linux,code = "none";
+                };
+                L9: teststatus@4000 {
+                        compatible = "sifive,test0";
+                        reg = <0x4000 0x1000>;
+                        reg-names = "control";
+                };
+		L12: tlclk {
+			#clock-cells = <0>;
+			clock-frequency = <32500000>;
+			clock-output-names = "tlclk";
+			compatible = "fixed-clock";
+		};
+	};
+};
diff --git a/bsp/coreip-s76-arty/metal.h b/bsp/coreip-s76-arty/metal.h
new file mode 100644
index 0000000..aa261fc
--- /dev/null
+++ b/bsp/coreip-s76-arty/metal.h
@@ -0,0 +1,492 @@
+#ifndef ASSEMBLY
+
+#ifndef COREIP_S76_ARTY__METAL_H
+#define COREIP_S76_ARTY__METAL_H
+
+#ifdef __METAL_MACHINE_MACROS
+
+#ifndef __METAL_CLIC_SUBINTERRUPTS
+#define __METAL_CLIC_SUBINTERRUPTS 0
+#endif
+
+#else /* ! __METAL_MACHINE_MACROS */
+
+#define __METAL_CLINT_2000000_INTERRUPTS 2
+
+#define METAL_MAX_CLINT_INTERRUPTS 2
+
+#define __METAL_INTERRUPT_CONTROLLER_C000000_INTERRUPTS 1
+
+#define METAL_MAX_PLIC_INTERRUPTS 1
+
+#define METAL_MAX_CLIC_INTERRUPTS 0
+
+#define METAL_MAX_LOCAL_EXT_INTERRUPTS 0
+
+#define __METAL_GLOBAL_EXTERNAL_INTERRUPTS_INTERRUPTS 4
+
+#define METAL_MAX_GLOBAL_EXT_INTERRUPTS 4
+
+#define __METAL_GPIO_10060000_INTERRUPTS 4
+
+#define __METAL_GPIO_20002000_INTERRUPTS 16
+
+#define METAL_MAX_GPIO_INTERRUPTS 16
+
+#define __METAL_SERIAL_20000000_INTERRUPTS 1
+
+#define METAL_MAX_UART_INTERRUPTS 1
+
+
+#include <metal/drivers/fixed-clock.h>
+#include <metal/drivers/riscv,clint0.h>
+#include <metal/drivers/riscv,cpu.h>
+#include <metal/drivers/riscv,plic0.h>
+#include <metal/pmp.h>
+#include <metal/drivers/sifive,global-external-interrupts0.h>
+#include <metal/drivers/sifive,gpio0.h>
+#include <metal/drivers/sifive,gpio-buttons.h>
+#include <metal/drivers/sifive,gpio-leds.h>
+#include <metal/drivers/sifive,gpio-switches.h>
+#include <metal/drivers/sifive,spi0.h>
+#include <metal/drivers/sifive,test0.h>
+#include <metal/drivers/sifive,uart0.h>
+
+/* From tlclk */
+asm (".weak __metal_dt_tlclk");
+struct __metal_driver_fixed_clock __metal_dt_tlclk;
+
+/* From clint@2000000 */
+asm (".weak __metal_dt_clint_2000000");
+struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000;
+
+/* From cpu@0 */
+asm (".weak __metal_dt_cpu_0");
+struct __metal_driver_cpu __metal_dt_cpu_0;
+
+/* From interrupt_controller */
+asm (".weak __metal_dt_interrupt_controller");
+struct __metal_driver_riscv_cpu_intc __metal_dt_interrupt_controller;
+
+/* From interrupt_controller@c000000 */
+asm (".weak __metal_dt_interrupt_controller_c000000");
+struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000;
+
+/* From global_external_interrupts */
+asm (".weak __metal_dt_global_external_interrupts");
+struct __metal_driver_sifive_global_external_interrupts0 __metal_dt_global_external_interrupts;
+
+/* From gpio@10060000 */
+asm (".weak __metal_dt_gpio_10060000");
+struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10060000;
+
+/* From gpio@20002000 */
+asm (".weak __metal_dt_gpio_20002000");
+struct __metal_driver_sifive_gpio0 __metal_dt_gpio_20002000;
+
+/* From button@0 */
+asm (".weak __metal_dt_button_0");
+struct __metal_driver_sifive_gpio_button __metal_dt_button_0;
+
+/* From button@1 */
+asm (".weak __metal_dt_button_1");
+struct __metal_driver_sifive_gpio_button __metal_dt_button_1;
+
+/* From button@2 */
+asm (".weak __metal_dt_button_2");
+struct __metal_driver_sifive_gpio_button __metal_dt_button_2;
+
+/* From button@3 */
+asm (".weak __metal_dt_button_3");
+struct __metal_driver_sifive_gpio_button __metal_dt_button_3;
+
+/* From led@0red */
+asm (".weak __metal_dt_led_0red");
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0red;
+
+/* From led@0green */
+asm (".weak __metal_dt_led_0green");
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0green;
+
+/* From led@0blue */
+asm (".weak __metal_dt_led_0blue");
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue;
+
+/* From switch@0 */
+asm (".weak __metal_dt_switch_0");
+struct __metal_driver_sifive_gpio_switch __metal_dt_switch_0;
+
+/* From switch@1 */
+asm (".weak __metal_dt_switch_1");
+struct __metal_driver_sifive_gpio_switch __metal_dt_switch_1;
+
+/* From switch@2 */
+asm (".weak __metal_dt_switch_2");
+struct __metal_driver_sifive_gpio_switch __metal_dt_switch_2;
+
+/* From switch@3 */
+asm (".weak __metal_dt_switch_3");
+struct __metal_driver_sifive_gpio_switch __metal_dt_switch_3;
+
+/* From spi@20004000 */
+asm (".weak __metal_dt_spi_20004000");
+struct __metal_driver_sifive_spi0 __metal_dt_spi_20004000;
+
+/* From teststatus@4000 */
+asm (".weak __metal_dt_teststatus_4000");
+struct __metal_driver_sifive_test0 __metal_dt_teststatus_4000;
+
+/* From serial@20000000 */
+asm (".weak __metal_dt_serial_20000000");
+struct __metal_driver_sifive_uart0 __metal_dt_serial_20000000;
+
+
+/* From tlclk */
+struct __metal_driver_fixed_clock __metal_dt_tlclk = {
+    .vtable = &__metal_driver_vtable_fixed_clock,
+    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock,
+    .rate = 32500000UL,
+};
+
+/* From clint@2000000 */
+struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000 = {
+    .vtable = &__metal_driver_vtable_riscv_clint0,
+    .controller.vtable = &__metal_driver_vtable_riscv_clint0.clint_vtable,
+    .control_base = 33554432UL,
+    .control_size = 65536UL,
+    .init_done = 0,
+    .num_interrupts = METAL_MAX_CLINT_INTERRUPTS,
+    .interrupt_parent = &__metal_dt_interrupt_controller.controller,
+    .interrupt_lines[0] = 3,
+    .interrupt_lines[1] = 7,
+};
+
+/* From cpu@0 */
+struct __metal_driver_cpu __metal_dt_cpu_0 = {
+    .vtable = &__metal_driver_vtable_cpu,
+    .cpu.vtable = &__metal_driver_vtable_cpu.cpu_vtable,
+    .timebase = 1000000UL,
+    .interrupt_controller = &__metal_dt_interrupt_controller.controller,
+};
+
+/* From interrupt_controller */
+struct __metal_driver_riscv_cpu_intc __metal_dt_interrupt_controller = {
+    .vtable = &__metal_driver_vtable_riscv_cpu_intc,
+    .controller.vtable = &__metal_driver_vtable_riscv_cpu_intc.controller_vtable,
+    .init_done = 0,
+    .interrupt_controller = 1,
+};
+
+/* From interrupt_controller@c000000 */
+struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000 = {
+    .vtable = &__metal_driver_vtable_riscv_plic0,
+    .controller.vtable = &__metal_driver_vtable_riscv_plic0.plic_vtable,
+    .init_done = 0,
+/* From interrupt_controller */
+    .interrupt_parent = &__metal_dt_interrupt_controller.controller,
+    .interrupt_line = 11UL,
+    .control_base = 201326592UL,
+    .control_size = 67108864UL,
+    .max_priority = 7UL,
+    .num_interrupts = 30UL,
+    .interrupt_controller = 1,
+};
+
+/* From global_external_interrupts */
+struct __metal_driver_sifive_global_external_interrupts0 __metal_dt_global_external_interrupts = {
+    .vtable = &__metal_driver_vtable_sifive_global_external_interrupts0,
+    .irc.vtable = &__metal_driver_vtable_sifive_global_external_interrupts0.global0_vtable,
+    .init_done = 0,
+/* From interrupt_controller@c000000 */
+    .interrupt_parent = &__metal_dt_interrupt_controller_c000000.controller,
+    .num_interrupts = METAL_MAX_GLOBAL_EXT_INTERRUPTS,
+    .interrupt_lines[0] = 21,
+    .interrupt_lines[1] = 22,
+    .interrupt_lines[2] = 23,
+    .interrupt_lines[3] = 24,
+};
+
+/* From gpio@10060000 */
+struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10060000 = {
+    .vtable = &__metal_driver_vtable_sifive_gpio0,
+    .base = 268828672UL,
+    .size = 4096UL,
+/* From interrupt_controller@c000000 */
+    .interrupt_parent = &__metal_dt_interrupt_controller_c000000.controller,
+    .num_interrupts = METAL_MAX_GPIO_INTERRUPTS,
+    .interrupt_lines[0] = 27,
+    .interrupt_lines[1] = 28,
+    .interrupt_lines[2] = 29,
+    .interrupt_lines[3] = 30,
+};
+
+/* From gpio@20002000 */
+struct __metal_driver_sifive_gpio0 __metal_dt_gpio_20002000 = {
+    .vtable = &__metal_driver_vtable_sifive_gpio0,
+    .base = 536879104UL,
+    .size = 4096UL,
+/* From interrupt_controller@c000000 */
+    .interrupt_parent = &__metal_dt_interrupt_controller_c000000.controller,
+    .num_interrupts = METAL_MAX_GPIO_INTERRUPTS,
+    .interrupt_lines[0] = 1,
+    .interrupt_lines[1] = 2,
+    .interrupt_lines[2] = 3,
+    .interrupt_lines[3] = 4,
+    .interrupt_lines[4] = 5,
+    .interrupt_lines[5] = 6,
+    .interrupt_lines[6] = 7,
+    .interrupt_lines[7] = 8,
+    .interrupt_lines[8] = 9,
+    .interrupt_lines[9] = 10,
+    .interrupt_lines[10] = 11,
+    .interrupt_lines[11] = 12,
+    .interrupt_lines[12] = 13,
+    .interrupt_lines[13] = 14,
+    .interrupt_lines[14] = 15,
+    .interrupt_lines[15] = 16,
+};
+
+/* From button@0 */
+struct __metal_driver_sifive_gpio_button __metal_dt_button_0 = {
+    .vtable = &__metal_driver_vtable_sifive_button,
+    .button.vtable = &__metal_driver_vtable_sifive_button.button_vtable,
+/* From gpio@10060000 */
+    .gpio = &__metal_dt_gpio_10060000,
+    .pin = 4UL,
+/* From global_external_interrupts */
+    .interrupt_parent = &__metal_dt_global_external_interrupts.irc,
+    .interrupt_line = 0UL,
+    .label = "BTN0",
+};
+
+/* From button@1 */
+struct __metal_driver_sifive_gpio_button __metal_dt_button_1 = {
+    .vtable = &__metal_driver_vtable_sifive_button,
+    .button.vtable = &__metal_driver_vtable_sifive_button.button_vtable,
+/* From gpio@10060000 */
+    .gpio = &__metal_dt_gpio_10060000,
+    .pin = 5UL,
+/* From global_external_interrupts */
+    .interrupt_parent = &__metal_dt_global_external_interrupts.irc,
+    .interrupt_line = 1UL,
+    .label = "BTN1",
+};
+
+/* From button@2 */
+struct __metal_driver_sifive_gpio_button __metal_dt_button_2 = {
+    .vtable = &__metal_driver_vtable_sifive_button,
+    .button.vtable = &__metal_driver_vtable_sifive_button.button_vtable,
+/* From gpio@10060000 */
+    .gpio = &__metal_dt_gpio_10060000,
+    .pin = 6UL,
+/* From global_external_interrupts */
+    .interrupt_parent = &__metal_dt_global_external_interrupts.irc,
+    .interrupt_line = 2UL,
+    .label = "BTN2",
+};
+
+/* From button@3 */
+struct __metal_driver_sifive_gpio_button __metal_dt_button_3 = {
+    .vtable = &__metal_driver_vtable_sifive_button,
+    .button.vtable = &__metal_driver_vtable_sifive_button.button_vtable,
+/* From gpio@10060000 */
+    .gpio = &__metal_dt_gpio_10060000,
+    .pin = 7UL,
+/* From global_external_interrupts */
+    .interrupt_parent = &__metal_dt_global_external_interrupts.irc,
+    .interrupt_line = 3UL,
+    .label = "BTN3",
+};
+
+/* From led@0red */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0red = {
+    .vtable = &__metal_driver_vtable_sifive_led,
+    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+/* From gpio@10060000 */
+    .gpio = &__metal_dt_gpio_10060000,
+    .pin = 0UL,
+    .label = "LD0red",
+};
+
+/* From led@0green */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0green = {
+    .vtable = &__metal_driver_vtable_sifive_led,
+    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+/* From gpio@10060000 */
+    .gpio = &__metal_dt_gpio_10060000,
+    .pin = 1UL,
+    .label = "LD0green",
+};
+
+/* From led@0blue */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue = {
+    .vtable = &__metal_driver_vtable_sifive_led,
+    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+/* From gpio@10060000 */
+    .gpio = &__metal_dt_gpio_10060000,
+    .pin = 2UL,
+    .label = "LD0blue",
+};
+
+/* From switch@0 */
+struct __metal_driver_sifive_gpio_switch __metal_dt_switch_0 = {
+    .vtable = &__metal_driver_vtable_sifive_switch,
+    .flip.vtable = &__metal_driver_vtable_sifive_switch.switch_vtable,
+    .gpio = NULL,
+    .pin = 0,
+/* From global_external_interrupts */
+    .interrupt_parent = &__metal_dt_global_external_interrupts.irc,
+    .interrupt_line = 0UL,
+    .label = "SW0",
+};
+
+/* From switch@1 */
+struct __metal_driver_sifive_gpio_switch __metal_dt_switch_1 = {
+    .vtable = &__metal_driver_vtable_sifive_switch,
+    .flip.vtable = &__metal_driver_vtable_sifive_switch.switch_vtable,
+    .gpio = NULL,
+    .pin = 0,
+/* From global_external_interrupts */
+    .interrupt_parent = &__metal_dt_global_external_interrupts.irc,
+    .interrupt_line = 1UL,
+    .label = "SW1",
+};
+
+/* From switch@2 */
+struct __metal_driver_sifive_gpio_switch __metal_dt_switch_2 = {
+    .vtable = &__metal_driver_vtable_sifive_switch,
+    .flip.vtable = &__metal_driver_vtable_sifive_switch.switch_vtable,
+    .gpio = NULL,
+    .pin = 0,
+/* From global_external_interrupts */
+    .interrupt_parent = &__metal_dt_global_external_interrupts.irc,
+    .interrupt_line = 2UL,
+    .label = "SW2",
+};
+
+/* From switch@3 */
+struct __metal_driver_sifive_gpio_switch __metal_dt_switch_3 = {
+    .vtable = &__metal_driver_vtable_sifive_switch,
+    .flip.vtable = &__metal_driver_vtable_sifive_switch.switch_vtable,
+    .gpio = NULL,
+    .pin = 0,
+/* From global_external_interrupts */
+    .interrupt_parent = &__metal_dt_global_external_interrupts.irc,
+    .interrupt_line = 3UL,
+    .label = "SW3",
+};
+
+/* From spi@20004000 */
+struct __metal_driver_sifive_spi0 __metal_dt_spi_20004000 = {
+    .vtable = &__metal_driver_vtable_sifive_spi0,
+    .spi.vtable = &__metal_driver_vtable_sifive_spi0.spi,
+    .control_base = 536887296UL,
+    .control_size = 4096UL,
+/* From tlclk */
+    .clock = &__metal_dt_tlclk.clock,
+    .pinmux = NULL,
+};
+
+/* From teststatus@4000 */
+struct __metal_driver_sifive_test0 __metal_dt_teststatus_4000 = {
+    .vtable = &__metal_driver_vtable_sifive_test0,
+    .shutdown.vtable = &__metal_driver_vtable_sifive_test0.shutdown,
+    .base = 16384UL,
+    .size = 4096UL,
+};
+
+/* From serial@20000000 */
+struct __metal_driver_sifive_uart0 __metal_dt_serial_20000000 = {
+    .vtable = &__metal_driver_vtable_sifive_uart0,
+    .uart.vtable = &__metal_driver_vtable_sifive_uart0.uart,
+    .control_base = 536870912UL,
+    .control_size = 4096UL,
+/* From tlclk */
+    .clock = &__metal_dt_tlclk.clock,
+    .pinmux = NULL,
+/* From interrupt_controller@c000000 */
+    .interrupt_parent = &__metal_dt_interrupt_controller_c000000.controller,
+    .num_interrupts = METAL_MAX_UART_INTERRUPTS,
+    .interrupt_line = 25UL,
+};
+
+
+/* From serial@20000000 */
+#define __METAL_DT_STDOUT_UART_HANDLE (&__metal_dt_serial_20000000.uart)
+
+#define __METAL_DT_SERIAL_20000000_HANDLE (&__metal_dt_serial_20000000.uart)
+
+#define __METAL_DT_STDOUT_UART_BAUD 115200
+
+/* From clint@2000000 */
+#define __METAL_DT_RISCV_CLINT0_HANDLE (&__metal_dt_clint_2000000.controller)
+
+#define __METAL_DT_CLINT_2000000_HANDLE (&__metal_dt_clint_2000000.controller)
+
+/* From cpu@0 */
+#define __METAL_DT_RISCV_CPU_HANDLE (&__metal_dt_cpu_0.cpu)
+
+#define __METAL_DT_CPU_0_HANDLE (&__metal_dt_cpu_0.cpu)
+
+#define __METAL_DT_MAX_HARTS 1
+
+asm (".weak __metal_cpu_table");
+struct __metal_driver_cpu *__metal_cpu_table[] = {
+					&__metal_dt_cpu_0};
+
+/* From interrupt_controller */
+#define __METAL_DT_RISCV_CPU_INTC_HANDLE (&__metal_dt_interrupt_controller.controller)
+
+#define __METAL_DT_INTERRUPT_CONTROLLER_HANDLE (&__metal_dt_interrupt_controller.controller)
+
+/* From interrupt_controller@c000000 */
+#define __METAL_DT_RISCV_PLIC0_HANDLE (&__metal_dt_interrupt_controller_c000000.controller)
+
+#define __METAL_DT_INTERRUPT_CONTROLLER_C000000_HANDLE (&__metal_dt_interrupt_controller_c000000.controller)
+
+/* From global_external_interrupts */
+#define __METAL_DT_SIFIVE_GLOBAL_EXINTR0_HANDLE (&__metal_dt_global_external_interrupts.irc)
+
+#define __METAL_DT_GLOBAL_EXTERNAL_INTERRUPTS_HANDLE (&__metal_dt_global_external_interrupts.irc)
+
+#define __METAL_DT_MAX_BUTTONS 4
+
+asm (".weak __metal_button_table");
+struct __metal_driver_sifive_gpio_button *__metal_button_table[] = {
+					&__metal_dt_button_0,
+					&__metal_dt_button_1,
+					&__metal_dt_button_2,
+					&__metal_dt_button_3};
+
+#define __METAL_DT_MAX_LEDS 3
+
+asm (".weak __metal_led_table");
+struct __metal_driver_sifive_gpio_led *__metal_led_table[] = {
+					&__metal_dt_led_0red,
+					&__metal_dt_led_0green,
+					&__metal_dt_led_0blue};
+
+#define __METAL_DT_MAX_SWITCHES 4
+
+asm (".weak __metal_switch_table");
+struct __metal_driver_sifive_gpio_switch *__metal_switch_table[] = {
+					&__metal_dt_switch_0,
+					&__metal_dt_switch_1,
+					&__metal_dt_switch_2,
+					&__metal_dt_switch_3};
+
+#define __METAL_DT_MAX_SPIS 1
+
+asm (".weak __metal_spi_table");
+struct __metal_driver_sifive_spi0 *__metal_spi_table[] = {
+					&__metal_dt_spi_20004000};
+
+/* From teststatus@4000 */
+#define __METAL_DT_SHUTDOWN_HANDLE (&__metal_dt_teststatus_4000.shutdown)
+
+#define __METAL_DT_TESTSTATUS_4000_HANDLE (&__metal_dt_teststatus_4000.shutdown)
+
+
+#endif /* ! __METAL_MACHINE_MACROS */
+#endif /* COREIP_S76_ARTY__METAL_H*/
+#endif /* ! ASSEMBLY */
diff --git a/bsp/coreip-s76-arty/metal.lds b/bsp/coreip-s76-arty/metal.lds
new file mode 100644
index 0000000..8a30906
--- /dev/null
+++ b/bsp/coreip-s76-arty/metal.lds
@@ -0,0 +1,225 @@
+OUTPUT_ARCH("riscv")
+
+ENTRY(_enter)
+
+MEMORY
+{
+	ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 0x10000000
+	flash (rxai!w) : ORIGIN = 0x40400000, LENGTH = 0x20000000
+}
+
+PHDRS
+{
+	flash PT_LOAD;
+	ram_init PT_LOAD;
+	itim_init PT_LOAD;
+	ram PT_NULL;
+	itim PT_NULL;
+}
+
+SECTIONS
+{
+	__stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
+	__heap_size = DEFINED(__heap_size) ? __heap_size : 0x400;
+
+
+	.init 		:
+	{
+		KEEP (*(.text.metal.init.enter))
+		KEEP (*(SORT_NONE(.init)))
+	} >flash AT>flash :flash
+
+
+	.text 		:
+	{
+		*(.text.unlikely .text.unlikely.*)
+		*(.text.startup .text.startup.*)
+		*(.text .text.*)
+		*(.itim .itim.*)
+		*(.gnu.linkonce.t.*)
+	} >flash AT>flash :flash
+
+
+	.fini 		:
+	{
+		KEEP (*(SORT_NONE(.fini)))
+	} >flash AT>flash :flash
+
+
+	PROVIDE (__etext = .);
+	PROVIDE (_etext = .);
+	PROVIDE (etext = .);
+
+
+	.rodata 		:
+	{
+		*(.rdata)
+		*(.rodata .rodata.*)
+		*(.gnu.linkonce.r.*)
+	} >flash AT>flash :flash
+
+
+	. = ALIGN(4);
+
+
+	.preinit_array 		:
+	{
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP (*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+	} >flash AT>flash :flash
+
+
+	.init_array 		:
+	{
+		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 = .);
+	} >flash AT>flash :flash
+
+
+	.finit_array 		:
+	{
+		PROVIDE_HIDDEN (__finit_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 (__finit_array_end = .);
+	} >flash AT>flash :flash
+
+
+	.ctors 		:
+	{
+		/* 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))
+	} >flash AT>flash :flash
+
+
+	.dtors 		:
+	{
+		KEEP (*crtbegin.o(.dtors))
+		KEEP (*crtbegin?.o(.dtors))
+		KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+		KEEP (*(SORT(.dtors.*)))
+		KEEP (*(.dtors))
+	} >flash AT>flash :flash
+
+
+	.litimalign 		:
+	{
+		. = ALIGN(4);
+		PROVIDE( metal_segment_itim_source_start = . );
+	} >flash AT>flash :flash
+
+
+	.ditimalign 		:
+	{
+		. = ALIGN(4);
+		PROVIDE( metal_segment_itim_target_start = . );
+	} >ram AT>flash :ram_init
+
+
+	.itim 		:
+	{
+	} >flash AT>flash :flash
+
+
+	. = ALIGN(8);
+	PROVIDE( metal_segment_itim_target_end = . );
+
+
+	.lalign 		:
+	{
+		. = ALIGN(4);
+		PROVIDE( _data_lma = . );
+		PROVIDE( metal_segment_data_source_start = . );
+	} >flash AT>flash :flash
+
+
+	.dalign 		:
+	{
+		. = ALIGN(4);
+		PROVIDE( metal_segment_data_target_start = . );
+	} >ram AT>flash :ram_init
+
+
+	.data 		:
+	{
+		*(.data .data.*)
+		*(.gnu.linkonce.d.*)
+		. = ALIGN(8);
+		PROVIDE( __global_pointer$ = . + 0x800 );
+		*(.sdata .sdata.*)
+		*(.gnu.linkonce.s.*)
+		. = ALIGN(8);
+		*(.srodata.cst16)
+		*(.srodata.cst8)
+		*(.srodata.cst4)
+		*(.srodata.cst2)
+		*(.srodata .srodata.*)
+	} >ram AT>flash :ram_init
+
+
+	. = ALIGN(4);
+	PROVIDE( _edata = . );
+	PROVIDE( edata = . );
+	PROVIDE( metal_segment_data_target_end = . );
+	PROVIDE( _fbss = . );
+	PROVIDE( __bss_start = . );
+	PROVIDE( metal_segment_bss_target_start = . );
+
+
+	.bss 		:
+	{
+		*(.sbss*)
+		*(.gnu.linkonce.sb.*)
+		*(.bss .bss.*)
+		*(.gnu.linkonce.b.*)
+		*(COMMON)
+		. = ALIGN(4);
+	} >ram AT>ram :ram
+
+
+	. = ALIGN(8);
+	PROVIDE( _end = . );
+	PROVIDE( end = . );
+	PROVIDE( metal_segment_bss_target_end = . );
+
+
+	.stack :
+	{
+		PROVIDE(metal_segment_stack_begin = .);
+		. = __stack_size;
+		PROVIDE( _sp = . );
+		PROVIDE(metal_segment_stack_end = .);
+	} >ram AT>ram :ram
+
+
+	.heap :
+	{
+		PROVIDE( metal_segment_heap_target_start = . );
+		. = __heap_size;
+		. = __heap_size == 0 ? 0 : ORIGIN(ram) + LENGTH(ram);
+		PROVIDE( metal_segment_heap_target_end = . );
+		PROVIDE( _heap_end = . );
+	} >ram AT>ram :ram
+
+
+}
+
diff --git a/bsp/coreip-s76-arty/openocd.cfg b/bsp/coreip-s76-arty/openocd.cfg
new file mode 100644
index 0000000..34b9f88
--- /dev/null
+++ b/bsp/coreip-s76-arty/openocd.cfg
@@ -0,0 +1,30 @@
+adapter_khz     10000
+
+#source [find interface/ftdi/olimex-arm-usb-tiny-h.cfg]
+
+interface ftdi
+ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H"
+ftdi_vid_pid 0x15ba 0x002a
+
+ftdi_layout_init 0x0808 0x0a1b
+ftdi_layout_signal nSRST -oe 0x0200
+ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100
+ftdi_layout_signal LED -data 0x0800
+#
+
+set _CHIPNAME riscv
+jtag newtap $_CHIPNAME cpu -irlen 5
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME riscv -chain-position $_TARGETNAME
+$_TARGETNAME configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
+
+flash bank my_first_flash fespi 0x40000000 0 0 0 $_TARGETNAME 0x20004000
+init
+#reset
+if {[ info exists pulse_srst]} {
+  ftdi_set_signal nSRST 0
+  ftdi_set_signal nSRST z
+}
+halt
+#flash protect 0 64 last off
diff --git a/bsp/coreip-s76-arty/settings.mk b/bsp/coreip-s76-arty/settings.mk
new file mode 100644
index 0000000..1627f4b
--- /dev/null
+++ b/bsp/coreip-s76-arty/settings.mk
@@ -0,0 +1,2 @@
+RISCV_ARCH=rv64imac
+RISCV_ABI=lp64
-- 
cgit v1.2.3