diff options
27 files changed, 4703 insertions, 24 deletions
diff --git a/.gitmodules b/.gitmodules index fd90c58..f642da7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -58,3 +58,6 @@  [submodule "freedom-devicetree-tools"]  	path = freedom-devicetree-tools  	url = https://github.com/sifive/freedom-devicetree-tools.git +[submodule "software/test-coreip"] +	path = software/test-coreip +	url = https://github.com/sifive/test-coreip.git @@ -56,6 +56,11 @@ PROGRAM_LST = $(SRC_DIR)/$(CONFIGURATION)/$(PROGRAM).lst  # Finds the directory in which this BSP is located, ensuring that there is  # exactly one.  BSP_DIR := $(wildcard $(TARGET_ROOT)/bsp/$(TARGET)) + +# Only perform these error checks and include the standalone.mk fragment  +# if we're not processing one of the "list-" targets +ifneq ($@,$(filter $@, list-targets list-target-tags list-programs list-options)) +  ifeq ($(words $(BSP_DIR)),0)  $(error Unable to find BSP for $(TARGET), expected to find "bsp/$(TARGET)")  endif @@ -77,6 +82,9 @@ endif  include scripts/standalone.mk +# End of exclusion when procesinng "list-" targets.  +endif +  #############################################################  # Prints help message  ############################################################# @@ -214,7 +222,11 @@ standalone: \  	find $</scripts/elf2hex -name ".git*" | xargs rm -rf +ifeq ($(PORT_DIR),)  	$(MAKE) -C $(SRC_DIR) clean +else +	$(MAKE) -C $(SRC_DIR) PORT_DIR=${PORT_DIR} clean +endif  	cp -r $(SRC_DIR)/* $</src/  	cp debug.mk $</debug.mk @@ -222,7 +234,7 @@ standalone: \  	echo "PROGRAM = $(PROGRAM)" > $</Makefile  ifneq ($(PORT_DIR),) -	echo "PORT_DIR = $(PORT_DIR)" > $</Makefile +	echo "PORT_DIR = $(PORT_DIR)" >> $</Makefile  endif  	cat scripts/standalone.mk >> $</Makefile  	cat scripts/libmetal.mk >> $</Makefile @@ -243,7 +255,11 @@ standalone: \  	find $</freedom-metal -name ".git*" | xargs rm -rf +ifeq ($(PORT_DIR),)  	$(MAKE) -C $(SRC_DIR) clean +else +	$(MAKE) -C $(SRC_DIR) PORT_DIR=${PORT_DIR} clean +endif  	cp -r $(SRC_DIR)/* $</src/  	cp debug.mk $</debug.mk @@ -251,7 +267,7 @@ standalone: \  	echo "PROGRAM = $(PROGRAM)" > $</Makefile  ifneq ($(PORT_DIR),) -        echo "PORT_DIR = $(PORT_DIR)" > $</Makefile +	echo "PORT_DIR = $(PORT_DIR)" >> $</Makefile  endif  	cat scripts/standalone.mk >> $</Makefile  	cat scripts/libmetal.mk >> $</Makefile diff --git a/bsp/qemu-sifive-e31/README.md b/bsp/qemu-sifive-e31/README.md new file mode 100644 index 0000000..72889b9 --- /dev/null +++ b/bsp/qemu-sifive-e31/README.md @@ -0,0 +1,14 @@ +SiFive QEMU E31 is a virtual development platform matching the Freedom E310. It’s the best way to start prototyping and developing your RISC‑V applications. + +This target is ideal for getting familiarize with RISC-V ISA instructions set and freedom-metal libraries. It supports: + +- 1 hart with RV32IMAC core +- 4 hardware breakpoints +- 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 +- 1 RGB LEDS + +This BSP matches the QEMU code in https://github.com/sifive/riscv-qemu/tree/riscv-qemu-3.1 diff --git a/bsp/qemu-sifive-e31/design.dts b/bsp/qemu-sifive-e31/design.dts new file mode 100644 index 0000000..d6f3540 --- /dev/null +++ b/bsp/qemu-sifive-e31/design.dts @@ -0,0 +1,202 @@ +/dts-v1/; + +/ { +        #address-cells = <1>; +        #size-cells = <1>; +        compatible = "sifive,qemu-sifive-e31"; +        model = "sifive,qemu-sifive-e31"; + +        chosen { +                stdout-path = "/soc/serial@10013000:115200"; +                metal,entry = <&spi0 0x400000>; +        }; + +        cpus { +                #address-cells = <1>; +                #size-cells = <0>; +                compatible = "sifive,fe310-g000"; +                L6: cpu@0 { +                        clocks = <&hfclk>; +                        compatible = "sifive,rocket0", "riscv"; +                        device_type = "cpu"; +                        i-cache-block-size = <64>; +                        i-cache-sets = <128>; +                        i-cache-size = <16384>; +                        next-level-cache = <&spi0>; +                        reg = <0>; +                        riscv,isa = "rv32imac"; +                        sifive,dtim = <&dtim>; +                        status = "okay"; +                        timebase-frequency = <1000000>; +                        hardware-exec-breakpoint-count = <4>; +                        hlic: interrupt-controller { +                                #interrupt-cells = <1>; +                                compatible = "riscv,cpu-intc"; +                                interrupt-controller; +                        }; +                }; +        }; + +        soc { +                #address-cells = <1>; +                #size-cells = <1>; +                #clock-cells = <1>; +                compatible = "sifive,qemu-sifive-e31"; +                ranges; + +                hfxoscin: clock@0 { +                        #clock-cells = <0>; +                        compatible = "fixed-clock"; +                        clock-frequency = <16000000>; +                }; +                hfxoscout: clock@1 { +                        compatible = "sifive,fe310-g000,hfxosc"; +                        clocks = <&hfxoscin>; +                        reg = <&prci 0x4>; +                        reg-names = "config"; +                }; +                hfroscin: clock@2 { +                        #clock-cells = <0>; +                        compatible = "fixed-clock"; +                        clock-frequency = <72000000>; +                }; +                hfroscout: clock@3 { +                        compatible = "sifive,fe310-g000,hfrosc"; +                        clocks = <&hfroscin>; +                        reg = <&prci 0x0>; +                        reg-names = "config"; +                }; +                hfclk: clock@4 { +                        compatible = "sifive,fe310-g000,pll"; +                        clocks = <&hfxoscout &hfroscout>; +                        clock-names = "pllref", "pllsel0"; +                        reg = <&prci 0x8 &prci 0xc>; +                        reg-names = "config", "divider"; +			clock-frequency = <16000000>; +                }; + +                lfroscin: clock@5 { +                        #clock-cells = <0>; +                        compatible = "fixed-clock"; +                        clock-frequency = <32000000>; +                }; +                lfclk: clock@6 { +                        compatible = "sifive,fe310-g000,lfrosc"; +                        clocks = <&lfroscin>; +                        reg = <&aon 0x70>; +                        reg-names = "config"; +                }; + +                aon: aon@10000000 { +                        compatible = "sifive,aon0"; +                        reg = <0x10000000 0x8000>; +                        reg-names = "mem"; +                }; + +                prci: prci@10008000 { +                        compatible = "sifive,fe310-g000,prci"; +                        reg = <0x10008000 0x8000>; +                        reg-names = "mem"; +                }; + +                clint: clint@2000000 { +                        compatible = "riscv,clint0"; +                        interrupts-extended = <&hlic 3 &hlic 7>; +                        reg = <0x2000000 0x10000>; +                        reg-names = "control"; +                }; +                local-external-interrupts-0 { +                        compatible = "sifive,local-external-interrupts0"; +                        interrupt-parent = <&hlic>; +                        interrupts = <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31>; +                }; +                plic: interrupt-controller@c000000 { +                        #interrupt-cells = <1>; +                        compatible = "riscv,plic0"; +                        interrupt-controller; +                        interrupts-extended = <&hlic 11>; +                        reg = <0xc000000 0x4000000>; +                        reg-names = "control"; +                        riscv,max-priority = <7>; +                        riscv,ndev = <26>; +                }; +                global-external-interrupts { +                        compatile = "sifive,global-external-interrupts0"; +                        interrupt-parent = <&plic>; +                        interrupts = <1 2 3 4>; +                }; + +                debug-controller@0 { +                        compatible = "sifive,debug-011", "riscv,debug-011"; +                        interrupts-extended = <&hlic 65535>; +                        reg = <0x0 0x100>; +                        reg-names = "control"; +                }; + +                maskrom@1000 { +                        reg = <0x1000 0x2000>; +                        reg-names = "mem"; +                }; +                otp@20000 { +                        reg = <0x20000 0x2000 0x10010000 0x1000>; +                        reg-names = "mem", "control"; +                }; + +                dtim: dtim@80000000 { +                        compatible = "sifive,dtim0"; +                        reg = <0x80000000 0x4000>; +                        reg-names = "mem"; +                }; + +                pwm@10015000 { +                        compatible = "sifive,pwm0"; +                        interrupt-parent = <&plic>; +                        interrupts = <23 24 25 26>; +                        reg = <0x10015000 0x1000>; +                        reg-names = "control"; +                }; +                gpio0: gpio@10012000 { +                        compatible = "sifive,gpio0"; +                        interrupt-parent = <&plic>; +                        interrupts = <7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22>; +                        reg = <0x10012000 0x1000>; +                        reg-names = "control"; +                }; +                uart0: serial@10013000 { +                        compatible = "sifive,uart0"; +                        interrupt-parent = <&plic>; +                        interrupts = <5>; +                        reg = <0x10013000 0x1000>; +                        reg-names = "control"; +                        clocks = <&hfclk>; +                        pinmux = <&gpio0 0x30000 0x30000>; +                }; +                spi0: spi@10014000 { +                        compatible = "sifive,spi0"; +                        interrupt-parent = <&plic>; +                        interrupts = <6>; +                        reg = <0x10014000 0x1000 0x20000000 0x20000000>; +                        reg-names = "control", "mem"; +                        clocks = <&hfclk>; +                        pinmux = <&gpio0 0x0003C 0x0003C>; +                }; +                led@0red { +                        compatible = "sifive,gpio-leds"; +                        label = "LD0red"; +                        gpios = <&gpio0 22>; +                        linux,default-trigger = "none"; +                }; +                led@0green { +                        compatible = "sifive,gpio-leds"; +                        label = "LD0green"; +                        gpios = <&gpio0 19>; +                        linux,default-trigger = "none"; +                }; +                led@0blue { +                        compatible = "sifive,gpio-leds"; +                        label = "LD0blue"; +                        gpios = <&gpio0 21>; +                        linux,default-trigger = "none"; +                }; +        }; +}; diff --git a/bsp/qemu-sifive-e31/design.reglist b/bsp/qemu-sifive-e31/design.reglist new file mode 100644 index 0000000..921dd83 --- /dev/null +++ b/bsp/qemu-sifive-e31/design.reglist @@ -0,0 +1,54 @@ +zero +ra +sp +gp +tp +t0 +t1 +t2 +fp +s1 +a0 +a1 +a2 +a3 +a4 +a5 +a6 +a7 +s2 +s3 +s4 +s5 +s6 +s7 +s8 +s9 +s10 +s11 +t3 +t4 +t5 +t6 +pc +mstatus +misa +mie +mtvec +mscratch +mepc +mcause +mtval +mip +mvendorid +marchid +mimpid +mhartid +tselect +tdata1 +tdata2 +tdata3 +dcsr +dpc +dscratch +priv diff --git a/bsp/qemu-sifive-e31/metal-inline.h b/bsp/qemu-sifive-e31/metal-inline.h new file mode 100644 index 0000000..3f2f6bc --- /dev/null +++ b/bsp/qemu-sifive-e31/metal-inline.h @@ -0,0 +1,249 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +#ifndef ASSEMBLY + +#ifndef QEMU_SIFIVE_E31__METAL_INLINE_H +#define QEMU_SIFIVE_E31__METAL_INLINE_H + +#include <metal/machine.h> + + +/* --------------------- fixed_clock ------------ */ +extern inline unsigned long __metal_driver_fixed_clock_rate(struct metal_clock *clock); + + +/* --------------------- fixed_factor_clock ------------ */ + + +/* --------------------- sifive_clint0 ------------ */ +extern inline unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller); +extern inline unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller); +extern inline struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx); +extern inline int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx); + + +/* --------------------- cpu ------------ */ +extern inline int __metal_driver_cpu_hartid(struct metal_cpu *cpu); +extern inline int __metal_driver_cpu_timebase(struct metal_cpu *cpu); +extern inline struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu); +extern inline int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu); + + +/* --------------------- sifive_plic0 ------------ */ +extern inline unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller); +extern inline unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller); +extern inline struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx); +extern inline int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx); + + +/* --------------------- sifive_clic0 ------------ */ + + +/* --------------------- sifive_local_external_interrupts0 ------------ */ +extern inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx); + + +/* --------------------- sifive_global_external_interrupts0 ------------ */ + + +/* --------------------- sifive_gpio0 ------------ */ +extern inline unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio); +extern inline unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio); +extern inline int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio); +extern inline struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio); +extern inline int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx); + + +/* --------------------- sifive_gpio_button ------------ */ + + +/* --------------------- sifive_gpio_led ------------ */ +extern inline struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led); +extern inline int __metal_driver_sifive_gpio_led_pin(struct metal_led *led); +extern inline char * __metal_driver_sifive_gpio_led_label(struct metal_led *led); + + +/* --------------------- sifive_gpio_switch ------------ */ + + +/* --------------------- sifive_spi0 ------------ */ +extern inline unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi); +extern inline unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi); +extern inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi); +extern inline unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi); +extern inline unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi); + + +/* --------------------- sifive_test0 ------------ */ + + +/* --------------------- sifive_uart0 ------------ */ +extern inline unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart); +extern inline unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart); +extern inline int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart); +extern inline struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart); +extern inline int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart); +extern inline struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart); +extern inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart); +extern inline unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart); +extern inline unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart); + + +/* --------------------- sifive_fe310_g000_hfrosc ------------ */ +extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock); +extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock); +extern inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock); +extern inline long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock); + + +/* --------------------- sifive_fe310_g000_hfxosc ------------ */ +extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock); +extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock); +extern inline long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock); + + +/* --------------------- sifive_fe310_g000_pll ------------ */ +extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock); +extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock); +extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( ); +extern inline long __metal_driver_sifive_fe310_g000_pll_config_offset( ); +extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock); +extern inline long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock); +extern inline long __metal_driver_sifive_fe310_g000_pll_init_rate( ); + + +/* --------------------- fe310_g000_prci ------------ */ +extern inline long __metal_driver_sifive_fe310_g000_prci_base( ); +extern inline long __metal_driver_sifive_fe310_g000_prci_size( ); +extern inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( ); + + +/* --------------------- sifive_fu540_c000_l2 ------------ */ + + +/* From clock@0 */ +struct __metal_driver_fixed_clock __metal_dt_clock_0 = { +    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +/* From clock@2 */ +struct __metal_driver_fixed_clock __metal_dt_clock_2 = { +    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +/* From clock@5 */ +struct __metal_driver_fixed_clock __metal_dt_clock_5 = { +    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +struct metal_memory __metal_dt_mem_dtim_80000000 = { +    ._base_address = 2147483648UL, +    ._size = 16384UL, +    ._attrs = { +        .R = 1, +        .W = 1, +        .X = 1, +        .C = 1, +        .A = 1}, +}; + +struct metal_memory __metal_dt_mem_spi_10014000 = { +    ._base_address = 536870912UL, +    ._size = 536870912UL, +    ._attrs = { +        .R = 1, +        .W = 1, +        .X = 1, +        .C = 1, +        .A = 1}, +}; + +/* From clint@2000000 */ +struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000 = { +    .controller.vtable = &__metal_driver_vtable_riscv_clint0.clint_vtable, +    .init_done = 0, +}; + +/* From cpu@0 */ +struct __metal_driver_cpu __metal_dt_cpu_0 = { +    .cpu.vtable = &__metal_driver_vtable_cpu.cpu_vtable, +}; + +/* From interrupt_controller */ +struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller = { +    .controller.vtable = &__metal_driver_vtable_riscv_cpu_intc.controller_vtable, +    .init_done = 0, +}; + +/* From interrupt_controller@c000000 */ +struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000 = { +    .controller.vtable = &__metal_driver_vtable_riscv_plic0.plic_vtable, +    .init_done = 0, +}; + +/* From local_external_interrupts_0 */ +struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0 = { +    .irc.vtable = &__metal_driver_vtable_sifive_local_external_interrupts0.local0_vtable, +    .init_done = 0, +}; + +/* From gpio@10012000 */ +struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000 = { +    .gpio.vtable = &__metal_driver_vtable_sifive_gpio0.gpio, +}; + +/* From led@0red */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0red = { +    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable, +}; + +/* From led@0green */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0green = { +    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable, +}; + +/* From led@0blue */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue = { +    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable, +}; + +/* From spi@10014000 */ +struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000 = { +    .spi.vtable = &__metal_driver_vtable_sifive_spi0.spi, +}; + +/* From serial@10013000 */ +struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000 = { +    .uart.vtable = &__metal_driver_vtable_sifive_uart0.uart, +}; + +/* From clock@3 */ +struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3 = { +    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfrosc.clock, +}; + +/* From clock@1 */ +struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1 = { +    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfxosc.clock, +}; + +/* From clock@4 */ +struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4 = { +    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_pll.clock, +}; + +/* From prci@10008000 */ +struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000 = { +}; + + +#endif /* QEMU_SIFIVE_E31__METAL_INLINE_H*/ +#endif /* ! ASSEMBLY */ diff --git a/bsp/qemu-sifive-e31/metal-platform.h b/bsp/qemu-sifive-e31/metal-platform.h new file mode 100644 index 0000000..6582722 --- /dev/null +++ b/bsp/qemu-sifive-e31/metal-platform.h @@ -0,0 +1,222 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +#ifndef QEMU_SIFIVE_E31__METAL_PLATFORM_H +#define QEMU_SIFIVE_E31__METAL_PLATFORM_H + +/* From clock@0 */ +#define METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY 16000000UL + +/* From clock@2 */ +#define METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY 72000000UL + +/* From clock@5 */ +#define METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY 32000000UL + +#define METAL_FIXED_CLOCK + +/* From clint@2000000 */ +#define METAL_RISCV_CLINT0_2000000_BASE_ADDRESS 33554432UL +#define METAL_RISCV_CLINT0_0_BASE_ADDRESS 33554432UL +#define METAL_RISCV_CLINT0_2000000_SIZE 65536UL +#define METAL_RISCV_CLINT0_0_SIZE 65536UL + +#define METAL_RISCV_CLINT0 +#define METAL_RISCV_CLINT0_MSIP_BASE 0UL +#define METAL_RISCV_CLINT0_MTIMECMP_BASE 16384UL +#define METAL_RISCV_CLINT0_MTIME 49144UL + +/* From interrupt_controller@c000000 */ +#define METAL_RISCV_PLIC0_C000000_BASE_ADDRESS 201326592UL +#define METAL_RISCV_PLIC0_0_BASE_ADDRESS 201326592UL +#define METAL_RISCV_PLIC0_C000000_SIZE 67108864UL +#define METAL_RISCV_PLIC0_0_SIZE 67108864UL +#define METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY 7UL +#define METAL_RISCV_PLIC0_0_RISCV_MAX_PRIORITY 7UL +#define METAL_RISCV_PLIC0_C000000_RISCV_NDEV 27UL +#define METAL_RISCV_PLIC0_0_RISCV_NDEV 27UL + +#define METAL_RISCV_PLIC0 +#define METAL_RISCV_PLIC0_PRIORITY_BASE 0UL +#define METAL_RISCV_PLIC0_PENDING_BASE 4096UL +#define METAL_RISCV_PLIC0_ENABLE_BASE 8192UL +#define METAL_RISCV_PLIC0_THRESHOLD 2097152UL +#define METAL_RISCV_PLIC0_CLAIM 2097156UL + +/* From aon@10000000 */ +#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL +#define METAL_SIFIVE_AON0_0_SIZE 32768UL + +#define METAL_SIFIVE_AON0 +#define METAL_SIFIVE_AON0_WDOGCFG 0UL +#define METAL_SIFIVE_AON0_WDOGCOUNT 8UL +#define METAL_SIFIVE_AON0_WDOGS 16UL +#define METAL_SIFIVE_AON0_WDOGFEED 24UL +#define METAL_SIFIVE_AON0_WDOGKEY 28UL +#define METAL_SIFIVE_AON0_WDOGCMP 32UL +#define METAL_SIFIVE_AON0_RTCCFG 64UL +#define METAL_SIFIVE_AON0_RTCLO 72UL +#define METAL_SIFIVE_AON0_RTCHI 72UL +#define METAL_SIFIVE_AON0_RTCS 80UL +#define METAL_SIFIVE_AON0_RTCCMP 96UL +#define METAL_SIFIVE_AON0_LFROSCCFG 112UL +#define METAL_SIFIVE_AON0_BACKUP0 128UL +#define METAL_SIFIVE_AON0_BACKUP1 132UL +#define METAL_SIFIVE_AON0_BACKUP2 136UL +#define METAL_SIFIVE_AON0_BACKUP3 140UL +#define METAL_SIFIVE_AON0_BACKUP4 144UL +#define METAL_SIFIVE_AON0_BACKUP5 148UL +#define METAL_SIFIVE_AON0_BACKUP6 152UL +#define METAL_SIFIVE_AON0_BACKUP7 152UL +#define METAL_SIFIVE_AON0_BACKUP8 160UL +#define METAL_SIFIVE_AON0_BACKUP9 164UL +#define METAL_SIFIVE_AON0_BACKUP10 168UL +#define METAL_SIFIVE_AON0_BACKUP11 172UL +#define METAL_SIFIVE_AON0_BACKUP12 176UL +#define METAL_SIFIVE_AON0_BACKUP13 180UL +#define METAL_SIFIVE_AON0_BACKUP14 184UL +#define METAL_SIFIVE_AON0_BACKUP15 188UL +#define METAL_SIFIVE_AON0_BACKUP16 192UL +#define METAL_SIFIVE_AON0_BACKUP17 196UL +#define METAL_SIFIVE_AON0_BACKUP18 200UL +#define METAL_SIFIVE_AON0_BACKUP19 204UL +#define METAL_SIFIVE_AON0_BACKUP20 208UL +#define METAL_SIFIVE_AON0_BACKUP21 212UL +#define METAL_SIFIVE_AON0_BACKUP22 216UL +#define METAL_SIFIVE_AON0_BACKUP23 220UL +#define METAL_SIFIVE_AON0_BACKUP24 224UL +#define METAL_SIFIVE_AON0_BACKUP25 228UL +#define METAL_SIFIVE_AON0_BACKUP26 232UL +#define METAL_SIFIVE_AON0_BACKUP27 236UL +#define METAL_SIFIVE_AON0_BACKUP28 240UL +#define METAL_SIFIVE_AON0_BACKUP29 244UL +#define METAL_SIFIVE_AON0_BACKUP30 248UL +#define METAL_SIFIVE_AON0_BACKUP31 252UL +#define METAL_SIFIVE_AON0_PMU_WAKEUP_BASE 256UL +#define METAL_SIFIVE_AON0_PWM_SLEEP_BASE 288UL +#define METAL_SIFIVE_AON0_PMUIE 320UL +#define METAL_SIFIVE_AON0_PMUCAUSE 324UL +#define METAL_SIFIVE_AON0_PMUSLEEP 328UL +#define METAL_SIFIVE_AON0_PMUKEY 332UL + +/* From clock@3 */ + +#define METAL_SIFIVE_FE310_G000_HFROSC + +/* From clock@1 */ + +#define METAL_SIFIVE_FE310_G000_HFXOSC + +/* From prci@10008000 */ +#define METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS 268468224UL +#define METAL_SIFIVE_FE310_G000_PRCI_0_BASE_ADDRESS 268468224UL +#define METAL_SIFIVE_FE310_G000_PRCI_10008000_SIZE 32768UL +#define METAL_SIFIVE_FE310_G000_PRCI_0_SIZE 32768UL + +#define METAL_SIFIVE_FE310_G000_PRCI +#define METAL_SIFIVE_FE310_G000_PRCI_HFROSCCFG 0UL +#define METAL_SIFIVE_FE310_G000_PRCI_HFXOSCCFG 4UL +#define METAL_SIFIVE_FE310_G000_PRCI_PLLCFG 8UL +#define METAL_SIFIVE_FE310_G000_PRCI_PLLOUTDIV 12UL + +/* From clock@4 */ +#define METAL_SIFIVE_FE310_G000_PLL_4_CLOCK_FREQUENCY 16000000UL + +#define METAL_SIFIVE_FE310_G000_PLL + +/* From gpio@10012000 */ +#define METAL_SIFIVE_GPIO0_10012000_BASE_ADDRESS 268509184UL +#define METAL_SIFIVE_GPIO0_0_BASE_ADDRESS 268509184UL +#define METAL_SIFIVE_GPIO0_10012000_SIZE 4096UL +#define METAL_SIFIVE_GPIO0_0_SIZE 4096UL + +#define METAL_SIFIVE_GPIO0 +#define METAL_SIFIVE_GPIO0_VALUE 0UL +#define METAL_SIFIVE_GPIO0_INPUT_EN 4UL +#define METAL_SIFIVE_GPIO0_OUTPUT_EN 8UL +#define METAL_SIFIVE_GPIO0_PORT 12UL +#define METAL_SIFIVE_GPIO0_PUE 16UL +#define METAL_SIFIVE_GPIO0_DS 20UL +#define METAL_SIFIVE_GPIO0_RISE_IE 24UL +#define METAL_SIFIVE_GPIO0_RISE_IP 28UL +#define METAL_SIFIVE_GPIO0_FALL_IE 32UL +#define METAL_SIFIVE_GPIO0_FALL_IP 36UL +#define METAL_SIFIVE_GPIO0_HIGH_IE 40UL +#define METAL_SIFIVE_GPIO0_HIGH_IP 44UL +#define METAL_SIFIVE_GPIO0_LOW_IE 48UL +#define METAL_SIFIVE_GPIO0_LOW_IP 52UL +#define METAL_SIFIVE_GPIO0_IOF_EN 56UL +#define METAL_SIFIVE_GPIO0_IOF_SEL 60UL +#define METAL_SIFIVE_GPIO0_OUT_XOR 64UL + +/* From led@0red */ + +/* From led@0green */ + +/* From led@0blue */ + +#define METAL_SIFIVE_GPIO_LEDS + +/* From local_external_interrupts_0 */ + +#define METAL_SIFIVE_LOCAL_EXTERNAL_INTERRUPTS0 + +/* From pwm@10015000 */ +#define METAL_SIFIVE_PWM0_10015000_BASE_ADDRESS 268521472UL +#define METAL_SIFIVE_PWM0_0_BASE_ADDRESS 268521472UL +#define METAL_SIFIVE_PWM0_10015000_SIZE 4096UL +#define METAL_SIFIVE_PWM0_0_SIZE 4096UL + +#define METAL_SIFIVE_PWM0 +#define METAL_SIFIVE_PWM0_PWMCFG 0UL +#define METAL_SIFIVE_PWM0_PWMCOUNT 8UL +#define METAL_SIFIVE_PWM0_PWMS 16UL +#define METAL_SIFIVE_PWM0_PWMCMP0 32UL +#define METAL_SIFIVE_PWM0_PWMCMP1 36UL +#define METAL_SIFIVE_PWM0_PWMCMP2 40UL +#define METAL_SIFIVE_PWM0_PWMCMP3 44UL + +/* From spi@10014000 */ +#define METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS 268517376UL +#define METAL_SIFIVE_SPI0_0_BASE_ADDRESS 268517376UL +#define METAL_SIFIVE_SPI0_10014000_SIZE 4096UL +#define METAL_SIFIVE_SPI0_0_SIZE 4096UL + +#define METAL_SIFIVE_SPI0 +#define METAL_SIFIVE_SPI0_SCKDIV 0UL +#define METAL_SIFIVE_SPI0_SCKMODE 4UL +#define METAL_SIFIVE_SPI0_CSID 16UL +#define METAL_SIFIVE_SPI0_CSDEF 20UL +#define METAL_SIFIVE_SPI0_CSMODE 24UL +#define METAL_SIFIVE_SPI0_DELAY0 40UL +#define METAL_SIFIVE_SPI0_DELAY1 44UL +#define METAL_SIFIVE_SPI0_FMT 64UL +#define METAL_SIFIVE_SPI0_TXDATA 72UL +#define METAL_SIFIVE_SPI0_RXDATA 76UL +#define METAL_SIFIVE_SPI0_TXMARK 80UL +#define METAL_SIFIVE_SPI0_RXMARK 84UL +#define METAL_SIFIVE_SPI0_FCTRL 96UL +#define METAL_SIFIVE_SPI0_FFMT 100UL +#define METAL_SIFIVE_SPI0_IE 112UL +#define METAL_SIFIVE_SPI0_IP 116UL + +/* From serial@10013000 */ +#define METAL_SIFIVE_UART0_10013000_BASE_ADDRESS 268513280UL +#define METAL_SIFIVE_UART0_0_BASE_ADDRESS 268513280UL +#define METAL_SIFIVE_UART0_10013000_SIZE 4096UL +#define METAL_SIFIVE_UART0_0_SIZE 4096UL + +#define METAL_SIFIVE_UART0 +#define METAL_SIFIVE_UART0_TXDATA 0UL +#define METAL_SIFIVE_UART0_RXDATA 4UL +#define METAL_SIFIVE_UART0_TXCTRL 8UL +#define METAL_SIFIVE_UART0_RXCTRL 12UL +#define METAL_SIFIVE_UART0_IE 16UL +#define METAL_SIFIVE_UART0_IP 20UL +#define METAL_SIFIVE_UART0_DIV 24UL + +#endif /* QEMU_SIFIVE_E31__METAL_PLATFORM_H*/ diff --git a/bsp/qemu-sifive-e31/metal.default.lds b/bsp/qemu-sifive-e31/metal.default.lds new file mode 100644 index 0000000..6bd988b --- /dev/null +++ b/bsp/qemu-sifive-e31/metal.default.lds @@ -0,0 +1,234 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +OUTPUT_ARCH("riscv") + +ENTRY(_enter) + +MEMORY +{ +	ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 0x4000 +	flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 0x1fc00000 +} + +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; +	PROVIDE(__stack_size = __stack_size); +	__heap_size = DEFINED(__heap_size) ? __heap_size : 0x400; +	PROVIDE(__metal_boot_hart = 0); +	PROVIDE(__metal_chicken_bit = 0); + + +	.init 		: +	{ +		KEEP (*(.text.metal.init.enter)) +		KEEP (*(SORT_NONE(.init))) +		KEEP (*(.text.libgloss.start)) +	} >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.*) +		. = ALIGN(8); +		*(.srodata.cst16) +		*(.srodata.cst8) +		*(.srodata.cst4) +		*(.srodata.cst2) +		*(.srodata .srodata.*) +	} >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 		: +	{ +		*(.itim .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.* .sdata2.*) +		*(.gnu.linkonce.s.*) +	} >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; +		PROVIDE( metal_segment_heap_target_end = . ); +		PROVIDE( _heap_end = . ); +	} >ram AT>ram :ram + + +} + diff --git a/bsp/qemu-sifive-e31/metal.h b/bsp/qemu-sifive-e31/metal.h new file mode 100644 index 0000000..b15ce54 --- /dev/null +++ b/bsp/qemu-sifive-e31/metal.h @@ -0,0 +1,868 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +#ifndef ASSEMBLY + +#include <metal/machine/platform.h> + +#ifdef __METAL_MACHINE_MACROS + +#ifndef MACROS_IF_QEMU_SIFIVE_E31__METAL_H +#define MACROS_IF_QEMU_SIFIVE_E31__METAL_H + +#define __METAL_CLINT_NUM_PARENTS 2 + +#ifndef __METAL_CLINT_NUM_PARENTS +#define __METAL_CLINT_NUM_PARENTS 0 +#endif +#define __METAL_PLIC_SUBINTERRUPTS 27 + +#define __METAL_PLIC_NUM_PARENTS 1 + +#ifndef __METAL_PLIC_SUBINTERRUPTS +#define __METAL_PLIC_SUBINTERRUPTS 0 +#endif +#ifndef __METAL_PLIC_NUM_PARENTS +#define __METAL_PLIC_NUM_PARENTS 0 +#endif +#ifndef __METAL_CLIC_SUBINTERRUPTS +#define __METAL_CLIC_SUBINTERRUPTS 0 +#endif + +#endif /* MACROS_IF_SIFIVE_HIFIVE1__METAL_H*/ + +#else /* ! __METAL_MACHINE_MACROS */ + +#ifndef MACROS_ELSE_SIFIVE_HIFIVE1__METAL_H +#define MACROS_ELSE_SIFIVE_HIFIVE1__METAL_H + +#define __METAL_CLINT_2000000_INTERRUPTS 2 + +#define METAL_MAX_CLINT_INTERRUPTS 2 + +#define __METAL_CLINT_NUM_PARENTS 2 + +#define __METAL_INTERRUPT_CONTROLLER_C000000_INTERRUPTS 1 + +#define __METAL_PLIC_SUBINTERRUPTS 27 + +#define METAL_MAX_PLIC_INTERRUPTS 1 + +#define __METAL_PLIC_NUM_PARENTS 1 + +#define __METAL_CLIC_SUBINTERRUPTS 0 +#define METAL_MAX_CLIC_INTERRUPTS 0 + +#define __METAL_LOCAL_EXTERNAL_INTERRUPTS_0_INTERRUPTS 16 + +#define METAL_MAX_LOCAL_EXT_INTERRUPTS 16 + +#define METAL_MAX_GLOBAL_EXT_INTERRUPTS 0 + +#define __METAL_GPIO_10012000_INTERRUPTS 16 + +#define METAL_MAX_GPIO_INTERRUPTS 16 + +#define __METAL_SERIAL_10013000_INTERRUPTS 1 + +#define METAL_MAX_UART_INTERRUPTS 1 + + +#include <metal/drivers/fixed-clock.h> +#include <metal/memory.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_local-external-interrupts0.h> +#include <metal/drivers/sifive_gpio0.h> +#include <metal/drivers/sifive_gpio-leds.h> +#include <metal/drivers/sifive_spi0.h> +#include <metal/drivers/sifive_uart0.h> +#include <metal/drivers/sifive_fe310-g000_hfrosc.h> +#include <metal/drivers/sifive_fe310-g000_hfxosc.h> +#include <metal/drivers/sifive_fe310-g000_pll.h> +#include <metal/drivers/sifive_fe310-g000_prci.h> + +/* From clock@0 */ +struct __metal_driver_fixed_clock __metal_dt_clock_0; + +/* From clock@2 */ +struct __metal_driver_fixed_clock __metal_dt_clock_2; + +/* From clock@5 */ +struct __metal_driver_fixed_clock __metal_dt_clock_5; + +struct metal_memory __metal_dt_mem_dtim_80000000; + +struct metal_memory __metal_dt_mem_spi_10014000; + +/* From clint@2000000 */ +struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000; + +/* From cpu@0 */ +struct __metal_driver_cpu __metal_dt_cpu_0; + +struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller; + +/* From interrupt_controller@c000000 */ +struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000; + +/* From local_external_interrupts_0 */ +struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0; + +/* From gpio@10012000 */ +struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000; + +/* From led@0red */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0red; + +/* From led@0green */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0green; + +/* From led@0blue */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue; + +/* From spi@10014000 */ +struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000; + +/* From serial@10013000 */ +struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000; + +/* From clock@3 */ +struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3; + +/* From clock@1 */ +struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1; + +/* From clock@4 */ +struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4; + +/* From prci@10008000 */ +struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000; + + + +/* --------------------- fixed_clock ------------ */ +static inline unsigned long __metal_driver_fixed_clock_rate(struct metal_clock *clock) +{ +	if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_0) { +		return METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY; +	} +	else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_2) { +		return METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY; +	} +	else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_5) { +		return METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- fixed_factor_clock ------------ */ + + +/* --------------------- sifive_clint0 ------------ */ +static inline unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) { +		return METAL_RISCV_CLINT0_2000000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) { +		return METAL_RISCV_CLINT0_2000000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) { +		return METAL_MAX_CLINT_INTERRUPTS; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else if (idx == 1) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return 3; +	} +	else if (idx == 1) { +		return 7; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- cpu ------------ */ +static inline int __metal_driver_cpu_hartid(struct metal_cpu *cpu) +{ +	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { +		return 0; +	} +	else { +		return -1; +	} +} + +static inline int __metal_driver_cpu_timebase(struct metal_cpu *cpu) +{ +	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { +		return 1000000; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu) +{ +	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { +		return &__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu) +{ +	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { +		return 0; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- sifive_plic0 ------------ */ +static inline unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { +		return METAL_RISCV_PLIC0_C000000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { +		return METAL_RISCV_PLIC0_C000000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { +		return METAL_RISCV_PLIC0_C000000_RISCV_NDEV; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { +		return METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else if (idx == 0) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return 11; +	} +	else if (idx == 0) { +		return 11; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- sifive_clic0 ------------ */ + + +/* --------------------- sifive_local_external_interrupts0 ------------ */ +static inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_local_external_interrupts_0) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_local_external_interrupts_0) { +		return METAL_MAX_LOCAL_EXT_INTERRUPTS; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return 16; +	} +	else if (idx == 1) { +		return 17; +	} +	else if (idx == 2) { +		return 18; +	} +	else if (idx == 3) { +		return 19; +	} +	else if (idx == 4) { +		return 20; +	} +	else if (idx == 5) { +		return 21; +	} +	else if (idx == 6) { +		return 22; +	} +	else if (idx == 7) { +		return 23; +	} +	else if (idx == 8) { +		return 24; +	} +	else if (idx == 9) { +		return 25; +	} +	else if (idx == 10) { +		return 26; +	} +	else if (idx == 11) { +		return 27; +	} +	else if (idx == 12) { +		return 28; +	} +	else if (idx == 13) { +		return 29; +	} +	else if (idx == 14) { +		return 30; +	} +	else if (idx == 15) { +		return 31; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- sifive_global_external_interrupts0 ------------ */ + + +/* --------------------- sifive_gpio0 ------------ */ +static inline unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio) +{ +	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { +		return METAL_SIFIVE_GPIO0_10012000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio) +{ +	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { +		return METAL_SIFIVE_GPIO0_10012000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio) +{ +	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { +		return METAL_MAX_GPIO_INTERRUPTS; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio) +{ +	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { +		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx) +{ +	if (((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 0)) { +		return 7; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 1))) { +		return 8; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 2))) { +		return 9; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 3))) { +		return 10; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 4))) { +		return 11; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 5))) { +		return 12; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 6))) { +		return 13; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 7))) { +		return 14; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 8))) { +		return 15; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 9))) { +		return 16; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 10))) { +		return 17; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 11))) { +		return 18; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 12))) { +		return 19; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 13))) { +		return 20; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 14))) { +		return 21; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 15))) { +		return 22; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- sifive_gpio_button ------------ */ + + +/* --------------------- sifive_gpio_led ------------ */ +static inline struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led) +{ +	if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0red) { +		return (struct metal_gpio *)&__metal_dt_gpio_10012000; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) { +		return (struct metal_gpio *)&__metal_dt_gpio_10012000; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) { +		return (struct metal_gpio *)&__metal_dt_gpio_10012000; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_gpio_led_pin(struct metal_led *led) +{ +	if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0red) { +		return 22; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) { +		return 19; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) { +		return 21; +	} +	else { +		return 0; +	} +} + +static inline char * __metal_driver_sifive_gpio_led_label(struct metal_led *led) +{ +	if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0red) { +		return "LD0red"; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) { +		return "LD0green"; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) { +		return "LD0blue"; +	} +	else { +		return ""; +	} +} + + + +/* --------------------- sifive_gpio_switch ------------ */ + + +/* --------------------- sifive_spi0 ------------ */ +static inline unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi) +{ +	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { +		return METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi) +{ +	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { +		return METAL_SIFIVE_SPI0_10014000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline struct metal_clock * __metal_driver_sifive_spi0_clock(struct metal_spi *spi) +{ +		return (struct metal_clock *)&__metal_dt_clock_4.clock; +} + +static inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi) +{ +		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; +} + +static inline unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi) +{ +		return 60; +} + +static inline unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi) +{ +		return 60; +} + + + +/* --------------------- sifive_test0 ------------ */ + + +/* --------------------- sifive_uart0 ------------ */ +static inline unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart) +{ +	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { +		return METAL_SIFIVE_UART0_10013000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart) +{ +	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { +		return METAL_SIFIVE_UART0_10013000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart) +{ +	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { +		return METAL_MAX_UART_INTERRUPTS; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart) +{ +	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { +		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart) +{ +		return 5; +} + +static inline struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart) +{ +		return (struct metal_clock *)&__metal_dt_clock_4.clock; +} + +static inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart) +{ +		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; +} + +static inline unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart) +{ +		return 196608; +} + +static inline unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart) +{ +		return 196608; +} + + + +/* --------------------- sifive_fe310_g000_hfrosc ------------ */ +static inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock) +{ +		return (struct metal_clock *)&__metal_dt_clock_2.clock; +} + +static inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock) +{ +		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock) +{ +		return &__metal_driver_vtable_sifive_fe310_g000_prci; +} + +static inline long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_HFROSCCFG; +} + + + +/* --------------------- sifive_fe310_g000_hfxosc ------------ */ +static inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock) +{ +		return (struct metal_clock *)&__metal_dt_clock_0.clock; +} + +static inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock) +{ +		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static inline long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_HFXOSCCFG; +} + + + +/* --------------------- sifive_fe310_g000_pll ------------ */ +static inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock) +{ +		return (struct metal_clock *)&__metal_dt_clock_3.clock; +} + +static inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock) +{ +		return (struct metal_clock *)&__metal_dt_clock_1.clock; +} + +static inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock) +{ +		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static inline long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_PLLOUTDIV; +} + +static inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( ) +{ +		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static inline long __metal_driver_sifive_fe310_g000_pll_config_offset( ) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_PLLCFG; +} + +static inline long __metal_driver_sifive_fe310_g000_pll_init_rate( ) +{ +		return 16000000; +} + + + +/* --------------------- sifive_fe310_g000_prci ------------ */ +static inline long __metal_driver_sifive_fe310_g000_prci_base( ) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS; +} + +static inline long __metal_driver_sifive_fe310_g000_prci_size( ) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_10008000_SIZE; +} + +static inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( ) +{ +		return &__metal_driver_vtable_sifive_fe310_g000_prci; +} + + + +/* --------------------- sifive_fu540_c000_l2 ------------ */ + + +#define __METAL_DT_MAX_MEMORIES 2 + +asm (".weak __metal_memory_table"); +struct metal_memory *__metal_memory_table[] = { +					&__metal_dt_mem_dtim_80000000, +					&__metal_dt_mem_spi_10014000}; + +/* From serial@10013000 */ +#define __METAL_DT_STDOUT_UART_HANDLE (&__metal_dt_serial_10013000.uart) + +#define __METAL_DT_SERIAL_10013000_HANDLE (&__metal_dt_serial_10013000.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) + +#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@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 local_external_interrupts_0 */ +#define __METAL_DT_SIFIVE_LOCAL_EXINTR0_HANDLE (&__metal_dt_local_external_interrupts_0.irc) + +#define __METAL_DT_LOCAL_EXTERNAL_INTERRUPTS_0_HANDLE (&__metal_dt_local_external_interrupts_0.irc) + +#define __MEE_DT_MAX_GPIOS 1 + +asm (".weak __metal_gpio_table"); +struct __metal_driver_sifive_gpio0 *__metal_gpio_table[] = { +					&__metal_dt_gpio_10012000}; + +#define __METAL_DT_MAX_BUTTONS 0 + +asm (".weak __metal_button_table"); +struct __metal_driver_sifive_gpio_button *__metal_button_table[] = { +					NULL }; +#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 0 + +asm (".weak __metal_switch_table"); +struct __metal_driver_sifive_gpio_switch *__metal_switch_table[] = { +					NULL }; +#define __METAL_DT_MAX_SPIS 1 + +asm (".weak __metal_spi_table"); +struct __metal_driver_sifive_spi0 *__metal_spi_table[] = { +					&__metal_dt_spi_10014000}; + +/* From clock@4 */ +#define __METAL_DT_SIFIVE_FE310_G000_PLL_HANDLE (&__metal_dt_clock_4) + +#define __METAL_DT_CLOCK_4_HANDLE (&__metal_dt_clock_4) + +#endif /* MACROS_ELSE_QEMU_SIFIVE_E31__METAL_H*/ + +#endif /* ! __METAL_MACHINE_MACROS */ + +#endif /* ! ASSEMBLY */ diff --git a/bsp/qemu-sifive-e31/metal.ramrodata.lds b/bsp/qemu-sifive-e31/metal.ramrodata.lds new file mode 100644 index 0000000..3322e4a --- /dev/null +++ b/bsp/qemu-sifive-e31/metal.ramrodata.lds @@ -0,0 +1,231 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +OUTPUT_ARCH("riscv") + +ENTRY(_enter) + +MEMORY +{ +	ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 0x4000 +	flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 0x1fc00000 +} + +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; +	PROVIDE(__stack_size = __stack_size); +	__heap_size = DEFINED(__heap_size) ? __heap_size : 0x400; +	PROVIDE(__metal_boot_hart = 0); +	PROVIDE(__metal_chicken_bit = 0); + + +	.init 		: +	{ +		KEEP (*(.text.metal.init.enter)) +		KEEP (*(SORT_NONE(.init))) +		KEEP (*(.text.libgloss.start)) +	} >flash AT>flash :flash + + + + +	.fini 		: +	{ +		KEEP (*(SORT_NONE(.fini))) +	} >flash AT>flash :flash + + +	PROVIDE (__etext = .); +	PROVIDE (_etext = .); +	PROVIDE (etext = .); + + + + +	. = 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 		: +	{ +		*(.itim .itim.*) +	} >flash AT>flash :flash + + +	. = ALIGN(8); +	PROVIDE( metal_segment_itim_target_end = . ); +	.text 		: +	{ +		*(.text.unlikely .text.unlikely.*) +		*(.text.startup .text.startup.*) +		*(.text .text.*) +		*(.gnu.linkonce.t.*) +		*(.itim .itim.*) +	} >flash AT>flash :flash + + +	.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 		: +	{ +		*(.rdata) +		*(.rodata .rodata.*) +		*(.gnu.linkonce.r.*) +		. = ALIGN(8); +		*(.srodata.cst16) +		*(.srodata.cst8) +		*(.srodata.cst4) +		*(.srodata.cst2) +		*(.srodata .srodata.*) +		*(.data .data.*) +		*(.gnu.linkonce.d.*) +		. = ALIGN(8); +		PROVIDE( __global_pointer$ = . + 0x800 ); +		*(.sdata .sdata.* .sdata2.*) +		*(.gnu.linkonce.s.*) +	} >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; +		PROVIDE( metal_segment_heap_target_end = . ); +		PROVIDE( _heap_end = . ); +	} >ram AT>ram :ram + + +} + diff --git a/bsp/qemu-sifive-e31/metal.scratchpad.lds b/bsp/qemu-sifive-e31/metal.scratchpad.lds new file mode 100644 index 0000000..14e64ea --- /dev/null +++ b/bsp/qemu-sifive-e31/metal.scratchpad.lds @@ -0,0 +1,234 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +OUTPUT_ARCH("riscv") + +ENTRY(_enter) + +MEMORY +{ +	ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 0x4000 +	flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 0x1fc00000 +} + +PHDRS +{ +	flash PT_LOAD; +	ram_init PT_LOAD; +	itim_init PT_LOAD; +	ram PT_LOAD; +	itim PT_LOAD; +} + +SECTIONS +{ +	__stack_size = DEFINED(__stack_size) ? __stack_size : 0x400; +	PROVIDE(__stack_size = __stack_size); +	__heap_size = DEFINED(__heap_size) ? __heap_size : 0x400; +	PROVIDE(__metal_boot_hart = 0); +	PROVIDE(__metal_chicken_bit = 0); + + +	.init 		: +	{ +		KEEP (*(.text.metal.init.enter)) +		KEEP (*(SORT_NONE(.init))) +		KEEP (*(.text.libgloss.start)) +	} >ram AT>ram :ram + + +	.text 		: +	{ +		*(.text.unlikely .text.unlikely.*) +		*(.text.startup .text.startup.*) +		*(.text .text.*) +		*(.itim .itim.*) +		*(.gnu.linkonce.t.*) +	} >ram AT>ram :ram + + +	.fini 		: +	{ +		KEEP (*(SORT_NONE(.fini))) +	} >ram AT>ram :ram + + +	PROVIDE (__etext = .); +	PROVIDE (_etext = .); +	PROVIDE (etext = .); + + +	.rodata 		: +	{ +		*(.rdata) +		*(.rodata .rodata.*) +		*(.gnu.linkonce.r.*) +		. = ALIGN(8); +		*(.srodata.cst16) +		*(.srodata.cst8) +		*(.srodata.cst4) +		*(.srodata.cst2) +		*(.srodata .srodata.*) +	} >ram AT>ram :ram + + +	. = ALIGN(4); + + +	.preinit_array 		: +	{ +		PROVIDE_HIDDEN (__preinit_array_start = .); +		KEEP (*(.preinit_array)) +		PROVIDE_HIDDEN (__preinit_array_end = .); +	} >ram AT>ram :ram + + +	.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 = .); +	} >ram AT>ram :ram + + +	.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 = .); +	} >ram AT>ram :ram + + +	.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)) +	} >ram AT>ram :ram + + +	.dtors 		: +	{ +		KEEP (*crtbegin.o(.dtors)) +		KEEP (*crtbegin?.o(.dtors)) +		KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) +		KEEP (*(SORT(.dtors.*))) +		KEEP (*(.dtors)) +	} >ram AT>ram :ram + + +	.litimalign 		: +	{ +		. = ALIGN(4); +		PROVIDE( metal_segment_itim_source_start = . ); +	} >ram AT>ram :ram + + +	.ditimalign 		: +	{ +		. = ALIGN(4); +		PROVIDE( metal_segment_itim_target_start = . ); +	} >ram AT>ram :ram_init + + +	.itim 		: +	{ +		*(.itim .itim.*) +	} >ram AT>ram :ram_init + + +	. = ALIGN(8); +	PROVIDE( metal_segment_itim_target_end = . ); + + +	.lalign 		: +	{ +		. = ALIGN(4); +		PROVIDE( _data_lma = . ); +		PROVIDE( metal_segment_data_source_start = . ); +	} >ram AT>ram :ram + + +	.dalign 		: +	{ +		. = ALIGN(4); +		PROVIDE( metal_segment_data_target_start = . ); +	} >ram AT>ram :ram_init + + +	.data 		: +	{ +		*(.data .data.*) +		*(.gnu.linkonce.d.*) +		. = ALIGN(8); +		PROVIDE( __global_pointer$ = . + 0x800 ); +		*(.sdata .sdata.* .sdata2.*) +		*(.gnu.linkonce.s.*) +	} >ram AT>ram :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; +		PROVIDE( metal_segment_heap_target_end = . ); +		PROVIDE( _heap_end = . ); +	} >ram AT>ram :ram + + +} + diff --git a/bsp/qemu-sifive-e31/qemu.cfg b/bsp/qemu-sifive-e31/qemu.cfg new file mode 100644 index 0000000..acb1524 --- /dev/null +++ b/bsp/qemu-sifive-e31/qemu.cfg @@ -0,0 +1,5 @@ +# qemu config file + +[machine] +  type = "sifive_e" + diff --git a/bsp/qemu-sifive-e31/settings.mk b/bsp/qemu-sifive-e31/settings.mk new file mode 100644 index 0000000..4e34698 --- /dev/null +++ b/bsp/qemu-sifive-e31/settings.mk @@ -0,0 +1,13 @@ +# Copyright 2019 SiFive, Inc # +# SPDX-License-Identifier: Apache-2.0 # +# ----------------------------------- # +# ----------------------------------- # + +RISCV_ARCH=rv32imac +RISCV_ABI=ilp32 +RISCV_CMODEL=medlow +RISCV_SERIES=sifive-3-series + +TARGET_TAGS=qemu +TARGET_DHRY_ITERS=20000000 +TARGET_CORE_ITERS=5000 diff --git a/bsp/qemu-sifive-s51/README.md b/bsp/qemu-sifive-s51/README.md new file mode 100644 index 0000000..7825a98 --- /dev/null +++ b/bsp/qemu-sifive-s51/README.md @@ -0,0 +1,14 @@ +SiFive QEMU S51 is a virtual development platform matching the Freedom S510. It’s the best way to start prototyping and developing your RISC‑V applications. + +This target is ideal for getting familiarize with RISC-V ISA instructions set and freedom-metal libraries. It supports: + +- 1 hart with RV64IMAC core +- 4 hardware breakpoints +- 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 +- 1 RGB LEDS + +This BSP matches the QEMU code in https://github.com/sifive/riscv-qemu/tree/riscv-qemu-3.1 diff --git a/bsp/qemu-sifive-s51/design.dts b/bsp/qemu-sifive-s51/design.dts new file mode 100644 index 0000000..083653e --- /dev/null +++ b/bsp/qemu-sifive-s51/design.dts @@ -0,0 +1,202 @@ +/dts-v1/; + +/ { +        #address-cells = <1>; +        #size-cells = <1>; +        compatible = "sifive,qemu-sifive-s51"; +        model = "sifive,qemu-sifive-s51"; + +        chosen { +                stdout-path = "/soc/serial@10013000:115200"; +                metal,entry = <&spi0 0x400000>; +        }; + +        cpus { +                #address-cells = <1>; +                #size-cells = <0>; +                compatible = "sifive,fs510-g000"; +                L6: cpu@0 { +                        clocks = <&hfclk>; +                        compatible = "sifive,rocket0", "riscv"; +                        device_type = "cpu"; +                        i-cache-block-size = <64>; +                        i-cache-sets = <128>; +                        i-cache-size = <16384>; +                        next-level-cache = <&spi0>; +                        reg = <0>; +                        riscv,isa = "rv64imac"; +                        sifive,dtim = <&dtim>; +                        status = "okay"; +                        timebase-frequency = <1000000>; +                        hardware-exec-breakpoint-count = <4>; +                        hlic: interrupt-controller { +                                #interrupt-cells = <1>; +                                compatible = "riscv,cpu-intc"; +                                interrupt-controller; +                        }; +                }; +        }; + +        soc { +                #address-cells = <1>; +                #size-cells = <1>; +                #clock-cells = <1>; +                compatible = "sifive,qemu-sifive-s51"; +                ranges; + +                hfxoscin: clock@0 { +                        #clock-cells = <0>; +                        compatible = "fixed-clock"; +                        clock-frequency = <16000000>; +                }; +                hfxoscout: clock@1 { +                        compatible = "sifive,fs510-g000,hfxosc"; +                        clocks = <&hfxoscin>; +                        reg = <&prci 0x4>; +                        reg-names = "config"; +                }; +                hfroscin: clock@2 { +                        #clock-cells = <0>; +                        compatible = "fixed-clock"; +                        clock-frequency = <72000000>; +                }; +                hfroscout: clock@3 { +                        compatible = "sifive,fs510-g000,hfrosc"; +                        clocks = <&hfroscin>; +                        reg = <&prci 0x0>; +                        reg-names = "config"; +                }; +                hfclk: clock@4 { +                        compatible = "sifive,fs510-g000,pll"; +                        clocks = <&hfxoscout &hfroscout>; +                        clock-names = "pllref", "pllsel0"; +                        reg = <&prci 0x8 &prci 0xc>; +                        reg-names = "config", "divider"; +			clock-frequency = <16000000>; +                }; + +                lfroscin: clock@5 { +                        #clock-cells = <0>; +                        compatible = "fixed-clock"; +                        clock-frequency = <32000000>; +                }; +                lfclk: clock@6 { +                        compatible = "sifive,fs510-g000,lfrosc"; +                        clocks = <&lfroscin>; +                        reg = <&aon 0x70>; +                        reg-names = "config"; +                }; + +                aon: aon@10000000 { +                        compatible = "sifive,aon0"; +                        reg = <0x10000000 0x8000>; +                        reg-names = "mem"; +                }; + +                prci: prci@10008000 { +                        compatible = "sifive,fs510-g000,prci"; +                        reg = <0x10008000 0x8000>; +                        reg-names = "mem"; +                }; + +                clint: clint@2000000 { +                        compatible = "riscv,clint0"; +                        interrupts-extended = <&hlic 3 &hlic 7>; +                        reg = <0x2000000 0x10000>; +                        reg-names = "control"; +                }; +                local-external-interrupts-0 { +                        compatible = "sifive,local-external-interrupts0"; +                        interrupt-parent = <&hlic>; +                        interrupts = <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31>; +                }; +                plic: interrupt-controller@c000000 { +                        #interrupt-cells = <1>; +                        compatible = "riscv,plic0"; +                        interrupt-controller; +                        interrupts-extended = <&hlic 11>; +                        reg = <0xc000000 0x4000000>; +                        reg-names = "control"; +                        riscv,max-priority = <7>; +                        riscv,ndev = <26>; +                }; +                global-external-interrupts { +                        compatile = "sifive,global-external-interrupts0"; +                        interrupt-parent = <&plic>; +                        interrupts = <1 2 3 4>; +                }; + +                debug-controller@0 { +                        compatible = "sifive,debug-011", "riscv,debug-011"; +                        interrupts-extended = <&hlic 65535>; +                        reg = <0x0 0x100>; +                        reg-names = "control"; +                }; + +                maskrom@1000 { +                        reg = <0x1000 0x2000>; +                        reg-names = "mem"; +                }; +                otp@20000 { +                        reg = <0x20000 0x2000 0x10010000 0x1000>; +                        reg-names = "mem", "control"; +                }; + +                dtim: dtim@80000000 { +                        compatible = "sifive,dtim0"; +                        reg = <0x80000000 0x4000>; +                        reg-names = "mem"; +                }; + +                pwm@10015000 { +                        compatible = "sifive,pwm0"; +                        interrupt-parent = <&plic>; +                        interrupts = <23 24 25 26>; +                        reg = <0x10015000 0x1000>; +                        reg-names = "control"; +                }; +                gpio0: gpio@10012000 { +                        compatible = "sifive,gpio0"; +                        interrupt-parent = <&plic>; +                        interrupts = <7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22>; +                        reg = <0x10012000 0x1000>; +                        reg-names = "control"; +                }; +                uart0: serial@10013000 { +                        compatible = "sifive,uart0"; +                        interrupt-parent = <&plic>; +                        interrupts = <5>; +                        reg = <0x10013000 0x1000>; +                        reg-names = "control"; +                        clocks = <&hfclk>; +                        pinmux = <&gpio0 0x30000 0x30000>; +                }; +                spi0: spi@10014000 { +                        compatible = "sifive,spi0"; +                        interrupt-parent = <&plic>; +                        interrupts = <6>; +                        reg = <0x10014000 0x1000 0x20000000 0x20000000>; +                        reg-names = "control", "mem"; +                        clocks = <&hfclk>; +                        pinmux = <&gpio0 0x0003C 0x0003C>; +                }; +                led@0red { +                        compatible = "sifive,gpio-leds"; +                        label = "LD0red"; +                        gpios = <&gpio0 22>; +                        linux,default-trigger = "none"; +                }; +                led@0green { +                        compatible = "sifive,gpio-leds"; +                        label = "LD0green"; +                        gpios = <&gpio0 19>; +                        linux,default-trigger = "none"; +                }; +                led@0blue { +                        compatible = "sifive,gpio-leds"; +                        label = "LD0blue"; +                        gpios = <&gpio0 21>; +                        linux,default-trigger = "none"; +                }; +        }; +}; diff --git a/bsp/qemu-sifive-s51/design.reglist b/bsp/qemu-sifive-s51/design.reglist new file mode 100644 index 0000000..921dd83 --- /dev/null +++ b/bsp/qemu-sifive-s51/design.reglist @@ -0,0 +1,54 @@ +zero +ra +sp +gp +tp +t0 +t1 +t2 +fp +s1 +a0 +a1 +a2 +a3 +a4 +a5 +a6 +a7 +s2 +s3 +s4 +s5 +s6 +s7 +s8 +s9 +s10 +s11 +t3 +t4 +t5 +t6 +pc +mstatus +misa +mie +mtvec +mscratch +mepc +mcause +mtval +mip +mvendorid +marchid +mimpid +mhartid +tselect +tdata1 +tdata2 +tdata3 +dcsr +dpc +dscratch +priv diff --git a/bsp/qemu-sifive-s51/metal-inline.h b/bsp/qemu-sifive-s51/metal-inline.h new file mode 100644 index 0000000..eafd455 --- /dev/null +++ b/bsp/qemu-sifive-s51/metal-inline.h @@ -0,0 +1,249 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +#ifndef ASSEMBLY + +#ifndef QEMU_SIFIVE_S51__METAL_INLINE_H +#define QEMU_SIFIVE_S51__METAL_INLINE_H + +#include <metal/machine.h> + + +/* --------------------- fixed_clock ------------ */ +extern inline unsigned long __metal_driver_fixed_clock_rate(struct metal_clock *clock); + + +/* --------------------- fixed_factor_clock ------------ */ + + +/* --------------------- sifive_clint0 ------------ */ +extern inline unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller); +extern inline unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller); +extern inline struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx); +extern inline int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx); + + +/* --------------------- cpu ------------ */ +extern inline int __metal_driver_cpu_hartid(struct metal_cpu *cpu); +extern inline int __metal_driver_cpu_timebase(struct metal_cpu *cpu); +extern inline struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu); +extern inline int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu); + + +/* --------------------- sifive_plic0 ------------ */ +extern inline unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller); +extern inline unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller); +extern inline struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx); +extern inline int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx); + + +/* --------------------- sifive_clic0 ------------ */ + + +/* --------------------- sifive_local_external_interrupts0 ------------ */ +extern inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller); +extern inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx); + + +/* --------------------- sifive_global_external_interrupts0 ------------ */ + + +/* --------------------- sifive_gpio0 ------------ */ +extern inline unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio); +extern inline unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio); +extern inline int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio); +extern inline struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio); +extern inline int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx); + + +/* --------------------- sifive_gpio_button ------------ */ + + +/* --------------------- sifive_gpio_led ------------ */ +extern inline struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led); +extern inline int __metal_driver_sifive_gpio_led_pin(struct metal_led *led); +extern inline char * __metal_driver_sifive_gpio_led_label(struct metal_led *led); + + +/* --------------------- sifive_gpio_switch ------------ */ + + +/* --------------------- sifive_spi0 ------------ */ +extern inline unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi); +extern inline unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi); +extern inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi); +extern inline unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi); +extern inline unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi); + + +/* --------------------- sifive_test0 ------------ */ + + +/* --------------------- sifive_uart0 ------------ */ +extern inline unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart); +extern inline unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart); +extern inline int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart); +extern inline struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart); +extern inline int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart); +extern inline struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart); +extern inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart); +extern inline unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart); +extern inline unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart); + + +/* --------------------- sifive_fe310_g000_hfrosc ------------ */ +extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock); +extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock); +extern inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock); +extern inline long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock); + + +/* --------------------- sifive_fe310_g000_hfxosc ------------ */ +extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock); +extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock); +extern inline long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock); + + +/* --------------------- sifive_fe310_g000_pll ------------ */ +extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock); +extern inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock); +extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( ); +extern inline long __metal_driver_sifive_fe310_g000_pll_config_offset( ); +extern inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock); +extern inline long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock); +extern inline long __metal_driver_sifive_fe310_g000_pll_init_rate( ); + + +/* --------------------- fe310_g000_prci ------------ */ +extern inline long __metal_driver_sifive_fe310_g000_prci_base( ); +extern inline long __metal_driver_sifive_fe310_g000_prci_size( ); +extern inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( ); + + +/* --------------------- sifive_fu540_c000_l2 ------------ */ + + +/* From clock@0 */ +struct __metal_driver_fixed_clock __metal_dt_clock_0 = { +    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +/* From clock@2 */ +struct __metal_driver_fixed_clock __metal_dt_clock_2 = { +    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +/* From clock@5 */ +struct __metal_driver_fixed_clock __metal_dt_clock_5 = { +    .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +struct metal_memory __metal_dt_mem_dtim_80000000 = { +    ._base_address = 2147483648UL, +    ._size = 16384UL, +    ._attrs = { +        .R = 1, +        .W = 1, +        .X = 1, +        .C = 1, +        .A = 1}, +}; + +struct metal_memory __metal_dt_mem_spi_10014000 = { +    ._base_address = 536870912UL, +    ._size = 536870912UL, +    ._attrs = { +        .R = 1, +        .W = 1, +        .X = 1, +        .C = 1, +        .A = 1}, +}; + +/* From clint@2000000 */ +struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000 = { +    .controller.vtable = &__metal_driver_vtable_riscv_clint0.clint_vtable, +    .init_done = 0, +}; + +/* From cpu@0 */ +struct __metal_driver_cpu __metal_dt_cpu_0 = { +    .cpu.vtable = &__metal_driver_vtable_cpu.cpu_vtable, +}; + +/* From interrupt_controller */ +struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller = { +    .controller.vtable = &__metal_driver_vtable_riscv_cpu_intc.controller_vtable, +    .init_done = 0, +}; + +/* From interrupt_controller@c000000 */ +struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000 = { +    .controller.vtable = &__metal_driver_vtable_riscv_plic0.plic_vtable, +    .init_done = 0, +}; + +/* From local_external_interrupts_0 */ +struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0 = { +    .irc.vtable = &__metal_driver_vtable_sifive_local_external_interrupts0.local0_vtable, +    .init_done = 0, +}; + +/* From gpio@10012000 */ +struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000 = { +    .gpio.vtable = &__metal_driver_vtable_sifive_gpio0.gpio, +}; + +/* From led@0red */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0red = { +    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable, +}; + +/* From led@0green */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0green = { +    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable, +}; + +/* From led@0blue */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue = { +    .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable, +}; + +/* From spi@10014000 */ +struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000 = { +    .spi.vtable = &__metal_driver_vtable_sifive_spi0.spi, +}; + +/* From serial@10013000 */ +struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000 = { +    .uart.vtable = &__metal_driver_vtable_sifive_uart0.uart, +}; + +/* From clock@3 */ +struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3 = { +    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfrosc.clock, +}; + +/* From clock@1 */ +struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1 = { +    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfxosc.clock, +}; + +/* From clock@4 */ +struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4 = { +    .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_pll.clock, +}; + +/* From prci@10008000 */ +struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000 = { +}; + + +#endif /* QEMU_SIFIVE_S51__METAL_INLINE_H*/ +#endif /* ! ASSEMBLY */ diff --git a/bsp/qemu-sifive-s51/metal-platform.h b/bsp/qemu-sifive-s51/metal-platform.h new file mode 100644 index 0000000..650fdbd --- /dev/null +++ b/bsp/qemu-sifive-s51/metal-platform.h @@ -0,0 +1,222 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +#ifndef QEMU_SIFIVE_S51__METAL_PLATFORM_H +#define QEMU_SIFIVE_S51__METAL_PLATFORM_H + +/* From clock@0 */ +#define METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY 16000000UL + +/* From clock@2 */ +#define METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY 72000000UL + +/* From clock@5 */ +#define METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY 32000000UL + +#define METAL_FIXED_CLOCK + +/* From clint@2000000 */ +#define METAL_RISCV_CLINT0_2000000_BASE_ADDRESS 33554432UL +#define METAL_RISCV_CLINT0_0_BASE_ADDRESS 33554432UL +#define METAL_RISCV_CLINT0_2000000_SIZE 65536UL +#define METAL_RISCV_CLINT0_0_SIZE 65536UL + +#define METAL_RISCV_CLINT0 +#define METAL_RISCV_CLINT0_MSIP_BASE 0UL +#define METAL_RISCV_CLINT0_MTIMECMP_BASE 16384UL +#define METAL_RISCV_CLINT0_MTIME 49144UL + +/* From interrupt_controller@c000000 */ +#define METAL_RISCV_PLIC0_C000000_BASE_ADDRESS 201326592UL +#define METAL_RISCV_PLIC0_0_BASE_ADDRESS 201326592UL +#define METAL_RISCV_PLIC0_C000000_SIZE 67108864UL +#define METAL_RISCV_PLIC0_0_SIZE 67108864UL +#define METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY 7UL +#define METAL_RISCV_PLIC0_0_RISCV_MAX_PRIORITY 7UL +#define METAL_RISCV_PLIC0_C000000_RISCV_NDEV 27UL +#define METAL_RISCV_PLIC0_0_RISCV_NDEV 27UL + +#define METAL_RISCV_PLIC0 +#define METAL_RISCV_PLIC0_PRIORITY_BASE 0UL +#define METAL_RISCV_PLIC0_PENDING_BASE 4096UL +#define METAL_RISCV_PLIC0_ENABLE_BASE 8192UL +#define METAL_RISCV_PLIC0_THRESHOLD 2097152UL +#define METAL_RISCV_PLIC0_CLAIM 2097156UL + +/* From aon@10000000 */ +#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL +#define METAL_SIFIVE_AON0_0_SIZE 32768UL + +#define METAL_SIFIVE_AON0 +#define METAL_SIFIVE_AON0_WDOGCFG 0UL +#define METAL_SIFIVE_AON0_WDOGCOUNT 8UL +#define METAL_SIFIVE_AON0_WDOGS 16UL +#define METAL_SIFIVE_AON0_WDOGFEED 24UL +#define METAL_SIFIVE_AON0_WDOGKEY 28UL +#define METAL_SIFIVE_AON0_WDOGCMP 32UL +#define METAL_SIFIVE_AON0_RTCCFG 64UL +#define METAL_SIFIVE_AON0_RTCLO 72UL +#define METAL_SIFIVE_AON0_RTCHI 72UL +#define METAL_SIFIVE_AON0_RTCS 80UL +#define METAL_SIFIVE_AON0_RTCCMP 96UL +#define METAL_SIFIVE_AON0_LFROSCCFG 112UL +#define METAL_SIFIVE_AON0_BACKUP0 128UL +#define METAL_SIFIVE_AON0_BACKUP1 132UL +#define METAL_SIFIVE_AON0_BACKUP2 136UL +#define METAL_SIFIVE_AON0_BACKUP3 140UL +#define METAL_SIFIVE_AON0_BACKUP4 144UL +#define METAL_SIFIVE_AON0_BACKUP5 148UL +#define METAL_SIFIVE_AON0_BACKUP6 152UL +#define METAL_SIFIVE_AON0_BACKUP7 152UL +#define METAL_SIFIVE_AON0_BACKUP8 160UL +#define METAL_SIFIVE_AON0_BACKUP9 164UL +#define METAL_SIFIVE_AON0_BACKUP10 168UL +#define METAL_SIFIVE_AON0_BACKUP11 172UL +#define METAL_SIFIVE_AON0_BACKUP12 176UL +#define METAL_SIFIVE_AON0_BACKUP13 180UL +#define METAL_SIFIVE_AON0_BACKUP14 184UL +#define METAL_SIFIVE_AON0_BACKUP15 188UL +#define METAL_SIFIVE_AON0_BACKUP16 192UL +#define METAL_SIFIVE_AON0_BACKUP17 196UL +#define METAL_SIFIVE_AON0_BACKUP18 200UL +#define METAL_SIFIVE_AON0_BACKUP19 204UL +#define METAL_SIFIVE_AON0_BACKUP20 208UL +#define METAL_SIFIVE_AON0_BACKUP21 212UL +#define METAL_SIFIVE_AON0_BACKUP22 216UL +#define METAL_SIFIVE_AON0_BACKUP23 220UL +#define METAL_SIFIVE_AON0_BACKUP24 224UL +#define METAL_SIFIVE_AON0_BACKUP25 228UL +#define METAL_SIFIVE_AON0_BACKUP26 232UL +#define METAL_SIFIVE_AON0_BACKUP27 236UL +#define METAL_SIFIVE_AON0_BACKUP28 240UL +#define METAL_SIFIVE_AON0_BACKUP29 244UL +#define METAL_SIFIVE_AON0_BACKUP30 248UL +#define METAL_SIFIVE_AON0_BACKUP31 252UL +#define METAL_SIFIVE_AON0_PMU_WAKEUP_BASE 256UL +#define METAL_SIFIVE_AON0_PWM_SLEEP_BASE 288UL +#define METAL_SIFIVE_AON0_PMUIE 320UL +#define METAL_SIFIVE_AON0_PMUCAUSE 324UL +#define METAL_SIFIVE_AON0_PMUSLEEP 328UL +#define METAL_SIFIVE_AON0_PMUKEY 332UL + +/* From clock@3 */ + +#define METAL_SIFIVE_FE310_G000_HFROSC + +/* From clock@1 */ + +#define METAL_SIFIVE_FE310_G000_HFXOSC + +/* From prci@10008000 */ +#define METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS 268468224UL +#define METAL_SIFIVE_FE310_G000_PRCI_0_BASE_ADDRESS 268468224UL +#define METAL_SIFIVE_FE310_G000_PRCI_10008000_SIZE 32768UL +#define METAL_SIFIVE_FE310_G000_PRCI_0_SIZE 32768UL + +#define METAL_SIFIVE_FE310_G000_PRCI +#define METAL_SIFIVE_FE310_G000_PRCI_HFROSCCFG 0UL +#define METAL_SIFIVE_FE310_G000_PRCI_HFXOSCCFG 4UL +#define METAL_SIFIVE_FE310_G000_PRCI_PLLCFG 8UL +#define METAL_SIFIVE_FE310_G000_PRCI_PLLOUTDIV 12UL + +/* From clock@4 */ +#define METAL_SIFIVE_FE310_G000_PLL_4_CLOCK_FREQUENCY 16000000UL + +#define METAL_SIFIVE_FE310_G000_PLL + +/* From gpio@10012000 */ +#define METAL_SIFIVE_GPIO0_10012000_BASE_ADDRESS 268509184UL +#define METAL_SIFIVE_GPIO0_0_BASE_ADDRESS 268509184UL +#define METAL_SIFIVE_GPIO0_10012000_SIZE 4096UL +#define METAL_SIFIVE_GPIO0_0_SIZE 4096UL + +#define METAL_SIFIVE_GPIO0 +#define METAL_SIFIVE_GPIO0_VALUE 0UL +#define METAL_SIFIVE_GPIO0_INPUT_EN 4UL +#define METAL_SIFIVE_GPIO0_OUTPUT_EN 8UL +#define METAL_SIFIVE_GPIO0_PORT 12UL +#define METAL_SIFIVE_GPIO0_PUE 16UL +#define METAL_SIFIVE_GPIO0_DS 20UL +#define METAL_SIFIVE_GPIO0_RISE_IE 24UL +#define METAL_SIFIVE_GPIO0_RISE_IP 28UL +#define METAL_SIFIVE_GPIO0_FALL_IE 32UL +#define METAL_SIFIVE_GPIO0_FALL_IP 36UL +#define METAL_SIFIVE_GPIO0_HIGH_IE 40UL +#define METAL_SIFIVE_GPIO0_HIGH_IP 44UL +#define METAL_SIFIVE_GPIO0_LOW_IE 48UL +#define METAL_SIFIVE_GPIO0_LOW_IP 52UL +#define METAL_SIFIVE_GPIO0_IOF_EN 56UL +#define METAL_SIFIVE_GPIO0_IOF_SEL 60UL +#define METAL_SIFIVE_GPIO0_OUT_XOR 64UL + +/* From led@0red */ + +/* From led@0green */ + +/* From led@0blue */ + +#define METAL_SIFIVE_GPIO_LEDS + +/* From local_external_interrupts_0 */ + +#define METAL_SIFIVE_LOCAL_EXTERNAL_INTERRUPTS0 + +/* From pwm@10015000 */ +#define METAL_SIFIVE_PWM0_10015000_BASE_ADDRESS 268521472UL +#define METAL_SIFIVE_PWM0_0_BASE_ADDRESS 268521472UL +#define METAL_SIFIVE_PWM0_10015000_SIZE 4096UL +#define METAL_SIFIVE_PWM0_0_SIZE 4096UL + +#define METAL_SIFIVE_PWM0 +#define METAL_SIFIVE_PWM0_PWMCFG 0UL +#define METAL_SIFIVE_PWM0_PWMCOUNT 8UL +#define METAL_SIFIVE_PWM0_PWMS 16UL +#define METAL_SIFIVE_PWM0_PWMCMP0 32UL +#define METAL_SIFIVE_PWM0_PWMCMP1 36UL +#define METAL_SIFIVE_PWM0_PWMCMP2 40UL +#define METAL_SIFIVE_PWM0_PWMCMP3 44UL + +/* From spi@10014000 */ +#define METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS 268517376UL +#define METAL_SIFIVE_SPI0_0_BASE_ADDRESS 268517376UL +#define METAL_SIFIVE_SPI0_10014000_SIZE 4096UL +#define METAL_SIFIVE_SPI0_0_SIZE 4096UL + +#define METAL_SIFIVE_SPI0 +#define METAL_SIFIVE_SPI0_SCKDIV 0UL +#define METAL_SIFIVE_SPI0_SCKMODE 4UL +#define METAL_SIFIVE_SPI0_CSID 16UL +#define METAL_SIFIVE_SPI0_CSDEF 20UL +#define METAL_SIFIVE_SPI0_CSMODE 24UL +#define METAL_SIFIVE_SPI0_DELAY0 40UL +#define METAL_SIFIVE_SPI0_DELAY1 44UL +#define METAL_SIFIVE_SPI0_FMT 64UL +#define METAL_SIFIVE_SPI0_TXDATA 72UL +#define METAL_SIFIVE_SPI0_RXDATA 76UL +#define METAL_SIFIVE_SPI0_TXMARK 80UL +#define METAL_SIFIVE_SPI0_RXMARK 84UL +#define METAL_SIFIVE_SPI0_FCTRL 96UL +#define METAL_SIFIVE_SPI0_FFMT 100UL +#define METAL_SIFIVE_SPI0_IE 112UL +#define METAL_SIFIVE_SPI0_IP 116UL + +/* From serial@10013000 */ +#define METAL_SIFIVE_UART0_10013000_BASE_ADDRESS 268513280UL +#define METAL_SIFIVE_UART0_0_BASE_ADDRESS 268513280UL +#define METAL_SIFIVE_UART0_10013000_SIZE 4096UL +#define METAL_SIFIVE_UART0_0_SIZE 4096UL + +#define METAL_SIFIVE_UART0 +#define METAL_SIFIVE_UART0_TXDATA 0UL +#define METAL_SIFIVE_UART0_RXDATA 4UL +#define METAL_SIFIVE_UART0_TXCTRL 8UL +#define METAL_SIFIVE_UART0_RXCTRL 12UL +#define METAL_SIFIVE_UART0_IE 16UL +#define METAL_SIFIVE_UART0_IP 20UL +#define METAL_SIFIVE_UART0_DIV 24UL + +#endif /* QEMU_SIFIVE_S51__METAL_PLATFORM_H*/ diff --git a/bsp/qemu-sifive-s51/metal.default.lds b/bsp/qemu-sifive-s51/metal.default.lds new file mode 100644 index 0000000..6bd988b --- /dev/null +++ b/bsp/qemu-sifive-s51/metal.default.lds @@ -0,0 +1,234 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +OUTPUT_ARCH("riscv") + +ENTRY(_enter) + +MEMORY +{ +	ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 0x4000 +	flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 0x1fc00000 +} + +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; +	PROVIDE(__stack_size = __stack_size); +	__heap_size = DEFINED(__heap_size) ? __heap_size : 0x400; +	PROVIDE(__metal_boot_hart = 0); +	PROVIDE(__metal_chicken_bit = 0); + + +	.init 		: +	{ +		KEEP (*(.text.metal.init.enter)) +		KEEP (*(SORT_NONE(.init))) +		KEEP (*(.text.libgloss.start)) +	} >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.*) +		. = ALIGN(8); +		*(.srodata.cst16) +		*(.srodata.cst8) +		*(.srodata.cst4) +		*(.srodata.cst2) +		*(.srodata .srodata.*) +	} >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 		: +	{ +		*(.itim .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.* .sdata2.*) +		*(.gnu.linkonce.s.*) +	} >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; +		PROVIDE( metal_segment_heap_target_end = . ); +		PROVIDE( _heap_end = . ); +	} >ram AT>ram :ram + + +} + diff --git a/bsp/qemu-sifive-s51/metal.h b/bsp/qemu-sifive-s51/metal.h new file mode 100644 index 0000000..3d3df92 --- /dev/null +++ b/bsp/qemu-sifive-s51/metal.h @@ -0,0 +1,868 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +#ifndef ASSEMBLY + +#include <metal/machine/platform.h> + +#ifdef __METAL_MACHINE_MACROS + +#ifndef MACROS_IF_QEMU_SIFIVE_S51__METAL_H +#define MACROS_IF_QEMU_SIFIVE_S51__METAL_H + +#define __METAL_CLINT_NUM_PARENTS 2 + +#ifndef __METAL_CLINT_NUM_PARENTS +#define __METAL_CLINT_NUM_PARENTS 0 +#endif +#define __METAL_PLIC_SUBINTERRUPTS 27 + +#define __METAL_PLIC_NUM_PARENTS 1 + +#ifndef __METAL_PLIC_SUBINTERRUPTS +#define __METAL_PLIC_SUBINTERRUPTS 0 +#endif +#ifndef __METAL_PLIC_NUM_PARENTS +#define __METAL_PLIC_NUM_PARENTS 0 +#endif +#ifndef __METAL_CLIC_SUBINTERRUPTS +#define __METAL_CLIC_SUBINTERRUPTS 0 +#endif + +#endif /* MACROS_IF_SIFIVE_HIFIVE1__METAL_H*/ + +#else /* ! __METAL_MACHINE_MACROS */ + +#ifndef MACROS_ELSE_SIFIVE_HIFIVE1__METAL_H +#define MACROS_ELSE_SIFIVE_HIFIVE1__METAL_H + +#define __METAL_CLINT_2000000_INTERRUPTS 2 + +#define METAL_MAX_CLINT_INTERRUPTS 2 + +#define __METAL_CLINT_NUM_PARENTS 2 + +#define __METAL_INTERRUPT_CONTROLLER_C000000_INTERRUPTS 1 + +#define __METAL_PLIC_SUBINTERRUPTS 27 + +#define METAL_MAX_PLIC_INTERRUPTS 1 + +#define __METAL_PLIC_NUM_PARENTS 1 + +#define __METAL_CLIC_SUBINTERRUPTS 0 +#define METAL_MAX_CLIC_INTERRUPTS 0 + +#define __METAL_LOCAL_EXTERNAL_INTERRUPTS_0_INTERRUPTS 16 + +#define METAL_MAX_LOCAL_EXT_INTERRUPTS 16 + +#define METAL_MAX_GLOBAL_EXT_INTERRUPTS 0 + +#define __METAL_GPIO_10012000_INTERRUPTS 16 + +#define METAL_MAX_GPIO_INTERRUPTS 16 + +#define __METAL_SERIAL_10013000_INTERRUPTS 1 + +#define METAL_MAX_UART_INTERRUPTS 1 + + +#include <metal/drivers/fixed-clock.h> +#include <metal/memory.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_local-external-interrupts0.h> +#include <metal/drivers/sifive_gpio0.h> +#include <metal/drivers/sifive_gpio-leds.h> +#include <metal/drivers/sifive_spi0.h> +#include <metal/drivers/sifive_uart0.h> +#include <metal/drivers/sifive_fe310-g000_hfrosc.h> +#include <metal/drivers/sifive_fe310-g000_hfxosc.h> +#include <metal/drivers/sifive_fe310-g000_pll.h> +#include <metal/drivers/sifive_fe310-g000_prci.h> + +/* From clock@0 */ +struct __metal_driver_fixed_clock __metal_dt_clock_0; + +/* From clock@2 */ +struct __metal_driver_fixed_clock __metal_dt_clock_2; + +/* From clock@5 */ +struct __metal_driver_fixed_clock __metal_dt_clock_5; + +struct metal_memory __metal_dt_mem_dtim_80000000; + +struct metal_memory __metal_dt_mem_spi_10014000; + +/* From clint@2000000 */ +struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000; + +/* From cpu@0 */ +struct __metal_driver_cpu __metal_dt_cpu_0; + +struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller; + +/* From interrupt_controller@c000000 */ +struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000; + +/* From local_external_interrupts_0 */ +struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0; + +/* From gpio@10012000 */ +struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000; + +/* From led@0red */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0red; + +/* From led@0green */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0green; + +/* From led@0blue */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue; + +/* From spi@10014000 */ +struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000; + +/* From serial@10013000 */ +struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000; + +/* From clock@3 */ +struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3; + +/* From clock@1 */ +struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1; + +/* From clock@4 */ +struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4; + +/* From prci@10008000 */ +struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000; + + + +/* --------------------- fixed_clock ------------ */ +static inline unsigned long __metal_driver_fixed_clock_rate(struct metal_clock *clock) +{ +	if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_0) { +		return METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY; +	} +	else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_2) { +		return METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY; +	} +	else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_5) { +		return METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- fixed_factor_clock ------------ */ + + +/* --------------------- sifive_clint0 ------------ */ +static inline unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) { +		return METAL_RISCV_CLINT0_2000000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) { +		return METAL_RISCV_CLINT0_2000000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) { +		return METAL_MAX_CLINT_INTERRUPTS; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else if (idx == 1) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return 3; +	} +	else if (idx == 1) { +		return 7; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- cpu ------------ */ +static inline int __metal_driver_cpu_hartid(struct metal_cpu *cpu) +{ +	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { +		return 0; +	} +	else { +		return -1; +	} +} + +static inline int __metal_driver_cpu_timebase(struct metal_cpu *cpu) +{ +	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { +		return 1000000; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu) +{ +	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { +		return &__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu) +{ +	if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { +		return 0; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- sifive_plic0 ------------ */ +static inline unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { +		return METAL_RISCV_PLIC0_C000000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { +		return METAL_RISCV_PLIC0_C000000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { +		return METAL_RISCV_PLIC0_C000000_RISCV_NDEV; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { +		return METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else if (idx == 0) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return 11; +	} +	else if (idx == 0) { +		return 11; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- sifive_clic0 ------------ */ + + +/* --------------------- sifive_local_external_interrupts0 ------------ */ +static inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_local_external_interrupts_0) { +		return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller) +{ +	if ((uintptr_t)controller == (uintptr_t)&__metal_dt_local_external_interrupts_0) { +		return METAL_MAX_LOCAL_EXT_INTERRUPTS; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx) +{ +	if (idx == 0) { +		return 16; +	} +	else if (idx == 1) { +		return 17; +	} +	else if (idx == 2) { +		return 18; +	} +	else if (idx == 3) { +		return 19; +	} +	else if (idx == 4) { +		return 20; +	} +	else if (idx == 5) { +		return 21; +	} +	else if (idx == 6) { +		return 22; +	} +	else if (idx == 7) { +		return 23; +	} +	else if (idx == 8) { +		return 24; +	} +	else if (idx == 9) { +		return 25; +	} +	else if (idx == 10) { +		return 26; +	} +	else if (idx == 11) { +		return 27; +	} +	else if (idx == 12) { +		return 28; +	} +	else if (idx == 13) { +		return 29; +	} +	else if (idx == 14) { +		return 30; +	} +	else if (idx == 15) { +		return 31; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- sifive_global_external_interrupts0 ------------ */ + + +/* --------------------- sifive_gpio0 ------------ */ +static inline unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio) +{ +	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { +		return METAL_SIFIVE_GPIO0_10012000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio) +{ +	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { +		return METAL_SIFIVE_GPIO0_10012000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio) +{ +	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { +		return METAL_MAX_GPIO_INTERRUPTS; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio) +{ +	if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { +		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx) +{ +	if (((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 0)) { +		return 7; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 1))) { +		return 8; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 2))) { +		return 9; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 3))) { +		return 10; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 4))) { +		return 11; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 5))) { +		return 12; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 6))) { +		return 13; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 7))) { +		return 14; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 8))) { +		return 15; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 9))) { +		return 16; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 10))) { +		return 17; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 11))) { +		return 18; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 12))) { +		return 19; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 13))) { +		return 20; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 14))) { +		return 21; +	} +	else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 15))) { +		return 22; +	} +	else { +		return 0; +	} +} + + + +/* --------------------- sifive_gpio_button ------------ */ + + +/* --------------------- sifive_gpio_led ------------ */ +static inline struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led) +{ +	if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0red) { +		return (struct metal_gpio *)&__metal_dt_gpio_10012000; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) { +		return (struct metal_gpio *)&__metal_dt_gpio_10012000; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) { +		return (struct metal_gpio *)&__metal_dt_gpio_10012000; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_gpio_led_pin(struct metal_led *led) +{ +	if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0red) { +		return 22; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) { +		return 19; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) { +		return 21; +	} +	else { +		return 0; +	} +} + +static inline char * __metal_driver_sifive_gpio_led_label(struct metal_led *led) +{ +	if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0red) { +		return "LD0red"; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) { +		return "LD0green"; +	} +	else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) { +		return "LD0blue"; +	} +	else { +		return ""; +	} +} + + + +/* --------------------- sifive_gpio_switch ------------ */ + + +/* --------------------- sifive_spi0 ------------ */ +static inline unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi) +{ +	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { +		return METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi) +{ +	if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { +		return METAL_SIFIVE_SPI0_10014000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline struct metal_clock * __metal_driver_sifive_spi0_clock(struct metal_spi *spi) +{ +		return (struct metal_clock *)&__metal_dt_clock_4.clock; +} + +static inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi) +{ +		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; +} + +static inline unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi) +{ +		return 60; +} + +static inline unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi) +{ +		return 60; +} + + + +/* --------------------- sifive_test0 ------------ */ + + +/* --------------------- sifive_uart0 ------------ */ +static inline unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart) +{ +	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { +		return METAL_SIFIVE_UART0_10013000_BASE_ADDRESS; +	} +	else { +		return 0; +	} +} + +static inline unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart) +{ +	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { +		return METAL_SIFIVE_UART0_10013000_SIZE; +	} +	else { +		return 0; +	} +} + +static inline int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart) +{ +	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { +		return METAL_MAX_UART_INTERRUPTS; +	} +	else { +		return 0; +	} +} + +static inline struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart) +{ +	if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { +		return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; +	} +	else { +		return NULL; +	} +} + +static inline int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart) +{ +		return 5; +} + +static inline struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart) +{ +		return (struct metal_clock *)&__metal_dt_clock_4.clock; +} + +static inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart) +{ +		return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; +} + +static inline unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart) +{ +		return 196608; +} + +static inline unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart) +{ +		return 196608; +} + + + +/* --------------------- sifive_fe310_g000_hfrosc ------------ */ +static inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock) +{ +		return (struct metal_clock *)&__metal_dt_clock_2.clock; +} + +static inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock) +{ +		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock) +{ +		return &__metal_driver_vtable_sifive_fe310_g000_prci; +} + +static inline long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_HFROSCCFG; +} + + + +/* --------------------- sifive_fe310_g000_hfxosc ------------ */ +static inline struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock) +{ +		return (struct metal_clock *)&__metal_dt_clock_0.clock; +} + +static inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock) +{ +		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static inline long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_HFXOSCCFG; +} + + + +/* --------------------- sifive_fe310_g000_pll ------------ */ +static inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock) +{ +		return (struct metal_clock *)&__metal_dt_clock_3.clock; +} + +static inline struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock) +{ +		return (struct metal_clock *)&__metal_dt_clock_1.clock; +} + +static inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock) +{ +		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static inline long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_PLLOUTDIV; +} + +static inline struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( ) +{ +		return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static inline long __metal_driver_sifive_fe310_g000_pll_config_offset( ) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_PLLCFG; +} + +static inline long __metal_driver_sifive_fe310_g000_pll_init_rate( ) +{ +		return 16000000; +} + + + +/* --------------------- sifive_fe310_g000_prci ------------ */ +static inline long __metal_driver_sifive_fe310_g000_prci_base( ) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS; +} + +static inline long __metal_driver_sifive_fe310_g000_prci_size( ) +{ +		return METAL_SIFIVE_FE310_G000_PRCI_10008000_SIZE; +} + +static inline const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( ) +{ +		return &__metal_driver_vtable_sifive_fe310_g000_prci; +} + + + +/* --------------------- sifive_fu540_c000_l2 ------------ */ + + +#define __METAL_DT_MAX_MEMORIES 2 + +asm (".weak __metal_memory_table"); +struct metal_memory *__metal_memory_table[] = { +					&__metal_dt_mem_dtim_80000000, +					&__metal_dt_mem_spi_10014000}; + +/* From serial@10013000 */ +#define __METAL_DT_STDOUT_UART_HANDLE (&__metal_dt_serial_10013000.uart) + +#define __METAL_DT_SERIAL_10013000_HANDLE (&__metal_dt_serial_10013000.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) + +#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@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 local_external_interrupts_0 */ +#define __METAL_DT_SIFIVE_LOCAL_EXINTR0_HANDLE (&__metal_dt_local_external_interrupts_0.irc) + +#define __METAL_DT_LOCAL_EXTERNAL_INTERRUPTS_0_HANDLE (&__metal_dt_local_external_interrupts_0.irc) + +#define __MEE_DT_MAX_GPIOS 1 + +asm (".weak __metal_gpio_table"); +struct __metal_driver_sifive_gpio0 *__metal_gpio_table[] = { +					&__metal_dt_gpio_10012000}; + +#define __METAL_DT_MAX_BUTTONS 0 + +asm (".weak __metal_button_table"); +struct __metal_driver_sifive_gpio_button *__metal_button_table[] = { +					NULL }; +#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 0 + +asm (".weak __metal_switch_table"); +struct __metal_driver_sifive_gpio_switch *__metal_switch_table[] = { +					NULL }; +#define __METAL_DT_MAX_SPIS 1 + +asm (".weak __metal_spi_table"); +struct __metal_driver_sifive_spi0 *__metal_spi_table[] = { +					&__metal_dt_spi_10014000}; + +/* From clock@4 */ +#define __METAL_DT_SIFIVE_FE310_G000_PLL_HANDLE (&__metal_dt_clock_4) + +#define __METAL_DT_CLOCK_4_HANDLE (&__metal_dt_clock_4) + +#endif /* MACROS_ELSE_QEMU_SIFIVE_S51__METAL_H*/ + +#endif /* ! __METAL_MACHINE_MACROS */ + +#endif /* ! ASSEMBLY */ diff --git a/bsp/qemu-sifive-s51/metal.ramrodata.lds b/bsp/qemu-sifive-s51/metal.ramrodata.lds new file mode 100644 index 0000000..3322e4a --- /dev/null +++ b/bsp/qemu-sifive-s51/metal.ramrodata.lds @@ -0,0 +1,231 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +OUTPUT_ARCH("riscv") + +ENTRY(_enter) + +MEMORY +{ +	ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 0x4000 +	flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 0x1fc00000 +} + +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; +	PROVIDE(__stack_size = __stack_size); +	__heap_size = DEFINED(__heap_size) ? __heap_size : 0x400; +	PROVIDE(__metal_boot_hart = 0); +	PROVIDE(__metal_chicken_bit = 0); + + +	.init 		: +	{ +		KEEP (*(.text.metal.init.enter)) +		KEEP (*(SORT_NONE(.init))) +		KEEP (*(.text.libgloss.start)) +	} >flash AT>flash :flash + + + + +	.fini 		: +	{ +		KEEP (*(SORT_NONE(.fini))) +	} >flash AT>flash :flash + + +	PROVIDE (__etext = .); +	PROVIDE (_etext = .); +	PROVIDE (etext = .); + + + + +	. = 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 		: +	{ +		*(.itim .itim.*) +	} >flash AT>flash :flash + + +	. = ALIGN(8); +	PROVIDE( metal_segment_itim_target_end = . ); +	.text 		: +	{ +		*(.text.unlikely .text.unlikely.*) +		*(.text.startup .text.startup.*) +		*(.text .text.*) +		*(.gnu.linkonce.t.*) +		*(.itim .itim.*) +	} >flash AT>flash :flash + + +	.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 		: +	{ +		*(.rdata) +		*(.rodata .rodata.*) +		*(.gnu.linkonce.r.*) +		. = ALIGN(8); +		*(.srodata.cst16) +		*(.srodata.cst8) +		*(.srodata.cst4) +		*(.srodata.cst2) +		*(.srodata .srodata.*) +		*(.data .data.*) +		*(.gnu.linkonce.d.*) +		. = ALIGN(8); +		PROVIDE( __global_pointer$ = . + 0x800 ); +		*(.sdata .sdata.* .sdata2.*) +		*(.gnu.linkonce.s.*) +	} >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; +		PROVIDE( metal_segment_heap_target_end = . ); +		PROVIDE( _heap_end = . ); +	} >ram AT>ram :ram + + +} + diff --git a/bsp/qemu-sifive-s51/metal.scratchpad.lds b/bsp/qemu-sifive-s51/metal.scratchpad.lds new file mode 100644 index 0000000..14e64ea --- /dev/null +++ b/bsp/qemu-sifive-s51/metal.scratchpad.lds @@ -0,0 +1,234 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +OUTPUT_ARCH("riscv") + +ENTRY(_enter) + +MEMORY +{ +	ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 0x4000 +	flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 0x1fc00000 +} + +PHDRS +{ +	flash PT_LOAD; +	ram_init PT_LOAD; +	itim_init PT_LOAD; +	ram PT_LOAD; +	itim PT_LOAD; +} + +SECTIONS +{ +	__stack_size = DEFINED(__stack_size) ? __stack_size : 0x400; +	PROVIDE(__stack_size = __stack_size); +	__heap_size = DEFINED(__heap_size) ? __heap_size : 0x400; +	PROVIDE(__metal_boot_hart = 0); +	PROVIDE(__metal_chicken_bit = 0); + + +	.init 		: +	{ +		KEEP (*(.text.metal.init.enter)) +		KEEP (*(SORT_NONE(.init))) +		KEEP (*(.text.libgloss.start)) +	} >ram AT>ram :ram + + +	.text 		: +	{ +		*(.text.unlikely .text.unlikely.*) +		*(.text.startup .text.startup.*) +		*(.text .text.*) +		*(.itim .itim.*) +		*(.gnu.linkonce.t.*) +	} >ram AT>ram :ram + + +	.fini 		: +	{ +		KEEP (*(SORT_NONE(.fini))) +	} >ram AT>ram :ram + + +	PROVIDE (__etext = .); +	PROVIDE (_etext = .); +	PROVIDE (etext = .); + + +	.rodata 		: +	{ +		*(.rdata) +		*(.rodata .rodata.*) +		*(.gnu.linkonce.r.*) +		. = ALIGN(8); +		*(.srodata.cst16) +		*(.srodata.cst8) +		*(.srodata.cst4) +		*(.srodata.cst2) +		*(.srodata .srodata.*) +	} >ram AT>ram :ram + + +	. = ALIGN(4); + + +	.preinit_array 		: +	{ +		PROVIDE_HIDDEN (__preinit_array_start = .); +		KEEP (*(.preinit_array)) +		PROVIDE_HIDDEN (__preinit_array_end = .); +	} >ram AT>ram :ram + + +	.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 = .); +	} >ram AT>ram :ram + + +	.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 = .); +	} >ram AT>ram :ram + + +	.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)) +	} >ram AT>ram :ram + + +	.dtors 		: +	{ +		KEEP (*crtbegin.o(.dtors)) +		KEEP (*crtbegin?.o(.dtors)) +		KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) +		KEEP (*(SORT(.dtors.*))) +		KEEP (*(.dtors)) +	} >ram AT>ram :ram + + +	.litimalign 		: +	{ +		. = ALIGN(4); +		PROVIDE( metal_segment_itim_source_start = . ); +	} >ram AT>ram :ram + + +	.ditimalign 		: +	{ +		. = ALIGN(4); +		PROVIDE( metal_segment_itim_target_start = . ); +	} >ram AT>ram :ram_init + + +	.itim 		: +	{ +		*(.itim .itim.*) +	} >ram AT>ram :ram_init + + +	. = ALIGN(8); +	PROVIDE( metal_segment_itim_target_end = . ); + + +	.lalign 		: +	{ +		. = ALIGN(4); +		PROVIDE( _data_lma = . ); +		PROVIDE( metal_segment_data_source_start = . ); +	} >ram AT>ram :ram + + +	.dalign 		: +	{ +		. = ALIGN(4); +		PROVIDE( metal_segment_data_target_start = . ); +	} >ram AT>ram :ram_init + + +	.data 		: +	{ +		*(.data .data.*) +		*(.gnu.linkonce.d.*) +		. = ALIGN(8); +		PROVIDE( __global_pointer$ = . + 0x800 ); +		*(.sdata .sdata.* .sdata2.*) +		*(.gnu.linkonce.s.*) +	} >ram AT>ram :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; +		PROVIDE( metal_segment_heap_target_end = . ); +		PROVIDE( _heap_end = . ); +	} >ram AT>ram :ram + + +} + diff --git a/bsp/qemu-sifive-s51/qemu.cfg b/bsp/qemu-sifive-s51/qemu.cfg new file mode 100644 index 0000000..acb1524 --- /dev/null +++ b/bsp/qemu-sifive-s51/qemu.cfg @@ -0,0 +1,5 @@ +# qemu config file + +[machine] +  type = "sifive_e" + diff --git a/bsp/qemu-sifive-s51/settings.mk b/bsp/qemu-sifive-s51/settings.mk new file mode 100644 index 0000000..eb72b20 --- /dev/null +++ b/bsp/qemu-sifive-s51/settings.mk @@ -0,0 +1,13 @@ +# Copyright 2019 SiFive, Inc # +# SPDX-License-Identifier: Apache-2.0 # +# ----------------------------------- # +# ----------------------------------- # + +RISCV_ARCH=rv64imac +RISCV_ABI=lp64 +RISCV_CMODEL=medany +RISCV_SERIES=sifive-5-series + +TARGET_TAGS=qemu +TARGET_DHRY_ITERS=20000000 +TARGET_CORE_ITERS=5000 diff --git a/bsp/update-targets.sh b/bsp/update-targets.sh index 198cd5a..fe9458a 100755 --- a/bsp/update-targets.sh +++ b/bsp/update-targets.sh @@ -80,6 +80,7 @@ MEE_HEADER_GENERATOR=freedom-metal_header-generator  LDSCRIPT_GENERATOR=freedom-ldscript-generator  MAKEATTRIB_GENERATOR=freedom-makeattributes-generator  BARE_HEADER_GENERATOR=freedom-bare_header-generator +OPENOCDCFG_GENERATOR=freedom-openocdcfg-generator  DTS_FILENAME=design.dts  DTB_FILENAME=temp.dtb @@ -89,6 +90,7 @@ LDS_RAMRODATA_FILENAME=metal.ramrodata.lds  LDS_SCRATCHPAD_FILENAME=metal.scratchpad.lds  SETTINGS_FILENAME=settings.mk  BARE_HEADER_FILENAME=metal-platform.h +OPENOCDCFG_FILENAME=openocd.cfg  update_target() {      TARGET=$1 @@ -113,6 +115,12 @@ update_target() {      $MAKEATTRIB_GENERATOR -d $TARGET/$DTB_FILENAME -b $TARGET_TYPE -o $TARGET/$SETTINGS_FILENAME || warn "Failed to produce $TARGET/$SETTINGS_FILENAME"      $BARE_HEADER_GENERATOR -d $TARGET/$DTB_FILENAME -o $TARGET/$BARE_HEADER_FILENAME || warn "Failed to produce $TARGET/$BARE_HEADER_FILENAME" +    if [[ "$TARGET_TYPE" =~ "arty" || "$TARGET_TYPE" =~ "hifive" ]] ; then +        if [ `grep -c "jlink" $TARGET/$SETTINGS_FILENAME` -ne 1 ] ; then +            $OPENOCDCFG_GENERATOR -d $TARGET/$DTB_FILENAME -o $TARGET/$OPENOCDCFG_FILENAME || warn "Failed to produce $TARGET/$OPENOCDCFG_FILENAME" +        fi +    fi +      # Remove temporary .dtb      rm $TARGET/$DTB_FILENAME diff --git a/scripts/standalone.mk b/scripts/standalone.mk index d0740cd..2378b12 100644 --- a/scripts/standalone.mk +++ b/scripts/standalone.mk @@ -50,12 +50,10 @@ endif  endif  ifeq ($(PROGRAM),coremark) -ifeq ($(CONFIGURATION),release)  ifeq ($(LINK_TARGET),)  LINK_TARGET = ramrodata  endif  endif -endif  ifeq ($(LINK_TARGET),)  LINK_TARGET = default @@ -121,6 +119,27 @@ RISCV_CCASFLAGS += --specs=nano.specs  RISCV_CFLAGS    += --specs=nano.specs  RISCV_CXXFLAGS  += --specs=nano.specs +# Turn on garbage collection for unused sections +RISCV_LDFLAGS += -Wl,--gc-sections +# Turn on linker map file generation +RISCV_LDFLAGS += -Wl,-Map,$(PROGRAM).map +# Turn off the C standard library +RISCV_LDFLAGS += -nostartfiles -nostdlib +# Find the archive files and linker scripts +RISCV_LDFLAGS += -L$(sort $(dir $(abspath $(filter %.a,$^)))) -T$(abspath $(filter %.lds,$^)) + +# Link to the relevant libraries +RISCV_LDLIBS += -Wl,--start-group -lc -lgcc -lmetal -lmetal-gloss -Wl,--end-group + +# Load the configuration Makefile +CONFIGURATION_FILE = $(wildcard $(CONFIGURATION).mk) +ifeq ($(words $(CONFIGURATION_FILE)),0) +$(error Unable to find the Makefile $(CONFIGURATION).mk for CONFIGURATION=$(CONFIGURATION)) +endif +include $(CONFIGURATION).mk + +# Benchmark CFLAGS go after loading the CONFIGURATION so that they can override the optimization level +  ifeq ($(PROGRAM),dhrystone)  ifeq ($(DHRY_OPTION),)  # Ground rules (default) @@ -144,25 +163,6 @@ endif  RISCV_XCFLAGS += -DITERATIONS=$(TARGET_CORE_ITERS)  endif -# Turn on garbage collection for unused sections -RISCV_LDFLAGS += -Wl,--gc-sections -# Turn on linker map file generation -RISCV_LDFLAGS += -Wl,-Map,$(PROGRAM).map -# Turn off the C standard library -RISCV_LDFLAGS += -nostartfiles -nostdlib -# Find the archive files and linker scripts -RISCV_LDFLAGS += -L$(sort $(dir $(abspath $(filter %.a,$^)))) -T$(abspath $(filter %.lds,$^)) - -# Link to the relevant libraries -RISCV_LDLIBS += -Wl,--start-group -lc -lgcc -lmetal -lmetal-gloss -Wl,--end-group - -# Load the configuration Makefile -CONFIGURATION_FILE = $(wildcard $(CONFIGURATION).mk) -ifeq ($(words $(CONFIGURATION_FILE)),0) -$(error Unable to find the Makefile $(CONFIGURATION).mk for CONFIGURATION=$(CONFIGURATION)) -endif -include $(CONFIGURATION).mk -  #############################################################  # Software  ############################################################# @@ -221,7 +221,7 @@ endif  .PHONY: clean-software  clean-software: -	$(MAKE) -C $(SRC_DIR) clean +	$(MAKE) -C $(SRC_DIR) PORT_DIR=$(PORT_DIR) clean  	rm -rf $(SRC_DIR)/$(CONFIGURATION)  .PHONY: clean  clean: clean-software diff --git a/software/test-coreip b/software/test-coreip new file mode 160000 +Subproject 99345558aebeef2e630f2e0b8392ea20da7354b  | 
