diff options
Diffstat (limited to '')
| -rw-r--r-- | platform/wavelet3d/host_sw/gfx.h | 14 | ||||
| -rw-r--r-- | platform/wavelet3d/host_sw/gfx_boot.c | 65 | ||||
| -rw-r--r-- | platform/wavelet3d/host_sw/gfx_regmap.h | 31 | ||||
| -rw-r--r-- | platform/wavelet3d/host_sw/init.c | 46 | ||||
| -rw-r--r-- | platform/wavelet3d/host_sw/init.h | 6 | ||||
| -rw-r--r-- | platform/wavelet3d/host_sw/log.h | 12 | ||||
| -rw-r--r-- | platform/wavelet3d/host_sw/main.c | 69 | ||||
| -rw-r--r-- | platform/wavelet3d/host_sw/mod.mk | 5 | ||||
| -rw-r--r-- | platform/wavelet3d/host_sw/sgdma.c | 82 | ||||
| -rw-r--r-- | platform/wavelet3d/host_sw/sgdma.h | 8 |
10 files changed, 269 insertions, 69 deletions
diff --git a/platform/wavelet3d/host_sw/gfx.h b/platform/wavelet3d/host_sw/gfx.h new file mode 100644 index 0000000..2677ef4 --- /dev/null +++ b/platform/wavelet3d/host_sw/gfx.h @@ -0,0 +1,14 @@ +#ifndef GFX_H +#define GFX_H + +enum gfx_probe_result +{ + GFX_PROBE_BOOTROM, + GFX_PROBE_FIRMWARE, + GFX_PROBE_FAILED, +}; + +enum gfx_probe_result gfx_probe(void); +int gfx_fw_load(const void *image, size_t image_len); + +#endif diff --git a/platform/wavelet3d/host_sw/gfx_boot.c b/platform/wavelet3d/host_sw/gfx_boot.c new file mode 100644 index 0000000..eadca68 --- /dev/null +++ b/platform/wavelet3d/host_sw/gfx_boot.c @@ -0,0 +1,65 @@ +#define MOD_NAME "gfx" + +#include <stdio.h> + +#include "gfx.h" +#include "gfx_regmap.h" +#include "log.h" +#include "sgdma.h" + +enum gfx_probe_result gfx_probe(void) +{ + log("probing 0x%08x", GFX_CTRL_BASE); + + unsigned magic = GFX_CTRL_MAGIC; + log("magic=0x%08x", magic); + + if (magic != GFX_MAGIC_ID) { + log("bad magic"); + return GFX_PROBE_FAILED; + } + + log("magic ok"); + + struct gfx_hw_id hw_id = GFX_CTRL_HW_ID; + struct gfx_fw_id fw_id = GFX_CTRL_FW_ID; + unsigned hostif_rev = GFX_CTRL_HOSTIF_REV; + + log + ( + "3D graphics accelerator IP core v%u.%u.%u", + hw_id.major, hw_id.minor, hw_id.patch + ); + + log + ( + "%s rev %u.%u.%02u #%02u", + hostif_rev ? "firmware" : "bootloader", + fw_id.year, fw_id.month, fw_id.day, fw_id.build + ); + + switch (hostif_rev) { + case 0: + log("scheduler is in bootloader rom"); + return GFX_PROBE_BOOTROM; + + case 1: + log("found regmap revision %u", hostif_rev); + return GFX_PROBE_FIRMWARE; + + default: + log("unknown regmap revision %u", hostif_rev); + return GFX_PROBE_FAILED; + } +} + +int gfx_fw_load(const void *image, size_t image_len) +{ + log("uploading fw image (len=%zu)", image_len); + + sgdma_memcpy(GFX_VRAM_BASE, image, image_len); + sgdma_barrier(); + + *(void *volatile *)&GFX_CTRL_FW_ID = GFX_VRAM_BASE; + return 0; +} diff --git a/platform/wavelet3d/host_sw/gfx_regmap.h b/platform/wavelet3d/host_sw/gfx_regmap.h new file mode 100644 index 0000000..505c9c2 --- /dev/null +++ b/platform/wavelet3d/host_sw/gfx_regmap.h @@ -0,0 +1,31 @@ +#ifndef GFX_REGMAP_H +#define GFX_REGMAP_H + +struct gfx_hw_id +{ + unsigned patch : 8; + unsigned minor : 8; + unsigned major : 8; + unsigned rsvd : 8; +}; + +struct gfx_fw_id +{ + unsigned build : 10; + unsigned day : 5; + unsigned month : 4; + unsigned year : 12; + unsigned rsvd : 1; +}; + +#define GFX_CTRL_BASE 0x20000000 +#define GFX_CTRL_MAGIC (*(volatile unsigned *)(GFX_CTRL_BASE + 0x00)) +#define GFX_CTRL_HW_ID (*(volatile struct gfx_hw_id *)(GFX_CTRL_BASE + 0x04)) +#define GFX_CTRL_FW_ID (*(volatile struct gfx_fw_id *)(GFX_CTRL_BASE + 0x08)) +#define GFX_CTRL_HOSTIF_REV (*(volatile unsigned *)(GFX_CTRL_BASE + 0x0c)) + +#define GFX_MAGIC_ID 0x4a7a7b0c + +#define GFX_VRAM_BASE ((void *)0x1c000000) + +#endif diff --git a/platform/wavelet3d/host_sw/init.c b/platform/wavelet3d/host_sw/init.c new file mode 100644 index 0000000..3acc8f3 --- /dev/null +++ b/platform/wavelet3d/host_sw/init.c @@ -0,0 +1,46 @@ +#define MOD_NAME "init" + +#include <stdlib.h> + +#include "gfx.h" +#include "init.h" +#include "log.h" + +extern const unsigned char _binary_gfx_fw_bin_start[]; +extern const unsigned char _binary_gfx_fw_bin_end; +extern const unsigned char _binary_gfx_fw_bin_size; + +static void __attribute__((noreturn)) init_gfx_failed(void) +{ + log("fatal: probe of gfx device failed"); + abort(); +} + +static void init_gfx(int bootrom) +{ + switch (gfx_probe()) { + case GFX_PROBE_FAILED: + init_gfx_failed(); + break; + + case GFX_PROBE_BOOTROM: + if (bootrom) + log("gfx bootloader didn't handover to firmware"); + + size_t fw_size = (size_t)&_binary_gfx_fw_bin_size; + if (bootrom || gfx_fw_load(_binary_gfx_fw_bin_start, fw_size) < 0) + init_gfx_failed(); + + init_gfx(1); + break; + + case GFX_PROBE_FIRMWARE: + break; + } +} + +void init(void) +{ + log("host cpu is up"); + init_gfx(0); +} diff --git a/platform/wavelet3d/host_sw/init.h b/platform/wavelet3d/host_sw/init.h new file mode 100644 index 0000000..a4e62a9 --- /dev/null +++ b/platform/wavelet3d/host_sw/init.h @@ -0,0 +1,6 @@ +#ifndef INIT_H +#define INIT_H + +void init(void); + +#endif diff --git a/platform/wavelet3d/host_sw/log.h b/platform/wavelet3d/host_sw/log.h new file mode 100644 index 0000000..1396342 --- /dev/null +++ b/platform/wavelet3d/host_sw/log.h @@ -0,0 +1,12 @@ +#ifndef LOG_H +#define LOG_H + +#include <stdio.h> + +#ifdef MOD_NAME + #define log(fmt, ...) printf(MOD_NAME ": " fmt "\n", ##__VA_ARGS__) +#else + #define log(fmt, ...) printf(fmt "\n", ##__VA_ARGS__) +#endif + +#endif diff --git a/platform/wavelet3d/host_sw/main.c b/platform/wavelet3d/host_sw/main.c index 5dfedce..7513c4c 100644 --- a/platform/wavelet3d/host_sw/main.c +++ b/platform/wavelet3d/host_sw/main.c @@ -1,72 +1,7 @@ -#include <stdio.h> - -struct gfx_hw_id -{ - unsigned patch : 8; - unsigned minor : 8; - unsigned major : 8; - unsigned rsvd : 8; -}; - -struct gfx_fw_id -{ - unsigned build : 10; - unsigned day : 5; - unsigned month : 4; - unsigned year : 12; - unsigned rsvd : 1; -}; - -#define GFX_CTRL_BASE 0x20000000 -#define GFX_CTRL_MAGIC (*(volatile unsigned *)(GFX_CTRL_BASE + 0x00)) -#define GFX_CTRL_HW_ID (*(volatile struct gfx_hw_id *)(GFX_CTRL_BASE + 0x04)) -#define GFX_CTRL_FW_ID (*(volatile struct gfx_fw_id *)(GFX_CTRL_BASE + 0x08)) -#define GFX_CTRL_HOSTIF_REV (*(volatile unsigned *)(GFX_CTRL_BASE + 0x0c)) - -#define GFX_MAGIC_ID 0x4a7a7b0c +#include "init.h" int main() { - printf("gfx: probing 0x%08x\n", GFX_CTRL_BASE); - - unsigned magic = GFX_CTRL_MAGIC; - printf("gfx: magic=0x%08x\n", magic); - - if (magic != GFX_MAGIC_ID) - printf("gfx: bad magic, probe failed\n"); - - printf("gfx: magic ok\n"); - - struct gfx_hw_id hw_id = GFX_CTRL_HW_ID; - struct gfx_fw_id fw_id = GFX_CTRL_FW_ID; - unsigned hostif_rev = GFX_CTRL_HOSTIF_REV; - - printf - ( - "gfx: 3D graphics accelerator IP core v%u.%u.%u\n", - hw_id.major, hw_id.minor, hw_id.patch - ); - - switch (hostif_rev) { - case 0: - printf("gfx: scheduler is in bootloader rom\n"); - break; - - case 1: - printf("gfx: detected regmap revision %u\n", hostif_rev); - break; - - default: - printf("gfx: unknown regmap revision %u\n", hostif_rev); - break; - } - - printf - ( - "gfx: %s rev %u.%u.%02u #%02u\n", - hostif_rev ? "firmware" : "bootloader", - fw_id.year, fw_id.month, fw_id.day, fw_id.build - ); - + init(); return 0; } diff --git a/platform/wavelet3d/host_sw/mod.mk b/platform/wavelet3d/host_sw/mod.mk index b68c47d..2563f9e 100644 --- a/platform/wavelet3d/host_sw/mod.mk +++ b/platform/wavelet3d/host_sw/mod.mk @@ -1,14 +1,15 @@ cores := w3d_host_flash w3d_host_sw w3d_picolibc define core/w3d_host_sw - $(this)/deps := w3d_picolibc + $(this)/deps := gfx_firmware w3d_picolibc $(this)/cross := riscv32-none-elf- $(this)/hooks := cc objcopy obj $(this)/obj_deps := picolibc/picolibc.specs - $(this)/cc_files := main.c + $(this)/cc_files := main.c gfx_boot.c init.c sgdma.c $(this)/cc_flags = -g -march=rv32imafc -mabi=ilp32f --specs=$$(obj)/picolibc/picolibc.specs + $(this)/ld_extra := gfx_fw_payload.o $(this)/ld_flags := --oslib=semihost $(this)/ld_binary := w3d_host_flash diff --git a/platform/wavelet3d/host_sw/sgdma.c b/platform/wavelet3d/host_sw/sgdma.c new file mode 100644 index 0000000..11241f8 --- /dev/null +++ b/platform/wavelet3d/host_sw/sgdma.c @@ -0,0 +1,82 @@ +#define MOD_NAME "dma" + +#include <stddef.h> + +#include "log.h" +#include "sgdma.h" + +struct sgdma_ctrl +{ + unsigned start_busy : 1; + unsigned interrupt : 1; + unsigned int_en : 1; + unsigned abort : 1; + unsigned err : 1; + unsigned reserved : 27; +}; + +struct sgdma_entry +{ + unsigned src_lo; + unsigned src_hi : 30; + unsigned flags : 2; + unsigned dst_lo; + unsigned dst_hi : 30; + unsigned mbz : 1; + unsigned int_en : 1; + unsigned length; +}; + +// axisgfsm.v, la lista de axisgdma.v está mala +enum sgdma_entry_flags +{ + SGDMA_ENTRY_CONT = 0b00, + SGDMA_ENTRY_LAST = 0b01, + SGDMA_ENTRY_SKIP = 0b10, + SGDMA_ENTRY_JUMP = 0b11, +}; + +#define SGDMA_BASE 0x28000000 +#define SGDMA_CTRL (*(volatile struct sgdma_ctrl *)(SGDMA_BASE + 0x00)) +#define SGDMA_TBLLO (*(volatile unsigned *) (SGDMA_BASE + 0x08)) +#define SGDMA_TBLHI (*(volatile unsigned *) (SGDMA_BASE + 0x0c)) + +int sgdma_done(void) +{ + return !SGDMA_CTRL.start_busy; +} + +void sgdma_barrier(void) +{ + while (!sgdma_done()); //FIXME +} + +void sgdma_memcpy(void *dest, const void *src, size_t len) +{ + struct sgdma_entry entry = { + .src_lo = (unsigned)src, + .src_hi = 0, + .flags = SGDMA_ENTRY_LAST, + .dst_lo = (unsigned)dest, + .dst_hi = 0, + .mbz = 0, + .int_en = 0, + .length = (unsigned)len, + }; + + SGDMA_TBLLO = (unsigned)&entry; + SGDMA_TBLHI = 0; + + struct sgdma_ctrl ctrl = { + .start_busy = 1, + .interrupt = 0, + .int_en = 0, + .abort = 0, + .err = 0, + .reserved = 0, + }; + + SGDMA_CTRL = ctrl; + + sgdma_barrier(); //TODO, sin esto sgdma lee entry corrupto +} diff --git a/platform/wavelet3d/host_sw/sgdma.h b/platform/wavelet3d/host_sw/sgdma.h new file mode 100644 index 0000000..d39e4a5 --- /dev/null +++ b/platform/wavelet3d/host_sw/sgdma.h @@ -0,0 +1,8 @@ +#ifndef SGDMA_H +#define SGDMA_H + +int sgdma_done(void); +void sgdma_memcpy(void *dest, const void *src, size_t len); +void sgdma_barrier(void); + +#endif |
