soc: nuvoton: numaker: add poweroff for m46x

Add support of sys_poweroff API on m46x series.
It could support SPD standby or DPD deep power down mode.

Signed-off-by: cyliang tw <cyliang@nuvoton.com>
diff --git a/dts/arm/nuvoton/m46x.dtsi b/dts/arm/nuvoton/m46x.dtsi
index f89523c..cdab366 100644
--- a/dts/arm/nuvoton/m46x.dtsi
+++ b/dts/arm/nuvoton/m46x.dtsi
@@ -54,6 +54,7 @@
 			clk-pclkdiv = <(NUMAKER_CLK_PCLKDIV_APB0DIV_DIV2 |
 					 NUMAKER_CLK_PCLKDIV_APB1DIV_DIV2)>;
 			core-clock = <200000000>;
+			powerdown-mode = <NUMAKER_CLK_PMUCTL_PDMSEL_DPD>;
 
 			pcc: peripheral-clock-controller {
 				compatible = "nuvoton,numaker-pcc";
diff --git a/dts/bindings/clock/nuvoton,numaker-scc.yaml b/dts/bindings/clock/nuvoton,numaker-scc.yaml
index 99ea7ed..b2143e6 100644
--- a/dts/bindings/clock/nuvoton,numaker-scc.yaml
+++ b/dts/bindings/clock/nuvoton,numaker-scc.yaml
@@ -47,3 +47,9 @@
     type: int
     description: |
       Configure core clock (HCLK)
+
+  powerdown-mode:
+    type: int
+    description: |
+      Configure power down mode, please choose one of NUMAKER_CLK_PMUCTL_PDMSEL_XXX
+      from numaker_xxx_clock.h
diff --git a/include/zephyr/dt-bindings/clock/numaker_m46x_clock.h b/include/zephyr/dt-bindings/clock/numaker_m46x_clock.h
index 9243ab7..82deb4d 100644
--- a/include/zephyr/dt-bindings/clock/numaker_m46x_clock.h
+++ b/include/zephyr/dt-bindings/clock/numaker_m46x_clock.h
@@ -1300,4 +1300,10 @@
 
 /* End of M460 BSP clk.h copy */
 
+#define NUMAKER_CLK_PMUCTL_PDMSEL_PD 0x00000000
+#define NUMAKER_CLK_PMUCTL_PDMSEL_LLPD 0x00000001
+#define NUMAKER_CLK_PMUCTL_PDMSEL_FWPD 0x00000002
+#define NUMAKER_CLK_PMUCTL_PDMSEL_SPD 0x00000004
+#define NUMAKER_CLK_PMUCTL_PDMSEL_DPD 0x00000006
+
 #endif
diff --git a/soc/nuvoton/numaker/m46x/CMakeLists.txt b/soc/nuvoton/numaker/m46x/CMakeLists.txt
index 58be053..16544cf 100644
--- a/soc/nuvoton/numaker/m46x/CMakeLists.txt
+++ b/soc/nuvoton/numaker/m46x/CMakeLists.txt
@@ -6,4 +6,6 @@
 
 zephyr_include_directories(.)
 
+zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c)
+
 set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "")
diff --git a/soc/nuvoton/numaker/m46x/Kconfig b/soc/nuvoton/numaker/m46x/Kconfig
index 408b306..3346e1f 100644
--- a/soc/nuvoton/numaker/m46x/Kconfig
+++ b/soc/nuvoton/numaker/m46x/Kconfig
@@ -9,6 +9,7 @@
 	select CPU_HAS_FPU
 	select CPU_HAS_ARM_MPU
 	select CORTEX_M_SYSTICK if SYS_CLOCK_EXISTS
+	select HAS_POWEROFF
 
 config SOC_M467
 	select HAS_NUMAKER_HAL
diff --git a/soc/nuvoton/numaker/m46x/poweroff.c b/soc/nuvoton/numaker/m46x/poweroff.c
new file mode 100644
index 0000000..4854a1d
--- /dev/null
+++ b/soc/nuvoton/numaker/m46x/poweroff.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2024 Nuvoton Technology Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/kernel.h>
+#include <zephyr/devicetree.h>
+#include <zephyr/sys/poweroff.h>
+#include <NuMicro.h>
+
+void z_sys_poweroff(void)
+{
+	SYS_UnlockReg();
+
+	/* Clear all wake-up flag */
+	CLK->PMUSTS |= CLK_PMUSTS_CLRWK_Msk;
+
+	/* Select Power-down mode */
+	CLK_SetPowerDownMode(DT_PROP_OR(DT_NODELABEL(scc), powerdown_mode, CLK_PMUCTL_PDMSEL_SPD));
+
+	/* Enable RTC wake-up */
+	CLK_ENABLE_RTCWK();
+
+	/* Enter to Power-down mode */
+	CLK_PowerDown();
+
+	k_cpu_idle();
+
+	CODE_UNREACHABLE;
+}
diff --git a/soc/nuvoton/numaker/m46x/soc.c b/soc/nuvoton/numaker/m46x/soc.c
index f199312..d62a8bf 100644
--- a/soc/nuvoton/numaker/m46x/soc.c
+++ b/soc/nuvoton/numaker/m46x/soc.c
@@ -16,6 +16,9 @@
 	/* Unlock protected registers */
 	SYS_UnlockReg();
 
+	/* Release I/O hold status */
+	CLK->IOPDCTL = 1;
+
 	/*
 	 * -------------------
 	 * Init System Clock