summaryrefslogtreecommitdiff
path: root/riscv/riscv-probe/libfemto/drivers/htif.c
diff options
context:
space:
mode:
authorCarlos Maiolino <[email protected]>2025-07-10 22:18:39 +0200
committerCarlos Maiolino <[email protected]>2025-07-10 22:18:39 +0200
commit8c6fc0c15415b32080a848bbde640e104098cf13 (patch)
tree04a21bd28f9dc82c8e216390d6208ed93b9bcd11 /riscv/riscv-probe/libfemto/drivers/htif.c
Initial drop
Add some riscv code Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'riscv/riscv-probe/libfemto/drivers/htif.c')
-rw-r--r--riscv/riscv-probe/libfemto/drivers/htif.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/riscv/riscv-probe/libfemto/drivers/htif.c b/riscv/riscv-probe/libfemto/drivers/htif.c
new file mode 100644
index 0000000..ef6995e
--- /dev/null
+++ b/riscv/riscv-probe/libfemto/drivers/htif.c
@@ -0,0 +1,91 @@
+// See LICENSE for license details.
+
+#ifdef __riscv
+
+#include "femto.h"
+#include "spinlock.h"
+
+struct { uint32_t arr[2]; } volatile tohost __attribute__((section(".htif")));
+struct { uint32_t arr[2]; } volatile fromhost __attribute__((section(".htif")));
+
+static spinlock_t htif_lock = SPINLOCK_INIT;
+
+static inline void htif_send(uint8_t dev, uint8_t cmd, int64_t data)
+{
+ /* endian neutral encoding with ordered 32-bit writes */
+ union { uint32_t arr[2]; uint64_t val; } encode = {
+ .val = (uint64_t)dev << 56 | (uint64_t)cmd << 48 | data
+ };
+ tohost.arr[0] = encode.arr[0];
+ tohost.arr[1] = encode.arr[1];
+}
+
+static inline void htif_recv(uint8_t *dev, uint8_t *cmd, int64_t *data)
+{
+ /* endian neutral decoding with ordered 32-bit reads */
+ union { uint32_t arr[2]; uint64_t val; } decode;
+ decode.arr[0] = fromhost.arr[0];
+ decode.arr[1] = fromhost.arr[1];
+ *dev = decode.val >> 56;
+ *cmd = (decode.val >> 48) & 0xff;
+ *data = decode.val << 16 >> 16;
+}
+
+static int64_t htif_get_fromhost(uint8_t dev, uint8_t cmd)
+{
+ /* receive data for specified device and command */
+ uint8_t rdev, rcmd;
+ int64_t data;
+ htif_recv(&rdev, &rcmd, &data);
+ return rdev == dev && rcmd == cmd ? data : -1;
+}
+
+static void htif_set_tohost(uint8_t dev, uint8_t cmd, int64_t data)
+{
+ /* send data with specified device and command */
+ while (tohost.arr[0]) {
+ asm volatile ("" : : "r" (fromhost.arr[0]));
+ asm volatile ("" : : "r" (fromhost.arr[1]));
+ }
+ htif_send(dev, cmd, data);
+}
+
+static int htif_getchar()
+{
+ int ch;
+ spinlock_lock(&htif_lock);
+ if ((ch = htif_get_fromhost(1, 0) & 0xff)) {
+ htif_set_tohost(1, 0, 0);
+ }
+ spinlock_unlock(&htif_lock);
+ return ch;
+}
+
+static int htif_putchar(int ch)
+{
+ spinlock_lock(&htif_lock);
+ htif_set_tohost(1, 1, ch & 0xff);
+ spinlock_unlock(&htif_lock);
+ return ch & 0xff;
+}
+
+static void htif_poweroff(int status)
+{
+ for (;;) {
+ htif_set_tohost(0, 0, 1);
+ }
+}
+
+console_device_t console_htif = {
+ NULL,
+ htif_getchar,
+ htif_putchar
+};
+
+
+poweroff_device_t poweroff_htif = {
+ NULL,
+ htif_poweroff
+};
+
+#endif