summaryrefslogtreecommitdiff
path: root/platform/wavelet3d/host_sw
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--platform/wavelet3d/host_sw/gfx.h14
-rw-r--r--platform/wavelet3d/host_sw/gfx_boot.c65
-rw-r--r--platform/wavelet3d/host_sw/gfx_regmap.h31
-rw-r--r--platform/wavelet3d/host_sw/init.c46
-rw-r--r--platform/wavelet3d/host_sw/init.h6
-rw-r--r--platform/wavelet3d/host_sw/log.h12
-rw-r--r--platform/wavelet3d/host_sw/main.c69
-rw-r--r--platform/wavelet3d/host_sw/mod.mk5
-rw-r--r--platform/wavelet3d/host_sw/sgdma.c82
-rw-r--r--platform/wavelet3d/host_sw/sgdma.h8
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