From 3195459c67e88af9c70a89e4d456d248e361575c Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Thu, 23 May 2024 20:22:48 -0600 Subject: rtl/gfx/firmware: implement firmware stub --- rtl/gfx/firmware/gfx_bootrom.S | 2 +- rtl/gfx/firmware/link.ld | 217 +++++++++++++++++++++++++++++++++++++++++ rtl/gfx/firmware/main.c | 78 +++++++++++++++ rtl/gfx/firmware/mod.mk | 20 +++- rtl/gfx/firmware/start.S | 64 ++++++++++++ 5 files changed, 379 insertions(+), 2 deletions(-) create mode 100644 rtl/gfx/firmware/link.ld create mode 100644 rtl/gfx/firmware/main.c create mode 100644 rtl/gfx/firmware/start.S (limited to 'rtl') diff --git a/rtl/gfx/firmware/gfx_bootrom.S b/rtl/gfx/firmware/gfx_bootrom.S index 75f5826..9079e31 100644 --- a/rtl/gfx/firmware/gfx_bootrom.S +++ b/rtl/gfx/firmware/gfx_bootrom.S @@ -52,7 +52,7 @@ _start: and t2, t2, a6 beq t2, zero, .write_done - andi t0, t0, ~0b11 + andi t0, t0, 0b111100 # Entendemos words 0-15 bne t0, a3, .wait_axi sw zero, 0(a0) # Pass magic & hardware version diff --git a/rtl/gfx/firmware/link.ld b/rtl/gfx/firmware/link.ld new file mode 100644 index 0000000..50ac46b --- /dev/null +++ b/rtl/gfx/firmware/link.ld @@ -0,0 +1,217 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2019 Keith Packard + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +ENTRY(_start) + +/* + * These values should be provided by the application. We'll include + * some phony values here to make things link for testing + */ + +MEMORY +{ + ram (rwx) : + ORIGIN = DEFINED(__ram) ? __ram : 0x00000000, + LENGTH = DEFINED(__ram_size) ? __ram_size : 0x00002000 +} + +PHDRS +{ + ram PT_LOAD; +} + +SECTIONS +{ + PROVIDE(__stack = ORIGIN(ram) + LENGTH(ram)); + + .init : { + KEEP (*(.text.init.enter)) + KEEP (*(.data.init.enter)) + KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*))) + } >ram AT>ram :ram + + PROVIDE(__img_start = ADDR(.init)); + + .text : { + + /* code */ + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.* .opd .opd.*) + *(.gnu.linkonce.t.*) + KEEP (*(.fini .fini.*)) + __text_end = .; + + PROVIDE (__etext = __text_end); + PROVIDE (_etext = __text_end); + PROVIDE (etext = __text_end); + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + } >ram AT>ram :ram + + .rodata : { + + /* read-only data */ + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + + } >ram AT>ram :ram + + .data.rel.ro : { + + /* data that needs relocating */ + *(.data.rel.ro .data.rel.ro.*) + + } >ram AT>ram :ram + + .data : ALIGN_WITH_INPUT { + *(.data .data.*) + *(.gnu.linkonce.d.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + PROVIDE( __global_pointer$ = . + 0x800 ); + PROVIDE( _gp = . + 0x8000); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + PROVIDE(__data_end = .); + + . = ALIGN(8); + } >ram AT>ram :ram + + PROVIDE(__data_start = ADDR(.data)); + PROVIDE(__data_source = LOADADDR(.data)); + + PROVIDE( __edata = __data_end ); + PROVIDE( _edata = __data_end ); + PROVIDE( edata = __data_end ); + PROVIDE( __data_size = __data_end - __data_start ); + + PROVIDE(__img_end = __data_end); + PROVIDE(__img_size = __img__end - __img_start); + + .bss (NOLOAD) : { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + + /* Align the heap */ + . = ALIGN(8); + __bss_end = .; + } >ram AT>ram :ram + + PROVIDE( __bss_start = ADDR(.bss) ); + PROVIDE( __end = __bss_end ); + _end = __bss_end; + PROVIDE( end = __bss_end ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + + /* Define a stack region to make sure it fits in memory */ + .stack (NOLOAD) : { + . += (DEFINED(__stack_size) ? __stack_size : 0x00001000); + } >ram :ram + + /* Throw away C++ exception handling information */ + + + + /DISCARD/ : { + *(.note .note.*) + *(.eh_frame .eh_frame.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx*) + } + + + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1. */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions. */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2. */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2. */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions. */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3. */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF 5. */ + .debug_addr 0 : { *(.debug_addr) } + .debug_line_str 0 : { *(.debug_line_str) } + .debug_loclists 0 : { *(.debug_loclists) } + .debug_macro 0 : { *(.debug_macro) } + .debug_names 0 : { *(.debug_names) } + .debug_rnglists 0 : { *(.debug_rnglists) } + .debug_str_offsets 0 : { *(.debug_str_offsets) } + .debug_sup 0 : { *(.debug_sup) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } +} diff --git a/rtl/gfx/firmware/main.c b/rtl/gfx/firmware/main.c new file mode 100644 index 0000000..f75a9cb --- /dev/null +++ b/rtl/gfx/firmware/main.c @@ -0,0 +1,78 @@ +struct hostif_ctrl +{ + unsigned arint : 1; + unsigned awint : 1; + unsigned rsvd2 : 6; + unsigned arvalid : 1; + unsigned awvalid : 1; + unsigned rdone : 1; + unsigned wvalid : 1; + unsigned bdone : 1; + unsigned rsvd13 : 19; +}; + +struct hostif_ar +{ + unsigned valid : 1; + unsigned rsvd1 : 1; + unsigned addr : 30; +}; + +struct hostif_aw +{ + unsigned valid : 1; + unsigned rsvd1 : 1; + unsigned addr : 30; +}; + +struct hostif_r +{ + unsigned data : 32; +}; + +struct hostif_w +{ + unsigned data : 32; +}; + +struct hostif_b0 +{ + unsigned valid : 1; + unsigned rsvd1 : 31; +}; + +#define HOSTIF_BASE 0x00300000 +#define HOSTIF_CTRL (*(volatile struct hostif_ctrl *)(HOSTIF_BASE + 0x00)) +#define HOSTIF_AR (*(volatile struct hostif_ar *) (HOSTIF_BASE + 0x04)) +#define HOSTIF_AW (*(volatile struct hostif_aw *) (HOSTIF_BASE + 0x08)) +#define HOSTIF_R (*(volatile struct hostif_r *) (HOSTIF_BASE + 0x0c)) +#define HOSTIF_W (*(volatile struct hostif_w *) (HOSTIF_BASE + 0x10)) +#define HOSTIF_B (*(volatile struct hostif_b *) (HOSTIF_BASE + 0x14)) + +int main(unsigned magic, unsigned hw_rev) +{ + while (1) { + struct hostif_ar ar; + while (!(ar = HOSTIF_AR).valid); + + switch (ar.addr & 3) { + case 0b00: + HOSTIF_R.data = magic; + break; + + case 0b01: + HOSTIF_R.data = hw_rev; + break; + + case 0b10: + HOSTIF_R.data = hw_rev; + break; + + case 0b11: + HOSTIF_R.data = 1; + break; + } + + while (!HOSTIF_CTRL.rdone); + } +} diff --git a/rtl/gfx/firmware/mod.mk b/rtl/gfx/firmware/mod.mk index 2a37a9c..087aadc 100644 --- a/rtl/gfx/firmware/mod.mk +++ b/rtl/gfx/firmware/mod.mk @@ -1,4 +1,4 @@ -cores := gfx_bootrom +cores := gfx_bootrom gfx_firmware define core/gfx_bootrom $(this)/cross := riscv32-none-elf- @@ -15,3 +15,21 @@ define core/gfx_bootrom $(this)/makehex_src := gfx_bootrom.bin $(this)/makehex_obj := gfx_bootrom.hex endef + +define core/gfx_firmware + $(this)/cross := riscv32-none-elf- + $(this)/hooks := cc objcopy bin2rel obj + + $(this)/obj_deps := /$(here)link.ld + + $(this)/cc_files := start.S main.c + $(this)/cc_flags = -g -O3 -march=rv32imc -mabi=ilp32 + $(this)/ld_flags := -nostartfiles -nostdlib -T$(here)link.ld + $(this)/ld_binary := gfx_fw + + $(this)/objcopy_src := gfx_fw + $(this)/objcopy_obj := gfx_fw.bin + + $(this)/bin2rel_src := gfx_fw.bin + $(this)/bin2rel_obj := gfx_fw_payload.o +endef diff --git a/rtl/gfx/firmware/start.S b/rtl/gfx/firmware/start.S new file mode 100644 index 0000000..c696119 --- /dev/null +++ b/rtl/gfx/firmware/start.S @@ -0,0 +1,64 @@ +.section .text.init.enter +.global _start + +_start: + li t0, 0x4a7a7b0c + beq a0, t0, _magic_ok + ret + +_magic_ok: + lui t0, %hi(__img_start) + addi t0, t0, %lo(__img_start) + la t1, __img_start + la t2, _early_copy_end + sub t2, t2, t1 + +_early_copy_loop: + lw t3, 0(t1) + sw t3, 0(t0) + addi t0, t0, 4 + addi t1, t1, 4 + addi t2, t2, -4 + bgtz t2, _early_copy_loop + + lui t2, %hi(_running_on_ram) + addi t2, t2, %lo(_running_on_ram) + jr t2 + +_running_on_ram: + la t2, __img_end + sub t2, t2, t0 + +_full_copy_loop: + lw t3, 0(t1) + lw t4, 4(t1) + lw t5, 8(t1) + lw t6, 12(t1) + sw t3, 0(t0) + sw t4, 4(t0) + sw t5, 8(t0) + sw t6, 12(t0) + addi t0, t0, 16 + addi t1, t1, 16 + addi t2, t2, -16 + bgtz t2, _full_copy_loop + +.balign 4 +_early_copy_end: + la t0, __bss_start + la t2, __bss_end + sub t2, t2, t0 + +_clear_bss_loop: + sw zero, 0(t0) + sw zero, 4(t0) + sw zero, 8(t0) + sw zero, 12(t0) + addi t0, t0, 16 + addi t2, t2, -16 + bgtz t2, _clear_bss_loop + +_start_done: + la sp, __stack + call main + j . -- cgit v1.2.3