arch: riscv: custom: add Andes CSR support

Rework Andes-specific CSR to use RISC-V custom CSR common code.
Move these stuff to 'arch/riscv/custom/andes':

1. Rename 'soc_v5.h' to 'andes_csr.h' for CSR definitions.
2. Replace '_start' with '__reset' hook for low-level CSR initialization.
3. Move CSR context to common macro '__custom_csr_save/restore_context'.
4. Move 'EXECIT' CSR support to common code.
5. Move PMA CSR driver to common code.
6. Use RISC-V common linker.ld instead of SoC-specific linker.ld.

Signed-off-by: Jimmy Zheng <jimmyzhe@andestech.com>
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 5d3e854..ba6dfc9 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -528,4 +528,6 @@
 rsource "Kconfig.isa"
 rsource "core/Kconfig"
 
+rsource "custom/Kconfig"
+
 endmenu
diff --git a/arch/riscv/custom/Kconfig b/arch/riscv/custom/Kconfig
new file mode 100644
index 0000000..01204b6
--- /dev/null
+++ b/arch/riscv/custom/Kconfig
@@ -0,0 +1,8 @@
+# Copyright (c) 2025 Andes Technology Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+if DT_HAS_ANDESTECH_ANDESCORE_V5_ENABLED
+
+rsource "andes/Kconfig"
+
+endif # DT_HAS_ANDESTECH_ANDESCORE_V5_ENABLED
diff --git a/arch/riscv/custom/andes/CMakeLists.txt b/arch/riscv/custom/andes/CMakeLists.txt
new file mode 100644
index 0000000..1b0c491
--- /dev/null
+++ b/arch/riscv/custom/andes/CMakeLists.txt
@@ -0,0 +1,10 @@
+# Copyright (c) 2025 Andes Technology Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_include_directories(.)
+
+zephyr_sources_ifdef(CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA pma.c)
+zephyr_sources_ifndef(CONFIG_INCLUDE_RESET_VECTOR reset.S)
+zephyr_linker_sources_ifdef(CONFIG_RISCV_CUSTOM_CSR_ANDES_EXECIT RODATA SORT_KEY 0x0 execit.ld)
+zephyr_linker_sources_ifdef(CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA RAM_SECTIONS SORT_KEY 0x0 pma_align_start.ld)
+zephyr_linker_sources_ifdef(CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA RAM_SECTIONS SORT_KEY z_end pma_align_end.ld)
diff --git a/arch/riscv/custom/andes/Kconfig b/arch/riscv/custom/andes/Kconfig
new file mode 100644
index 0000000..142f8f8
--- /dev/null
+++ b/arch/riscv/custom/andes/Kconfig
@@ -0,0 +1,73 @@
+# Copyright (c) 2025 Andes Technology Corporation
+# SPDX-License-Identifier: Apache-2.0
+
+config CPU_HAS_ANDES_EXECIT
+	bool
+	help
+	  The AndesCore supports EXEC.IT instruction.
+
+config RISCV_CUSTOM_CSR_ANDES_EXECIT
+	bool "Andes V5 EXEC.IT extension"
+	depends on CPU_HAS_ANDES_EXECIT
+	depends on RISCV_ISA_EXT_C
+	depends on !RISCV_GENERIC_TOOLCHAIN
+	depends on !LINKER_USE_NO_RELAX
+	help
+	  The EXEC.IT extension (Execution on Instruction Table) generate
+	  a look-up table and replaces suitable 32-bit instructions with
+	  the 16-bit "exec.it <INDEX>".
+
+config RISCV_CUSTOM_CSR_ANDES_NEXECIT
+	bool "Andes V5 New EXEC.IT opcode encoding"
+	depends on RISCV_CUSTOM_CSR_ANDES_EXECIT
+	help
+	  The New EXEC.IT instruction is an alias of EXEC.IT with different
+	  opcode encoding.
+
+config CPU_HAS_ANDES_HWDSP
+	bool
+	help
+	  The AndesCore supports hardware DSP extension.
+
+config RISCV_CUSTOM_CSR_ANDES_HWDSP
+	bool "AndeStar V5 DSP ISA"
+	depends on CPU_HAS_ANDES_HWDSP
+	depends on !RISCV_GENERIC_TOOLCHAIN
+	help
+	  This option enables the AndeStar v5 hardware DSP, in order to
+	  support using the DSP instructions.
+
+config CPU_HAS_ANDES_PFT
+	bool
+	help
+	  The AndesCore supports PowerBrake extension.
+
+config RISCV_CUSTOM_CSR_ANDES_PFT
+	bool "Andes V5 PowerBrake extension"
+	depends on CPU_HAS_ANDES_PFT
+	help
+	  The PowerBrake extension throttles performance by reducing instruction
+	  executing rate.
+
+config CPU_HAS_ANDES_PMA
+	bool
+	help
+	  The AndesCore supports Programmable PMA.
+
+config RISCV_CUSTOM_CSR_ANDES_PMA
+	bool "Andes V5 Physical Memory Attribute (PMA)"
+	depends on CPU_HAS_ANDES_PMA
+	select ARCH_HAS_NOCACHE_MEMORY_SUPPORT
+	help
+	  This option enables the Andes V5 PMA, in order to support SW to
+	  configure physical memory attribute by PMA CSRs. The address
+	  matching of Andes V5 PMA is like RISC-V PMP NAPOT mode
+	  (power-of-two alignment).
+
+config RISCV_CUSTOM_CSR_ANDES_PMA_NAPOT_GRANULARITY
+	int
+	depends on RISCV_CUSTOM_CSR_ANDES_PMA
+	default 4096
+	help
+	  Minimum size (and alignment) of an PMA region. Use this symbol
+	  to guarantee minimum size and alignment of PMA regions.
diff --git a/soc/andestech/ae350/soc_v5.h b/arch/riscv/custom/andes/andes_csr.h
similarity index 85%
rename from soc/andestech/ae350/soc_v5.h
rename to arch/riscv/custom/andes/andes_csr.h
index 111a021..be3b272 100644
--- a/soc/andestech/ae350/soc_v5.h
+++ b/arch/riscv/custom/andes/andes_csr.h
@@ -1,11 +1,14 @@
 /*
- * Copyright (c) 2021 Andes Technology Corporation
- *
+ * Copyright (c) 2025 Andes Technology Corporation
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#ifndef __RISCV_ANDES_V5_SOC_V5_H_
-#define __RISCV_ANDES_V5_SOC_V5_H_
+#ifndef ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_CSR_H_
+#define ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_CSR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /* Control and Status Registers (CSRs) available for Andes V5 SoCs */
 #define NDS_MMISC_CTL                0x7D0
@@ -46,4 +49,8 @@
 #define NDS_PMAADDR14                0xBDE
 #define NDS_PMAADDR15                0xBDF
 
-#endif /* __RISCV_ANDES_V5_SOC_V5_H_ */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_CSR_H_ */
diff --git a/arch/riscv/custom/andes/csr_context.h b/arch/riscv/custom/andes/csr_context.h
new file mode 100644
index 0000000..d92ceff
--- /dev/null
+++ b/arch/riscv/custom/andes/csr_context.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2025 Andes Technology Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Extra definitions required for CONFIG_RISCV_SOC_CONTEXT_SAVE.
+ */
+
+#ifndef ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_CSR_CONTEXT_H_
+#define ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_CSR_CONTEXT_H_
+
+#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
+
+/* Andes V5 specific registers. */
+#if defined(CONFIG_RISCV_CUSTOM_CSR_ANDES_PFT) && \
+	defined(CONFIG_RISCV_CUSTOM_CSR_ANDES_HWDSP)
+	#define CUSTOM_CSR_ESF_MEMBERS			\
+		uint32_t mxstatus;			\
+		uint32_t ucode				\
+
+	#define CUSTOM_CSR_ESF_INIT			\
+		0,					\
+		0
+
+#elif defined(CONFIG_RISCV_CUSTOM_CSR_ANDES_PFT)
+	#define CUSTOM_CSR_ESF_MEMBERS			\
+		uint32_t mxstatus
+
+	#define CUSTOM_CSR_ESF_INIT			\
+		0
+
+#elif defined(CONFIG_RISCV_CUSTOM_CSR_ANDES_HWDSP)
+	#define CUSTOM_CSR_ESF_MEMBERS			\
+		uint32_t ucode
+
+	#define CUSTOM_CSR_ESF_INIT			\
+		0
+
+#endif
+
+#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
+
+#endif /* ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_CSR_CONTEXT_H_ */
diff --git a/arch/riscv/custom/andes/csr_irq.inc b/arch/riscv/custom/andes/csr_irq.inc
new file mode 100644
index 0000000..52a4200
--- /dev/null
+++ b/arch/riscv/custom/andes/csr_irq.inc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025 Andes Technology Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/offsets.h>
+#include <zephyr/toolchain.h>
+#include <andes_csr.h>
+
+#ifdef CONFIG_64BIT
+	/* register-wide load/store based on ld/sd (XLEN = 64) */
+
+	.macro lr, rd, mem
+	ld \rd, \mem
+	.endm
+
+	.macro sr, rs, mem
+	sd \rs, \mem
+	.endm
+
+#else
+	/* register-wide load/store based on lw/sw (XLEN = 32) */
+
+	.macro lr, rd, mem
+	lw \rd, \mem
+	.endm
+
+	.macro sr, rs, mem
+	sw \rs, \mem
+	.endm
+
+#endif
+
+#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
+
+	.macro __custom_csr_save_context __soc_esf_reg reg
+
+#ifdef CONFIG_RISCV_CUSTOM_CSR_ANDES_PFT
+	csrr \reg, NDS_MXSTATUS
+	sr \reg, __soc_esf_t_mxstatus_OFFSET(\__soc_esf_reg)
+#endif
+
+#ifdef CONFIG_RISCV_CUSTOM_CSR_ANDES_HWDSP
+	csrr \reg, NDS_UCODE
+	sr \reg, __soc_esf_t_ucode_OFFSET(\__soc_esf_reg)
+#endif
+
+	.endm
+
+	.macro  __custom_csr_restore_context __soc_esf_reg reg
+
+#ifdef CONFIG_RISCV_CUSTOM_CSR_ANDES_PFT
+	lr \reg, __soc_esf_t_mxstatus_OFFSET(\__soc_esf_reg)
+	csrw NDS_MXSTATUS, \reg
+#endif
+#ifdef CONFIG_RISCV_CUSTOM_CSR_ANDES_HWDSP
+	lr \reg, __soc_esf_t_ucode_OFFSET(\__soc_esf_reg)
+	csrw NDS_UCODE, \reg
+#endif
+
+	.endm
+
+#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
diff --git a/arch/riscv/custom/andes/csr_offsets.h b/arch/riscv/custom/andes/csr_offsets.h
new file mode 100644
index 0000000..a5ef20d
--- /dev/null
+++ b/arch/riscv/custom/andes/csr_offsets.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2025 Andes Technology Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Extra definitions required for CONFIG_RISCV_SOC_OFFSETS.
+ */
+
+#ifndef ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_CSR_OFFSETS_H_
+#define ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_CSR_OFFSETS_H_
+
+#ifdef CONFIG_RISCV_SOC_OFFSETS
+
+/* Andes V5 specific registers. */
+#if defined(CONFIG_RISCV_CUSTOM_CSR_ANDES_PFT) && \
+	defined(CONFIG_RISCV_CUSTOM_CSR_ANDES_HWDSP)
+	#define GEN_CUSTOM_CSR_OFFSET_SYMS()		\
+		GEN_OFFSET_SYM(soc_esf_t, mxstatus);	\
+		GEN_OFFSET_SYM(soc_esf_t, ucode)
+
+#elif defined(CONFIG_RISCV_CUSTOM_CSR_ANDES_PFT)
+	#define GEN_CUSTOM_CSR_OFFSET_SYMS()		\
+		GEN_OFFSET_SYM(soc_esf_t, mxstatus)
+
+#elif defined(CONFIG_RISCV_CUSTOM_CSR_ANDES_HWDSP)
+	#define GEN_CUSTOM_CSR_OFFSET_SYMS()		\
+		GEN_OFFSET_SYM(soc_esf_t, ucode)
+
+#endif
+
+#endif /* CONFIG_RISCV_SOC_OFFSETS */
+
+#endif /* ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_CSR_OFFSETS_H_ */
diff --git a/soc/andestech/ae350/common_linker/execit.ld b/arch/riscv/custom/andes/execit.ld
similarity index 100%
rename from soc/andestech/ae350/common_linker/execit.ld
rename to arch/riscv/custom/andes/execit.ld
diff --git a/soc/andestech/ae350/pma.c b/arch/riscv/custom/andes/pma.c
similarity index 94%
rename from soc/andestech/ae350/pma.c
rename to arch/riscv/custom/andes/pma.c
index 326bdf3..1e9d41c 100644
--- a/soc/andestech/ae350/pma.c
+++ b/arch/riscv/custom/andes/pma.c
@@ -1,16 +1,14 @@
 /*
- * Copyright (c) 2021 Andes Technology Corporation
- *
+ * Copyright (c) 2025 Andes Technology Corporation
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#include "soc_v5.h"
-
 #include <zephyr/init.h>
 #include <zephyr/kernel.h>
 #include <zephyr/arch/cpu.h>
 #include <zephyr/linker/linker-defs.h>
 #include <zephyr/arch/riscv/csr.h>
+#include <andes_csr.h>
 
 #ifndef CONFIG_ASSERT
 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
@@ -149,7 +147,7 @@
 static int pma_region_is_valid(const struct pma_region *region)
 {
 	/* Region size must greater or equal to the minimum PMA region size */
-	if (region->size < CONFIG_SOC_ANDES_V5_PMA_REGION_MIN_ALIGN_AND_SIZE) {
+	if (region->size < CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA_NAPOT_GRANULARITY) {
 		return -EINVAL;
 	}
 
@@ -204,10 +202,10 @@
 		/* This CPU doesn't support PMA */
 
 		__ASSERT(0, "CPU doesn't support PMA. "
-			    "Please disable CONFIG_SOC_ANDES_V5_PMA\n");
+			"Please disable CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA\n");
 #ifndef CONFIG_ASSERT
 		LOG_ERR("CPU doesn't support PMA. "
-			"Please disable CONFIG_SOC_ANDES_V5_PMA");
+			"Please disable CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA");
 #endif
 		return;
 	}
diff --git a/soc/andestech/ae350/pma.h b/arch/riscv/custom/andes/pma.h
similarity index 66%
rename from soc/andestech/ae350/pma.h
rename to arch/riscv/custom/andes/pma.h
index 459db7c..11b5879 100644
--- a/soc/andestech/ae350/pma.h
+++ b/arch/riscv/custom/andes/pma.h
@@ -1,10 +1,13 @@
 /*
- * Copyright (c) 2021 Andes Technology Corporation
+ * Copyright (c) 2025 Andes Technology Corporation
  * Copyright (c) 2024 Meta Platforms
  *
  * SPDX-License-Identifier: Apache-2.0
  */
 
+#ifndef ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_PMA_H_
+#define ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_PMA_H_
+
 /*
  * @brief Init PMA CSRs of each CPU core
  *
@@ -16,3 +19,5 @@
 
 /* Initialize PMA */
 void pma_init(void);
+
+#endif /* ZEPHYR_ARCH_RISCV_CUSTOM_ANDES_PMA_H_ */
diff --git a/arch/riscv/custom/andes/pma_align_end.ld b/arch/riscv/custom/andes/pma_align_end.ld
new file mode 100644
index 0000000..a403409
--- /dev/null
+++ b/arch/riscv/custom/andes/pma_align_end.ld
@@ -0,0 +1,6 @@
+/*
+ * Copyright (c) 2025 Andes Technology Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma pop_macro("MPU_ALIGN")
diff --git a/arch/riscv/custom/andes/pma_align_start.ld b/arch/riscv/custom/andes/pma_align_start.ld
new file mode 100644
index 0000000..db3621c
--- /dev/null
+++ b/arch/riscv/custom/andes/pma_align_start.ld
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2025 Andes Technology Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma push_macro("MPU_ALIGN")
+#undef MPU_ALIGN
+/* Make linker section alignment comply with PMA granularity. */
+#define MPU_ALIGN(region_size) \
+    . = ALIGN(CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA_NAPOT_GRANULARITY); \
+    . = ALIGN( 1 << LOG2CEIL(region_size))
diff --git a/arch/riscv/custom/andes/reset.S b/arch/riscv/custom/andes/reset.S
new file mode 100644
index 0000000..1214c80
--- /dev/null
+++ b/arch/riscv/custom/andes/reset.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2025 Andes Technology Corporation
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <andes_csr.h>
+#include <zephyr/toolchain.h>
+#include <zephyr/devicetree.h>
+
+/* exports */
+GTEXT(__reset)
+
+/* imports */
+GTEXT(__initialize)
+
+SECTION_FUNC(reset, __reset)
+
+#ifdef CONFIG_RISCV_CUSTOM_CSR_ANDES_EXECIT
+	/* Initialize EXECIT table */
+	la t0, _ITB_BASE_
+	csrw NDS_UITB, t0
+#endif
+
+#ifdef CONFIG_ICACHE
+	/* Enable I cache with HW prefetcher. */
+	li t0, (1 << 9) | (1 << 0)
+	csrs NDS_MCACHE_CTL, t0
+#endif
+
+#ifdef CONFIG_DCACHE
+	/*
+	 * Enable D cache with HW prefetcher and D-cache write-around
+	 * (threshold: 4 cache lines).
+	 */
+	li t0, (0x3 << 13)
+	csrc NDS_MCACHE_CTL, t0
+	li t0, (1 << 13) | (1 << 10) | (1 << 1)
+	csrs NDS_MCACHE_CTL, t0
+
+#if DT_HAS_COMPAT_STATUS_OKAY(andestech_l2c)
+	/* Enable D-cache CM (Coherence Manager). */
+	li t0, (1 << 19)
+	csrs NDS_MCACHE_CTL, t0
+
+	/* Check if CPU support CM or not. */
+	csrr t0, NDS_MCACHE_CTL
+	li t1, (1 << 19)
+	and t0, t0, t1
+	beqz t0, cache_enable_finish
+
+	/* If CPU support CM, check if CM is enabled. */
+	li t1, (1 << 20)
+check_cm_enabled:
+	csrr t0, NDS_MCACHE_CTL
+	and t0, t0, t1
+	beqz t0, check_cm_enabled
+
+cache_enable_finish:
+#endif /* DT_HAS_COMPAT_STATUS_OKAY(andestech_l2c) */
+#endif
+
+	/* Enable misaligned access and non-blocking load */
+	li t0, (1 << 8) | (1 << 6)
+	csrs NDS_MMISC_CTL, t0
+
+	/* Jump to __initialize */
+	call __initialize
diff --git a/boards/andestech/adp_xc7k_ae350/adp_xc7k_ae350_clic_defconfig b/boards/andestech/adp_xc7k_ae350/adp_xc7k_ae350_clic_defconfig
index f34e627..b61e901 100644
--- a/boards/andestech/adp_xc7k_ae350/adp_xc7k_ae350_clic_defconfig
+++ b/boards/andestech/adp_xc7k_ae350/adp_xc7k_ae350_clic_defconfig
@@ -1,15 +1,6 @@
 CONFIG_XIP=n
 CONFIG_CONSOLE=y
 CONFIG_UART_CONSOLE=y
-
-# Serial driver options
 CONFIG_SERIAL=y
-
-# GPIO driver options
 CONFIG_GPIO=y
-
-# PMP granularity options
 CONFIG_PMP_GRANULARITY=8
-
-# EXEC.IT options
-CONFIG_SOC_ANDES_V5_EXECIT=y
diff --git a/boards/andestech/adp_xc7k_ae350/adp_xc7k_ae350_defconfig b/boards/andestech/adp_xc7k_ae350/adp_xc7k_ae350_defconfig
index f34e627..b61e901 100644
--- a/boards/andestech/adp_xc7k_ae350/adp_xc7k_ae350_defconfig
+++ b/boards/andestech/adp_xc7k_ae350/adp_xc7k_ae350_defconfig
@@ -1,15 +1,6 @@
 CONFIG_XIP=n
 CONFIG_CONSOLE=y
 CONFIG_UART_CONSOLE=y
-
-# Serial driver options
 CONFIG_SERIAL=y
-
-# GPIO driver options
 CONFIG_GPIO=y
-
-# PMP granularity options
 CONFIG_PMP_GRANULARITY=8
-
-# EXEC.IT options
-CONFIG_SOC_ANDES_V5_EXECIT=y
diff --git a/drivers/cache/cache_andes.c b/drivers/cache/cache_andes.c
index eb9dcc7..6b5c7a7 100644
--- a/drivers/cache/cache_andes.c
+++ b/drivers/cache/cache_andes.c
@@ -4,13 +4,12 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#include "soc_v5.h"
-
 #include <zephyr/init.h>
 #include <zephyr/kernel.h>
 #include <zephyr/arch/riscv/csr.h>
 #include <zephyr/drivers/cache.h>
 #include <zephyr/logging/log.h>
+#include <andes_csr.h>
 
 LOG_MODULE_REGISTER(cache_andes, CONFIG_CACHE_LOG_LEVEL);
 
diff --git a/soc/andestech/ae350/CMakeLists.txt b/soc/andestech/ae350/CMakeLists.txt
index 8c7f70a..fdb98a7 100644
--- a/soc/andestech/ae350/CMakeLists.txt
+++ b/soc/andestech/ae350/CMakeLists.txt
@@ -4,26 +4,19 @@
 
 zephyr_sources(
   soc.c
-  start.S
   soc_irq.S
 )
 
-zephyr_sources_ifdef(CONFIG_SOC_ANDES_V5_PMA pma.c)
-zephyr_linker_sources(ROM_START SORT_KEY 0x0 common_linker/init.ld)
-zephyr_linker_sources_ifdef(CONFIG_SOC_ANDES_V5_EXECIT RODATA SORT_KEY 0x0 common_linker/execit.ld)
-zephyr_linker_sources_ifdef(CONFIG_XIP RAM_SECTIONS SORT_KEY 0x0 common_linker/ram_start_nonzero.ld)
+zephyr_linker_sources_ifdef(CONFIG_XIP RAM_SECTIONS SORT_KEY 0x0 ram_start_nonzero.ld)
+set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "")
 
 # Note: AndeStar V5 DSP needs custom Andes V5 toolchain
-if(CONFIG_SOC_ANDES_V5_HWDSP)
+if(CONFIG_RISCV_CUSTOM_CSR_ANDES_HWDSP)
   zephyr_cc_option(-mext-dsp)
 endif()
 
 # Note: AndeStar V5 EXEC.IT needs custom Andes V5 toolchain
-if(CONFIG_SOC_ANDES_V5_EXECIT)
+if(CONFIG_RISCV_CUSTOM_CSR_ANDES_EXECIT)
   zephyr_cc_option(-mexecit)
   zephyr_ld_options(-Wl,--mexecit)
 endif()
-
-if(CONFIG_SOC_SERIES_ANDES_AE350)
-  set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "")
-endif()
diff --git a/soc/andestech/ae350/Kconfig b/soc/andestech/ae350/Kconfig
index 61db6d1..da4cc01 100644
--- a/soc/andestech/ae350/Kconfig
+++ b/soc/andestech/ae350/Kconfig
@@ -11,11 +11,17 @@
 	select RISCV_ISA_EXT_C
 	select RISCV_ISA_EXT_ZICSR
 	select RISCV_ISA_EXT_ZIFENCEI
-	select ATOMIC_OPERATIONS_BUILTIN
-	select INCLUDE_RESET_VECTOR
 	select CPU_HAS_DCACHE
 	select CPU_HAS_ICACHE
-	select CACHE_MANAGEMENT if DCACHE
+	select CPU_HAS_ANDES_EXECIT
+	select CPU_HAS_ANDES_HWDSP
+	select CPU_HAS_ANDES_PFT
+	select CPU_HAS_ANDES_PMA
+	select RISCV_SOC_CONTEXT_SAVE if RISCV_CUSTOM_CSR_ANDES_HWDSP
+	select RISCV_SOC_CONTEXT_SAVE if RISCV_CUSTOM_CSR_ANDES_PFT
+	select ATOMIC_OPERATIONS_BUILTIN
+	select SOC_EARLY_INIT_HOOK if RISCV_CUSTOM_CSR_ANDES_PMA
+	select SOC_PER_CORE_INIT_HOOK if RISCV_CUSTOM_CSR_ANDES_PMA
 	imply XIP
 
 config SOC_ANDES_AE350
@@ -66,49 +72,24 @@
 endchoice
 
 config SOC_ANDES_V5_HWDSP
-	bool "AndeStar V5 DSP ISA"
-	select RISCV_SOC_CONTEXT_SAVE
-	depends on !RISCV_GENERIC_TOOLCHAIN
-	help
-		This option enables the AndeStar v5 hardware DSP, in order to
-		support using the DSP instructions.
+	bool
+	select DEPRECATED
 
 config SOC_ANDES_V5_PFT
-	bool "Andes V5 PowerBrake extension"
-	default y
-	select RISCV_SOC_CONTEXT_SAVE
-	help
-		The PowerBrake extension throttles performance by reducing instruction
-		executing rate.
+	bool
+	select DEPRECATED
 
 config SOC_ANDES_V5_EXECIT
-	bool "Andes V5 EXEC.IT extension"
-	depends on RISCV_ISA_EXT_C
-	depends on !RISCV_GENERIC_TOOLCHAIN
-	depends on !LINKER_USE_NO_RELAX
-	help
-		The EXEC.IT extension (Execution on Instruction Table) generate
-		a look-up table and replaces suitable 32-bit instructions with
-		the 16-bit "exec.it <INDEX>".
+	bool
+	select DEPRECATED
 
 config SOC_ANDES_V5_PMA
-	bool "Andes V5 Physical Memory Attribute (PMA)"
-	select ARCH_HAS_NOCACHE_MEMORY_SUPPORT
-	select SOC_EARLY_INIT_HOOK
-	select SOC_PER_CORE_INIT_HOOK
-	help
-		This option enables the Andes V5 PMA, in order to support SW to
-		configure physical memory attribute by PMA CSRs. The address
-		matching of Andes V5 PMA is like RISC-V PMP NAPOT mode
-		(power-of-two alignment).
+	bool
+	select DEPRECATED
 
 config SOC_ANDES_V5_PMA_REGION_MIN_ALIGN_AND_SIZE
-	int
-	depends on SOC_ANDES_V5_PMA
-	default 4096
-	help
-		Minimum size (and alignment) of an PMA region. Use this symbol
-		to guarantee minimum size and alignment of PMA regions.
+	bool
+	select DEPRECATED
 
 config SOC_ANDES_V5_L2C
 	bool
diff --git a/soc/andestech/ae350/Kconfig.defconfig b/soc/andestech/ae350/Kconfig.defconfig
index 0721248..81a1ce0 100644
--- a/soc/andestech/ae350/Kconfig.defconfig
+++ b/soc/andestech/ae350/Kconfig.defconfig
@@ -3,17 +3,11 @@
 
 if SOC_SERIES_ANDES_AE350
 
-# Kconfig picks the first default with a satisfied condition.
-# SoC defaults should be parsed before SoC Series defaults, because SoCs usually
-# overrides SoC Series values.
 rsource "Kconfig.defconfig.ae*"
 
 config SYS_CLOCK_HW_CYCLES_PER_SEC
 	default 60000000
 
-config KERNEL_ENTRY
-	default "entry"
-
 config RISCV_GENERIC_TOOLCHAIN
 	default y if "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr"
 	default n
diff --git a/soc/andestech/ae350/common_linker/init.ld b/soc/andestech/ae350/common_linker/init.ld
deleted file mode 100644
index 0feb828..0000000
--- a/soc/andestech/ae350/common_linker/init.ld
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Copyright (c) 2023 Andes Technology Corporation
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-KEEP(*(.init.*))
diff --git a/soc/andestech/ae350/linker.ld b/soc/andestech/ae350/linker.ld
deleted file mode 100644
index 36e4e51..0000000
--- a/soc/andestech/ae350/linker.ld
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Copyright (c) 2016-2017 Jean-Paul Etienne <fractalclone@gmail.com>
- * Copyright (c) 2021 Andes Technology Corporation
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/**
- * @file
- * @brief Linker command/script file
- *
- * Linker script for the ae350 platform
- */
-
-#include <zephyr/devicetree.h>
-
-#include <zephyr/linker/sections.h>
-#include <zephyr/linker/devicetree_regions.h>
-
-#include <zephyr/linker/linker-defs.h>
-#include <zephyr/linker/linker-tool.h>
-
-#ifdef CONFIG_XIP
-#define ROMABLE_REGION              ROM
-#else
-#define ROMABLE_REGION              RAM
-#endif
-#define RAMABLE_REGION              RAM
-
-#define _EXCEPTION_SECTION_NAME     exceptions
-#define _RESET_SECTION_NAME         reset
-
-#ifdef CONFIG_XIP
-#if DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_flash), soc_nv_flash, okay)
-#ifdef CONFIG_FLASH_LOAD_OFFSET
-#define ROM_BASE (DT_REG_ADDR(DT_CHOSEN(zephyr_flash)) + \
-				CONFIG_FLASH_LOAD_OFFSET)
-#else /* !CONFIG_FLASH_LOAD_OFFSET */
-#define ROM_BASE DT_REG_ADDR(DT_CHOSEN(zephyr_flash))
-#endif /* CONFIG_FLASH_LOAD_OFFSET */
-#define ROM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_flash))
-#elif DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_flash), jedec_spi_nor)
-/* For jedec,spi-nor we expect the spi controller to memory map the flash
- * and for that mapping to be the second register property of the spi
- * controller.
- */
-#define SPI_CTRL DT_PARENT(DT_CHOSEN(zephyr_flash))
-#define ROM_BASE DT_REG_ADDR_BY_IDX(SPI_CTRL, 1)
-#define ROM_SIZE DT_REG_SIZE_BY_IDX(SPI_CTRL, 1)
-#endif
-#else /* CONFIG_XIP */
-#define ROM_BASE CONFIG_SRAM_BASE_ADDRESS
-#define ROM_SIZE KB(CONFIG_SRAM_SIZE)
-#endif /* CONFIG_XIP */
-
-#define RAM_BASE CONFIG_SRAM_BASE_ADDRESS
-#define RAM_SIZE KB(CONFIG_SRAM_SIZE)
-
-#ifdef CONFIG_RISCV_PMP
-	#define MPU_MIN_SIZE CONFIG_PMP_GRANULARITY
-	#define MPU_MIN_SIZE_ALIGN . = ALIGN(MPU_MIN_SIZE);
-	#if defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT)
-		#define MPU_ALIGN(region_size) \
-			. = ALIGN(MPU_MIN_SIZE); \
-			. = ALIGN( 1 << LOG2CEIL(region_size))
-	#else
-		#define MPU_ALIGN(region_size) \
-			. = ALIGN(MPU_MIN_SIZE)
-	#endif
-#else
-	#define MPU_MIN_SIZE_ALIGN
-	#define MPU_ALIGN(region_size) . = ALIGN(4)
-#endif
-
-MEMORY
-{
-#ifdef CONFIG_XIP
-    ROM (rx)  : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE
-#endif
-    RAM (rwx) : ORIGIN = RAM_BASE, LENGTH = RAM_SIZE
-
-    LINKER_DT_REGIONS()
-
-    /* Used by and documented in include/linker/intlist.ld */
-    IDT_LIST  (wx)      : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
-}
-
-ENTRY(CONFIG_KERNEL_ENTRY)
-
-SECTIONS
-    {
-
-#include <zephyr/linker/rel-sections.ld>
-
-#ifdef CONFIG_LLEXT
-#include <zephyr/linker/llext-sections.ld>
-#endif
-
-    /*
-     * The .plt and .iplt are here according to
-     * 'riscv32-zephyr-elf-ld --verbose', before text section.
-     */
-    SECTION_PROLOGUE(.plt,,)
-	{
-		*(.plt)
-	}
-
-    SECTION_PROLOGUE(.iplt,,)
-	{
-		*(.iplt)
-	}
-
-    GROUP_START(ROMABLE_REGION)
-
-    SECTION_PROLOGUE(rom_start,,)
-    {
-		. = ALIGN(16);
-		MPU_ALIGN(__rom_region_size);
-		__rom_region_start = ABSOLUTE(.);
-/* Located in generated directory. This file is populated by calling
- * zephyr_linker_sources(ROM_START ...).
- */
-#include <snippets-rom-start.ld>
-    } GROUP_LINK_IN(ROMABLE_REGION)
-
-#ifdef CONFIG_CODE_DATA_RELOCATION
-#include <linker_relocate.ld>
-#endif
-
-    SECTION_PROLOGUE(_RESET_SECTION_NAME,,)
-    {
-		KEEP(*(.reset.*))
-    } GROUP_LINK_IN(ROMABLE_REGION)
-
-    SECTION_PROLOGUE(_EXCEPTION_SECTION_NAME,,)
-    {
-		 KEEP(*(".exception.entry.*"))
-		 *(".exception.other.*")
-    } GROUP_LINK_IN(ROMABLE_REGION)
-
-    SECTION_PROLOGUE(_TEXT_SECTION_NAME,,)
-	{
-		. = ALIGN(4);
-		KEEP(*(.openocd_debug))
-		KEEP(*(".openocd_debug.*"))
-
-		__text_region_start = .;
-
-		*(.text)
-		*(".text.*")
-		*(.gnu.linkonce.t.*)
-#include <zephyr/linker/kobject-text.ld>
-	} GROUP_LINK_IN(ROMABLE_REGION)
-
-    __text_region_end = .;
-
-	__rodata_region_start = .;
-#include <zephyr/linker/common-rom.ld>
-/* Located in generated directory. This file is populated by calling
- * zephyr_linker_sources(ROM_SECTIONS ...). Useful for grouping iterable RO structs.
- */
-#include <snippets-rom-sections.ld>
-#include <zephyr/linker/thread-local-storage.ld>
-
-    SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
-	{
-		 . = ALIGN(4);
-		 *(.srodata)
-		 *(".srodata.*")
-		 *(.rodata)
-		 *(".rodata.*")
-		 *(.gnu.linkonce.r.*)
-		 *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
-
-/* Located in generated directory. This file is populated by the
- * zephyr_linker_sources() Cmake function.
- */
-#include <snippets-rodata.ld>
-#include <zephyr/linker/kobject-rom.ld>
-	. = ALIGN(4);
-	} GROUP_LINK_IN(ROMABLE_REGION)
-
-#include <zephyr/linker/cplusplus-rom.ld>
-	__rodata_region_end = .;
-
-	/* For non-XIP system, __rom_region_end symbol should be set to
-	 * the end of common ROMABLE_REGIONs (text and rodata) instead of
-	 * the linker script end, so it wouldn't mistakenly contain
-	 * RAMABLE_REGION in it.
-	 */
-#ifndef CONFIG_XIP
-#ifdef CONFIG_RISCV_PMP
-	SECTION_PROLOGUE(rom_mpu_padding,,)
-	{
-		MPU_ALIGN(__rodata_region_end - __rom_region_start);
-	} GROUP_LINK_IN(ROMABLE_REGION)
-#endif /* CONFIG_RISCV_PMP */
-
-	__rom_region_end = .;
-	__rom_region_size = __rom_region_end - __rom_region_start;
-#endif /* CONFIG_XIP */
-    GROUP_END(ROMABLE_REGION)
-
-    GROUP_START(RAMABLE_REGION)
-
-	. = RAM_BASE;
-	_image_ram_start = .;
-
-#ifdef CONFIG_SOC_ANDES_V5_PMA
-#pragma push_macro("MPU_ALIGN")
-#undef MPU_ALIGN
-/* Make linker section alignment comply with PMA granularity. */
-#define MPU_ALIGN(region_size) \
-    . = ALIGN(CONFIG_SOC_ANDES_V5_PMA_REGION_MIN_ALIGN_AND_SIZE); \
-    . = ALIGN( 1 << LOG2CEIL(region_size))
-#endif
-
-/* Located in generated directory. This file is populated by the
- * zephyr_linker_sources() Cmake function.
- */
-#include <snippets-ram-sections.ld>
-
-#ifdef CONFIG_SOC_ANDES_V5_PMA
-#pragma pop_macro("MPU_ALIGN")
-#endif
-
-#if defined(CONFIG_USERSPACE)
-#define APP_SHARED_ALIGN MPU_MIN_SIZE_ALIGN
-#define SMEM_PARTITION_ALIGN MPU_ALIGN
-
-#include <app_smem.ld>
-
-	_app_smem_size = _app_smem_end - _app_smem_start;
-	_app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME);
-#endif /* CONFIG_USERSPACE */
-
-    SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
-	{
-		MPU_MIN_SIZE_ALIGN
-		/*
-		 * For performance, BSS section is assumed to be 4 byte aligned and
-		 * a multiple of 4 bytes
-		 */
-		 . = ALIGN(4);
-		 __bss_start = .;
-		__kernel_ram_start = .;
-		 *(.sbss)
-		 *(".sbss.*")
-		 *(.bss)
-		 *(".bss.*")
-		 COMMON_SYMBOLS
-
-#ifdef CONFIG_CODE_DATA_RELOCATION
-#include <linker_sram_bss_relocate.ld>
-#endif
-
-		 /*
-		  * As memory is cleared in words only, it is simpler to ensure the BSS
-		  * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
-		  */
-		  __bss_end = ALIGN(4);
-	}  GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
-
-#include <zephyr/linker/common-noinit.ld>
-
-    SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
-	{
-		 . = ALIGN(4);
-		/* _image_ram_start = .; */
-		 __data_region_start = .;
-		 __data_start = .;
-
-		 *(.data)
-		 *(".data.*")
-
-#ifdef CONFIG_RISCV_GP
-		/*
-		 * RISC-V architecture has 12-bit signed immediate offsets in the
-		 * instructions. If we can put the most commonly accessed globals
-		 * in a special 4K span of memory addressed by the GP register, then
-		 * we can access those values in a single instruction, saving both
-		 * codespace and runtime.
-		 *
-		 * Since these immediate offsets are signed, place gp 0x800 past the
-		 * beginning of .sdata so that we can use both positive and negative
-		 * offsets.
-		 */
-		 . = ALIGN(8);
-		 PROVIDE (__global_pointer$ = . + 0x800);
-#endif
-
-		 *(.sdata .sdata.* .gnu.linkonce.s.*)
-
-/* Located in generated directory. This file is populated by the
- * zephyr_linker_sources() Cmake function.
- */
-#include <snippets-rwdata.ld>
-
-#ifdef CONFIG_CODE_DATA_RELOCATION
-#include <linker_sram_data_relocate.ld>
-#endif
-
-		 __data_end = .;
-
-	}  GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
-	__data_size = __data_end - __data_start;
-	__data_load_start = LOADADDR(_DATA_SECTION_NAME);
-
-	__data_region_load_start = LOADADDR(_DATA_SECTION_NAME);
-
-#include <zephyr/linker/common-ram.ld>
-#include <zephyr/linker/kobject-data.ld>
-#include <zephyr/linker/cplusplus-ram.ld>
-
-/* Located in generated directory. This file is populated by the
- * zephyr_linker_sources() Cmake function.
- */
-#include <snippets-data-sections.ld>
-
-    __data_region_end = .;
-
-	__kernel_ram_end = .;
-	__kernel_ram_size = __kernel_ram_end - __kernel_ram_start;
-
-#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay)
-GROUP_START(ITCM)
-
-	SECTION_PROLOGUE(_ITCM_SECTION_NAME,,SUBALIGN(8))
-	{
-		__itcm_start = .;
-		*(.itcm)
-		*(".itcm.*")
-
-/* Located in generated directory. This file is populated by the
- * zephyr_linker_sources() Cmake function. */
-#include <snippets-itcm-section.ld>
-
-		__itcm_end = .;
-	} GROUP_LINK_IN(ITCM AT> ROMABLE_REGION)
-
-	__itcm_size = __itcm_end - __itcm_start;
-	__itcm_load_start = LOADADDR(_ITCM_SECTION_NAME);
-
-GROUP_END(ITCM)
-#endif
-
-#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay)
-GROUP_START(DTCM)
-
-	SECTION_PROLOGUE(_DTCM_BSS_SECTION_NAME, (NOLOAD),SUBALIGN(8))
-	{
-		__dtcm_start = .;
-		__dtcm_bss_start = .;
-		*(.dtcm_bss)
-		*(".dtcm_bss.*")
-		__dtcm_bss_end = .;
-	} GROUP_LINK_IN(DTCM)
-
-	SECTION_PROLOGUE(_DTCM_NOINIT_SECTION_NAME, (NOLOAD),SUBALIGN(8))
-	{
-		__dtcm_noinit_start = .;
-		*(.dtcm_noinit)
-		*(".dtcm_noinit.*")
-		__dtcm_noinit_end = .;
-	} GROUP_LINK_IN(DTCM)
-
-	SECTION_PROLOGUE(_DTCM_DATA_SECTION_NAME,,SUBALIGN(8))
-	{
-		__dtcm_data_start = .;
-		*(.dtcm_data)
-		*(".dtcm_data.*")
-
-/* Located in generated directory. This file is populated by the
- * zephyr_linker_sources() Cmake function. */
-#include <snippets-dtcm-section.ld>
-
-		__dtcm_data_end = .;
-	} GROUP_LINK_IN(DTCM AT> ROMABLE_REGION)
-
-	__dtcm_end = .;
-
-	__dtcm_data_load_start = LOADADDR(_DTCM_DATA_SECTION_NAME);
-
-GROUP_END(DTCM)
-#endif
-
-/* Located in generated directory. This file is populated by the
- * zephyr_linker_sources() Cmake function.
- */
-#include <snippets-sections.ld>
-
-#define LAST_RAM_ALIGN MPU_MIN_SIZE_ALIGN
-
-#include <zephyr/linker/ram-end.ld>
-
-    GROUP_END(RAMABLE_REGION)
-
-#include <zephyr/linker/debug-sections.ld>
-
-    /DISCARD/ : { *(.note.GNU-stack) }
-
-    SECTION_PROLOGUE(.riscv.attributes, 0,)
-	{
-	KEEP(*(.riscv.attributes))
-	KEEP(*(.gnu.attributes))
-	}
-
-/* Output section descriptions are needed for these sections to suppress
- * warnings when "--orphan-handling=warn" is set for lld.
- */
-#if defined(CONFIG_LLVM_USE_LLD)
-    SECTION_PROLOGUE(.symtab, 0,) { *(.symtab) }
-    SECTION_PROLOGUE(.strtab, 0,) { *(.strtab) }
-    SECTION_PROLOGUE(.shstrtab, 0,) { *(.shstrtab) }
-#endif
-
-    /* Sections generated from 'zephyr,memory-region' nodes */
-    LINKER_DT_SECTIONS()
-
-#ifdef CONFIG_XIP
-/* Must be last in romable region */
-SECTION_PROLOGUE(.last_section,,)
-{
-  /* .last_section contains a fixed word to ensure location counter and actual
-   * rom region data usage match when CONFIG_LINKER_LAST_SECTION_ID=y. */
-  KEEP(*(.last_section))
-} GROUP_LINK_IN(ROMABLE_REGION)
-
-/* Because ROMABLE_REGION != RAMABLE_REGION in XIP-system, it is valid
- * to set __rom_region_end symbol at the end of linker script and
- * doesn't mistakenly contain the RAMABLE_REGION in it.
- */
-#ifndef CONFIG_RISCV_PMP
-__rom_region_end = LOADADDR(.last_section) + SIZEOF(.last_section);
-#else
-/* Padding __rom_region_end to matches the requirement of the MPU region.
- * __rom_region_size is used to configure the MPU region, but the actual rom
- * region data usage is ends at .last_section.
- */
-SECTION_PROLOGUE(rom_mpu_padding,(NOLOAD),)
-{
-	MPU_ALIGN(__rom_region_size);
-} GROUP_LINK_IN(ROMABLE_REGION)
-__rom_region_end = LOADADDR(rom_mpu_padding) + SIZEOF(rom_mpu_padding);
-#endif /* !CONFIG_RISCV_PMP */
-
-/* To provide the rom region size as a const expression,
- * calculate this value here.
- */
-__rom_region_size = __rom_region_end - __rom_region_start;
-#endif
-
-}
diff --git a/soc/andestech/ae350/common_linker/ram_start_nonzero.ld b/soc/andestech/ae350/ram_start_nonzero.ld
similarity index 100%
rename from soc/andestech/ae350/common_linker/ram_start_nonzero.ld
rename to soc/andestech/ae350/ram_start_nonzero.ld
diff --git a/soc/andestech/ae350/soc.c b/soc/andestech/ae350/soc.c
index 852da6d..58e5afa 100644
--- a/soc/andestech/ae350/soc.c
+++ b/soc/andestech/ae350/soc.c
@@ -4,22 +4,22 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#include "pma.h"
+#include <pma.h>
 
 #ifdef CONFIG_SOC_PER_CORE_INIT_HOOK
 void soc_per_core_init_hook(void)
 {
-#ifdef CONFIG_SOC_ANDES_V5_PMA
+#ifdef CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA
 	pma_init_per_core();
-#endif /* SOC_ANDES_V5_PMA */
+#endif /* CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA */
 }
 #endif /* CONFIG_SOC_PER_CORE_INIT_HOOK */
 
 #ifdef CONFIG_SOC_EARLY_INIT_HOOK
 void soc_early_init_hook(void)
 {
-#ifdef CONFIG_SOC_ANDES_V5_PMA
+#ifdef CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA
 	pma_init();
-#endif /* CONFIG_SOC_ANDES_V5_PMA */
+#endif /* CONFIG_RISCV_CUSTOM_CSR_ANDES_PMA */
 }
 #endif /* CONFIG_SOC_EARLY_INIT_HOOK */
diff --git a/soc/andestech/ae350/soc_context.h b/soc/andestech/ae350/soc_context.h
index 581a1ef..57825f3 100644
--- a/soc/andestech/ae350/soc_context.h
+++ b/soc/andestech/ae350/soc_context.h
@@ -11,33 +11,17 @@
 #ifndef SOC_RISCV_ANDES_V5_SOC_CONTEXT_H_
 #define SOC_RISCV_ANDES_V5_SOC_CONTEXT_H_
 
+#include <csr_context.h>
+
 #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
 
 /* Andes V5 specific registers. */
-#if defined(CONFIG_SOC_ANDES_V5_PFT) && defined(CONFIG_SOC_ANDES_V5_HWDSP)
-	#define SOC_ESF_MEMBERS				\
-		uint32_t mxstatus;			\
-		uint32_t ucode				\
 
-	#define SOC_ESF_INIT				\
-		0,					\
-		0
+#define SOC_ESF_MEMBERS				\
+	CUSTOM_CSR_ESF_MEMBERS
 
-#elif defined(CONFIG_SOC_ANDES_V5_PFT)
-	#define SOC_ESF_MEMBERS				\
-		uint32_t mxstatus
-
-	#define SOC_ESF_INIT				\
-		0
-
-#elif defined(CONFIG_SOC_ANDES_V5_HWDSP)
-	#define SOC_ESF_MEMBERS				\
-		uint32_t ucode
-
-	#define SOC_ESF_INIT				\
-		0
-
-#endif
+#define SOC_ESF_INIT				\
+	CUSTOM_CSR_ESF_INIT
 
 #endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
 
diff --git a/soc/andestech/ae350/soc_irq.S b/soc/andestech/ae350/soc_irq.S
index d5e28d3..7e7a45a 100644
--- a/soc/andestech/ae350/soc_irq.S
+++ b/soc/andestech/ae350/soc_irq.S
@@ -4,10 +4,10 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#include "soc_v5.h"
 
 #include <zephyr/offsets.h>
 #include <zephyr/toolchain.h>
+#include <csr_irq.inc>
 
 #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
 
@@ -17,36 +17,14 @@
 
 SECTION_FUNC(exception.other, __soc_save_context)
 
-#ifdef CONFIG_SOC_ANDES_V5_PFT
-	csrr t0, NDS_MXSTATUS
-#endif
-#ifdef CONFIG_SOC_ANDES_V5_HWDSP
-	csrr t1, NDS_UCODE
-#endif
+	__custom_csr_save_context a0, t0
 
-#ifdef CONFIG_SOC_ANDES_V5_PFT
-	sw t0, __soc_esf_t_mxstatus_OFFSET(a0)
-#endif
-#ifdef CONFIG_SOC_ANDES_V5_HWDSP
-	sw t1, __soc_esf_t_ucode_OFFSET(a0)
-#endif
 	ret
 
 SECTION_FUNC(exception.other, __soc_restore_context)
 
-#ifdef CONFIG_SOC_ANDES_V5_PFT
-	lw t0, __soc_esf_t_mxstatus_OFFSET(a0)
-#endif
-#ifdef CONFIG_SOC_ANDES_V5_HWDSP
-	lw t1, __soc_esf_t_ucode_OFFSET(a0)
-#endif
+	__custom_csr_restore_context a0, t0
 
-#ifdef CONFIG_SOC_ANDES_V5_PFT
-	csrw NDS_MXSTATUS, t0
-#endif
-#ifdef CONFIG_SOC_ANDES_V5_HWDSP
-	csrw NDS_UCODE, t1
-#endif
 	ret
 
 #endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
diff --git a/soc/andestech/ae350/soc_offsets.h b/soc/andestech/ae350/soc_offsets.h
index 5a85144..8c8cf71 100644
--- a/soc/andestech/ae350/soc_offsets.h
+++ b/soc/andestech/ae350/soc_offsets.h
@@ -11,23 +11,13 @@
 #ifndef SOC_RISCV_ANDES_V5_SOC_OFFSETS_H_
 #define SOC_RISCV_ANDES_V5_SOC_OFFSETS_H_
 
+#include <csr_offsets.h>
+
 #ifdef CONFIG_RISCV_SOC_OFFSETS
 
 /* Andes V5 specific registers. */
-#if defined(CONFIG_SOC_ANDES_V5_PFT) && defined(CONFIG_SOC_ANDES_V5_HWDSP)
-	#define GEN_SOC_OFFSET_SYMS()			\
-		GEN_OFFSET_SYM(soc_esf_t, mxstatus);	\
-		GEN_OFFSET_SYM(soc_esf_t, ucode)
-
-#elif defined(CONFIG_SOC_ANDES_V5_PFT)
-	#define GEN_SOC_OFFSET_SYMS()			\
-		GEN_OFFSET_SYM(soc_esf_t, mxstatus)
-
-#elif defined(CONFIG_SOC_ANDES_V5_HWDSP)
-	#define GEN_SOC_OFFSET_SYMS()			\
-		GEN_OFFSET_SYM(soc_esf_t, ucode)
-
-#endif
+#define GEN_SOC_OFFSET_SYMS()			\
+	GEN_CUSTOM_CSR_OFFSET_SYMS()
 
 #endif /* CONFIG_RISCV_SOC_OFFSETS */
 
diff --git a/soc/andestech/ae350/start.S b/soc/andestech/ae350/start.S
deleted file mode 100644
index 9f0ac85..0000000
--- a/soc/andestech/ae350/start.S
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2021 Andes Technology Corporation
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include "soc_v5.h"
-
-#include <zephyr/toolchain.h>
-
-/* exports */
-GTEXT(entry)
-
-SECTION_FUNC(init, entry)
-	/* Disable linker relaxation before GP register initialization. */
-	.option push
-	.option norelax
-
-#ifdef CONFIG_SOC_ANDES_V5_EXECIT
-	/* Initialize EXECIT table */
-	la t0, _ITB_BASE_
-	csrw NDS_UITB, t0
-#endif
-
-#ifdef CONFIG_ICACHE
-	/* Enable I cache with HW prefetcher. */
-	li t0, (1 << 9) | (1 << 0)
-	csrs NDS_MCACHE_CTL, t0
-#endif
-
-#ifdef CONFIG_DCACHE
-	/*
-	 * Enable D cache with HW prefetcher, D-cache write-around
-	 * (threshold: 4 cache lines), and CM (Coherence Manager).
-	 */
-	li t0, (0x3 << 13)
-	csrc NDS_MCACHE_CTL, t0
-	li t0, (1 << 19) | (1 << 13) | (1 << 10) | (1 << 1)
-	csrs NDS_MCACHE_CTL, t0
-
-	/* Check if CPU support CM or not. */
-	csrr t0, NDS_MCACHE_CTL
-	li t1, (1 << 19)
-	and t0, t0, t1
-	beqz t0, cache_enable_finish
-
-	/* If CPU support CM, check if CM is enabled. */
-	li t1, (1 << 20)
-check_cm_enabled:
-	csrr t0, NDS_MCACHE_CTL
-	and t0, t0, t1
-	beqz t0, check_cm_enabled
-
-cache_enable_finish:
-#endif
-
-	/* Enable misaligned access and non-blocking load */
-	li t0, (1 << 8) | (1 << 6)
-	csrs NDS_MMISC_CTL, t0
-
-	j __start
-
-	.option pop