From aae907cebbffcb979ce84b88ebd050052dd91276 Mon Sep 17 00:00:00 2001
From: user <mali@mali.com>
Date: Tue, 5 Dec 2023 14:34:10 +0800
Subject: [PATCH] [feat] Support e907 core boot up

---
 CMakeLists.txt                |   5 +-
 app/CMakeLists.txt            |   3 +-
 app/load_e907/CMakeLists.txt  |   7 +
 app/load_e907/eabi_compat.c   |  17 +++
 app/load_e907/main.c          | 256 ++++++++++++++++++++++++++++++++++
 app/load_e907/start.S         | 226 ++++++++++++++++++++++++++++++
 cmake/add_syterkit_app.cmake  |   4 +-
 drivers/sys-clk.c             |   2 +-
 drivers/sys-rproc.c           |  90 ++++++++++++
 include/drivers/sys-rproc.h   |  10 ++
 include/lib/elf/elf_loader.h  |  10 ++
 include/reg/reg-ccu.h         |  41 +++++-
 include/reg/reg-rproc.h       |  10 ++
 lib/elf/elf.c                 |  26 ++++
 scripts/genimage.sh           |   0
 scripts/genimage_loade907.cfg |  30 ++++
 16 files changed, 727 insertions(+), 10 deletions(-)
 create mode 100644 app/load_e907/CMakeLists.txt
 create mode 100644 app/load_e907/eabi_compat.c
 create mode 100644 app/load_e907/main.c
 create mode 100644 app/load_e907/start.S
 create mode 100644 drivers/sys-rproc.c
 create mode 100644 include/drivers/sys-rproc.h
 create mode 100644 include/lib/elf/elf_loader.h
 create mode 100644 include/reg/reg-rproc.h
 mode change 100644 => 100755 scripts/genimage.sh
 create mode 100644 scripts/genimage_loade907.cfg

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 46d22c8..8eaa9b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,8 +59,8 @@ project(SyterKit C CXX ASM)
 include(cmake/add_syterkit_app.cmake)
 
 configure_file(
-        "${PROJECT_SOURCE_DIR}/config.h.in"
-        "${PROJECT_BINARY_DIR}/config.h"
+    "${PROJECT_SOURCE_DIR}/config.h.in"
+    "${PROJECT_BINARY_DIR}/config.h"
 )
 
 set(CMAKE_AR "${CROSS_COMPILE}ar")
@@ -98,6 +98,7 @@ add_library(SyterKit
     drivers/sys-dram.c
     drivers/sys-sdcard.c
     drivers/sys-sdhci.c
+    drivers/sys-rproc.c
     drivers/sys-spi.c
     drivers/sys-sid.c
     drivers/sys-timer.c
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 57e01f9..7f3dbb4 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -4,4 +4,5 @@ add_subdirectory(hello_world)
 add_subdirectory(read_chipsid)
 add_subdirectory(init_dram)
 add_subdirectory(read_chip_efuse)
-add_subdirectory(syter_boot)
\ No newline at end of file
+add_subdirectory(syter_boot)
+add_subdirectory(load_e907)
\ No newline at end of file
diff --git a/app/load_e907/CMakeLists.txt b/app/load_e907/CMakeLists.txt
new file mode 100644
index 0000000..7c93e16
--- /dev/null
+++ b/app/load_e907/CMakeLists.txt
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: Apache-2.0
+
+add_syterkit_app(loade907 
+    start.S 
+    main.c
+    eabi_compat.c
+)
\ No newline at end of file
diff --git a/app/load_e907/eabi_compat.c b/app/load_e907/eabi_compat.c
new file mode 100644
index 0000000..965d43f
--- /dev/null
+++ b/app/load_e907/eabi_compat.c
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+void abort(void)
+{
+	while (1)
+		;
+}
+
+int raise(int signum)
+{
+	return 0;
+}
+
+/* Dummy function to avoid linker complaints */
+void __aeabi_unwind_cpp_pr0(void)
+{
+}
\ No newline at end of file
diff --git a/app/load_e907/main.c b/app/load_e907/main.c
new file mode 100644
index 0000000..50324f7
--- /dev/null
+++ b/app/load_e907/main.c
@@ -0,0 +1,256 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <types.h>
+
+#include <log.h>
+#include <config.h>
+
+#include <common.h>
+#include <arm32.h>
+#include <jmp.h>
+
+#include "sys-dram.h"
+#include "sys-spi.h"
+#include "sys-sdcard.h"
+#include "sys-sid.h"
+
+#include "ff.h"
+#include "elf_loader.h"
+
+extern uint32_t _start;
+extern uint32_t __spl_start;
+extern uint32_t __spl_end;
+extern uint32_t __spl_size;
+extern uint32_t __stack_srv_start;
+extern uint32_t __stack_srv_end;
+extern uint32_t __stack_ddr_srv_start;
+extern uint32_t __stack_ddr_srv_end;
+
+#define CONFIG_RISCV_ELF_FILENAME "e907.elf"
+#define CONFIG_RISCV_ELF_LOADADDR (0x41008000)
+
+#define CONFIG_SDMMC_SPEED_TEST_SIZE 1024 // (unit: 512B sectors)
+
+sunxi_uart_t uart_dbg = {
+	.base = 0x02500000,
+	.id = 0,
+	.gpio_tx = { GPIO_PIN(PORTH, 9), GPIO_PERIPH_MUX5 },
+	.gpio_rx = { GPIO_PIN(PORTH, 10), GPIO_PERIPH_MUX5 },
+};
+
+sunxi_uart_t uart_e907 = {
+	.base = 0x02500C00,
+	.id = 3,
+	.gpio_tx = { GPIO_PIN(PORTE, 0), GPIO_PERIPH_MUX7 },
+	.gpio_rx = { GPIO_PIN(PORTE, 1), GPIO_PERIPH_MUX7 },
+};
+
+sdhci_t sdhci0 = {
+	.name = "sdhci0",
+	.reg = (sdhci_reg_t *)0x04020000,
+	.voltage = MMC_VDD_27_36,
+	.width = MMC_BUS_WIDTH_4,
+	.clock = MMC_CLK_50M,
+	.removable = 0,
+	.isspi = FALSE,
+	.gpio_clk = { GPIO_PIN(PORTF, 2), GPIO_PERIPH_MUX2 },
+	.gpio_cmd = { GPIO_PIN(PORTF, 3), GPIO_PERIPH_MUX2 },
+	.gpio_d0 = { GPIO_PIN(PORTF, 1), GPIO_PERIPH_MUX2 },
+	.gpio_d1 = { GPIO_PIN(PORTF, 0), GPIO_PERIPH_MUX2 },
+	.gpio_d2 = { GPIO_PIN(PORTF, 5), GPIO_PERIPH_MUX2 },
+	.gpio_d3 = { GPIO_PIN(PORTF, 4), GPIO_PERIPH_MUX2 },
+};
+
+#define FILENAME_MAX_LEN 64
+typedef struct {
+	unsigned int offset;
+	unsigned int length;
+	unsigned char *dest;
+
+	char filename[FILENAME_MAX_LEN];
+} image_info_t;
+
+image_info_t image;
+
+#define CHUNK_SIZE 0x20000
+
+static int fatfs_loadimage(char *filename, BYTE *dest)
+{
+	FIL file;
+	UINT byte_to_read = CHUNK_SIZE;
+	UINT byte_read;
+	UINT total_read = 0;
+	FRESULT fret;
+	int ret;
+	uint32_t start, time;
+
+	fret = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
+	if (fret != FR_OK) {
+		printk(LOG_LEVEL_ERROR,
+		       "FATFS: open, filename: [%s]: error %d\r\n", filename,
+		       fret);
+		ret = -1;
+		goto open_fail;
+	}
+
+	start = time_ms();
+
+	do {
+		byte_read = 0;
+		fret = f_read(&file, (void *)(dest), byte_to_read, &byte_read);
+		dest += byte_to_read;
+		total_read += byte_read;
+	} while (byte_read >= byte_to_read && fret == FR_OK);
+
+	time = time_ms() - start + 1;
+
+	if (fret != FR_OK) {
+		printk(LOG_LEVEL_ERROR, "FATFS: read: error %d\r\n", fret);
+		ret = -1;
+		goto read_fail;
+	}
+	ret = 0;
+
+read_fail:
+	fret = f_close(&file);
+
+	printk(LOG_LEVEL_DEBUG, "FATFS: read in %ums at %.2fMB/S\r\n", time,
+	       (f32)(total_read / time) / 1024.0f);
+
+open_fail:
+	return ret;
+}
+
+static int load_sdcard(image_info_t *image)
+{
+	FATFS fs;
+	FRESULT fret;
+	int ret;
+	uint32_t start;
+
+	uint32_t test_time;
+	start = time_ms();
+	sdmmc_blk_read(&card0, (uint8_t *)(SDRAM_BASE), 0,
+		       CONFIG_SDMMC_SPEED_TEST_SIZE);
+	test_time = time_ms() - start;
+	printk(LOG_LEVEL_DEBUG, "SDMMC: speedtest %uKB in %ums at %uKB/S\r\n",
+	       (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time,
+	       (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time);
+
+	start = time_ms();
+
+	fret = f_mount(&fs, "", 1);
+	if (fret != FR_OK) {
+		printk(LOG_LEVEL_ERROR, "FATFS: mount error: %d\r\n", fret);
+		return -1;
+	} else {
+		printk(LOG_LEVEL_DEBUG, "FATFS: mount OK\r\n");
+	}
+
+	printk(LOG_LEVEL_INFO, "FATFS: read %s addr=%x\r\n", image->filename,
+	       (unsigned int)image->dest);
+	ret = fatfs_loadimage(image->filename, image->dest);
+	if (ret)
+		return ret;
+
+	/* umount fs */
+	fret = f_mount(0, "", 0);
+	if (fret != FR_OK) {
+		printk(LOG_LEVEL_ERROR, "FATFS: unmount error %d\r\n", fret);
+		return -1;
+	} else {
+		printk(LOG_LEVEL_DEBUG, "FATFS: unmount OK\r\n");
+	}
+	printk(LOG_LEVEL_DEBUG, "FATFS: done in %ums\r\n", time_ms() - start);
+
+	return 0;
+}
+
+void show_banner(void)
+{
+	uint32_t id[4];
+
+	printk(LOG_LEVEL_MUTE, "\r\n");
+	printk(LOG_LEVEL_INFO, " _____     _           _____ _ _   \r\n");
+	printk(LOG_LEVEL_INFO, "|   __|_ _| |_ ___ ___|  |  |_| |_ \r\n");
+	printk(LOG_LEVEL_INFO, "|__   | | |  _| -_|  _|    -| | _| \r\n");
+	printk(LOG_LEVEL_INFO, "|_____|_  |_| |___|_| |__|__|_|_|  \r\n");
+	printk(LOG_LEVEL_INFO, "      |___|                        \r\n");
+	printk(LOG_LEVEL_INFO, "***********************************\r\n");
+	printk(LOG_LEVEL_INFO, " %s V0.1.1 Commit: %s\r\n", PROJECT_NAME,
+	       PROJECT_GIT_HASH);
+	printk(LOG_LEVEL_INFO, "***********************************\r\n");
+
+	id[0] = read32(0x03006200 + 0x0);
+	id[1] = read32(0x03006200 + 0x4);
+	id[2] = read32(0x03006200 + 0x8);
+	id[3] = read32(0x03006200 + 0xc);
+
+	printk(LOG_LEVEL_INFO, "Chip ID is: %08x%08x%08x%08x\r\n", id[0], id[1],
+	       id[2], id[3]);
+}
+
+int main(void)
+{
+	sunxi_uart_init(&uart_dbg);
+
+	// sunxi_uart_init(&uart_e907);
+
+	show_banner();
+
+	sunxi_clk_init();
+
+	sunxi_dram_init();
+
+	sunxi_clk_dump();
+
+	memset(&image, 0, sizeof(image_info_t));
+
+	image.dest = (uint8_t *)CONFIG_RISCV_ELF_LOADADDR;
+
+	strcpy(image.filename, CONFIG_RISCV_ELF_FILENAME);
+
+	if (sunxi_sdhci_init(&sdhci0) != 0) {
+		printk(LOG_LEVEL_ERROR, "SMHC: %s controller init failed\r\n",
+		       sdhci0.name);
+		return 0;
+	} else {
+		printk(LOG_LEVEL_INFO,
+		       "SMHC: %s controller v%x initialized\r\n", sdhci0.name,
+		       sdhci0.reg->vers);
+	}
+
+	if (sdmmc_init(&card0, &sdhci0) != 0) {
+		printk(LOG_LEVEL_ERROR, "SMHC: init failed\r\n");
+		return 0;
+	}
+
+	if (load_sdcard(&image) != 0) {
+		printk(LOG_LEVEL_ERROR, "SMHC: loading failed\r\n");
+		return 0;
+	}
+
+	sunxi_e907_clock_reset();
+
+	uint32_t elf_run_addr = elf_get_entry_addr((phys_addr_t)image.dest);
+	printk(LOG_LEVEL_INFO, "RISC-V ELF run addr: 0x%08x\r\n", elf_run_addr);
+
+	if (load_elf_image((phys_addr_t)image.dest)) {
+		printk(LOG_LEVEL_ERROR, "RISC-V ELF load FAIL\r\n");
+	}
+
+	sunxi_e907_clock_init(elf_run_addr);
+
+	dump_e907_clock();
+
+	printk(LOG_LEVEL_INFO, "RISC-V E907 Core now Running... \r\n");
+
+	abort();
+
+	jmp_to_fel();
+
+	return 0;
+}
\ No newline at end of file
diff --git a/app/load_e907/start.S b/app/load_e907/start.S
new file mode 100644
index 0000000..223f829
--- /dev/null
+++ b/app/load_e907/start.S
@@ -0,0 +1,226 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <linkage.h>
+
+#define  ARMV7_USR_MODE        0x10
+#define  ARMV7_FIQ_MODE        0x11
+#define  ARMV7_IRQ_MODE        0x12
+#define  ARMV7_SVC_MODE        0x13
+#define  ARMV7_MON_MODE        0x16
+#define  ARMV7_ABT_MODE        0x17
+#define  ARMV7_UND_MODE        0x1b
+#define  ARMV7_SYSTEM_MODE     0x1f
+#define  ARMV7_MODE_MASK       0x1f
+#define  ARMV7_FIQ_MASK        0x40
+#define  ARMV7_IRQ_MASK        0x80
+
+.arm
+.globl reset
+.text
+
+reset:
+	/* Boot head information for BROM */
+	.long 0xea000016
+	.byte 'e', 'G', 'O', 'N', '.', 'B', 'T', '0'
+	.long 0x12345678                                /* checksum */
+	.long __spl_size                                /* spl size */
+	.long 0x30                                              /* boot header size */
+	.long 0x30303033                                /* boot header version */
+	.long 0x00020000                                /* return value */
+	.long 0x00028000                                /* run address */
+	.long 0x0                                               /* eGON version */
+	.byte 0x00, 0x00, 0x00, 0x00    /* platform information - 8byte */
+	.byte 0x34, 0x2e, 0x30, 0x00
+
+/*
+ * The actual reset code
+ */
+	mrs r0, cpsr
+	bic r0, r0, #ARMV7_MODE_MASK
+	orr r0, r0, #ARMV7_SVC_MODE
+	orr r0, r0, #(ARMV7_IRQ_MASK | ARMV7_FIQ_MASK)
+	bic r0, r0, #(1<<9)     @set little-endian
+	msr cpsr_c, r0
+
+/* Set vector base address register */
+
+	ldr r0, =_vector
+	mcr p15, 0, r0, c12, c0, 0
+	mrc p15, 0, r0, c1, c0, 0
+	bic r0, #(1 << 13)
+	mcr p15, 0, r0, c1, c0, 0
+
+	mrc     p15, 0, r0, c1, c0, 0
+	bic     r0, r0, #0x00002000     @ clear bits 13 (--V-)
+	bic     r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
+	orr     r0, r0, #0x00000800     @ set bit 11 (Z---) BTB
+	bic     r0, r0, #0x00001000     @ clear bit 12 (I) I-cache
+	mcr     p15, 0, r0, c1, c0, 0
+
+	/* Enable neon/vfp unit */
+	mrc p15, 0, r0, c1, c0, 2
+	orr r0, r0, #(0xf << 20)
+	mcr p15, 0, r0, c1, c0, 2
+	isb
+	mov r0, #0x40000000
+	vmsr fpexc, r0
+
+	/* Set stack pointer */
+	ldr sp, =__stack_srv_end
+
+	bl  clear_bss
+
+	/*
+		* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
+		* except if in HYP mode already
+		*/
+	mrs     r0, cpsr
+	and     r1, r0, #0x1f           @ mask mode bits
+	teq     r1, #0x1a               @ test for HYP mode
+	bicne   r0, r0, #0x1f           @ clear all mode bits
+	orrne   r0, r0, #0x13           @ set SVC mode
+	orr     r0, r0, #0xc0           @ disable FIQ and IRQ
+	msr     cpsr,r0
+
+	@set cntfrq to 24M
+	ldr r0, =24000000
+	mcr p15, 0, r0, c14, c0, 0
+
+	bl set_timer_count
+
+	bl main
+
+	clear_bss:
+	ldr     r0, =_sbss
+	ldr     r1, =_ebss
+	mov     r2, #0
+
+	clbss_1:
+	stmia   r0!, {r2}
+	cmp r0, r1
+	blt clbss_1
+
+	mov pc, lr
+
+_vector:
+	b reset
+	ldr pc, _undefined_instruction
+	ldr pc, _software_interrupt
+	ldr pc, _prefetch_abort
+	ldr pc, _data_abort
+	ldr pc, _not_used
+	ldr pc, _irq
+	ldr pc, _fiq
+
+_undefined_instruction:
+	.word undefined_instruction
+_software_interrupt:
+	.word software_interrupt
+_prefetch_abort:
+	.word prefetch_abort
+_data_abort:
+	.word data_abort
+_not_used:
+	.word not_used
+_irq:
+	.word irq
+_fiq:
+	.word fiq
+
+.macro save_regs
+	str lr, [sp, #-4]
+	mrs lr, spsr_all
+	str lr, [sp, #-8]
+	str r1, [sp, #-12]
+	str r0, [sp, #-16]
+	mov r0, sp
+	cps #0x13
+	ldr r1, [r0, #-4]
+	str r1, [sp, #-4]!
+	ldr r1, [r0, #-8]
+	str r1, [sp, #-(4 * 16)]
+	ldr r1, [r0, #-12]
+	ldr r0, [r0, #-16]
+	stmdb sp, {r0 - r14}^
+	sub sp, sp, #(4 * 16)
+	ldr r4, [sp]
+	and r0, r4, #0x1f
+	cmp r0, #0x10
+	beq 10f
+	cmp r0, #0x13
+	beq 11f
+	b .
+11:	add r1, sp, #(4 * 17)
+	str r1, [sp, #(4 * 14)]
+	str lr, [sp, #(4 * 15)]
+10:	add r1, sp, #(4 * 17)
+	str r1, [sp, #-4]!
+	mov r0, sp
+.endm
+
+.macro restore_regs
+	mov r12, sp
+	ldr sp, [r12], #4
+	ldr r1, [r12], #4
+	msr spsr_cxsf, r1
+	and r0, r1, #0x1f
+	cmp r0, #0x10
+	beq 20f
+	cmp r0, #0x13
+	beq 21f
+	b .
+20:	ldr lr, [r12, #(4 * 15)]
+	ldmia r12, {r0 - r14}^
+	movs pc, lr
+21:	ldm r12, {r0 - r15}^
+	mov r0, r0
+.endm
+
+/*
+ * Exception handlers
+ */
+	.align 5
+undefined_instruction:
+	sub lr, lr, #4
+	save_regs
+	bl arm32_do_undefined_instruction
+	restore_regs
+
+	.align 5
+software_interrupt:
+	sub lr, lr, #4
+	save_regs
+	bl arm32_do_software_interrupt
+	restore_regs
+
+	.align 5
+prefetch_abort:
+	sub lr, lr, #4
+	save_regs
+	bl arm32_do_prefetch_abort
+	restore_regs
+
+	.align 5
+data_abort:
+	sub lr, lr, #8
+	save_regs
+	bl arm32_do_data_abort
+	restore_regs
+
+	.align 5
+not_used:
+	b .
+
+	.align 5
+irq:
+	sub lr, lr, #4
+	save_regs
+	bl arm32_do_irq
+	restore_regs
+
+	.align 5
+fiq:
+	sub lr, lr, #4
+	save_regs
+	bl arm32_do_fiq
+	restore_regs
diff --git a/cmake/add_syterkit_app.cmake b/cmake/add_syterkit_app.cmake
index 53eb287..e4ab7ab 100644
--- a/cmake/add_syterkit_app.cmake
+++ b/cmake/add_syterkit_app.cmake
@@ -4,7 +4,7 @@ function(add_syterkit_app target_name)
     add_executable(${target_name}_fel ${ARGN})
 
     set_target_properties(${target_name}_fel PROPERTIES LINK_DEPENDS "${LINK_SCRIPT_FEL}")
-    target_link_libraries(${target_name}_fel fatfs fdt SyterKit gcc -T"${LINK_SCRIPT_FEL}" -nostdlib -Wl,-z,noexecstack,-Map,${target_name}_fel.map)
+    target_link_libraries(${target_name}_fel fatfs fdt SyterKit elf gcc -T"${LINK_SCRIPT_FEL}" -nostdlib -Wl,-z,noexecstack,-Map,${target_name}_fel.map)
 
     add_custom_command(
         TARGET ${target_name}_fel
@@ -15,7 +15,7 @@ function(add_syterkit_app target_name)
     add_executable(${target_name}_bin ${ARGN})
 
     set_target_properties(${target_name}_bin PROPERTIES LINK_DEPENDS "${LINK_SCRIPT_BIN}")
-    target_link_libraries(${target_name}_bin fatfs fdt SyterKit gcc -T"${LINK_SCRIPT_BIN}" -nostdlib -Wl,-z,noexecstack,-Map,${target_name}_bin.map)
+    target_link_libraries(${target_name}_bin fatfs fdt elf SyterKit gcc -T"${LINK_SCRIPT_BIN}" -nostdlib -Wl,-z,noexecstack,-Map,${target_name}_bin.map)
 
     add_custom_command(
         TARGET ${target_name}_bin
diff --git a/drivers/sys-clk.c b/drivers/sys-clk.c
index 4428cdb..78bcb00 100644
--- a/drivers/sys-clk.c
+++ b/drivers/sys-clk.c
@@ -37,7 +37,7 @@ void sunxi_clk_init(void)
 	val = read32(CCU_BASE + CCU_PLL_CPU_CTRL_REG);
 	/* CPU_PLL: Output disable, PLL_N = 0, M = 0 */
 	val &= ~((1 << 27) | (0x3FF << 8) | 0x3);
-	val |= (1 << 30 | (1 << 29) | (17 << 8));
+	val |= (1 << 30 | (1 << 29) | (50 << 8));
 	write32(CCU_BASE + CCU_PLL_CPU_CTRL_REG, val);
 	sdelay(5);
 
diff --git a/drivers/sys-rproc.c b/drivers/sys-rproc.c
new file mode 100644
index 0000000..3e97247
--- /dev/null
+++ b/drivers/sys-rproc.c
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <types.h>
+#include <io.h>
+
+#include <log.h>
+
+#include "sys-rproc.h"
+#include "reg-ccu.h"
+#include "reg-rproc.h"
+
+void sunxi_e907_clock_init(uint32_t addr)
+{
+	uint32_t reg_val;
+
+	/* de-reset */
+	reg_val = read32(CCU_RISCV_CFG_BGR_REG);
+	reg_val |= CCU_RISCV_CFG_RST;
+	reg_val |= CCU_RISCV_CFG_GATING;
+	write32(CCU_RISCV_CFG_BGR_REG, reg_val);
+
+	/* set start addr */
+	reg_val = addr;
+	write32(RISCV_STA_ADD_REG, reg_val);
+
+	/* set e907 clock */
+	reg_val = read32(CCU_RISCV_CLK_REG);
+	reg_val &= ~(CCU_RISCV_CLK_MASK);
+	reg_val |= CCU_RISCV_CLK_PERI_600M;
+	write32(CCU_RISCV_CLK_REG, reg_val);
+
+	/* turn on clock gating reset */
+	reg_val = read32(CCU_RISCV_GATING_RST_REG);
+	reg_val |= CCU_RISCV_CLK_GATING;
+	reg_val |= CCU_RISCV_SOFT_RSTN;
+	reg_val |= CCU_RISCV_SYS_APB_SOFT_RSTN;
+	reg_val |= CCU_RISCV_GATING_RST_FIELD;
+	write32(CCU_RISCV_GATING_RST_REG, reg_val);
+}
+
+void sunxi_e907_clock_reset(void)
+{
+	uint32_t reg_val;
+
+	/* turn off clk gating */
+	reg_val = 0;
+	reg_val |= CCU_RISCV_GATING_RST_FIELD;
+	write32(CCU_RISCV_GATING_RST_REG, reg_val);
+
+	/* assert */
+	reg_val = read32(CCU_RISCV_CFG_BGR_REG);
+	reg_val &= ~(CCU_RISCV_CFG_RST);
+	reg_val &= ~(CCU_RISCV_CFG_GATING);
+	write32(CCU_RISCV_CFG_BGR_REG, reg_val);
+}
+
+void dump_e907_clock(void)
+{
+	uint32_t reg_val, pll_perf, factor_m, factor_n, pll_riscv;
+	uint32_t plln, pllm;
+	uint8_t p0, p1;
+
+	/* PLL PERI */
+	reg_val = read32(CCU_BASE + CCU_PLL_PERI_CTRL_REG);
+
+	if (reg_val & (1 << 31)) {
+		plln = ((reg_val >> 8) & 0xff) + 1;
+		pllm = (reg_val & 0x01) + 1;
+		p0 = ((reg_val >> 16) & 0x03) + 1;
+		p1 = ((reg_val >> 20) & 0x03) + 1;
+
+		pll_perf = (24 * plln) / (pllm * p0) >> 1;
+	} else {
+		printk(LOG_LEVEL_INFO, "CLK: PLL_peri disabled\r\n");
+		return;
+	}
+
+	reg_val = read32(CCU_RISCV_CLK_REG);
+	factor_m = (reg_val & 0x1F) + 1;
+	factor_n = ((reg_val >> 8) & 0x3) + 1;
+	pll_riscv = pll_perf / factor_m;
+
+	printk(LOG_LEVEL_INFO, "CLK: RISC-V PLL FREQ=%uMHz\r\n", pll_riscv);
+	printk(LOG_LEVEL_INFO, "CLK: RISC-V AXI FREQ=%uMHz\r\n",
+	       pll_riscv / factor_n);
+}
\ No newline at end of file
diff --git a/include/drivers/sys-rproc.h b/include/drivers/sys-rproc.h
new file mode 100644
index 0000000..047a246
--- /dev/null
+++ b/include/drivers/sys-rproc.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef __SYS_RPROC_H__
+#define __SYS_RPROC_H__
+
+void sunxi_e907_clock_init(uint32_t addr);
+
+void sunxi_e907_clock_reset(void);
+
+#endif // __SYS_RPROC_H__
\ No newline at end of file
diff --git a/include/lib/elf/elf_loader.h b/include/lib/elf/elf_loader.h
new file mode 100644
index 0000000..23ac00d
--- /dev/null
+++ b/include/lib/elf/elf_loader.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef __ELF_LOADER_H__
+#define __ELF_LOADER_H__
+
+phys_addr_t elf_get_entry_addr(phys_addr_t base);
+
+int load_elf_image(phys_addr_t img_addr);
+
+#endif // __ELF_LOADER_H__
\ No newline at end of file
diff --git a/include/reg/reg-ccu.h b/include/reg/reg-ccu.h
index 3ce2a3a..87c5570 100644
--- a/include/reg/reg-ccu.h
+++ b/include/reg/reg-ccu.h
@@ -102,10 +102,6 @@
 #define CCU_CSI_MASTER2_CLK_REG 0x0C10 /* CSI Master2 Clock Register */
 #define CCU_CSI_BGR_REG 0x0C2C /* CSI Bus Gating Reset Register */
 #define CCU_WIEGAND_BGR_REG 0x0C7C /* WIEGAND Bus Gating Reset Register */
-#define CCU_RISCV_CLK_REG 0x0D00 /* RISCV Clock Register */
-#define CCU_RISCV_GATING_RST_REG \
-	0x0D04 /* RISCV Gating and Reset Configuration Register */
-#define CCU_RISCV_CFG_BGR_REG 0x0D0C /* RISCV_CFG Bus Gating Reset Register */
 #define CCU_PLL_PRE_DIV_REG 0x0E00 /* PLL Pre Divider Register */
 #define CCU_AHB_GATE_EN_REG 0x0E04 /* AHB Gate Enable Register */
 #define CCU_PERIPLL_GATE_EN_REG 0x0E08 /* PERIPLL Gate Enable Register */
@@ -141,4 +137,41 @@
 #define CCU_MMC_BGR_SMHC1_RST (1 << 17)
 #define CCU_MMC_BGR_SMHC2_RST (1 << 18)
 
+/* This file defines the register addresses and bit fields for
+ * controlling the RISC-V subsystem in the CCU module. 
+ */
+#define CCU_RISCV_GATING_RST_REG \
+	(CCU_BASE + 0x0d04) // Register address for RISC-V gating reset control
+#define CCU_RISCV_GATING_RST_FIELD \
+	(0x16aa << 16) // Bit field value for RISC-V gating reset
+#define CCU_RISCV_SYS_APB_SOFT_RSTN \
+	(0x1 << 2) // Bit field value for RISC-V system APB soft reset
+#define CCU_RISCV_SOFT_RSTN (0x1 << 1) // Bit field value for RISC-V soft reset
+#define CCU_RISCV_CLK_GATING \
+	(0x1 << 0) // Bit field value for RISC-V clock gating
+
+#define CCU_RISCV_CLK_REG \
+	(CCU_BASE + 0x0d00) // Register address for RISC-V clock control
+#define CCU_RISCV_CLK_MASK (0x7 << 24) // Bit mask for RISC-V clock selection
+#define CCU_RISCV_CLK_HOSC \
+	(0) // Bit field value for high-frequency oscillator clock
+#define CCU_RISCV_CLK_32K (0x1 << 24) // Bit field value for 32 kHz clock
+#define CCU_RISCV_CLK_16M (0x2 << 24) // Bit field value for 16 MHz clock
+#define CCU_RISCV_CLK_PERI_600M \
+	(0x3 << 24) // Bit field value for 600 MHz peripheral clock
+#define CCU_RISCV_CLK_PERI_480M \
+	(0x4 << 24) // Bit field value for 480 MHz peripheral clock
+#define CCU_RISCV_CLK_CPUPLL (0x5 << 24) // Bit field value for CPU PLL clock
+
+#define CCU_PLL_CPUX_TUNING_REG \
+	(0x1400) // Register address for CPU PLL tuning control
+
+#define CCU_RISCV_CFG_BGR_REG \
+	(CCU_BASE +           \
+	 0x0d0c) // Register address for RISC-V configuration BGR control
+#define CCU_RISCV_CFG_RST \
+	(0x1 << 16) // Bit field value for RISC-V configuration reset
+#define CCU_RISCV_CFG_GATING \
+	(0x1 << 0) // Bit field value for RISC-V configuration gating
+
 #endif
diff --git a/include/reg/reg-rproc.h b/include/reg/reg-rproc.h
new file mode 100644
index 0000000..e65e5a5
--- /dev/null
+++ b/include/reg/reg-rproc.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef __REG_RPROC_H__
+#define __REG_RPROC_H__
+
+#define RISCV_CFG_BASE (0x06010000) // Base address for RISC-V configuration
+#define RISCV_STA_ADD_REG \
+	(RISCV_CFG_BASE + 0x0204) // Register address for RISC-V start address
+
+#endif // __REG_RPROC_H__
\ No newline at end of file
diff --git a/lib/elf/elf.c b/lib/elf/elf.c
index f0e3771..d3f0145 100644
--- a/lib/elf/elf.c
+++ b/lib/elf/elf.c
@@ -6,9 +6,32 @@
 
 #include <elf.h>
 #include <elf_helpers.h>
+#include <elf_loader.h>
 
 #include <log.h>
 
+void print_elf32_ehdr(Elf32_Ehdr *header)
+{
+	printk(LOG_LEVEL_DEBUG, "e_ident: ");
+	for (int i = 0; i < EI_NIDENT; i++) {
+		printk(LOG_LEVEL_MUTE, "%02x ", header->e_ident[i]);
+	}
+	printk(LOG_LEVEL_MUTE, "\r\n");
+	printk(LOG_LEVEL_DEBUG, "e_type: 0x%08x\r\n", header->e_type);
+	printk(LOG_LEVEL_DEBUG, "e_machine: 0x%08x\r\n", header->e_machine);
+	printk(LOG_LEVEL_DEBUG, "e_version: 0x%08x\r\n", header->e_version);
+	printk(LOG_LEVEL_DEBUG, "e_entry: 0x%08x\r\n", header->e_entry);
+	printk(LOG_LEVEL_DEBUG, "e_phoff: 0x%08x\r\n", header->e_phoff);
+	printk(LOG_LEVEL_DEBUG, "e_shoff: 0x%08x\r\n", header->e_shoff);
+	printk(LOG_LEVEL_DEBUG, "e_flags: 0x%08x\r\n", header->e_flags);
+	printk(LOG_LEVEL_DEBUG, "e_ehsize: 0x%08x\r\n", header->e_ehsize);
+	printk(LOG_LEVEL_DEBUG, "e_phentsize: 0x%08x\r\n", header->e_phentsize);
+	printk(LOG_LEVEL_DEBUG, "e_phnum: 0x%08x\r\n", header->e_phnum);
+	printk(LOG_LEVEL_DEBUG, "e_shentsize: 0x%08x\r\n", header->e_shentsize);
+	printk(LOG_LEVEL_DEBUG, "e_shnum: 0x%08x\r\n", header->e_shnum);
+	printk(LOG_LEVEL_DEBUG, "e_shstrndx: 0x%08x\r\n", header->e_shstrndx);
+}
+
 phys_addr_t elf_get_entry_addr(phys_addr_t base)
 {
 	Elf32_Ehdr *ehdr;
@@ -28,6 +51,9 @@ int load_elf_image(phys_addr_t img_addr)
 	void *src = NULL;
 
 	ehdr = (Elf32_Ehdr *)img_addr;
+
+	print_elf32_ehdr(ehdr);
+
 	phdr = (Elf32_Phdr *)(img_addr + ehdr->e_phoff);
 
 	/* load elf program segment */
diff --git a/scripts/genimage.sh b/scripts/genimage.sh
old mode 100644
new mode 100755
diff --git a/scripts/genimage_loade907.cfg b/scripts/genimage_loade907.cfg
new file mode 100644
index 0000000..24ba919
--- /dev/null
+++ b/scripts/genimage_loade907.cfg
@@ -0,0 +1,30 @@
+image boot.vfat {
+	vfat {
+		files = {
+			"e907.elf",
+		}
+	}
+	size = 8M
+}
+
+image sdcard.img {
+	hdimage {}
+
+	partition boot0 {
+		in-partition-table = "no"
+		image = "loade907_bin.bin"
+		offset = 8K
+	}
+
+	partition boot0-gpt {
+		in-partition-table = "no"
+		image = "loade907_bin.bin"
+		offset = 128K
+	}
+
+	partition kernel {
+		partition-type = 0xC
+		bootable = "true"
+		image = "boot.vfat"
+	}
+}
-- 
2.25.1

