Преглед изворни кода

bsp: k230: add sysctl driver

SystemCtrl includes:
- boot
- clock
- power
- reset

These drivers are built-in by default.

Signed-off-by: Wang Chen <unicorn_wang@outlook.com>
Wang Chen пре 4 месеци
родитељ
комит
33a719db63

+ 19 - 0
bsp/k230/drivers/interdrv/sysctl/SConscript

@@ -0,0 +1,19 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('Sysctl', src, depend = [''], CPPPATH = CPPPATH)
+
+objs = [group]
+
+file_list = os.listdir(cwd)
+
+for item in file_list:
+    if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
+        objs = objs + SConscript(os.path.join(item, 'SConscript'))
+
+Return('objs')

+ 19 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_boot/SConscript

@@ -0,0 +1,19 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('Sysctl_boot', src, depend = [''], CPPPATH = CPPPATH)
+
+objs = [group]
+
+file_list = os.listdir(cwd)
+
+for item in file_list:
+    if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
+        objs = objs + SConscript(os.path.join(item, 'SConscript'))
+
+Return('objs')

+ 97 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_boot/sysctl_boot.c

@@ -0,0 +1,97 @@
+/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rtthread.h>
+#include "sysctl_boot.h"
+#include "ioremap.h"
+#include "board.h"
+
+volatile sysctl_boot_t* sysctl_boot = (volatile sysctl_boot_t*)BOOT_BASE_ADDR;
+
+sysctl_boot_mode_e sysctl_boot_get_boot_mode(void)
+{
+    switch(sysctl_boot->soc_boot_ctl & 0x3) /* bit 0~1 */
+    {
+        case 1:
+            return SYSCTL_BOOT_NANDFLASH;
+        case 2:
+            return SYSCTL_BOOT_EMMC;
+        case 3:
+            return SYSCTL_BOOT_SDCARD;
+        case 0:
+        default:
+            return SYSCTL_BOOT_NORFLASH;
+    }
+}
+
+bool sysctl_boot_get_otp_bypass(void)
+{
+    if(sysctl_boot->soc_boot_ctl & 0x10)
+        return true;
+    else
+        return false;
+}
+
+void sysctl_boot_set_pll_lock(void)
+{
+    sysctl_boot->soc_boot_ctl |= 1 << 3;
+}
+
+void sysctl_boot_set_spi2axi(void)
+{
+    sysctl_boot->soc_boot_ctl |= 1 << 2;
+}
+
+void sysctl_boot_reset_soc(void)
+{
+    sysctl_boot->soc_glb_rst |= (1 << 0) | (1 << 16);
+    while(1)
+    {
+    }
+}
+
+
+void sysctl_boot_soc_sleep_ctl(void)
+{
+    sysctl_boot->soc_slp_ctl |= (1 << 4) | (1 << 20);
+}
+
+int sysctl_boot_read_is_boot_wakeup(void)
+{
+    return sysctl_boot->soc_wakeup_src;
+}
+
+int rt_hw_sysctl_boot_init(void)
+{
+    sysctl_boot = rt_ioremap((void*)BOOT_BASE_ADDR, BOOT_IO_SIZE);
+    if(!sysctl_boot)
+    {
+        rt_kprintf("sysctl_boot ioremap error\n");
+        return -1;
+    }
+
+    return 0;
+}
+INIT_BOARD_EXPORT(rt_hw_sysctl_boot_init);

+ 96 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_boot/sysctl_boot.h

@@ -0,0 +1,96 @@
+/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SYSCTL_BOOT_H__
+#define __SYSCTL_BOOT_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct pll {
+    volatile uint32_t cfg0;
+    volatile uint32_t cfg1;
+    volatile uint32_t ctl;
+    volatile uint32_t state;
+} pll_t;
+
+/*
+ * pll related registers see TRM 2.2.4 Table 2-2-8
+ * soc_glb_rst: see TRM 2.1.4 Table 2-2-1
+ * Others: see TRM 2.3.4 Table 2-3-2
+ */
+typedef struct sysctl_boot {
+    pll_t pll[4];
+    volatile uint32_t soc_boot_ctl;         /* 0x40 */
+    volatile uint32_t reserved0[7];         /* 0x44 0x48 0x4c 0x50 0x54 0x58 0x5c*/
+    volatile uint32_t soc_glb_rst;          /* 0x60 */
+    volatile uint32_t soc_rst_tim;          /* 0x64 */
+    volatile uint32_t soc_slp_tim;          /* 0x68 */
+    volatile uint32_t soc_slp_ctl;          /* 0x6c */
+    volatile uint32_t clk_stable_tim;       /* 0x70 */
+    volatile uint32_t cpu_wakeup_tim;       /* 0x74 */
+    volatile uint32_t soc_wakeup_src;       /* 0x78 */
+    volatile uint32_t cpu_wakeup_cfg;       /* 0x7c */
+    volatile uint32_t timer_pause_ctl;      /* 0x80 */
+    volatile uint32_t reserved1[3];         /* 0x84 0x88 0x8c */
+    volatile uint32_t sysctl_int0_raw;      /* 0x90 */
+    volatile uint32_t sysctl_int0_en;       /* 0x94 */
+    volatile uint32_t sysctl_int0_state;    /* 0x98 */
+    volatile uint32_t reserved2;            /* 0x9c */
+    volatile uint32_t sysctl_int1_raw;      /* 0xa0 */
+    volatile uint32_t sysctl_int1_en;       /* 0xa4 */
+    volatile uint32_t sysctl_int1_state;    /* 0xa8 */
+    volatile uint32_t reserved3;            /* 0xac */
+    volatile uint32_t sysctl_int2_raw;      /* 0xb0 */
+    volatile uint32_t sysctl_int2_en;       /* 0xb4 */
+    volatile uint32_t sysctl_int2_state;    /* 0xb8 */
+    volatile uint32_t reserved4[17];        /* 0xbc 0xc0-0xcc 0xd0-0xdc 0xe0-0xec 0xf0-0xfc*/
+    volatile uint32_t cpu0_hart_rstvec;     /* 0x100 */
+    volatile uint32_t cpu1_hart_rstvec;     /* 0x104 */
+    volatile uint32_t reserved5[4];         /* 0x108 0x10c 0x110 0x114 */
+    volatile uint32_t soc_sleep_mask;       /* 0x118 */
+} sysctl_boot_t;
+
+
+/* See TRM 1.4.1 Boot media Selection */
+typedef enum
+{
+    SYSCTL_BOOT_NORFLASH    = 0,
+    SYSCTL_BOOT_NANDFLASH   = 1,
+    SYSCTL_BOOT_EMMC        = 2,
+    SYSCTL_BOOT_SDCARD      = 3,
+    SYSCTL_BOOT_MAX,
+} sysctl_boot_mode_e;
+
+sysctl_boot_mode_e sysctl_boot_get_boot_mode(void);
+bool sysctl_boot_get_otp_bypass(void);
+void sysctl_boot_set_pll_lock(void);
+void sysctl_boot_set_spi2axi(void);
+void sysctl_boot_reset_soc(void);
+
+int sysctl_boot_read_is_boot_wakeup(void);
+void sysctl_boot_soc_sleep_ctl(void);
+
+#endif

+ 19 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_clock/SConscript

@@ -0,0 +1,19 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('Sysctl_clock', src, depend = [''], CPPPATH = CPPPATH)
+
+objs = [group]
+
+file_list = os.listdir(cwd)
+
+for item in file_list:
+    if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
+        objs = objs + SConscript(os.path.join(item, 'SConscript'))
+
+Return('objs')

+ 3470 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_clock/sysctl_clk.c

@@ -0,0 +1,3470 @@
+/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rtthread.h>
+#include <stdlib.h>
+#include <math.h>
+#include "sysctl_boot.h"
+#include "sysctl_clk.h"
+#include "ioremap.h"
+#include "board.h"
+
+/* created by yangfan */
+/* please refer to the sysctl_clk.h file for API description */
+
+#define OSC_CLOCK_FREQ_24M (24000000)
+#define TIMER_PULSE_IN (50000000)
+
+extern volatile sysctl_boot_t *sysctl_boot;
+volatile sysctl_clk_t* sysctl_clk = (volatile sysctl_clk_t*)CMU_BASE_ADDR;
+/* volatile sysctl_clk_attr_t *sysctl_attr; */
+
+/* Determine the properties of clk. */
+int sysctl_clk_attribute(sysctl_clk_node_e clk)
+{
+    switch(clk)
+    {
+        /*--------------------------- ROOT CLOCK: OSC24M, PLL0-3 ------------------------------------*/
+        case SYSCTL_CLK_ROOT_OSC_IN:
+        case SYSCTL_CLK_ROOT_TIMERX_PULSE_IN:
+        case SYSCTL_CLK_ROOT_PLL0:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_4:
+        case SYSCTL_CLK_ROOT_PLL1:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_4:
+        case SYSCTL_CLK_ROOT_PLL2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_4:
+        case SYSCTL_CLK_ROOT_PLL3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_4:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- CPU0 CLOCK ------------------------------------*/
+        case SYSCTL_CLK_CPU0_SRC:
+        case SYSCTL_CLK_CPU0_PLIC:
+        case SYSCTL_CLK_CPU0_ACLK:
+        case SYSCTL_CLK_CPU0_NOC_DDRCP4:
+        case SYSCTL_CLK_CPU0_PCLK:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- PMU CLOCK ------------------------------------*/
+        case SYSCTL_CLK_PMU_PCLK:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- HS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_HS_HCLK_HIGH_SRC:
+        case SYSCTL_CLK_HS_HCLK_HIGH_GATE:
+        case SYSCTL_CLK_HS_HCLK_SRC:
+        case SYSCTL_CLK_SD0_AHB_GATE:
+        case SYSCTL_CLK_SD1_AHB_GATE:
+        case SYSCTL_CLK_USB0_AHB_GATE:
+        case SYSCTL_CLK_USB1_AHB_GATE:
+        case SYSCTL_CLK_SSI1_AHB_GATE:
+        case SYSCTL_CLK_SSI2_AHB_GATE:
+
+        case SYSCTL_CLK_SSI0_AXI:
+        case SYSCTL_CLK_SSI1:
+        case SYSCTL_CLK_SSI2:
+        case SYSCTL_CLK_QSPI_AXI_SRC:
+        case SYSCTL_CLK_SSI1_ACLK_GATE:
+        case SYSCTL_CLK_SSI2_ACLK_GATE:
+
+        case SYSCTL_CLK_SSI0:
+
+        case SYSCTL_CLK_SD_AXI_SRC:
+        case SYSCTL_CLK_SD0_AXI_GATE:
+        case SYSCTL_CLK_SD1_AXI_GATE:
+        case SYSCTL_CLK_SD0_BASE_GATE:
+        case SYSCTL_CLK_SD1_BASE_GATE:
+
+        case SYSCTL_CLK_SD_CARD_SRC:
+        case SYSCTL_CLK_SD0_CARD_GATE:
+        case SYSCTL_CLK_SD1_CARD_GATE:
+
+        case SYSCTL_CLK_PLL0_DIV16:
+        case SYSCTL_CLK_USB_REF_50M:
+        case SYSCTL_CLK_USB0_REF_GATE:
+        case SYSCTL_CLK_USB1_REF_GATE:
+
+        case SYSCTL_CLK_SD_TIMER_SRC:
+        case SYSCTL_CLK_SD0_TIMER_GATE:
+        case SYSCTL_CLK_SD1_TIMER_GATE:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- LS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_LS_APB_SRC:
+        case SYSCTL_CLK_UART0_APB_GATE:
+        case SYSCTL_CLK_UART1_APB_GATE:
+        case SYSCTL_CLK_UART2_APB_GATE:
+        case SYSCTL_CLK_UART3_APB_GATE:
+        case SYSCTL_CLK_UART4_APB_GATE:
+        case SYSCTL_CLK_I2C0_APB_GATE:
+        case SYSCTL_CLK_I2C1_APB_GATE:
+        case SYSCTL_CLK_I2C2_APB_GATE:
+        case SYSCTL_CLK_I2C3_APB_GATE:
+        case SYSCTL_CLK_I2C4_APB_GATE:
+        case SYSCTL_CLK_GPIO_APB_GATE:
+        case SYSCTL_CLK_PWM_APB_GATE:
+        case SYSCTL_CLK_JAMLINK0_APB_GATE:
+        case SYSCTL_CLK_JAMLINK1_APB_GATE:
+        case SYSCTL_CLK_JAMLINK2_APB_GATE:
+        case SYSCTL_CLK_JAMLINK3_APB_GATE:
+        case SYSCTL_CLK_ADC_APB_GATE:
+
+        case SYSCTL_CLK_UART0_CORE:
+        case SYSCTL_CLK_UART1_CORE:
+        case SYSCTL_CLK_UART2_CORE:
+        case SYSCTL_CLK_UART3_CORE:
+        case SYSCTL_CLK_UART4_CORE:
+
+        case SYSCTL_CLK_JAMLINK_CO_DIV:
+        case SYSCTL_CLK_JAMLINK0_CO_GATE:
+        case SYSCTL_CLK_JAMLINK1_CO_GATE:
+        case SYSCTL_CLK_JAMLINK2_CO_GATE:
+        case SYSCTL_CLK_JAMLINK3_CO_GATE:
+
+        case SYSCTL_CLK_I2C0_CORE:
+        case SYSCTL_CLK_I2C1_CORE:
+        case SYSCTL_CLK_I2C2_CORE:
+        case SYSCTL_CLK_I2C3_CORE:
+        case SYSCTL_CLK_I2C4_CORE:
+
+        case SYSCTL_CLK_ADC:
+        case SYSCTL_CLK_GOIP_DEBOUNCE:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- SYSCTL CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SYSCTRL_APB_SRC:
+        case SYSCTL_CLK_WDT0_APB_GATE:
+        case SYSCTL_CLK_WDT1_APB_GATE:
+        case SYSCTL_CLK_TIMER_APB_GATE:
+        case SYSCTL_CLK_IOMUX_APB_GATE:
+        case SYSCTL_CLK_MAILBOX_APB_GATE:
+
+        case SYSCTL_CLK_HDI_CORE:
+
+        case SYSCTL_CLK_TIMESTAMP:
+
+        case SYSCTL_CLK_TEMP_SENSOR:
+
+        case SYSCTL_CLK_WDT0:
+        case SYSCTL_CLK_WDT1:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- TIMER CLOCK ------------------------------------*/
+        case SYSCTL_CLK_TIMERX_PULSE_IN:
+        case SYSCTL_CLK_TIMER0_SRC:
+        case SYSCTL_CLK_TIMER0:
+        case SYSCTL_CLK_TIMER1_SRC:
+        case SYSCTL_CLK_TIMER1:
+        case SYSCTL_CLK_TIMER2_SRC:
+        case SYSCTL_CLK_TIMER2:
+        case SYSCTL_CLK_TIMER3_SRC:
+        case SYSCTL_CLK_TIMER3:
+        case SYSCTL_CLK_TIMER4_SRC:
+        case SYSCTL_CLK_TIMER4:
+        case SYSCTL_CLK_TIMER5_SRC:
+        case SYSCTL_CLK_TIMER5:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- SHRM CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SHRM_SRC:
+        case SYSCTL_CLK_SHRM_DIV2:
+        case SYSCTL_CLK_SHRM_AXIS_SLAVE:
+        case SYSCTL_CLK_DECOMPRESS_AXI:
+
+        case SYSCTL_CLK_SHRM_APB:
+
+        case SYSCTL_CLK_SHRM_AXI_SRC:
+        case SYSCTL_CLK_NONAI2D_AXI_GATE:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- SEC CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SEC_APB:
+        case SYSCTL_CLK_SEC_FIX:
+
+        case SYSCTL_CLK_SEC_AXI:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- USB TEST MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_USB_480M:
+        case SYSCTL_CLK_USB_100M:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- DPHY DFT MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_DPHY_DFT_MODE:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        /*--------------------------- SPI2AXI CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SPI2AXI_AXI:
+        {
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+        }
+
+        default:
+            return SYSCTL_READ_ENABLE | SYSCTL_WRITE_ENABLE;
+    }
+}
+
+/*
+ * API of root node
+ * If PLL bypass, the output clock is 24m clock.
+ * If there is no bypass, the clock comes from PLL
+ */
+bool sysctl_boot_get_root_clk_bypass(sysctl_clk_node_e clk)
+{
+    switch(clk)
+    {
+        case SYSCTL_CLK_ROOT_PLL0:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_4:
+            return ((sysctl_boot->pll[0].cfg1 >> 19) & 0x1) ? true:false;
+
+        case SYSCTL_CLK_ROOT_PLL1:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_4:
+            return ((sysctl_boot->pll[1].cfg1 >> 19) & 0x1) ? true:false;
+
+        case SYSCTL_CLK_ROOT_PLL2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_4:
+            return ((sysctl_boot->pll[2].cfg1 >> 19) & 0x1) ? true:false;
+
+        case SYSCTL_CLK_ROOT_PLL3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_4:
+            return ((sysctl_boot->pll[3].cfg1 >> 19) & 0x1) ? true:false;
+
+        default:
+            return false;
+    }
+}
+
+/* if PLL bypass, the output clock is 24m clock. If there is no bypass, the clock comes from PLL */
+void sysctl_boot_set_root_clk_bypass(sysctl_clk_node_e clk, bool enable)
+{
+    volatile uint32_t ret;
+
+    switch(clk)
+    {
+        case SYSCTL_CLK_ROOT_PLL0:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_4:
+            if(true == enable)  /* enable bypass */
+            {
+                sysctl_boot->pll[0].cfg1 |= (1 << 19);
+            }
+            else
+            {
+                sysctl_boot->pll[0].cfg1 &= ~(1 << 19);
+            }
+            return;
+
+        case SYSCTL_CLK_ROOT_PLL1:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_4:
+            if(true == enable)  /* enable bypass */
+            {
+                sysctl_boot->pll[1].cfg1 |= (1 << 19);
+            }
+            else
+            {
+                sysctl_boot->pll[1].cfg1 &= ~(1 << 19);
+            }
+            return;
+
+        case SYSCTL_CLK_ROOT_PLL2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_4:
+            if(true == enable)  /* enable bypass */
+            {
+                sysctl_boot->pll[2].cfg1 |= (1 << 19);
+            }
+            else
+            {
+                sysctl_boot->pll[2].cfg1 &= ~(1 << 19);
+            }
+            return;
+
+        case SYSCTL_CLK_ROOT_PLL3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_4:
+            if(true == enable)  /* enable bypass */
+            {
+                sysctl_boot->pll[3].cfg1 |= (1 << 19);
+            }
+            else
+            {
+                sysctl_boot->pll[3].cfg1 &= ~(1 << 19);
+            }
+            return;
+
+        default:
+            return;
+    }
+}
+
+/* Get enable/disable state of PLL output clock */
+bool sysctl_boot_get_root_clk_en(sysctl_clk_node_e clk)
+{
+    switch(clk)
+    {
+        case SYSCTL_CLK_ROOT_PLL0:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_4:
+            return ((sysctl_boot->pll[0].ctl >> 2) & 0x1) ? true:false;
+
+        case SYSCTL_CLK_ROOT_PLL1:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_4:
+            return ((sysctl_boot->pll[1].ctl >> 2) & 0x1) ? true:false;
+
+        case SYSCTL_CLK_ROOT_PLL2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_4:
+            return ((sysctl_boot->pll[2].ctl >> 2) & 0x1) ? true:false;
+
+        case SYSCTL_CLK_ROOT_PLL3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_4:
+            return ((sysctl_boot->pll[3].ctl >> 2) & 0x1) ? true:false;
+
+        default:
+            return false;
+    }
+}
+
+/* Enable PLL output clock */
+void sysctl_boot_set_root_clk_en(sysctl_clk_node_e clk, bool enable)
+{
+    switch(clk)
+    {
+        case SYSCTL_CLK_ROOT_PLL0:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_4:
+            if(true == enable)
+            {
+                sysctl_boot->pll[0].ctl |= (1 << 2) | (1 << 18);     /* enable pll */
+            }
+
+            return;
+
+        case SYSCTL_CLK_ROOT_PLL1:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_4:
+            if(true == enable)
+            {
+                sysctl_boot->pll[1].ctl |= (1 << 2) | (1 << 18);     /* enable pll */
+            }
+
+            return;
+
+        case SYSCTL_CLK_ROOT_PLL2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_4:
+            if(true == enable)
+            {
+                sysctl_boot->pll[2].ctl |= (1 << 2) | (1 << 18);     /* enable pll */
+            }
+
+            return;
+
+        case SYSCTL_CLK_ROOT_PLL3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_4:
+            if(true == enable)
+            {
+                sysctl_boot->pll[3].ctl |= (1 << 2) | (1 << 18);     /* enable pll */
+            }
+
+            return;
+
+        default:
+            return;
+    }
+}
+
+/* PLL power supply */
+bool sysctl_boot_set_root_clk_pwroff(sysctl_clk_node_e clk)
+{
+    switch(clk)
+    {
+        case SYSCTL_CLK_ROOT_PLL0:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_4:
+            sysctl_boot->pll[0].ctl |= (1 << 0)|(1 << 16);
+            return true;
+
+        case SYSCTL_CLK_ROOT_PLL1:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_4:
+            sysctl_boot->pll[1].ctl |= (1 << 0)|(1 << 16);
+            return true;
+
+        case SYSCTL_CLK_ROOT_PLL2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_4:
+            sysctl_boot->pll[2].ctl |= (1 << 0)|(1 << 16);
+            return true;
+
+        case SYSCTL_CLK_ROOT_PLL3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_4:
+            sysctl_boot->pll[3].ctl |= (1 << 0)|(1 << 16);
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+/* Check the lock state of PLL. */
+bool sysctl_boot_get_root_clk_lock(sysctl_clk_node_e clk)
+{
+    switch(clk)
+    {
+        case SYSCTL_CLK_ROOT_PLL0:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_4:
+            return ((sysctl_boot->pll[0].state >> 0) & 0x1) ? true:false;
+
+        case SYSCTL_CLK_ROOT_PLL1:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_4:
+            return ((sysctl_boot->pll[1].state >> 0) & 0x1) ? true:false;
+
+        case SYSCTL_CLK_ROOT_PLL2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_4:
+            return ((sysctl_boot->pll[2].state >> 0) & 0x1) ? true:false;
+
+        case SYSCTL_CLK_ROOT_PLL3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_4:
+            return ((sysctl_boot->pll[3].state >> 0) & 0x1) ? true:false;
+
+        default:
+            return true;
+    }
+}
+
+/*
+ * Get PLL output frequency.
+ * freq = (double)OSC_CLOCK_FREQ_24M * (double)(fbdiv+1) / (double)(refdiv+1) / (double)(outdiv+1)
+ */
+uint32_t sysctl_boot_get_root_clk_freq(sysctl_clk_node_e clk)
+{
+    uint32_t refdiv;    /* reference clock divide */
+    uint32_t outdiv;    /* output clock divide */
+    uint32_t fbdiv;     /* feedback clock divide */
+    uint32_t freq;
+
+    switch(clk)
+    {
+        case SYSCTL_CLK_ROOT_OSC_IN:
+            return OSC_CLOCK_FREQ_24M;  /* 24MHz */
+
+        case SYSCTL_CLK_ROOT_TIMERX_PULSE_IN:
+            return TIMER_PULSE_IN;      /* 50MHz */
+
+        case SYSCTL_CLK_ROOT_PLL0:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL0_DIV_4:
+        {
+            if(true == sysctl_boot_get_root_clk_bypass(clk))
+            {
+                freq = OSC_CLOCK_FREQ_24M;
+            }
+            else
+            {
+                refdiv = (sysctl_boot->pll[0].cfg0 >> 16) & 0x3F;    /* bit 16~21 */
+                outdiv = (sysctl_boot->pll[0].cfg0 >> 24) & 0xF;     /* bit 24~27 */
+                fbdiv  = (sysctl_boot->pll[0].cfg0 >> 0)  & 0x1FFF;   /* bit 0~12 */
+                freq = (double)OSC_CLOCK_FREQ_24M * (double)(fbdiv+1) / (double)(refdiv+1) / (double)(outdiv+1);
+            }
+            switch(clk)
+            {
+                case SYSCTL_CLK_ROOT_PLL0:
+                    return freq;
+                case SYSCTL_CLK_ROOT_PLL0_DIV_2:
+                    return freq/2;
+                case SYSCTL_CLK_ROOT_PLL0_DIV_3:
+                    return freq/3;
+                default:
+                    return freq/4;
+            }
+        }
+
+        case SYSCTL_CLK_ROOT_PLL1:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL1_DIV_4:
+        {
+            if(true == sysctl_boot_get_root_clk_bypass(clk))
+            {
+                freq = OSC_CLOCK_FREQ_24M;
+            }
+            else
+            {
+                refdiv = (sysctl_boot->pll[1].cfg0 >> 16) & 0x3F;    /* bit 16~21 */
+                outdiv = (sysctl_boot->pll[1].cfg0 >> 24) & 0xF;     /* bit 24~27 */
+                fbdiv  = (sysctl_boot->pll[1].cfg0 >> 0)  & 0x1FFF;   /* bit 0~12 */
+                freq = (double)OSC_CLOCK_FREQ_24M * (double)(fbdiv+1) / (double)(refdiv+1) / (double)(outdiv+1);
+            }
+            switch(clk)
+            {
+                case SYSCTL_CLK_ROOT_PLL1:
+                    return freq;
+                case SYSCTL_CLK_ROOT_PLL1_DIV_2:
+                    return freq/2;
+                case SYSCTL_CLK_ROOT_PLL1_DIV_3:
+                    return freq/3;
+                default:
+                    return freq/4;
+            }
+        }
+
+        case SYSCTL_CLK_ROOT_PLL2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL2_DIV_4:
+        {
+            if(true == sysctl_boot_get_root_clk_bypass(clk))
+            {
+                freq = OSC_CLOCK_FREQ_24M;
+            }
+            else
+            {
+                refdiv = (sysctl_boot->pll[2].cfg0 >> 16) & 0x3F;    /* bit 16~21 */
+                outdiv = (sysctl_boot->pll[2].cfg0 >> 24) & 0xF;     /* bit 24~27 */
+                fbdiv  = (sysctl_boot->pll[2].cfg0 >> 0)  & 0x1FFF;   /* bit 0~12 */
+                freq = (double)OSC_CLOCK_FREQ_24M * (double)(fbdiv+1) / (double)(refdiv+1) / (double)(outdiv+1);
+            }
+            switch(clk)
+            {
+                case SYSCTL_CLK_ROOT_PLL2:
+                    return freq;
+                case SYSCTL_CLK_ROOT_PLL2_DIV_2:
+                    return freq/2;
+                case SYSCTL_CLK_ROOT_PLL2_DIV_3:
+                    return freq/3;
+                default:
+                    return freq/4;
+            }
+        }
+
+        case SYSCTL_CLK_ROOT_PLL3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_2:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_3:
+        case SYSCTL_CLK_ROOT_PLL3_DIV_4:
+        {
+            if(true == sysctl_boot_get_root_clk_bypass(clk))
+            {
+                freq = OSC_CLOCK_FREQ_24M;
+            }
+            else
+            {
+                refdiv = (sysctl_boot->pll[3].cfg0 >> 16) & 0x3F;    /* bit 16~21 */
+                outdiv = (sysctl_boot->pll[3].cfg0 >> 24) & 0xF;     /* bit 24~27 */
+                fbdiv  = (sysctl_boot->pll[3].cfg0 >> 0)  & 0x1FFF;   /* bit 0~12 */
+                freq = (double)OSC_CLOCK_FREQ_24M * (double)(fbdiv+1) / (double)(refdiv+1) / (double)(outdiv+1);
+            }
+            switch(clk)
+            {
+                case SYSCTL_CLK_ROOT_PLL3:
+                    return freq;
+                case SYSCTL_CLK_ROOT_PLL3_DIV_2:
+                    return freq/2;
+                case SYSCTL_CLK_ROOT_PLL3_DIV_3:
+                    return freq/3;
+                default:
+                    return freq/4;
+            }
+        }
+
+        default:
+            return 0;
+    }
+}
+
+/*
+ * Set the frequency of the PLL.
+ * Please configure the PLL frequency according to the above frequency division coefficient.
+ * Note: when configuring, you can't configure yourself. For example, the PLL
+ * attached to CPU can't stop before configuring the PLL of CPU, switch the
+ * clock first and then configure it. After configuration, switch it back.
+ */
+bool sysctl_boot_set_root_clk_freq(sysctl_clk_node_e clk, uint32_t fbdiv, uint32_t refdiv, uint32_t outdiv, uint32_t bwadj)
+{
+    uint32_t id;
+    uint32_t wait_us = 100;
+    volatile uint32_t ret;
+
+    if(SYSCTL_CLK_ROOT_PLL0 == clk)
+        id = 0;
+    else if(SYSCTL_CLK_ROOT_PLL1 == clk)
+        id = 1;
+    else if(SYSCTL_CLK_ROOT_PLL2 == clk)
+        id = 2;
+    else if(SYSCTL_CLK_ROOT_PLL3 == clk)
+        id = 3;
+    else
+        return false;
+
+    /*
+     * According to the k230 TRM manual, the configuration steps of PLL are
+     * as follows:
+     * 1. Configure PLLx_CTL.pllx_pwrdwn=1,close PLL output;
+     * 2. Configure PLL param PLLx_CFG0 and PLLx_CFG1;
+     * 3. Configure PLLx_CTL.pllx_init,The hardware will wait for the PLL to
+     *    automatically lock and turn on the PLL output.
+     */
+
+    /* 1. poweroff pll */
+    (void)sysctl_boot_set_root_clk_pwroff(clk);
+
+    /* 2. config divide */
+    sysctl_boot->pll[id].cfg0 = ((fbdiv &  0x1FFF) << 0) | ((refdiv &  0x3F) << 16) | ((outdiv & 0xF) << 24);
+    ret = sysctl_boot->pll[id].cfg1;
+    ret &= 0xfffff000;
+    sysctl_boot->pll[id].cfg1 = ret | ((bwadj & 0xfff) << 0);
+
+    /* 3. init pll. init will pwrup pll */
+    sysctl_boot->pll[id].ctl |= (1 << 1)|(1 << 17);
+
+    /* 4. check lock status */
+    while(1)
+    {
+        if(false == sysctl_boot_get_root_clk_lock(clk))
+        {
+            wait_us --;
+            if(wait_us == 0)
+                return false;
+        }
+        else
+            return true;
+    }
+}
+
+
+/*
+ * API of trunk and leaf node
+ */
+bool sysctl_clk_set_leaf_parent(sysctl_clk_node_e leaf, sysctl_clk_node_e parent)
+{
+    volatile uint32_t ret;
+
+    switch(sysctl_clk_attribute(leaf))
+    {
+        case 0:
+        case 1:
+            return false;
+        case 3:
+            break;
+    }
+
+    switch(leaf)
+    {
+        /*--------------------------- CPU0 CLOCK ------------------------------------*/
+        case SYSCTL_CLK_CPU0_SRC:
+        case SYSCTL_CLK_CPU0_PLIC:
+        case SYSCTL_CLK_CPU0_ACLK:
+        case SYSCTL_CLK_CPU0_NOC_DDRCP4:
+            return false;       /* always pll0_div2 */
+        case SYSCTL_CLK_CPU0_PCLK:
+            return false;       /* always pll0_div4 */
+
+        /*--------------------------- PMU CLOCK ------------------------------------*/
+        case SYSCTL_CLK_PMU_PCLK:
+            return false;       /* always osc24m */
+
+        /*--------------------------- HS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_HS_HCLK_HIGH_SRC:
+        case SYSCTL_CLK_HS_HCLK_HIGH_GATE:
+        case SYSCTL_CLK_HS_HCLK_SRC:
+        case SYSCTL_CLK_SD0_AHB_GATE:
+        case SYSCTL_CLK_SD1_AHB_GATE:
+        case SYSCTL_CLK_USB0_AHB_GATE:
+        case SYSCTL_CLK_USB1_AHB_GATE:
+        case SYSCTL_CLK_SSI1_AHB_GATE:
+        case SYSCTL_CLK_SSI2_AHB_GATE:
+            return false;       /* always pll0_div4 */
+
+        case SYSCTL_CLK_SSI0_AXI:
+        case SYSCTL_CLK_SSI1:
+        case SYSCTL_CLK_SSI2:
+        case SYSCTL_CLK_QSPI_AXI_SRC:
+        case SYSCTL_CLK_SSI1_ACLK_GATE:
+        case SYSCTL_CLK_SSI2_ACLK_GATE:
+            return false;       /* always pll0_div4 */
+
+        case SYSCTL_CLK_SSI0:
+        {
+            if(SYSCTL_CLK_ROOT_PLL0_DIV_2 == parent)
+            {
+                ret = sysctl_clk->hs_spi_cfg;
+                ret &= 0xfffbffff;
+                sysctl_clk->hs_spi_cfg = ret | (0 << 18);
+                return true;
+            }
+            else if(SYSCTL_CLK_ROOT_PLL2_DIV_4 == parent)
+            {
+                ret = sysctl_clk->hs_spi_cfg;
+                ret &= 0xfffbffff;
+                sysctl_clk->hs_spi_cfg = ret | (1 << 18);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        case SYSCTL_CLK_SD_AXI_SRC:
+        case SYSCTL_CLK_SD0_AXI_GATE:
+        case SYSCTL_CLK_SD1_AXI_GATE:
+        case SYSCTL_CLK_SD0_BASE_GATE:
+        case SYSCTL_CLK_SD1_BASE_GATE:
+            return false;
+
+        case SYSCTL_CLK_SD_CARD_SRC:
+        case SYSCTL_CLK_SD0_CARD_GATE:
+        case SYSCTL_CLK_SD1_CARD_GATE:
+            return false;
+
+        case SYSCTL_CLK_PLL0_DIV16:
+            return false;
+        case SYSCTL_CLK_USB_REF_50M:
+            return false;
+        case SYSCTL_CLK_USB0_REF_GATE:
+        case SYSCTL_CLK_USB1_REF_GATE:
+        {
+            if(SYSCTL_CLK_ROOT_OSC_IN == parent)
+            {
+                ret = sysctl_clk->hs_clken_cfg;
+                ret &= 0xff7fffff;
+                sysctl_clk->hs_clken_cfg = ret | (0 << 23);
+                return true;
+            }
+            else if(SYSCTL_CLK_USB_REF_50M == parent)
+            {
+                ret = sysctl_clk->hs_clken_cfg;
+                ret &= 0xff7fffff;
+                sysctl_clk->hs_clken_cfg = ret | (1 << 23);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        case SYSCTL_CLK_SD_TIMER_SRC:
+        case SYSCTL_CLK_SD0_TIMER_GATE:
+        case SYSCTL_CLK_SD1_TIMER_GATE:
+            return false;
+
+        /*--------------------------- LS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_LS_APB_SRC:
+        case SYSCTL_CLK_UART0_APB_GATE:
+        case SYSCTL_CLK_UART1_APB_GATE:
+        case SYSCTL_CLK_UART2_APB_GATE:
+        case SYSCTL_CLK_UART3_APB_GATE:
+        case SYSCTL_CLK_UART4_APB_GATE:
+        case SYSCTL_CLK_I2C0_APB_GATE:
+        case SYSCTL_CLK_I2C1_APB_GATE:
+        case SYSCTL_CLK_I2C2_APB_GATE:
+        case SYSCTL_CLK_I2C3_APB_GATE:
+        case SYSCTL_CLK_I2C4_APB_GATE:
+        case SYSCTL_CLK_GPIO_APB_GATE:
+        case SYSCTL_CLK_PWM_APB_GATE:
+        case SYSCTL_CLK_JAMLINK0_APB_GATE:
+        case SYSCTL_CLK_JAMLINK1_APB_GATE:
+        case SYSCTL_CLK_JAMLINK2_APB_GATE:
+        case SYSCTL_CLK_JAMLINK3_APB_GATE:
+        case SYSCTL_CLK_ADC_APB_GATE:
+            return false;
+
+        case SYSCTL_CLK_UART0_CORE:
+        case SYSCTL_CLK_UART1_CORE:
+        case SYSCTL_CLK_UART2_CORE:
+        case SYSCTL_CLK_UART3_CORE:
+        case SYSCTL_CLK_UART4_CORE:
+            return false;
+
+        case SYSCTL_CLK_JAMLINK_CO_DIV:
+        case SYSCTL_CLK_JAMLINK0_CO_GATE:
+        case SYSCTL_CLK_JAMLINK1_CO_GATE:
+        case SYSCTL_CLK_JAMLINK2_CO_GATE:
+        case SYSCTL_CLK_JAMLINK3_CO_GATE:
+            return false;
+
+        case SYSCTL_CLK_I2C0_CORE:
+        case SYSCTL_CLK_I2C1_CORE:
+        case SYSCTL_CLK_I2C2_CORE:
+        case SYSCTL_CLK_I2C3_CORE:
+        case SYSCTL_CLK_I2C4_CORE:
+            return false;
+
+        case SYSCTL_CLK_ADC:
+            return false;
+
+        case SYSCTL_CLK_GOIP_DEBOUNCE:
+            return false;
+
+        /*--------------------------- SYSCTL CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SYSCTRL_APB_SRC:
+        case SYSCTL_CLK_WDT0_APB_GATE:
+        case SYSCTL_CLK_WDT1_APB_GATE:
+        case SYSCTL_CLK_TIMER_APB_GATE:
+        case SYSCTL_CLK_IOMUX_APB_GATE:
+        case SYSCTL_CLK_MAILBOX_APB_GATE:
+            return false;
+
+        case SYSCTL_CLK_HDI_CORE:
+            return false;
+
+        case SYSCTL_CLK_TIMESTAMP:
+            return false;
+
+        case SYSCTL_CLK_TEMP_SENSOR:
+        case SYSCTL_CLK_WDT0:
+        case SYSCTL_CLK_WDT1:
+            return false;
+
+        /*--------------------------- TIMER CLOCK ------------------------------------*/
+        case SYSCTL_CLK_TIMERX_PULSE_IN:
+            return false;
+        case SYSCTL_CLK_TIMER0_SRC:
+            return false;
+        case SYSCTL_CLK_TIMER0:
+        {
+            if(SYSCTL_CLK_TIMER0_SRC == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xffffff7f;
+                sysctl_clk->sysctl_clken_cfg = ret | (0 << 7);
+                return true;
+            }
+            else if(SYSCTL_CLK_TIMERX_PULSE_IN == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xffffff7f;
+                sysctl_clk->sysctl_clken_cfg = ret | (1 << 7);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        case SYSCTL_CLK_TIMER1_SRC:
+            return false;
+        case SYSCTL_CLK_TIMER1:
+        {
+            if(SYSCTL_CLK_TIMER1_SRC == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xfffffeff;
+                sysctl_clk->sysctl_clken_cfg = ret | (0 << 8);
+                return true;
+            }
+            else if(SYSCTL_CLK_TIMERX_PULSE_IN == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xfffffeff;
+                sysctl_clk->sysctl_clken_cfg = ret | (1 << 8);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        case SYSCTL_CLK_TIMER2_SRC:
+            return false;
+        case SYSCTL_CLK_TIMER2:
+        {
+            if(SYSCTL_CLK_TIMER2_SRC == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xfffffdff;
+                sysctl_clk->sysctl_clken_cfg = ret | (0 << 9);
+                return true;
+            }
+            else if(SYSCTL_CLK_TIMERX_PULSE_IN == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xfffffdff;
+                sysctl_clk->sysctl_clken_cfg = ret | (1 << 9);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        case SYSCTL_CLK_TIMER3_SRC:
+            return false;
+        case SYSCTL_CLK_TIMER3:
+        {
+            if(SYSCTL_CLK_TIMER3_SRC == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xfffffbff;
+                sysctl_clk->sysctl_clken_cfg = ret | (0 << 10);
+                return true;
+            }
+            else if(SYSCTL_CLK_TIMERX_PULSE_IN == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xfffffbff;
+                sysctl_clk->sysctl_clken_cfg = ret | (1 << 10);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        case SYSCTL_CLK_TIMER4_SRC:
+            return false;
+        case SYSCTL_CLK_TIMER4:
+        {
+            if(SYSCTL_CLK_TIMER4_SRC == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xfffff7ff;
+                sysctl_clk->sysctl_clken_cfg = ret | (0 << 11);
+                return true;
+            }
+            else if(SYSCTL_CLK_TIMERX_PULSE_IN == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xfffff7ff;
+                sysctl_clk->sysctl_clken_cfg = ret | (1 << 11);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        case SYSCTL_CLK_TIMER5_SRC:
+            return false;
+        case SYSCTL_CLK_TIMER5:
+        {
+            if(SYSCTL_CLK_TIMER5_SRC == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xffffefff;
+                sysctl_clk->sysctl_clken_cfg = ret | (0 << 12);
+                return true;
+            }
+            else if(SYSCTL_CLK_TIMERX_PULSE_IN == parent)
+            {
+                ret = sysctl_clk->sysctl_clken_cfg;
+                ret &= 0xffffefff;
+                sysctl_clk->sysctl_clken_cfg = ret | (1 << 12);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        /*--------------------------- SHRM CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SHRM_SRC:
+        {
+            if(SYSCTL_CLK_ROOT_PLL0_DIV_2 == parent)
+            {
+                ret = sysctl_clk->shrm_clk_cfg;
+                ret &= 0xffffbfff;
+                sysctl_clk->shrm_clk_cfg = ret | (0 << 14);
+                return true;
+            }
+            else if(SYSCTL_CLK_ROOT_PLL3_DIV_2 == parent)
+            {
+                ret = sysctl_clk->shrm_clk_cfg;
+                ret &= 0xffffbfff;
+                sysctl_clk->shrm_clk_cfg = ret | (1 << 14);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+        case SYSCTL_CLK_SHRM_DIV2:
+        case SYSCTL_CLK_SHRM_AXIS_SLAVE:
+        case SYSCTL_CLK_DECOMPRESS_AXI:
+            return false;
+
+        case SYSCTL_CLK_SHRM_APB:
+            return false;
+
+        case SYSCTL_CLK_SHRM_AXI_SRC:
+        case SYSCTL_CLK_NONAI2D_AXI_GATE:
+            return false;
+
+        /*--------------------------- SEC CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SEC_APB:
+        case SYSCTL_CLK_SEC_FIX:
+            return false;
+
+        case SYSCTL_CLK_SEC_AXI:
+            return false;
+
+        /*--------------------------- USB TEST MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_USB_480M:
+        case SYSCTL_CLK_USB_100M:
+            return false;
+
+        /*--------------------------- DPHY DFT MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_DPHY_DFT_MODE:
+            return false;
+
+        /*--------------------------- SPI2AXI CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SPI2AXI_AXI:
+            return false;
+
+        default:
+            return false;
+    }
+}
+
+/*
+ * Get the clock source of the leaf node on the clock tree, that is, read the
+ * value of the register corresponding to MUX;
+ * SYSCTL_CLK_ROOT_MAX is returned by default.
+ */
+sysctl_clk_node_e sysctl_clk_get_leaf_parent(sysctl_clk_node_e leaf)
+{
+    switch(sysctl_clk_attribute(leaf))
+    {
+        case 0:
+            return SYSCTL_CLK_ROOT_MAX;
+        case 1:
+        case 3:
+            break;
+    }
+
+    switch(leaf)
+    {
+        /*--------------------------- CPU0 CLOCK ------------------------------------*/
+        case SYSCTL_CLK_CPU0_SRC:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_2;
+        case SYSCTL_CLK_CPU0_PLIC:
+        case SYSCTL_CLK_CPU0_ACLK:
+            return SYSCTL_CLK_CPU0_SRC;
+        case SYSCTL_CLK_CPU0_NOC_DDRCP4:
+            return SYSCTL_CLK_CPU0_ACLK;
+        case SYSCTL_CLK_CPU0_PCLK:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+
+        /*--------------------------- PMU CLOCK ------------------------------------*/
+        case SYSCTL_CLK_PMU_PCLK:
+            return SYSCTL_CLK_ROOT_OSC_IN;
+
+        /*--------------------------- HS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_HS_HCLK_HIGH_SRC:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+        case SYSCTL_CLK_HS_HCLK_HIGH_GATE:
+            return SYSCTL_CLK_HS_HCLK_HIGH_SRC;
+        case SYSCTL_CLK_HS_HCLK_SRC:
+            return SYSCTL_CLK_HS_HCLK_HIGH_SRC;
+        case SYSCTL_CLK_SD0_AHB_GATE:
+        case SYSCTL_CLK_SD1_AHB_GATE:
+        case SYSCTL_CLK_USB0_AHB_GATE:
+        case SYSCTL_CLK_USB1_AHB_GATE:
+        case SYSCTL_CLK_SSI1_AHB_GATE:
+        case SYSCTL_CLK_SSI2_AHB_GATE:
+            return SYSCTL_CLK_HS_HCLK_SRC;
+
+        case SYSCTL_CLK_SSI0_AXI:
+        case SYSCTL_CLK_SSI1:
+        case SYSCTL_CLK_SSI2:
+        case SYSCTL_CLK_QSPI_AXI_SRC:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+        case SYSCTL_CLK_SSI1_ACLK_GATE:
+        case SYSCTL_CLK_SSI2_ACLK_GATE:
+            return SYSCTL_CLK_QSPI_AXI_SRC;
+
+        case SYSCTL_CLK_SSI0:
+        {
+            if(0 == ((sysctl_clk->hs_spi_cfg >> 18) & 0x1))
+                return SYSCTL_CLK_ROOT_PLL0_DIV_2;
+            else
+                return SYSCTL_CLK_ROOT_PLL2_DIV_4;
+        }
+
+        case SYSCTL_CLK_SD_AXI_SRC:
+            return SYSCTL_CLK_ROOT_PLL2_DIV_4;
+        case SYSCTL_CLK_SD0_AXI_GATE:
+        case SYSCTL_CLK_SD1_AXI_GATE:
+        case SYSCTL_CLK_SD0_BASE_GATE:
+        case SYSCTL_CLK_SD1_BASE_GATE:
+            return SYSCTL_CLK_SD_AXI_SRC;
+
+        case SYSCTL_CLK_SD_CARD_SRC:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+        case SYSCTL_CLK_SD0_CARD_GATE:
+        case SYSCTL_CLK_SD1_CARD_GATE:
+            return SYSCTL_CLK_SD_CARD_SRC;
+
+        case SYSCTL_CLK_PLL0_DIV16:
+            return SYSCTL_CLK_ROOT_PLL0;
+        case SYSCTL_CLK_USB_REF_50M:
+            return SYSCTL_CLK_PLL0_DIV16;
+        case SYSCTL_CLK_USB0_REF_GATE:
+        case SYSCTL_CLK_USB1_REF_GATE:
+        {
+            if(0 == ((sysctl_clk->hs_clken_cfg >> 23) & 0x1))
+                return SYSCTL_CLK_ROOT_OSC_IN;
+            else
+                return SYSCTL_CLK_USB_REF_50M;
+        }
+
+        case SYSCTL_CLK_SD_TIMER_SRC:
+            return SYSCTL_CLK_ROOT_OSC_IN;
+        case SYSCTL_CLK_SD0_TIMER_GATE:
+        case SYSCTL_CLK_SD1_TIMER_GATE:
+            return SYSCTL_CLK_SD_TIMER_SRC;
+
+        /*--------------------------- LS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_LS_APB_SRC:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+        case SYSCTL_CLK_UART0_APB_GATE:
+        case SYSCTL_CLK_UART1_APB_GATE:
+        case SYSCTL_CLK_UART2_APB_GATE:
+        case SYSCTL_CLK_UART3_APB_GATE:
+        case SYSCTL_CLK_UART4_APB_GATE:
+        case SYSCTL_CLK_I2C0_APB_GATE:
+        case SYSCTL_CLK_I2C1_APB_GATE:
+        case SYSCTL_CLK_I2C2_APB_GATE:
+        case SYSCTL_CLK_I2C3_APB_GATE:
+        case SYSCTL_CLK_I2C4_APB_GATE:
+        case SYSCTL_CLK_GPIO_APB_GATE:
+        case SYSCTL_CLK_PWM_APB_GATE:
+        case SYSCTL_CLK_JAMLINK0_APB_GATE:
+        case SYSCTL_CLK_JAMLINK1_APB_GATE:
+        case SYSCTL_CLK_JAMLINK2_APB_GATE:
+        case SYSCTL_CLK_JAMLINK3_APB_GATE:
+        case SYSCTL_CLK_ADC_APB_GATE:
+            return SYSCTL_CLK_LS_APB_SRC;
+
+        case SYSCTL_CLK_UART0_CORE:
+        case SYSCTL_CLK_UART1_CORE:
+        case SYSCTL_CLK_UART2_CORE:
+        case SYSCTL_CLK_UART3_CORE:
+        case SYSCTL_CLK_UART4_CORE:
+            return SYSCTL_CLK_PLL0_DIV16;
+
+        case SYSCTL_CLK_JAMLINK_CO_DIV:
+            return SYSCTL_CLK_PLL0_DIV16;
+        case SYSCTL_CLK_JAMLINK0_CO_GATE:
+        case SYSCTL_CLK_JAMLINK1_CO_GATE:
+        case SYSCTL_CLK_JAMLINK2_CO_GATE:
+        case SYSCTL_CLK_JAMLINK3_CO_GATE:
+            return SYSCTL_CLK_JAMLINK_CO_DIV;
+
+        case SYSCTL_CLK_I2C0_CORE:
+        case SYSCTL_CLK_I2C1_CORE:
+        case SYSCTL_CLK_I2C2_CORE:
+        case SYSCTL_CLK_I2C3_CORE:
+        case SYSCTL_CLK_I2C4_CORE:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+
+        case SYSCTL_CLK_ADC:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+
+        case SYSCTL_CLK_GOIP_DEBOUNCE:
+            return SYSCTL_CLK_ROOT_OSC_IN;
+
+        /*--------------------------- SYSCTL CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SYSCTRL_APB_SRC:
+            return SYSCTL_CLK_PLL0_DIV16;
+        case SYSCTL_CLK_WDT0_APB_GATE:
+        case SYSCTL_CLK_WDT1_APB_GATE:
+        case SYSCTL_CLK_TIMER_APB_GATE:
+        case SYSCTL_CLK_IOMUX_APB_GATE:
+        case SYSCTL_CLK_MAILBOX_APB_GATE:
+            return SYSCTL_CLK_SYSCTRL_APB_SRC;
+
+        case SYSCTL_CLK_HDI_CORE:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+
+        case SYSCTL_CLK_TIMESTAMP:
+            return SYSCTL_CLK_ROOT_PLL1_DIV_4;
+
+        case SYSCTL_CLK_TEMP_SENSOR:
+        case SYSCTL_CLK_WDT0:
+        case SYSCTL_CLK_WDT1:
+            return SYSCTL_CLK_ROOT_OSC_IN;
+
+        /*--------------------------- TIMER CLOCK ------------------------------------*/
+        case SYSCTL_CLK_TIMERX_PULSE_IN:
+            return SYSCTL_CLK_ROOT_TIMERX_PULSE_IN;     /* 注意,此处需要review。因为pulse是外部输入信号,这里如何定义其父时钟? */
+        case SYSCTL_CLK_TIMER0_SRC:
+            return SYSCTL_CLK_PLL0_DIV16;
+        case SYSCTL_CLK_TIMER0:
+        {
+            if(0 == ((sysctl_clk->sysctl_clken_cfg >> 7) & 0x1))
+                return SYSCTL_CLK_TIMER0_SRC;
+            else
+                return SYSCTL_CLK_TIMERX_PULSE_IN;
+        }
+        case SYSCTL_CLK_TIMER1_SRC:
+            return SYSCTL_CLK_PLL0_DIV16;
+        case SYSCTL_CLK_TIMER1:
+        {
+            if(0 == ((sysctl_clk->sysctl_clken_cfg >> 8) & 0x1))
+                return SYSCTL_CLK_TIMER1_SRC;
+            else
+                return SYSCTL_CLK_TIMERX_PULSE_IN;
+        }
+        case SYSCTL_CLK_TIMER2_SRC:
+            return SYSCTL_CLK_PLL0_DIV16;
+        case SYSCTL_CLK_TIMER2:
+        {
+            if(0 == ((sysctl_clk->sysctl_clken_cfg >> 9) & 0x1))
+                return SYSCTL_CLK_TIMER2_SRC;
+            else
+                return SYSCTL_CLK_TIMERX_PULSE_IN;
+        }
+        case SYSCTL_CLK_TIMER3_SRC:
+            return SYSCTL_CLK_PLL0_DIV16;
+        case SYSCTL_CLK_TIMER3:
+        {
+            if(0 == ((sysctl_clk->sysctl_clken_cfg >> 10) & 0x1))
+                return SYSCTL_CLK_TIMER3_SRC;
+            else
+                return SYSCTL_CLK_TIMERX_PULSE_IN;
+        }
+        case SYSCTL_CLK_TIMER4_SRC:
+            return SYSCTL_CLK_PLL0_DIV16;
+        case SYSCTL_CLK_TIMER4:
+        {
+            if(0 == ((sysctl_clk->sysctl_clken_cfg >> 11) & 0x1))
+                return SYSCTL_CLK_TIMER4_SRC;
+            else
+                return SYSCTL_CLK_TIMERX_PULSE_IN;
+        }
+        case SYSCTL_CLK_TIMER5_SRC:
+            return SYSCTL_CLK_PLL0_DIV16;
+        case SYSCTL_CLK_TIMER5:
+        {
+            if(0 == ((sysctl_clk->sysctl_clken_cfg >> 12) & 0x1))
+                return SYSCTL_CLK_TIMER5_SRC;
+            else
+                return SYSCTL_CLK_TIMERX_PULSE_IN;
+        }
+
+        /*--------------------------- SHRM CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SHRM_SRC:
+        {
+            if(0 == ((sysctl_clk->shrm_clk_cfg >> 14) & 0x1))
+                return SYSCTL_CLK_ROOT_PLL0_DIV_2;
+            else
+                return SYSCTL_CLK_ROOT_PLL3_DIV_2;
+        }
+        case SYSCTL_CLK_SHRM_DIV2:
+            return SYSCTL_CLK_SHRM_SRC;
+        case SYSCTL_CLK_SHRM_AXIS_SLAVE:
+            return SYSCTL_CLK_SHRM_DIV2;
+        case SYSCTL_CLK_DECOMPRESS_AXI:
+            return SYSCTL_CLK_SHRM_SRC;
+
+        case SYSCTL_CLK_SHRM_APB:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+
+        case SYSCTL_CLK_SHRM_AXI_SRC:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+        case SYSCTL_CLK_NONAI2D_AXI_GATE:
+            return SYSCTL_CLK_SHRM_AXI_SRC;
+
+        /*--------------------------- SEC CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SEC_APB:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+
+        case SYSCTL_CLK_SEC_FIX:
+        case SYSCTL_CLK_SEC_AXI:
+            return SYSCTL_CLK_ROOT_PLL1_DIV_4;
+
+        /*--------------------------- USB TEST MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_USB_480M:
+            return SYSCTL_CLK_ROOT_PLL1;
+        case SYSCTL_CLK_USB_100M:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+
+        /*--------------------------- DPHY DFT MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_DPHY_DFT_MODE:
+            return SYSCTL_CLK_ROOT_PLL0;
+
+        /*--------------------------- SPI2AXI CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SPI2AXI_AXI:
+            return SYSCTL_CLK_ROOT_PLL0_DIV_4;
+
+        default:
+            return SYSCTL_CLK_ROOT_MAX;
+    }
+}
+
+/*
+ * Set the clock node enable.
+ * Note: only set the enable of this clock node, and do not set the enable of
+ * the upstream clock.
+ */
+void sysctl_clk_set_leaf_en(sysctl_clk_node_e leaf, bool enable)
+{
+    volatile uint32_t ret;
+    switch(sysctl_clk_attribute(leaf))
+    {
+        case 0:
+        case 1:
+            return;
+        case 3:
+            break;
+    }
+
+    switch(leaf)
+    {
+        /*--------------------------- CPU0 CLOCK ------------------------------------*/
+        case SYSCTL_CLK_CPU0_SRC:
+            if(enable == true)
+                sysctl_clk->cpu0_clk_cfg |= (1 << 0);
+            else
+                sysctl_clk->cpu0_clk_cfg &= ~(1 << 0);
+            break;
+        case SYSCTL_CLK_CPU0_PLIC:
+            if(enable == true)
+                sysctl_clk->cpu0_clk_cfg |= (1 << 9);
+            else
+                sysctl_clk->cpu0_clk_cfg &= ~(1 << 9);
+            break;
+        case SYSCTL_CLK_CPU0_ACLK:
+            break;
+        case SYSCTL_CLK_CPU0_NOC_DDRCP4:
+            if(enable == true)
+                sysctl_clk->ddr_clk_cfg |= (1 << 7);
+            else
+                sysctl_clk->ddr_clk_cfg &= ~(1 << 7);
+            break;
+        case SYSCTL_CLK_CPU0_PCLK:
+            if(enable == true)
+                sysctl_clk->cpu0_clk_cfg |= (1 << 13);
+            else
+                sysctl_clk->cpu0_clk_cfg &= ~(1 << 13);
+            break;
+
+        /*--------------------------- PMU CLOCK ------------------------------------*/
+        case SYSCTL_CLK_PMU_PCLK:
+            if(enable == true)
+                sysctl_clk->pmu_clk_cfg |= (1 << 0);
+            else
+                sysctl_clk->pmu_clk_cfg &= ~(1 << 0);
+            break;
+
+        /*--------------------------- HS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_HS_HCLK_HIGH_SRC:
+            break;
+        case SYSCTL_CLK_HS_HCLK_HIGH_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 1);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 1);
+            break;
+
+        case SYSCTL_CLK_HS_HCLK_SRC:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 0);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 0);
+            break;
+
+        case SYSCTL_CLK_SD0_AHB_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 2);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 2);
+            break;
+
+        case SYSCTL_CLK_SD1_AHB_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 3);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 3);
+            break;
+
+        case SYSCTL_CLK_USB0_AHB_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 4);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 4);
+            break;
+
+        case SYSCTL_CLK_USB1_AHB_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 5);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 5);
+            break;
+
+        case SYSCTL_CLK_SSI1_AHB_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 7);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 7);
+            break;
+
+        case SYSCTL_CLK_SSI2_AHB_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 8);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 8);
+            break;
+
+        case SYSCTL_CLK_SSI0_AXI:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 27);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 27);
+            break;
+
+        case SYSCTL_CLK_SSI1:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 25);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 25);
+            break;
+
+        case SYSCTL_CLK_SSI2:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 26);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 26);
+            break;
+
+        case SYSCTL_CLK_QSPI_AXI_SRC:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 28);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 28);
+            break;
+
+        case SYSCTL_CLK_SSI1_ACLK_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 29);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 29);
+            break;
+
+        case SYSCTL_CLK_SSI2_ACLK_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 30);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 30);
+            break;
+
+        case SYSCTL_CLK_SSI0:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 24);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 24);
+            break;
+
+        case SYSCTL_CLK_SD_AXI_SRC:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 9);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 9);
+            break;
+
+        case SYSCTL_CLK_SD0_AXI_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 13);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 13);
+            break;
+
+        case SYSCTL_CLK_SD1_AXI_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 17);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 17);
+            break;
+
+        case SYSCTL_CLK_SD0_BASE_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 14);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 14);
+            break;
+
+        case SYSCTL_CLK_SD1_BASE_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 18);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 18);
+            break;
+
+        case SYSCTL_CLK_SD_CARD_SRC:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 11);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 11);
+            break;
+
+        case SYSCTL_CLK_SD0_CARD_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 15);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 15);
+            break;
+
+        case SYSCTL_CLK_SD1_CARD_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 19);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 19);
+            break;
+
+        case SYSCTL_CLK_PLL0_DIV16:
+            break;
+        case SYSCTL_CLK_USB_REF_50M:
+            break;
+
+        case SYSCTL_CLK_USB0_REF_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 21);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 21);
+            break;
+
+        case SYSCTL_CLK_USB1_REF_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 22);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 22);
+            break;
+
+        case SYSCTL_CLK_SD_TIMER_SRC:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 12);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 12);
+            break;
+
+        case SYSCTL_CLK_SD0_TIMER_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 16);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 16);
+            break;
+
+        case SYSCTL_CLK_SD1_TIMER_GATE:
+            if(enable == true)
+                sysctl_clk->hs_clken_cfg |= (1 << 20);
+            else
+                sysctl_clk->hs_clken_cfg &= ~(1 << 20);
+            break;
+
+        /*--------------------------- LS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_LS_APB_SRC:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 0);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 0);
+            break;
+
+        case SYSCTL_CLK_UART0_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 1);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 1);
+            break;
+
+        case SYSCTL_CLK_UART1_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 2);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 2);
+            break;
+
+        case SYSCTL_CLK_UART2_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 3);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 3);
+            break;
+
+        case SYSCTL_CLK_UART3_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 4);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 4);
+            break;
+
+        case SYSCTL_CLK_UART4_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 5);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 5);
+            break;
+
+        case SYSCTL_CLK_I2C0_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 6);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 6);
+            break;
+
+        case SYSCTL_CLK_I2C1_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 7);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 7);
+            break;
+
+        case SYSCTL_CLK_I2C2_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 8);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 8);
+            break;
+
+        case SYSCTL_CLK_I2C3_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 9);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 9);
+            break;
+
+        case SYSCTL_CLK_I2C4_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 10);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 10);
+            break;
+
+        case SYSCTL_CLK_GPIO_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 11);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 11);
+            break;
+
+        case SYSCTL_CLK_PWM_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 12);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 12);
+            break;
+
+        case SYSCTL_CLK_JAMLINK0_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg1 |= (1 << 4);
+            else
+                sysctl_clk->ls_clken_cfg1 &= ~(1 << 4);
+            break;
+
+        case SYSCTL_CLK_JAMLINK1_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg1 |= (1 << 5);
+            else
+                sysctl_clk->ls_clken_cfg1 &= ~(1 << 5);
+            break;
+
+        case SYSCTL_CLK_JAMLINK2_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg1 |= (1 << 6);
+            else
+                sysctl_clk->ls_clken_cfg1 &= ~(1 << 6);
+            break;
+
+        case SYSCTL_CLK_JAMLINK3_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg1 |= (1 << 7);
+            else
+                sysctl_clk->ls_clken_cfg1 &= ~(1 << 7);
+            break;
+
+        case SYSCTL_CLK_ADC_APB_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 15);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 15);
+            break;
+
+        case SYSCTL_CLK_UART0_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 16);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 16);
+            break;
+
+        case SYSCTL_CLK_UART1_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 17);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 17);
+            break;
+
+        case SYSCTL_CLK_UART2_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 18);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 18);
+            break;
+
+        case SYSCTL_CLK_UART3_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 19);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 19);
+            break;
+
+        case SYSCTL_CLK_UART4_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 20);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 20);
+            break;
+
+        case SYSCTL_CLK_JAMLINK_CO_DIV:
+            break;
+        case SYSCTL_CLK_JAMLINK0_CO_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg1 |= (1 << 0);
+            else
+                sysctl_clk->ls_clken_cfg1 &= ~(1 << 0);
+            break;
+
+        case SYSCTL_CLK_JAMLINK1_CO_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg1 |= (1 << 1);
+            else
+                sysctl_clk->ls_clken_cfg1 &= ~(1 << 1);
+            break;
+
+        case SYSCTL_CLK_JAMLINK2_CO_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg1 |= (1 << 2);
+            else
+                sysctl_clk->ls_clken_cfg1 &= ~(1 << 2);
+            break;
+
+        case SYSCTL_CLK_JAMLINK3_CO_GATE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg1 |= (1 << 3);
+            else
+                sysctl_clk->ls_clken_cfg1 &= ~(1 << 3);
+            break;
+
+        case SYSCTL_CLK_I2C0_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 21);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 21);
+            break;
+
+        case SYSCTL_CLK_I2C1_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 22);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 22);
+            break;
+
+        case SYSCTL_CLK_I2C2_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 23);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 23);
+            break;
+
+        case SYSCTL_CLK_I2C3_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 24);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 24);
+            break;
+
+        case SYSCTL_CLK_I2C4_CORE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 25);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 25);
+            break;
+
+        case SYSCTL_CLK_ADC:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 26);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 26);
+            break;
+
+        case SYSCTL_CLK_GOIP_DEBOUNCE:
+            if(enable == true)
+                sysctl_clk->ls_clken_cfg0 |= (1 << 27);
+            else
+                sysctl_clk->ls_clken_cfg0 &= ~(1 << 27);
+            break;
+
+        /*--------------------------- SYSCTL CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SYSCTRL_APB_SRC:
+            break;
+        case SYSCTL_CLK_WDT0_APB_GATE:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 1);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 1);
+            break;
+
+        case SYSCTL_CLK_WDT1_APB_GATE:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 2);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 2);
+            break;
+
+        case SYSCTL_CLK_TIMER_APB_GATE:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 3);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 3);
+            break;
+
+        case SYSCTL_CLK_IOMUX_APB_GATE:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 20);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 20);
+            break;
+
+        case SYSCTL_CLK_MAILBOX_APB_GATE:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 4);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 4);
+            break;
+
+        case SYSCTL_CLK_HDI_CORE:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 21);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 21);
+            break;
+
+        case SYSCTL_CLK_TIMESTAMP:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 19);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 19);
+            break;
+
+        case SYSCTL_CLK_TEMP_SENSOR:
+            break;
+
+        case SYSCTL_CLK_WDT0:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 5);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 5);
+
+        case SYSCTL_CLK_WDT1:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 6);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 6);
+
+        /*--------------------------- TIMER CLOCK ------------------------------------*/
+        case SYSCTL_CLK_TIMERX_PULSE_IN:
+            break;
+        case SYSCTL_CLK_TIMER0_SRC:
+            break;
+        case SYSCTL_CLK_TIMER0:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 13);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 13);
+            break;
+
+        case SYSCTL_CLK_TIMER1_SRC:
+            break;
+        case SYSCTL_CLK_TIMER1:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 14);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 14);
+            break;
+
+        case SYSCTL_CLK_TIMER2_SRC:
+            break;
+        case SYSCTL_CLK_TIMER2:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 15);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 15);
+            break;
+
+        case SYSCTL_CLK_TIMER3_SRC:
+            break;
+        case SYSCTL_CLK_TIMER3:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 16);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 16);
+            break;
+
+        case SYSCTL_CLK_TIMER4_SRC:
+            break;
+        case SYSCTL_CLK_TIMER4:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 17);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 17);
+            break;
+
+        case SYSCTL_CLK_TIMER5_SRC:
+            break;
+        case SYSCTL_CLK_TIMER5:
+            if(enable == true)
+                sysctl_clk->sysctl_clken_cfg |= (1 << 18);
+            else
+                sysctl_clk->sysctl_clken_cfg &= ~(1 << 18);
+            break;
+
+        /*--------------------------- SHRM CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SHRM_SRC:
+            if(enable == true)
+                sysctl_clk->shrm_clk_cfg |= (1 << 10);
+            else
+                sysctl_clk->shrm_clk_cfg &= ~(1 << 10);
+            break;
+
+        case SYSCTL_CLK_SHRM_DIV2:
+            break;
+        case SYSCTL_CLK_SHRM_AXIS_SLAVE:
+            if(enable == true)
+                sysctl_clk->shrm_clk_cfg |= (1 << 11);
+            else
+                sysctl_clk->shrm_clk_cfg &= ~(1 << 11);
+            break;
+
+        case SYSCTL_CLK_DECOMPRESS_AXI:
+            if(enable == true)
+                sysctl_clk->shrm_clk_cfg |= (1 << 7);
+            else
+                sysctl_clk->shrm_clk_cfg &= ~(1 << 7);
+            break;
+
+        case SYSCTL_CLK_SHRM_APB:
+            if(enable == true)
+                sysctl_clk->shrm_clk_cfg |= (1 << 0);
+            else
+                sysctl_clk->shrm_clk_cfg &= ~(1 << 0);
+            break;
+
+        case SYSCTL_CLK_SHRM_AXI_SRC:
+            if(enable == true)
+                sysctl_clk->shrm_clk_cfg |= (1 << 12);
+            else
+                sysctl_clk->shrm_clk_cfg &= ~(1 << 12);
+            break;
+
+        case SYSCTL_CLK_NONAI2D_AXI_GATE:
+            if(enable == true)
+                sysctl_clk->shrm_clk_cfg |= (1 << 9);
+            else
+                sysctl_clk->shrm_clk_cfg &= ~(1 << 9);
+            break;
+
+        /*--------------------------- SEC CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SEC_APB:
+            if(enable == true)
+                sysctl_clk->sec_clk_div |= (1 << 0);
+            else
+                sysctl_clk->sec_clk_div &= ~(1 << 0);
+            break;
+
+        case SYSCTL_CLK_SEC_FIX:
+            if(enable == true)
+                sysctl_clk->sec_clk_div |= (1 << 5);
+            else
+                sysctl_clk->sec_clk_div &= ~(1 << 5);
+            break;
+
+        case SYSCTL_CLK_SEC_AXI:
+            if(enable == true)
+                sysctl_clk->sec_clk_div |= (1 << 4);
+            else
+                sysctl_clk->sec_clk_div &= ~(1 << 4);
+            break;
+
+        /*--------------------------- USB TEST MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_USB_480M:
+            if(enable == true)
+                sysctl_clk->usb_test_clk_div |= (1 << 0);
+            else
+                sysctl_clk->usb_test_clk_div &= ~(1 << 0);
+            break;
+
+        case SYSCTL_CLK_USB_100M:
+            if(enable == true)
+                sysctl_clk->usb_test_clk_div |= (1 << 0);
+            else
+                sysctl_clk->usb_test_clk_div &= ~(1 << 0);
+            break;
+
+        /*--------------------------- DPHY DFT MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_DPHY_DFT_MODE:
+            if(enable == true)
+                sysctl_clk->dphy_test_clk_div |= (1 << 0);
+            else
+                sysctl_clk->dphy_test_clk_div &= ~(1 << 0);
+            break;
+
+        /*--------------------------- SPI2AXI CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SPI2AXI_AXI:
+            if(enable == true)
+                sysctl_clk->spi2axi_clk_div |= (1 << 0);
+            else
+                sysctl_clk->spi2axi_clk_div &= ~(1 << 0);
+            break;
+
+        default:
+            break;
+    }
+}
+
+/* Get the enable status of this clock node */
+bool sysctl_clk_get_leaf_en(sysctl_clk_node_e leaf)
+{
+    switch(sysctl_clk_attribute(leaf))
+    {
+        case 0:
+            return false;
+        case 1:
+        case 3:
+            break;
+    }
+
+    switch(leaf)
+    {
+        /*--------------------------- CPU0 CLOCK ------------------------------------*/
+        case SYSCTL_CLK_CPU0_SRC:
+            return (0 == ((sysctl_clk->cpu0_clk_cfg >> 0) & 0x1)) ? false : true;
+        case SYSCTL_CLK_CPU0_PLIC:
+            return (0 == ((sysctl_clk->cpu0_clk_cfg >> 9) & 0x1)) ? false : true;
+        case SYSCTL_CLK_CPU0_ACLK:
+            return true;
+        case SYSCTL_CLK_CPU0_NOC_DDRCP4:
+            return (0 == ((sysctl_clk->ddr_clk_cfg >> 7) & 0x1)) ? false : true;
+        case SYSCTL_CLK_CPU0_PCLK:
+            return (0 == ((sysctl_clk->cpu0_clk_cfg >> 7) & 0x1)) ? false : true;
+
+        /*--------------------------- PMU CLOCK ------------------------------------*/
+        case SYSCTL_CLK_PMU_PCLK:
+            return (0 == ((sysctl_clk->pmu_clk_cfg >> 0) & 0x1)) ? false : true;
+
+        /*--------------------------- HS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_HS_HCLK_HIGH_SRC:
+            return true;
+        case SYSCTL_CLK_HS_HCLK_HIGH_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 1) & 0x1)) ? false : true;
+        case SYSCTL_CLK_HS_HCLK_SRC:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 0) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD0_AHB_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 2) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD1_AHB_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 3) & 0x1)) ? false : true;
+        case SYSCTL_CLK_USB0_AHB_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 4) & 0x1)) ? false : true;
+        case SYSCTL_CLK_USB1_AHB_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 5) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SSI1_AHB_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 7) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SSI2_AHB_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 8) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_SSI0_AXI:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 27) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SSI1:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 25) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SSI2:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 26) & 0x1)) ? false : true;
+        case SYSCTL_CLK_QSPI_AXI_SRC:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 28) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SSI1_ACLK_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 29) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SSI2_ACLK_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 30) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_SSI0:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 24) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_SD_AXI_SRC:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 9) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD0_AXI_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 13) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD1_AXI_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 17) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD0_BASE_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 14) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD1_BASE_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 18) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_SD_CARD_SRC:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 11) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD0_CARD_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 15) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD1_CARD_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 19) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_PLL0_DIV16:
+            return true;
+        case SYSCTL_CLK_USB_REF_50M:
+            return true;
+        case SYSCTL_CLK_USB0_REF_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 21) & 0x1)) ? false : true;
+        case SYSCTL_CLK_USB1_REF_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 22) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_SD_TIMER_SRC:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 12) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD0_TIMER_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 16) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SD1_TIMER_GATE:
+            return (0 == ((sysctl_clk->hs_clken_cfg >> 20) & 0x1)) ? false : true;
+
+
+        /*--------------------------- LS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_LS_APB_SRC:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 0) & 0x1)) ? false : true;
+        case SYSCTL_CLK_UART0_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 1) & 0x1)) ? false : true;
+        case SYSCTL_CLK_UART1_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 2) & 0x1)) ? false : true;
+        case SYSCTL_CLK_UART2_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 3) & 0x1)) ? false : true;
+        case SYSCTL_CLK_UART3_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 4) & 0x1)) ? false : true;
+        case SYSCTL_CLK_UART4_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 5) & 0x1)) ? false : true;
+        case SYSCTL_CLK_I2C0_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 6) & 0x1)) ? false : true;
+        case SYSCTL_CLK_I2C1_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 7) & 0x1)) ? false : true;
+        case SYSCTL_CLK_I2C2_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 8) & 0x1)) ? false : true;
+        case SYSCTL_CLK_I2C3_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 9) & 0x1)) ? false : true;
+        case SYSCTL_CLK_I2C4_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 10) & 0x1)) ? false : true;
+        case SYSCTL_CLK_GPIO_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 11) & 0x1)) ? false : true;
+        case SYSCTL_CLK_PWM_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 12) & 0x1)) ? false : true;
+        case SYSCTL_CLK_JAMLINK0_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg1 >> 4) & 0x1)) ? false : true;
+        case SYSCTL_CLK_JAMLINK1_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg1 >> 5) & 0x1)) ? false : true;
+        case SYSCTL_CLK_JAMLINK2_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg1 >> 6) & 0x1)) ? false : true;
+        case SYSCTL_CLK_JAMLINK3_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg1 >> 7) & 0x1)) ? false : true;
+        case SYSCTL_CLK_ADC_APB_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 15) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_UART0_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 16) & 0x1)) ? false : true;
+        case SYSCTL_CLK_UART1_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 17) & 0x1)) ? false : true;
+        case SYSCTL_CLK_UART2_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 18) & 0x1)) ? false : true;
+        case SYSCTL_CLK_UART3_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 19) & 0x1)) ? false : true;
+        case SYSCTL_CLK_UART4_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 20) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_JAMLINK_CO_DIV:
+            return true;
+        case SYSCTL_CLK_JAMLINK0_CO_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg1 >> 0) & 0x1)) ? false : true;
+        case SYSCTL_CLK_JAMLINK1_CO_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg1 >> 1) & 0x1)) ? false : true;
+        case SYSCTL_CLK_JAMLINK2_CO_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg1 >> 2) & 0x1)) ? false : true;
+        case SYSCTL_CLK_JAMLINK3_CO_GATE:
+            return (0 == ((sysctl_clk->ls_clken_cfg1 >> 3) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_I2C0_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 21) & 0x1)) ? false : true;
+        case SYSCTL_CLK_I2C1_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 22) & 0x1)) ? false : true;
+        case SYSCTL_CLK_I2C2_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 23) & 0x1)) ? false : true;
+        case SYSCTL_CLK_I2C3_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 24) & 0x1)) ? false : true;
+        case SYSCTL_CLK_I2C4_CORE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 25) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_ADC:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 26) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_GOIP_DEBOUNCE:
+            return (0 == ((sysctl_clk->ls_clken_cfg0 >> 27) & 0x1)) ? false : true;
+
+        /*--------------------------- SYSCTL CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SYSCTRL_APB_SRC:
+            return true;
+        case SYSCTL_CLK_WDT0_APB_GATE:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 1) & 0x1)) ? false : true;
+        case SYSCTL_CLK_WDT1_APB_GATE:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 2) & 0x1)) ? false : true;
+        case SYSCTL_CLK_TIMER_APB_GATE:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 3) & 0x1)) ? false : true;
+        case SYSCTL_CLK_IOMUX_APB_GATE:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 20) & 0x1)) ? false : true;
+        case SYSCTL_CLK_MAILBOX_APB_GATE:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 4) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_HDI_CORE:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 21) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_TIMESTAMP:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 19) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_TEMP_SENSOR:
+            return true;
+
+        case SYSCTL_CLK_WDT0:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 5) & 0x1)) ? false : true;
+        case SYSCTL_CLK_WDT1:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 6) & 0x1)) ? false : true;
+
+        /*--------------------------- TIMER CLOCK ------------------------------------*/
+        case SYSCTL_CLK_TIMERX_PULSE_IN:
+            return true;
+        case SYSCTL_CLK_TIMER0_SRC:
+            return true;
+        case SYSCTL_CLK_TIMER0:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 13) & 0x1)) ? false : true;
+        case SYSCTL_CLK_TIMER1_SRC:
+            return true;
+        case SYSCTL_CLK_TIMER1:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 14) & 0x1)) ? false : true;
+        case SYSCTL_CLK_TIMER2_SRC:
+            return true;
+        case SYSCTL_CLK_TIMER2:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 15) & 0x1)) ? false : true;
+        case SYSCTL_CLK_TIMER3_SRC:
+            return true;
+        case SYSCTL_CLK_TIMER3:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 16) & 0x1)) ? false : true;
+        case SYSCTL_CLK_TIMER4_SRC:
+            return true;
+        case SYSCTL_CLK_TIMER4:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 17) & 0x1)) ? false : true;
+        case SYSCTL_CLK_TIMER5_SRC:
+            return true;
+        case SYSCTL_CLK_TIMER5:
+            return (0 == ((sysctl_clk->sysctl_clken_cfg >> 18) & 0x1)) ? false : true;
+
+        /*--------------------------- SHRM CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SHRM_SRC:
+            return (0 == ((sysctl_clk->shrm_clk_cfg >> 10) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SHRM_DIV2:
+            return true;
+        case SYSCTL_CLK_SHRM_AXIS_SLAVE:
+            return (0 == ((sysctl_clk->shrm_clk_cfg >> 11) & 0x1)) ? false : true;
+        case SYSCTL_CLK_DECOMPRESS_AXI:
+            return (0 == ((sysctl_clk->shrm_clk_cfg >> 7) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_SHRM_APB:
+            return (0 == ((sysctl_clk->shrm_clk_cfg >> 0) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_SHRM_AXI_SRC:
+            return (0 == ((sysctl_clk->shrm_clk_cfg >> 12) & 0x1)) ? false : true;
+
+        /*--------------------------- SEC CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SEC_APB:
+            return (0 == ((sysctl_clk->sec_clk_div >> 0) & 0x1)) ? false : true;
+        case SYSCTL_CLK_SEC_FIX:
+            return (0 == ((sysctl_clk->sec_clk_div >> 5) & 0x1)) ? false : true;
+
+        case SYSCTL_CLK_SEC_AXI:
+            return (0 == ((sysctl_clk->sec_clk_div >> 4) & 0x1)) ? false : true;
+
+        /*--------------------------- USB TEST MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_USB_480M:
+            return (0 == ((sysctl_clk->usb_test_clk_div >> 0) & 0x1)) ? false : true;
+        case SYSCTL_CLK_USB_100M:
+            return (0 == ((sysctl_clk->usb_test_clk_div >> 0) & 0x1)) ? false : true;
+
+        /*--------------------------- DPHY DFT MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_DPHY_DFT_MODE:
+            return (0 == ((sysctl_clk->dphy_test_clk_div >> 0) & 0x1)) ? false : true;
+
+        /*--------------------------- SPI2AXI CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SPI2AXI_AXI:
+            return (0 == ((sysctl_clk->spi2axi_clk_div >> 0) & 0x1)) ? false : true;
+
+        default:
+            return true;
+    }
+}
+
+/*
+ * Set the frequency division factor of this clock node.
+ * freq = root_freq * numerator / denominator
+ */
+bool sysctl_clk_set_leaf_div(sysctl_clk_node_e leaf, uint32_t numerator, uint32_t denominator)
+{
+    volatile uint32_t ret;
+
+    if(denominator == 0)
+        return false;
+
+    switch(sysctl_clk_attribute(leaf))
+    {
+        case 0:
+        case 1:
+            return false;
+        case 3:
+            break;
+    }
+
+    switch(leaf)
+    {
+        /*--------------------------- CPU0 CLOCK ------------------------------------*/
+        case SYSCTL_CLK_CPU0_SRC:
+        {
+            if((numerator > 16) || (numerator < 1) || (denominator != 16))
+                return false;
+            else
+            {
+                /* 1/16 --- 16/16 */
+                ret = sysctl_clk->cpu0_clk_cfg;
+                ret &= 0xffffffe1;
+                sysctl_clk->cpu0_clk_cfg = ret | (((numerator - 1) << 1) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_CPU0_PLIC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->cpu0_clk_cfg;
+                ret &= 0xffffe3ff;
+                sysctl_clk->cpu0_clk_cfg = ret | (((denominator - 1) << 10) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_CPU0_ACLK:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->cpu0_clk_cfg;
+                ret &= 0xfffffe3f;
+                sysctl_clk->cpu0_clk_cfg = ret | (((denominator - 1) << 6) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_CPU0_NOC_DDRCP4:
+            return false;
+        case SYSCTL_CLK_CPU0_PCLK:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->cpu0_clk_cfg;
+                ret &= 0xffffc7ff;
+                sysctl_clk->cpu0_clk_cfg = ret | (((denominator - 1) << 15) | (1 << 31));
+                return true;
+            }
+        }
+
+        /*--------------------------- PMU CLOCK ------------------------------------*/
+        case SYSCTL_CLK_PMU_PCLK:
+            return false;
+
+        /*--------------------------- HS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_HS_HCLK_HIGH_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->hs_sdclk_cfg;
+                ret &= 0xfffffff8;
+                sysctl_clk->hs_sdclk_cfg = ret | (((denominator - 1) << 0) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_HS_HCLK_HIGH_GATE:
+            return false;
+
+        case SYSCTL_CLK_HS_HCLK_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->hs_sdclk_cfg;
+                ret &= 0xffffffc7;
+                sysctl_clk->hs_sdclk_cfg = ret | (((denominator - 1) << 3) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_SD0_AHB_GATE:
+        case SYSCTL_CLK_SD1_AHB_GATE:
+        case SYSCTL_CLK_USB0_AHB_GATE:
+        case SYSCTL_CLK_USB1_AHB_GATE:
+        case SYSCTL_CLK_SSI1_AHB_GATE:
+        case SYSCTL_CLK_SSI2_AHB_GATE:
+            return false;
+
+        case SYSCTL_CLK_SSI0_AXI:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->hs_spi_cfg;
+                ret &= 0xfffff1ff;
+                sysctl_clk->hs_spi_cfg = ret | (((denominator - 1) << 9) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_SSI1:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->hs_spi_cfg;
+                ret &= 0xffffffc7;
+                sysctl_clk->hs_spi_cfg = ret | (((denominator - 1) << 3) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_SSI2:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->hs_spi_cfg;
+                ret &= 0xfffffe3f;
+                sysctl_clk->hs_spi_cfg = ret | (((denominator - 1) << 6) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_QSPI_AXI_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->hs_spi_cfg;
+                ret &= 0xffff8fff;
+                sysctl_clk->hs_spi_cfg = ret | (((denominator - 1) << 12) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_SSI1_ACLK_GATE:
+        case SYSCTL_CLK_SSI2_ACLK_GATE:
+            return false;
+
+        case SYSCTL_CLK_SSI0:
+            return false;
+
+        case SYSCTL_CLK_SD_AXI_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->hs_sdclk_cfg;
+                ret &= 0xfffffe3f;
+                sysctl_clk->hs_sdclk_cfg = ret | (((denominator - 1) << 6) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_SD0_AXI_GATE:
+        case SYSCTL_CLK_SD1_AXI_GATE:
+        case SYSCTL_CLK_SD0_BASE_GATE:
+        case SYSCTL_CLK_SD1_BASE_GATE:
+            return false;
+
+        case SYSCTL_CLK_SD_CARD_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->hs_sdclk_cfg;
+                ret &= 0xffff8fff;
+                sysctl_clk->hs_sdclk_cfg = ret | (((denominator - 1) << 12) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_SD0_CARD_GATE:
+        case SYSCTL_CLK_SD1_CARD_GATE:
+            return false;
+
+        case SYSCTL_CLK_PLL0_DIV16:
+            return false;
+        case SYSCTL_CLK_USB_REF_50M:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->hs_spi_cfg;
+                ret &= 0xfffc7fff;
+                sysctl_clk->hs_spi_cfg = ret | (((denominator - 1) << 15) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_USB0_REF_GATE:
+        case SYSCTL_CLK_USB1_REF_GATE:
+            return false;
+
+        case SYSCTL_CLK_SD_TIMER_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 32))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/32 */
+                ret = sysctl_clk->hs_sdclk_cfg;
+                ret &= 0xfff07fff;
+                sysctl_clk->hs_sdclk_cfg = ret | (((denominator - 1) << 15) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_SD0_TIMER_GATE:
+        case SYSCTL_CLK_SD1_TIMER_GATE:
+            return false;
+
+        /*--------------------------- LS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_LS_APB_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/4, 1/8 --- 1/8 */
+                ret = sysctl_clk->ls_clkdiv_cfg;
+                ret &= 0xfffffff8;
+                sysctl_clk->ls_clkdiv_cfg = ret | (((denominator - 1) << 0) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_UART0_APB_GATE:
+        case SYSCTL_CLK_UART1_APB_GATE:
+        case SYSCTL_CLK_UART2_APB_GATE:
+        case SYSCTL_CLK_UART3_APB_GATE:
+        case SYSCTL_CLK_UART4_APB_GATE:
+        case SYSCTL_CLK_I2C0_APB_GATE:
+        case SYSCTL_CLK_I2C1_APB_GATE:
+        case SYSCTL_CLK_I2C2_APB_GATE:
+        case SYSCTL_CLK_I2C3_APB_GATE:
+        case SYSCTL_CLK_I2C4_APB_GATE:
+        case SYSCTL_CLK_GPIO_APB_GATE:
+        case SYSCTL_CLK_PWM_APB_GATE:
+        case SYSCTL_CLK_JAMLINK0_APB_GATE:
+        case SYSCTL_CLK_JAMLINK1_APB_GATE:
+        case SYSCTL_CLK_JAMLINK2_APB_GATE:
+        case SYSCTL_CLK_JAMLINK3_APB_GATE:
+        case SYSCTL_CLK_ADC_APB_GATE:
+            return false;
+
+        case SYSCTL_CLK_UART0_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xfffffff8;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 0) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_UART1_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xffffffc7;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 3) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_UART2_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xfffffe3f;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 6) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_UART3_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xfffff1ff;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 9) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_UART4_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xffff8fff;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 12) | (1 << 31));
+                return true;
+            }
+        }
+
+        case SYSCTL_CLK_JAMLINK_CO_DIV:
+        {
+            if((numerator != 1) || (denominator < 2) || (denominator > 512) || (denominator % 2 != 0))
+                return false;
+            else
+            {
+                /* 1/2, 1/4, 1/8 --- 1/512 */
+                ret = sysctl_clk->ls_clkdiv_cfg;
+                ret &= 0x807fffff;
+                sysctl_clk->ls_clkdiv_cfg = ret | (((denominator/2 - 1) << 23) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_JAMLINK0_CO_GATE:
+        case SYSCTL_CLK_JAMLINK1_CO_GATE:
+        case SYSCTL_CLK_JAMLINK2_CO_GATE:
+        case SYSCTL_CLK_JAMLINK3_CO_GATE:
+            return false;
+
+        case SYSCTL_CLK_I2C0_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xfffc7fff;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 15) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_I2C1_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xffe3ffff;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 18) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_I2C2_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xff1fffff;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 21) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_I2C3_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xf8ffffff;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 24) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_I2C4_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->uart_i2c_clkdiv_cfg;
+                ret &= 0xc7ffffff;
+                sysctl_clk->uart_i2c_clkdiv_cfg = ret | (((denominator - 1) << 27) | (1 << 31));
+                return true;
+            }
+        }
+
+        case SYSCTL_CLK_ADC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 1024))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/1024 */
+                ret = sysctl_clk->ls_clkdiv_cfg;
+                ret &= 0xffffe007;
+                sysctl_clk->ls_clkdiv_cfg = ret | (((denominator - 1) << 3) | (1 << 31));
+                return true;
+            }
+        }
+
+        case SYSCTL_CLK_GOIP_DEBOUNCE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 1024))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/1024 */
+                ret = sysctl_clk->ls_clkdiv_cfg;
+                ret &= 0xff801fff;
+                sysctl_clk->ls_clkdiv_cfg = ret | (((denominator - 1) << 13) | (1 << 31));
+                return true;
+            }
+        }
+
+        /*--------------------------- SYSCTL CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SYSCTRL_APB_SRC:
+            return false;
+        case SYSCTL_CLK_WDT0_APB_GATE:
+        case SYSCTL_CLK_WDT1_APB_GATE:
+        case SYSCTL_CLK_TIMER_APB_GATE:
+        case SYSCTL_CLK_IOMUX_APB_GATE:
+        case SYSCTL_CLK_MAILBOX_APB_GATE:
+            return false;
+
+        case SYSCTL_CLK_HDI_CORE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->sysctl_clk_div_cfg;
+                ret &= 0x8fffffff;
+                sysctl_clk->sysctl_clk_div_cfg = ret | (((denominator - 1) << 28) | (1 << 31));
+                return true;
+            }
+        }
+
+        case SYSCTL_CLK_TIMESTAMP:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 32))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/32 */
+                ret = sysctl_clk->sysctl_clk_div_cfg;
+                ret &= 0xfff07fff;
+                sysctl_clk->sysctl_clk_div_cfg = ret | (((denominator - 1) << 15) | (1 << 31));
+                return true;
+            }
+        }
+
+        case SYSCTL_CLK_TEMP_SENSOR:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 256))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/256 */
+                ret = sysctl_clk->sysctl_clk_div_cfg;
+                ret &= 0xf00fffff;
+                sysctl_clk->sysctl_clk_div_cfg = ret | (((denominator - 1) << 20) | (1 << 31));
+                return true;
+            }
+        }
+
+        case SYSCTL_CLK_WDT0:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 64))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/64 */
+                ret = sysctl_clk->sysctl_clk_div_cfg;
+                ret &= 0xfffffe07;
+                sysctl_clk->sysctl_clk_div_cfg = ret | (((denominator - 1) << 3) | (1 << 31));
+                return true;
+            }
+        }
+
+        case SYSCTL_CLK_WDT1:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 64))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/64 */
+                ret = sysctl_clk->sysctl_clk_div_cfg;
+                ret &= 0xffff81ff;
+                sysctl_clk->sysctl_clk_div_cfg = ret | (((denominator - 1) << 9) | (1 << 31));
+                return true;
+            }
+        }
+
+        /*--------------------------- TIMER CLOCK ------------------------------------*/
+        case SYSCTL_CLK_TIMERX_PULSE_IN:
+            return false;
+        case SYSCTL_CLK_TIMER0_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->timer_clk_cfg;
+                ret &= 0xfffffff8;
+                sysctl_clk->timer_clk_cfg = ret | (((denominator - 1) << 0) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_TIMER0:
+            return false;
+
+        case SYSCTL_CLK_TIMER1_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->timer_clk_cfg;
+                ret &= 0xffffffc7;
+                sysctl_clk->timer_clk_cfg = ret | (((denominator - 1) << 3) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_TIMER1:
+            return false;
+
+        case SYSCTL_CLK_TIMER2_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->timer_clk_cfg;
+                ret &= 0xfffffe3f;
+                sysctl_clk->timer_clk_cfg = ret | (((denominator - 1) << 6) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_TIMER2:
+            return false;
+
+        case SYSCTL_CLK_TIMER3_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->timer_clk_cfg;
+                ret &= 0xfffff1ff;
+                sysctl_clk->timer_clk_cfg = ret | (((denominator - 1) << 9) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_TIMER3:
+            return false;
+
+        case SYSCTL_CLK_TIMER4_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->timer_clk_cfg;
+                ret &= 0xffff8fff;
+                sysctl_clk->timer_clk_cfg = ret | (((denominator - 1) << 12) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_TIMER4:
+            return false;
+
+        case SYSCTL_CLK_TIMER5_SRC:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->timer_clk_cfg;
+                ret &= 0xfffc7fff;
+                sysctl_clk->timer_clk_cfg = ret | (((denominator - 1) << 15) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_TIMER5:
+            return false;
+
+        /*--------------------------- SHRM CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SHRM_SRC:
+            return false;
+        case SYSCTL_CLK_SHRM_DIV2:
+            return false;
+        case SYSCTL_CLK_SHRM_AXIS_SLAVE:
+        case SYSCTL_CLK_DECOMPRESS_AXI:
+            return false;
+
+        case SYSCTL_CLK_SHRM_APB:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->shrm_clk_cfg;
+                ret &= 0xffe3ffff;
+                sysctl_clk->shrm_clk_cfg = ret | (((denominator - 1) << 18) | (1 << 31));
+                return true;
+            }
+        }
+
+        case SYSCTL_CLK_SHRM_AXI_SRC:
+        case SYSCTL_CLK_NONAI2D_AXI_GATE:
+            return false;
+
+        /*--------------------------- SEC CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SEC_APB:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->sec_clk_div;
+                ret &= 0xfffffff1;
+                sysctl_clk->sec_clk_div = ret | (((denominator - 1) << 1) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_SEC_FIX:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 32))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/32 */
+                ret = sysctl_clk->sec_clk_div;
+                ret &= 0xfffff83f;
+                sysctl_clk->sec_clk_div = ret | (((denominator - 1) << 6) | (1 << 31));
+                return true;
+            }
+        }
+
+        case SYSCTL_CLK_SEC_AXI:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->sec_clk_div;
+                ret &= 0xffffc7ff;
+                sysctl_clk->sec_clk_div = ret | (((denominator - 1) << 11) | (1 << 31));
+                return true;
+            }
+        }
+
+        /*--------------------------- USB TEST MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_USB_480M:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->usb_test_clk_div;
+                ret &= 0xfffffff1;
+                sysctl_clk->usb_test_clk_div = ret | (((denominator - 1) << 1) | (1 << 31));
+                return true;
+            }
+        }
+        case SYSCTL_CLK_USB_100M:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->usb_test_clk_div;
+                ret &= 0xffffff8f;
+                sysctl_clk->usb_test_clk_div = ret | (((denominator - 1) << 4) | (1 << 31));
+                return true;
+            }
+        }
+
+        /*--------------------------- DPHY DFT MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_DPHY_DFT_MODE:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 16))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/16 */
+                ret = sysctl_clk->dphy_test_clk_div;
+                ret &= 0xffffffe1;
+                sysctl_clk->dphy_test_clk_div = ret | (((denominator - 1) << 1) | (1 << 31));
+                return true;
+            }
+        }
+
+        /*--------------------------- SPI2AXI CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SPI2AXI_AXI:
+        {
+            if((numerator != 1) || (denominator < 1) || (denominator > 8))
+                return false;
+            else
+            {
+                /* 1/1, 1/2, 1/3 --- 1/8 */
+                ret = sysctl_clk->spi2axi_clk_div;
+                ret &= 0xfffffff1;
+                sysctl_clk->spi2axi_clk_div = ret | (((denominator - 1) << 1) | (1 << 31));
+                return true;
+            }
+        }
+
+        default:
+            return false;
+    }
+}
+
+/* Get the frequency division coefficient of this clock node */
+double sysctl_clk_get_leaf_div(sysctl_clk_node_e leaf)
+{
+    switch(sysctl_clk_attribute(leaf))
+    {
+        case 0:
+            return -1;
+        case 1:
+        case 3:
+            break;
+    }
+
+    switch(leaf)
+    {
+        /*--------------------------- CPU0 CLOCK ------------------------------------*/
+        case SYSCTL_CLK_CPU0_SRC:
+            return (double)(((sysctl_clk->cpu0_clk_cfg >> 1) & 0xF) + 1) / 16.0;    /* 1/16 --- 16/16 */
+        case SYSCTL_CLK_CPU0_PLIC:
+            return 1.0/(double)(((sysctl_clk->cpu0_clk_cfg >> 10) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_CPU0_ACLK:
+            return 1.0/(double)(((sysctl_clk->cpu0_clk_cfg >> 6) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_CPU0_NOC_DDRCP4:
+            return 1;
+        case SYSCTL_CLK_CPU0_PCLK:
+            return 1.0/(double)(((sysctl_clk->cpu0_clk_cfg >> 15) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+
+        /*--------------------------- PMU CLOCK ------------------------------------*/
+        case SYSCTL_CLK_PMU_PCLK:
+            return 1;
+
+        /*--------------------------- HS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_HS_HCLK_HIGH_SRC:
+            return 1.0/(double)(((sysctl_clk->hs_sdclk_cfg >> 0) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_HS_HCLK_HIGH_GATE:
+            return 1;
+        case SYSCTL_CLK_HS_HCLK_SRC:
+            return 1.0/(double)(((sysctl_clk->hs_sdclk_cfg >> 3) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_SD0_AHB_GATE:
+        case SYSCTL_CLK_SD1_AHB_GATE:
+        case SYSCTL_CLK_USB0_AHB_GATE:
+        case SYSCTL_CLK_USB1_AHB_GATE:
+        case SYSCTL_CLK_SSI1_AHB_GATE:
+        case SYSCTL_CLK_SSI2_AHB_GATE:
+            return 1;
+
+        case SYSCTL_CLK_SSI0_AXI:
+            return 1.0/(double)(((sysctl_clk->hs_spi_cfg >> 9) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_SSI1:
+            return 1.0/(double)(((sysctl_clk->hs_spi_cfg >> 3) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_SSI2:
+            return 1.0/(double)(((sysctl_clk->hs_spi_cfg >> 6) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_QSPI_AXI_SRC:
+            return 1.0/(double)(((sysctl_clk->hs_spi_cfg >> 12) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_SSI1_ACLK_GATE:
+        case SYSCTL_CLK_SSI2_ACLK_GATE:
+            return 1;
+
+        case SYSCTL_CLK_SSI0:
+            return 1;
+
+        case SYSCTL_CLK_SD_AXI_SRC:
+            return 1.0/(double)(((sysctl_clk->hs_sdclk_cfg >> 6) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_SD0_AXI_GATE:
+        case SYSCTL_CLK_SD1_AXI_GATE:
+        case SYSCTL_CLK_SD0_BASE_GATE:
+        case SYSCTL_CLK_SD1_BASE_GATE:
+            return 1;
+
+        case SYSCTL_CLK_SD_CARD_SRC:
+            return 1.0/(double)(((sysctl_clk->hs_sdclk_cfg >> 6) & 0x7) + 1);      /* maxinum = 1/2, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_SD0_CARD_GATE:
+        case SYSCTL_CLK_SD1_CARD_GATE:
+            return 1;
+
+        case SYSCTL_CLK_PLL0_DIV16:
+            return 1.0/16;
+        case SYSCTL_CLK_USB_REF_50M:
+            return 1.0/(double)(((sysctl_clk->hs_spi_cfg >> 15) & 0x7) + 1);        /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_USB0_REF_GATE:
+        case SYSCTL_CLK_USB1_REF_GATE:
+            return 1;
+
+        case SYSCTL_CLK_SD_TIMER_SRC:
+            return 1.0/(double)(((sysctl_clk->hs_sdclk_cfg >> 15) & 0x1F) + 1);      /* maxinum = 1/24, 1/24 --- 1/32 */
+        case SYSCTL_CLK_SD0_TIMER_GATE:
+        case SYSCTL_CLK_SD1_TIMER_GATE:
+            return 1;
+
+        /*--------------------------- LS CLOCK ------------------------------------*/
+        case SYSCTL_CLK_LS_APB_SRC:
+            return 1.0/(double)(((sysctl_clk->ls_clkdiv_cfg >> 0) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_UART0_APB_GATE:
+        case SYSCTL_CLK_UART1_APB_GATE:
+        case SYSCTL_CLK_UART2_APB_GATE:
+        case SYSCTL_CLK_UART3_APB_GATE:
+        case SYSCTL_CLK_UART4_APB_GATE:
+        case SYSCTL_CLK_I2C0_APB_GATE:
+        case SYSCTL_CLK_I2C1_APB_GATE:
+        case SYSCTL_CLK_I2C2_APB_GATE:
+        case SYSCTL_CLK_I2C3_APB_GATE:
+        case SYSCTL_CLK_I2C4_APB_GATE:
+        case SYSCTL_CLK_GPIO_APB_GATE:
+        case SYSCTL_CLK_PWM_APB_GATE:
+        case SYSCTL_CLK_JAMLINK0_APB_GATE:
+        case SYSCTL_CLK_JAMLINK1_APB_GATE:
+        case SYSCTL_CLK_JAMLINK2_APB_GATE:
+        case SYSCTL_CLK_JAMLINK3_APB_GATE:
+        case SYSCTL_CLK_ADC_APB_GATE:
+            return 1;
+
+        case SYSCTL_CLK_UART0_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 0) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_UART1_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 3) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_UART2_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 6) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_UART3_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 9) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_UART4_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 12) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+
+        case SYSCTL_CLK_JAMLINK_CO_DIV:
+            return 1.0/(double)(2 * (((sysctl_clk->ls_clkdiv_cfg >> 23) & 0xFF) + 1));      /* 1/2, 1/4, 1/8 --- 1/512 */
+        case SYSCTL_CLK_JAMLINK0_CO_GATE:
+        case SYSCTL_CLK_JAMLINK1_CO_GATE:
+        case SYSCTL_CLK_JAMLINK2_CO_GATE:
+        case SYSCTL_CLK_JAMLINK3_CO_GATE:
+            return 1;
+
+        case SYSCTL_CLK_I2C0_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 15) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_I2C1_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 18) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_I2C2_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 21) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_I2C3_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 24) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_I2C4_CORE:
+            return 1.0/(double)(((sysctl_clk->uart_i2c_clkdiv_cfg >> 27) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+
+        case SYSCTL_CLK_ADC:
+            return 1.0/(double)(((sysctl_clk->ls_clkdiv_cfg >> 3) & 0x3FF) + 1);      /* 1/1, 1/2, 1/3 --- 1/1024 */
+
+        case SYSCTL_CLK_GOIP_DEBOUNCE:
+            return 1.0/(double)(((sysctl_clk->ls_clkdiv_cfg >> 13) & 0x3FF) + 1);      /* 1/1, 1/2, 1/3 --- 1/1024 */
+
+        /*--------------------------- SYSCTL CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SYSCTRL_APB_SRC:
+            /* return 1.0/(double)(((sysctl_clk->sysctl_clk_div_cfg >> 0) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8  */
+            return 1;
+        case SYSCTL_CLK_WDT0_APB_GATE:
+        case SYSCTL_CLK_WDT1_APB_GATE:
+        case SYSCTL_CLK_TIMER_APB_GATE:
+        case SYSCTL_CLK_IOMUX_APB_GATE:
+        case SYSCTL_CLK_MAILBOX_APB_GATE:
+            return 1;
+
+        case SYSCTL_CLK_HDI_CORE:
+            return 1.0/(double)(((sysctl_clk->sysctl_clk_div_cfg >> 28) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+
+        case SYSCTL_CLK_TIMESTAMP:
+            return 1.0/(double)(((sysctl_clk->sysctl_clk_div_cfg >> 15) & 0x1F) + 1);      /* 1/1, 1/2, 1/3 --- 1/32 */
+
+        case SYSCTL_CLK_TEMP_SENSOR:
+            return 1.0/(double)(((sysctl_clk->sysctl_clk_div_cfg >> 20) & 0xFF) + 1);      /* 1/1, 1/2, 1/3 --- 1/256 */
+
+        case SYSCTL_CLK_WDT0:
+            return 1.0/(double)(((sysctl_clk->sysctl_clk_div_cfg >> 3) & 0x3F) + 1);      /* 1/1, 1/2, 1/3 --- 1/64 */
+
+        case SYSCTL_CLK_WDT1:
+            return 1.0/(double)(((sysctl_clk->sysctl_clk_div_cfg >> 9) & 0x3F) + 1);      /* 1/1, 1/2, 1/3 --- 1/64 */
+
+        /*--------------------------- TIMER CLOCK ------------------------------------*/
+        case SYSCTL_CLK_TIMERX_PULSE_IN:
+            return 1;
+        case SYSCTL_CLK_TIMER0_SRC:
+            return 1.0/(double)(((sysctl_clk->timer_clk_cfg >> 0) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_TIMER0:
+            return 1;
+
+        case SYSCTL_CLK_TIMER1_SRC:
+            return 1.0/(double)(((sysctl_clk->timer_clk_cfg >> 3) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_TIMER1:
+            return 1;
+
+        case SYSCTL_CLK_TIMER2_SRC:
+            return 1.0/(double)(((sysctl_clk->timer_clk_cfg >> 6) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_TIMER2:
+            return 1;
+
+        case SYSCTL_CLK_TIMER3_SRC:
+            return 1.0/(double)(((sysctl_clk->timer_clk_cfg >> 9) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_TIMER3:
+            return 1;
+
+        case SYSCTL_CLK_TIMER4_SRC:
+            return 1.0/(double)(((sysctl_clk->timer_clk_cfg >> 12) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_TIMER4:
+            return 1;
+
+        case SYSCTL_CLK_TIMER5_SRC:
+            return 1.0/(double)(((sysctl_clk->timer_clk_cfg >> 15) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_TIMER5:
+            return 1;
+
+
+        /*--------------------------- SHRM CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SHRM_SRC:
+            return 1;
+        case SYSCTL_CLK_SHRM_DIV2:
+            return 1.0/2;
+        case SYSCTL_CLK_SHRM_AXIS_SLAVE:
+        case SYSCTL_CLK_DECOMPRESS_AXI:
+            return 1;
+
+        case SYSCTL_CLK_SHRM_APB:
+            return 1.0/(double)(((sysctl_clk->shrm_clk_cfg >> 18) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+
+        case SYSCTL_CLK_SHRM_AXI_SRC:
+        case SYSCTL_CLK_NONAI2D_AXI_GATE:
+            return 1;
+
+        /*--------------------------- SEC CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SEC_APB:
+            return 1.0/(double)(((sysctl_clk->sec_clk_div >> 1) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_SEC_FIX:
+            return 1.0/(double)(((sysctl_clk->sec_clk_div >> 6) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+
+        case SYSCTL_CLK_SEC_AXI:
+            return 1.0/(double)(((sysctl_clk->sec_clk_div >> 11) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+
+        /*--------------------------- USB TEST MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_USB_480M:
+            return 1.0/(double)(((sysctl_clk->usb_test_clk_div >> 1) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+        case SYSCTL_CLK_USB_100M:
+            return 1.0/(double)(((sysctl_clk->usb_test_clk_div >> 4) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+
+        /*--------------------------- DPHY DFT MODE CLOCK ------------------------------------*/
+        case SYSCTL_CLK_DPHY_DFT_MODE:
+            return 1.0/(double)(((sysctl_clk->dphy_test_clk_div >> 1) & 0xF) + 1);      /* 1/1, 1/2, 1/3 --- 1/16 */
+
+        /*--------------------------- SPI2AXI CLOCK ------------------------------------*/
+        case SYSCTL_CLK_SPI2AXI_AXI:
+            return 1.0/(double)(((sysctl_clk->spi2axi_clk_div >> 1) & 0x7) + 1);      /* 1/1, 1/2, 1/3 --- 1/8 */
+
+        default:
+            return 1;
+    }
+}
+
+/*
+ * Calculate the frequency of this clock node.
+ * It searches the entire clock path, calculates the frequency division of each
+ * level starting from the clock source, and finally obtains the frequency of
+ * the current clock node.
+ * 1. For the clock of the root node, use sysctl_boot_get_root_clk_freq(node)
+ *    to get the clock frequency (the frequency division coefficient div=1 at
+ *    this time);
+ * 2. For the clock of the leaf node, use the while loop to search the root
+ *    node of the leaf node and calculate the div on the entire path. After
+ *    finding the root node, use sysctl_boot_get_root_clk_freq(node) * div to
+ *    calculate the frequency of the leaf node.
+ */
+uint32_t sysctl_clk_get_leaf_freq(sysctl_clk_node_e leaf)
+{
+    double div = 1.0;
+    sysctl_clk_node_e node;
+
+    node = leaf;
+
+    if(node == SYSCTL_CLK_TIMERX_PULSE_IN)
+    {
+        return (uint32_t)(50000000 * div);
+    }
+
+    /* calc leaf chain div */
+    while(node > SYSCTL_CLK_ROOT_MAX)
+    {
+        div *= sysctl_clk_get_leaf_div(node);
+        node = sysctl_clk_get_leaf_parent(node);
+    }
+
+    /* get root freq and calc leaf freq */
+    return (uint32_t)(sysctl_boot_get_root_clk_freq(node) * div);
+}
+
+int rt_hw_sysctl_clk_init(void)
+{
+    sysctl_clk = rt_ioremap((void*)CMU_BASE_ADDR, CMU_IO_SIZE);
+    if(!sysctl_clk)
+    {
+        rt_kprintf("sysctl_clk ioremap error\n");
+        return -1;
+    }
+
+    return 0;
+}
+INIT_BOARD_EXPORT(rt_hw_sysctl_clk_init);

+ 611 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_clock/sysctl_clk.h

@@ -0,0 +1,611 @@
+/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SYSCTL_CLK_H__
+#define __SYSCTL_CLK_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* See TRM 2.2.4 Table 2-2-9 */
+typedef struct sysctl_clk {
+    volatile uint32_t cpu0_clk_cfg;             /* 0x00 */
+    volatile uint32_t reserved_0;               /* 0x04 */
+    volatile uint32_t reserved_1;               /* 0x08 */
+    volatile uint32_t reserved_2;               /* 0x0c */
+    volatile uint32_t pmu_clk_cfg;              /* 0x10 */
+    volatile uint32_t reserved0[1];             /* 0x14 */
+    volatile uint32_t hs_clken_cfg;             /* 0x18 */
+    volatile uint32_t hs_sdclk_cfg;             /* 0x1c */
+    volatile uint32_t hs_spi_cfg;               /* 0x20 */
+    volatile uint32_t ls_clken_cfg0;            /* 0x24 */
+    volatile uint32_t ls_clken_cfg1;            /* 0x28 */
+    volatile uint32_t uart_i2c_clkdiv_cfg;      /* 0x2c */
+    volatile uint32_t ls_clkdiv_cfg;            /* 0x30 */
+    volatile uint32_t reserved_3;               /* 0x34 */
+    volatile uint32_t reserved_4;               /* 0x38 */
+    volatile uint32_t reserved_5;               /* 0x3c */
+    volatile uint32_t reserved_6;               /* 0x40 */
+    volatile uint32_t reserved_7;               /* 0x44 */
+    volatile uint32_t reserved1[2];             /* 0x48 0x4c */
+    volatile uint32_t sysctl_clken_cfg;         /* 0x50 */
+    volatile uint32_t timer_clk_cfg;            /* 0x54 */
+    volatile uint32_t sysctl_clk_div_cfg;       /* 0x58 */
+    volatile uint32_t shrm_clk_cfg;             /* 0x5c */
+    volatile uint32_t ddr_clk_cfg;              /* 0x60 */
+    volatile uint32_t reserved_8;               /* 0x64 */
+    volatile uint32_t reserved_9;               /* 0x68 */
+    volatile uint32_t reserved_10;              /* 0x6c */
+    volatile uint32_t reserved_11;              /* 0x70 */
+    volatile uint32_t reserved_12;              /* 0x74 */
+    volatile uint32_t reserved_13;              /* 0x78 */
+    volatile uint32_t reserved2[1];             /* 0x7c */
+    volatile uint32_t sec_clk_div;              /* 0x80 */
+    volatile uint32_t reserved3[31];            /* 0x84 0x88 0x8c 0x90 0x94 0x98 0x9c 0xa0-0xac 0xb0-0xbc 0xc0-0xcc 0xd0-0xdc 0xe0-0xec 0xf0-0xfc*/
+    volatile uint32_t usb_test_clk_div;         /* 0x100 */
+    volatile uint32_t dphy_test_clk_div;        /* 0x104 */
+    volatile uint32_t spi2axi_clk_div;          /* 0x108 */
+} sysctl_clk_t;
+
+/*
+ * Clock Tree and clock node table
+ *
+ * Abbreviations:
+ * - D: DIV
+ * - G: GATE
+ * - M: MUX
+ * - fD: fraDIV
+ */
+typedef enum {
+    /*
+     * First level is sysctl_boot / sysctrl_root module, which
+     * is composed of osc24m, pll[0|1|2|3], pll[0|1|2|3]_[div2|div3|div4] (pllx
+     * outputs 4 signals, namely pllx, div2, div3, and div4).
+     * Plus timerx_pulse_in, which is an external pulse input through the soc
+     * pin (pinmux) as a source of timer clock.
+     *
+     * - osc24m: fixed-clock
+     * - pll[0|1|2|3]: clock generated by PLL
+     * - pll[0|1|2|3]_[div2|div3|div4]: fixed-clock
+     * - timerx_pulse_in: fixed-clock, maxsize is 1MHz
+     *
+     * osc24m ---+--> pll0 ---+--------> pll0 ------->+
+     *           |            +--(D2)--> pll0_div2 -->|
+     *           |            +--(D3)--> pll0_div3 -->|
+     *           |            +--(D4)--> pll0_div4 -->|
+     *           |                                    |
+     *           +--> pll1 ---+--------> pll1 ------->|
+     *           |            +--(D2)--> pll1_div2 -->|
+     *           |            +--(D3)--> pll1_div3 -->|
+     *           |            +--(D4)--> pll1_div4 -->|
+     *           |                                    +--> sysctl_clock
+     *           +--> pll2 ---+--------> pll2 ------->|
+     *           |            +--(D2)--> pll2_div2 -->|
+     *           |            +--(D3)--> pll2_div3 -->|
+     *           |            +--(D4)--> pll2_div4 -->|
+     *           |                                    |
+     *           +--> pll3 ---+--------> pll3 ------->|
+     *           |            +--(D2)--> pll3_div2 -->|
+     *           |            +--(D3)--> pll3_div3 -->|
+     *           |            +--(D4)--> pll3_div4 -->|
+     *           |                                    |
+     *           +----------------------------------->+
+     *                                                |
+     * timerx_pulse_in ------------------------------>+
+     */
+    SYSCTL_CLK_ROOT_OSC_IN = 0,       /* 24M */
+    SYSCTL_CLK_ROOT_TIMERX_PULSE_IN,  /* 50M */
+    SYSCTL_CLK_ROOT_PLL0,             /* 1.6G */
+    SYSCTL_CLK_ROOT_PLL0_DIV_2,       /* 800M */
+    SYSCTL_CLK_ROOT_PLL0_DIV_3,       /* 533M */
+    SYSCTL_CLK_ROOT_PLL0_DIV_4,       /* 400M */
+    SYSCTL_CLK_ROOT_PLL1,             /* 2.376G */
+    SYSCTL_CLK_ROOT_PLL1_DIV_2,       /* 1.188G */
+    SYSCTL_CLK_ROOT_PLL1_DIV_3,       /* 792M */
+    SYSCTL_CLK_ROOT_PLL1_DIV_4,       /* 594M */
+    SYSCTL_CLK_ROOT_PLL2,             /* 2.667G */
+    SYSCTL_CLK_ROOT_PLL2_DIV_2,       /* 1.3335G */
+    SYSCTL_CLK_ROOT_PLL2_DIV_3,       /* 889M */
+    SYSCTL_CLK_ROOT_PLL2_DIV_4,       /* 666.75M */
+    SYSCTL_CLK_ROOT_PLL3,             /* 1.6G */
+    SYSCTL_CLK_ROOT_PLL3_DIV_2,       /* 800M */
+    SYSCTL_CLK_ROOT_PLL3_DIV_3,       /* 533M */
+    SYSCTL_CLK_ROOT_PLL3_DIV_4,       /* 400M */
+    SYSCTL_CLK_ROOT_MAX,
+
+    /*
+     * Second level is sysctl_clock module, which is composed of several clock sub-trees
+     * - CPU0: aclk/pliclk/pclk
+     * - pmu system: pclk
+     * - HS (High Speed) system: hs/sdx/ssix/usbx
+     * - LS (Low Speed) system : ls/uartx/i2cx/gpio/pwm/jamlinkx/audio/adc/codec
+     * - System Control (such as wdt, timer, iomux, mailbox): sysctl/wdtx/timer/iomux/mailbox/hdi/stc/ts
+     * - Timer: timerx
+     * - shrm (share memory) system: shrm/decompress/gsdma/nonai2d/pdma
+     * - sec (security) system: aclk/fixclk/pclk
+     * - usb test mode: clk480/clk100
+     * - dphy dft mode clock: dphy_test_clk
+     * - spi2axi clock: aclk
+     */
+
+    /*
+     * cpu0 clock tree:
+     *
+     * pll0_div2 --(DG)--> cpu0_src --+--(DG)--> cpu0_plic
+     *                                |--(D)---> cpu0_aclk
+     *                                +--(G)---> cpu0_noc_ddrcp4
+     * pll0_div4 --(DG)--> cpu0_pclk
+     */
+
+    /* root node: pll0_div2 */
+    SYSCTL_CLK_CPU0_SRC,        /* cpu0 core,defualt 800MHz ---> select pll0_div_2 */
+    SYSCTL_CLK_CPU0_PLIC,       /* cpu0 plic clk,400MHz */
+    SYSCTL_CLK_CPU0_ACLK,       /* cpu0 axi clk,400MHz */
+    SYSCTL_CLK_CPU0_NOC_DDRCP4, /* ddrc axi4clk & noc AXI clock,400MHz */
+    /* root node: pll0_div4 */
+    SYSCTL_CLK_CPU0_PCLK,       /* cpu0 apb pclk,200MHz */
+
+    /*
+     * pmu system clock tree:
+     *
+     * osc24m -->(G)--> pmu_pclk
+     *
+     * - pmu_pclk: pmu apb clk gate
+     */
+    SYSCTL_CLK_PMU_PCLK,
+
+    /*
+     * High-Speed system clock tree
+     *
+     * pll0_div4 --+--(D)--> hs_hclk_high_src --+--(G)----> hs_hclk_high_gate
+     *             |                            |
+     *             |                            +--(DG)--> hs_hclk_src --+--(G)--> sd0_ahb_gate
+     *             |                                                     |--(G)--> sd1_ahb_gate
+     *             |                                                     |--(G)--> ssi1_ahb_gate
+     *             |                                                     |--(G)--> ssi2_ahb_gate
+     *             |                                                     |--(G)--> usb0_ahb_gate
+     *             |                                                     +--(G)--> usb1_ahb_gate
+     *             |
+     *             +--(DG)--> ssi0_axi
+     *             |--(DG)--> ssi1
+     *             |--(DG)--> ssi2
+     *             +--(DG)--> qspi_axi_src --+--(G)--> ssi1_aclk_gate
+     *             |                         |
+     *             |                         +--(G)--> ssi2_aclk_gate
+     *             |
+     *             +--(DG)--> sd_card_src --+--(G)--> sd0_card_gate
+     *                                      |
+     *                                      +--(G)--> sd1_card_gate
+     *
+     * pll0_div2 --\
+     *             (M)--(G)--> ssi0
+     * pll2_div4 --/
+     *
+     *
+     * pll2_div4 --(DG)--> sd_axi_src --+--(G)--> sd0_axi_gate
+     *                                  |--(G)--> sd1_axi_gate
+     *                                  |--(G)--> sd0_base_gate
+     *                                  +--(G)--> sd1_base_gate
+     *
+     *
+     *
+     * osc24m -----------------------------------------\
+     *                                                (M)--+--(G)--> usb0_ref_gate
+     * pll0 --(D)--> pll0_div16 --(D)--> usb_ref_50m --/   |
+     *                                                     +--(G)--> usb1_ref_gate
+     *
+     *
+     * osc24m --(DG)--> sd_timer_src --+--(G)--> sd0_timer_gate
+     *                                 |
+     *                                 +--(G)--> sd1_timer_gate
+     */
+
+    /* root node: pll0_div4, through hs_hclk_high_src */
+    SYSCTL_CLK_HS_HCLK_HIGH_SRC,
+    SYSCTL_CLK_HS_HCLK_HIGH_GATE,
+    SYSCTL_CLK_HS_HCLK_SRC,
+    SYSCTL_CLK_SD0_AHB_GATE,
+    SYSCTL_CLK_SD1_AHB_GATE,
+    SYSCTL_CLK_USB0_AHB_GATE,
+    SYSCTL_CLK_USB1_AHB_GATE,
+    SYSCTL_CLK_SSI1_AHB_GATE,
+    SYSCTL_CLK_SSI2_AHB_GATE,
+
+    /* root node: pll0_div4 */
+    SYSCTL_CLK_SSI0_AXI,
+    SYSCTL_CLK_SSI1,
+    SYSCTL_CLK_SSI2,
+    SYSCTL_CLK_QSPI_AXI_SRC,
+    SYSCTL_CLK_SSI1_ACLK_GATE,
+    SYSCTL_CLK_SSI2_ACLK_GATE,
+
+    /*root node: pll0_div4, through sd_card_src */
+    SYSCTL_CLK_SD_CARD_SRC,
+    SYSCTL_CLK_SD0_CARD_GATE,
+    SYSCTL_CLK_SD1_CARD_GATE,
+
+    /* root node: pll0_div2 MUX pll2_div4 */
+    SYSCTL_CLK_SSI0, /* ospi core clk */
+
+    /* root node: pll2_div4 */
+    SYSCTL_CLK_SD_AXI_SRC,
+    SYSCTL_CLK_SD0_AXI_GATE,
+    SYSCTL_CLK_SD1_AXI_GATE,
+    SYSCTL_CLK_SD0_BASE_GATE,
+    SYSCTL_CLK_SD1_BASE_GATE,
+
+    /* root node: pll0_div16 */
+    SYSCTL_CLK_PLL0_DIV16,
+    SYSCTL_CLK_USB_REF_50M, /* usbx reference clk */
+    SYSCTL_CLK_USB0_REF_GATE,
+    SYSCTL_CLK_USB1_REF_GATE,
+
+    /* root node: osc24m */
+    SYSCTL_CLK_SD_TIMER_SRC,
+    SYSCTL_CLK_SD0_TIMER_GATE,
+    SYSCTL_CLK_SD1_TIMER_GATE,
+
+    /* Low-Speed system clock tree
+     *
+     *  pll0_div4 --(DG)--+--> ls_apb_src --+--(G) --> uart0_apb_gate
+     *                    |                 +--(G) --> uart1_apb_gate
+     *                    |                 +--(G) --> uart2_apb_gate
+     *                    |                 +--(G) --> uart3_apb_gate
+     *                    |                 +--(G) --> uart4_apb_gate
+     *                    |                 +--(G) --> i2c0_apb_gate
+     *                    |                 +--(G) --> i2c1_apb_gate
+     *                    |                 +--(G) --> i2c2_apb_gate
+     *                    |                 +--(G) --> i2c3_apb_gate
+     *                    |                 +--(G) --> i2c4_apb_gate
+     *                    |                 +--(G) --> gpio_apb_gate
+     *                    |                 +--(G) --> pwm_apb_gate
+     *                    |                 +--(G) --> jamlink0_apb_gate
+     *                    |                 +--(G) --> jamlink1_apb_gate
+     *                    |                 +--(G) --> jamlink2_apb_gate
+     *                    |                 +--(G) --> jamlink3_apb_gate
+     *                    |                 +--(G) --> audio_apb_gate
+     *                    |                 +--(G) --> adc_apb_gate
+     *                    |                 +--(G) --> codec_apb_gate
+     *                    |
+     *                    +--(DG)--> i2c0_core
+     *                    +--(DG)--> i2c1_core
+     *                    +--(DG)--> i2c2_core
+     *                    +--(DG)--> i2c3_core
+     *                    +--(DG)--> i2c4_core
+     *                    +--(DG)--> codec_adc
+     *                    +--(DG)--> codec_dac
+     *                    +--(DG)--> audio_dev
+     *                    +--(DG)--> pdm
+     *                    +--(DG)--> adc
+     *
+     * pll0 --(D)--> pll0_div16 --+--(DG)--> uart0_core
+     *                            +--(DG)--> uart1_core
+     *                            +--(DG)--> uart2_core
+     *                            +--(DG)--> uart3_core
+     *                            +--(DG)--> uart4_core
+     *
+     * pll0 --(D)--> pll0_div16 --(D)--> jamlink_CO_div --+--(G)--> jamlink0_CO_gate
+     *                                                    +--(G)--> jamlink1_CO_gate
+     *                                                    +--(G)--> jamlink2_CO_gate
+     *                                                    +--(G)--> jamlink3_CO_gate
+     *
+     * osc24m --(DG)--> gpio_debounce
+     */
+
+    /* root node: pll0_div4, through ls_apb_src */
+    SYSCTL_CLK_LS_APB_SRC,
+    SYSCTL_CLK_UART0_APB_GATE,
+    SYSCTL_CLK_UART1_APB_GATE,
+    SYSCTL_CLK_UART2_APB_GATE,
+    SYSCTL_CLK_UART3_APB_GATE,
+    SYSCTL_CLK_UART4_APB_GATE,
+    SYSCTL_CLK_I2C0_APB_GATE,
+    SYSCTL_CLK_I2C1_APB_GATE,
+    SYSCTL_CLK_I2C2_APB_GATE,
+    SYSCTL_CLK_I2C3_APB_GATE,
+    SYSCTL_CLK_I2C4_APB_GATE,
+    SYSCTL_CLK_GPIO_APB_GATE,
+    SYSCTL_CLK_PWM_APB_GATE,
+    SYSCTL_CLK_JAMLINK0_APB_GATE,
+    SYSCTL_CLK_JAMLINK1_APB_GATE,
+    SYSCTL_CLK_JAMLINK2_APB_GATE,
+    SYSCTL_CLK_JAMLINK3_APB_GATE,
+    SYSCTL_CLK_AUDIO_APB_GATE,
+    SYSCTL_CLK_ADC_APB_GATE,
+    SYSCTL_CLK_CODEC_APB_GATE,
+
+    /* root node: pll0_div4 */
+    SYSCTL_CLK_I2C0_CORE,
+    SYSCTL_CLK_I2C1_CORE,
+    SYSCTL_CLK_I2C2_CORE,
+    SYSCTL_CLK_I2C3_CORE,
+    SYSCTL_CLK_I2C4_CORE,
+    SYSCTL_CLK_CODEC_ADC,
+    SYSCTL_CLK_CODEC_DAC,
+    SYSCTL_CLK_AUDIO_DEV,
+    SYSCTL_CLK_PDM,
+    SYSCTL_CLK_ADC,
+
+    /* root node: pll0_div16 */
+    SYSCTL_CLK_UART0_CORE,
+    SYSCTL_CLK_UART1_CORE,
+    SYSCTL_CLK_UART2_CORE,
+    SYSCTL_CLK_UART3_CORE,
+    SYSCTL_CLK_UART4_CORE,
+
+    /* root node: pll0_div16, through jamlink_CO_div */
+    SYSCTL_CLK_JAMLINK_CO_DIV,
+    SYSCTL_CLK_JAMLINK0_CO_GATE,
+    SYSCTL_CLK_JAMLINK1_CO_GATE,
+    SYSCTL_CLK_JAMLINK2_CO_GATE,
+    SYSCTL_CLK_JAMLINK3_CO_GATE,
+
+    /* root node: osc24m */
+    SYSCTL_CLK_GOIP_DEBOUNCE,
+
+    /*
+     * System Control clock tree
+     *
+     * pll0_div16 --> sysctl_apb_src --+--(G)--> wdt0_apb_gate
+     *                                 +--(G)--> wdt1_apb_gate
+     *                                 +--(G)--> timer_apb_gate
+     *                                 +--(G)--> iomux_apb_gate
+     *                                 +--(G)--> mailbox_apb_gate
+     *
+     * pll0_div4 --(DG)--> hdi_core
+     *
+     * pll1_div4 --(DG)--> timestamp
+     *
+     * osc24m --(D)--> temp_sensor
+     *
+     * osc24m --+--(DG)--> wdt0
+     *          |
+     *          +--(DG)--> wdt1
+     */
+
+     /* root node: pll0_div16, through sysctl_apb_src */
+    SYSCTL_CLK_SYSCTRL_APB_SRC,
+    SYSCTL_CLK_WDT0_APB_GATE,
+    SYSCTL_CLK_WDT1_APB_GATE,
+    SYSCTL_CLK_TIMER_APB_GATE,
+    SYSCTL_CLK_IOMUX_APB_GATE,
+    SYSCTL_CLK_MAILBOX_APB_GATE,
+
+    /* root node: pll0_div4 */
+    SYSCTL_CLK_HDI_CORE,
+
+    /* root node: pll1_div4 */
+    SYSCTL_CLK_TIMESTAMP,
+
+    /* root node: osc24m */
+    SYSCTL_CLK_TEMP_SENSOR,
+
+    /* root node: osc24m */
+    SYSCTL_CLK_WDT0,
+    SYSCTL_CLK_WDT1,
+
+    /*
+     * timer clock tree
+     *
+     * pll0_div16 --(D)--> timer0_src --\
+     *                                  (M)--(G)-->timer0
+     * timerx_pulse_in -----------------/
+     *
+     * pll0_div16 --(D)--> timer1_src --\
+     *                                  (M)--(G)-->timer1
+     * timerx_pulse_in -----------------/
+     *
+     * pll0_div16 --(D)--> timer2_src --\
+     *                                  (M)--(G)-->timer2
+     * timerx_pulse_in -----------------/
+     *
+     * pll0_div16 --(D)--> timer3_src --\
+     *                                  (M)--(G)-->timer3
+     * timerx_pulse_in -----------------/
+     *
+     * pll0_div16 --(D)--> timer4_src --\
+     *                                  (M)--(G)-->timer4
+     * timerx_pulse_in -----------------/
+     *
+     * pll0_div16 --(D)--> timer5_src --\
+     *                                  (M)--(G)-->timer5
+     * timerx_pulse_in -----------------/
+     */
+
+    /* root node: pll0_div16 & timerx_pulse_in */
+    SYSCTL_CLK_TIMERX_PULSE_IN,
+    SYSCTL_CLK_TIMER0_SRC,
+    SYSCTL_CLK_TIMER0,
+    SYSCTL_CLK_TIMER1_SRC,
+    SYSCTL_CLK_TIMER1,
+    SYSCTL_CLK_TIMER2_SRC,
+    SYSCTL_CLK_TIMER2,
+    SYSCTL_CLK_TIMER3_SRC,
+    SYSCTL_CLK_TIMER3,
+    SYSCTL_CLK_TIMER4_SRC,
+    SYSCTL_CLK_TIMER4,
+    SYSCTL_CLK_TIMER5_SRC,
+    SYSCTL_CLK_TIMER5,
+
+    /*
+     * shrm system clock tree
+     *
+     * pll0_div2 --\
+     *             (M)--(G)--> shrm_src --+--(D)--> shrm_div2 --(G)--> shrm_axi_slave
+     * pll3_div2 --/                      |
+     *                                    +--(G)--> decompress_axi
+     *
+     * pll0_div4 -->(DG)--> shrm_apb
+     *
+     * pll0_div4 -->(G)--> shrm_axi_src --+--(G)--> gsdma_axi_gate
+     *                                    +--(G)--> nonai2d_axi_gate
+     *                                    +--(G)--> peri_dma_axi_gate
+     */
+
+    /* root node: pll0_div2 & pll3_div2 */
+    SYSCTL_CLK_SHRM_SRC,
+    SYSCTL_CLK_SHRM_DIV2,
+    SYSCTL_CLK_SHRM_AXIS_SLAVE,
+    SYSCTL_CLK_DECOMPRESS_AXI,
+
+    /* root node: pll0_div4 */
+    SYSCTL_CLK_SHRM_APB,
+
+    /* root node: pll0_div4, through shrm_axi_src */
+    SYSCTL_CLK_SHRM_AXI_SRC,
+    SYSCTL_CLK_GSDMA_AXI_GATE,
+    SYSCTL_CLK_NONAI2D_AXI_GATE,
+    SYSCTL_CLK_PERI_DMA_AXI_GATE,
+
+    /*
+     * Security system clock tree
+     *
+     * pll0_div4 --(DG)--> sec_apb
+     *
+     * pll1_div4 --+--(DG)--> sec_fix
+     *             |
+     *             +--(DG)--> sec_axi
+     */
+
+    /* root node: pll0_div4 */
+    SYSCTL_CLK_SEC_APB,
+
+    /* root node: pll1_div4 */
+    SYSCTL_CLK_SEC_FIX,
+    SYSCTL_CLK_SEC_AXI,
+
+    /*
+     * usb test mode clock tree
+     *
+     * pll1 --(DG)--> usb_480m
+     *
+     * pll0_div4 --(DG)--> usb_100m
+     */
+
+    /* root node: pll1 */
+    SYSCTL_CLK_USB_480M,
+
+    /* root node: pll0_div4 */
+    SYSCTL_CLK_USB_100M,
+
+    /*
+     * dphy dft mode clock tree
+     *
+     * pll0 --(DG)--> dphy_dft_mode
+     */
+
+    /* root node: pll0 */
+    SYSCTL_CLK_DPHY_DFT_MODE,
+
+    /*
+     * spi2axi clock tree
+     *
+     * pll0_div4 --(DG)--> spi2axi_axi
+     */
+
+    /* root node: pll0_div4 */
+    SYSCTL_CLK_SPI2AXI_AXI,
+
+    SYSCTL_CLK_NODE_MAX,
+} sysctl_clk_node_e;
+
+#define SYSCTL_READ_ENABLE    (1 << 0)
+#define SYSCTL_READ_DISABLE   (0 << 0)
+#define SYSCTL_WRITE_ENABLE   (1 << 1)
+#define SYSCTL_WRITE_DISABLE  (0 << 1)
+
+/*
+ * API for root clock. 24M, PLL0-3, these 5 clocks are root clocks
+ * It is assumed here that the big core has read and write permissions to the
+ * root clock, so the properties of clk are not judged in these APIs,
+ * because these APIs are only for the root clock.
+ */
+
+/*
+ * Get the bypass status of the PLL.
+ * If it is bypas, the PLL output is 24M OSC clock.
+ */
+bool sysctl_boot_get_root_clk_bypass(sysctl_clk_node_e clk);
+void sysctl_boot_set_root_clk_bypass(sysctl_clk_node_e clk, bool enable);
+
+/* Enable pll, enable 24M clock&pll */
+bool sysctl_boot_get_root_clk_en(sysctl_clk_node_e clk);
+void sysctl_boot_set_root_clk_en(sysctl_clk_node_e clk, bool enable);
+
+/* Get the phase-locked loop lock status */
+bool sysctl_boot_get_root_clk_lock(sysctl_clk_node_e clk);
+
+/* Get the root clock frequency */
+uint32_t sysctl_boot_get_root_clk_freq(sysctl_clk_node_e clk);
+
+/*
+ * Set the PLL clock frequency
+ * The formula for setting the PLL clock frequency is:
+ * pll_out_freq = (double)OSC_CLOCK_FREQ_24M * (double)(fbdiv+1) / (double)(refdiv+1) / (double)(outdiv+1)
+ */
+bool sysctl_boot_set_root_clk_freq(sysctl_clk_node_e clk, uint32_t fbdiv, uint32_t refdiv, uint32_t outdiv, uint32_t bwadj);
+
+/*
+ * API for trunk and leaf nodes in the clock tree, i.e. clocks other than the five root clocks.
+ */
+
+/*
+ * Set the leaf node clock source on the clock tree.
+ * Please set it according to the clock tree.
+ * Many clock nodes have only one clock source, so the setting will return false.
+ */
+bool sysctl_clk_set_leaf_parent(sysctl_clk_node_e leaf, sysctl_clk_node_e parent);
+
+/* Get the clock source of the leaf node in the clock tree */
+sysctl_clk_node_e sysctl_clk_get_leaf_parent(sysctl_clk_node_e leaf);
+
+/*
+ * Set the clock node enable.
+ * Note: only set the enable of this clock node, and do not set the enable of
+ * the upstream clock.
+ * Difference from Linux kernel: Linux kernel clock framework will automatically
+ * set the enable of the upstream clock. The test code does not have kernel
+ * framework, so only the enable of the clock of this node is set.
+ */
+void sysctl_clk_set_leaf_en(sysctl_clk_node_e leaf, bool enable);
+
+/* Get the enable status of this clock node */
+bool sysctl_clk_get_leaf_en(sysctl_clk_node_e leaf);
+
+/* Set the frequency division factor of this clock node */
+bool sysctl_clk_set_leaf_div(sysctl_clk_node_e leaf, uint32_t numerator, uint32_t denominator);
+
+/* Get the frequency division coefficient of this clock node */
+double sysctl_clk_get_leaf_div(sysctl_clk_node_e leaf);
+
+/*
+ * Calculate clock freqency.
+ * This API searches the entire clock path, calculates the frequency division
+ * at each level starting from the clock source, and finally obtains the
+ * current clock frequency.
+ */
+uint32_t sysctl_clk_get_leaf_freq(sysctl_clk_node_e leaf);
+
+#endif /* __SYSCTL_CLK_H__ */

+ 19 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_power/SConscript

@@ -0,0 +1,19 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('Sysctl_power', src, depend = [''], CPPPATH = CPPPATH)
+
+objs = [group]
+
+file_list = os.listdir(cwd)
+
+for item in file_list:
+    if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
+        objs = objs + SConscript(os.path.join(item, 'SConscript'))
+
+Return('objs')

+ 775 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_power/sysctl_pwr.c

@@ -0,0 +1,775 @@
+/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <stdio.h>
+#include "sysctl_pwr.h"
+#include "drv_hardlock.h"
+#include "ioremap.h"
+#include "board.h"
+
+volatile sysctl_pwr_s* sysctl_pwr = (volatile sysctl_pwr_s*)PWR_BASE_ADDR;
+
+/*****************************************************************************************
+*                                SET POWER DOMAIN'S TIME
+*   powerdomain:power domain
+*   timtype: idleReq_to_idleAck, idleAck_to_idle.....
+*   tim_value: ack_to_tim, idle_to_tim......
+*****************************************************************************************/
+
+/* ack timeout value, lpi idleReq to idleAck */
+bool sysctl_pwr_set_ack_to_tim(volatile uint32_t *reg, uint32_t ack_to_tim)
+{
+    volatile uint32_t *ret = reg;
+
+    if((NULL == reg) || (ack_to_tim > 0x1F))
+        return false;
+    else
+    {
+        *ret &= 0xffffffe0;
+        *reg = (*ret) | (ack_to_tim << 0);
+
+        return true;
+    }
+}
+
+/* idle timeout value, lpi idleAck to idle */
+bool sysctl_pwr_set_idle_to_tim(volatile uint32_t *reg, uint32_t idle_to_tim)
+{
+    volatile uint32_t *ret = reg;
+
+    if((NULL == reg) || (idle_to_tim > 0x1F))
+        return false;
+    else
+    {
+        *ret &= 0xffffe0ff;
+        *reg = (*ret) | (idle_to_tim << 8);
+
+        return true;
+    }
+}
+
+/* NOC power controller in idle min time, idle to idelReq(inactive) */
+bool sysctl_pwr_set_idle_hd_tim(volatile uint32_t *reg, uint32_t idle_hd_tim)
+{
+    volatile uint32_t *ret = reg;
+
+    if((NULL == reg) || (idle_hd_tim > 0x3F))
+        return false;
+    else
+    {
+        *ret &= 0xffc0ffff;
+        *reg = (*ret) | (idle_hd_tim << 16);
+
+        return true;
+    }
+}
+
+/*
+ * After turning ISO on/off, you need to wait for a while to ensure that the
+ * isolation cells in the power domain are actually enabled/disabled.
+ */
+bool sysctl_pwr_set_iso_su_tim(volatile uint32_t *reg, uint32_t iso_su_tim)
+{
+    volatile uint32_t *ret = reg;
+
+    if((NULL == reg) || (iso_su_tim > 0xF))
+        return false;
+    else
+    {
+        *ret &= 0xfffffff0;
+        *reg = (*ret) | (iso_su_tim << 0);
+
+        return true;
+    }
+}
+
+/*
+ * After powering off a power domain, it takes some time to exit the
+ * power-off state.
+ */
+bool sysctl_pwr_set_pd_hd_tim(volatile uint32_t *reg, uint32_t pd_hd_tim)
+{
+    volatile uint32_t *ret = reg;
+
+    if((NULL == reg) || (pd_hd_tim > 0xFF))
+        return false;
+    else
+    {
+        *ret &= 0xfffff00f;
+        *reg = (*ret) | (pd_hd_tim << 4);
+
+        return true;
+    }
+}
+
+/*
+ * After restoring the power supply of a power domain (bringup), you need to
+ * wait for a period of time to ensure that the power supply of the power domain
+ * is fully restored.
+ */
+bool sysctl_pwr_set_pwr_su_tim(volatile uint32_t *reg, uint32_t pwr_su_tim)
+{
+    volatile uint32_t *ret = reg;
+
+    if((NULL == reg) || (pwr_su_tim > 0xFF))
+        return false;
+    else
+    {
+        *ret &= 0xfff00fff;
+        *reg = (*ret) | (pwr_su_tim << 12);
+
+        return true;
+    }
+}
+
+/* set cpu1 wait for interrupt time */
+bool sysctl_pwr_set_wfi_tim(volatile uint32_t *reg, uint32_t wfi_tim)
+{
+    volatile uint32_t *ret = reg;
+
+    if((NULL == reg) || (wfi_tim > 0xFFF))
+        return false;
+    else
+    {
+        *ret &= 0x000fffff;
+        *reg = (*ret) | (wfi_tim << 20);
+
+        return true;
+    }
+}
+
+bool sysctl_pwr_set_tim(sysctl_pwr_domain_e powerdomain, sysctl_pwr_tim_e timtype, uint32_t tim_value)
+{
+    volatile uint32_t *pwr_reg = NULL;
+    volatile uint32_t *lpi_reg = NULL;
+    volatile uint32_t *wfi_reg = NULL;
+
+    if((powerdomain >= SYSCTL_PD_MAX) || (timtype >= SYSCTL_PWR_MAX_TIM))
+        return false;
+
+    switch(powerdomain)
+    {
+        case SYSCTL_PD_CPU1:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->cpu1_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->cpu1_lpi_tim;
+            wfi_reg = (volatile uint32_t *)&sysctl_pwr->cpu1_pwr_tim;
+            break;
+        }
+        case SYSCTL_PD_AI:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->ai_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->ai_lpi_tim;
+            break;
+        }
+        case SYSCTL_PD_DISP:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->disp_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->disp_lpi_tim;
+            break;
+        }
+        case SYSCTL_PD_VPU:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->vpu_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->vpu_lpi_tim;
+            break;
+        }
+        case SYSCTL_PD_DPU:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->dpu_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->dpu_lpi_tim;
+            break;
+        }
+        default:
+            return false;
+    }
+
+    switch(timtype)
+    {
+        case SYSCTL_PWR_ACK_TO_TIM:
+            return sysctl_pwr_set_ack_to_tim(pwr_reg, tim_value);
+        case SYSCTL_PWR_IDLE_TO_TIM:
+            return sysctl_pwr_set_idle_to_tim(pwr_reg, tim_value);
+        case SYSCTL_PWR_IDLE_HD_TIM:
+            return sysctl_pwr_set_idle_hd_tim(pwr_reg, tim_value);
+        case SYSCTL_PWR_ISO_SU_TIM:
+            return sysctl_pwr_set_iso_su_tim(lpi_reg, tim_value);
+        case SYSCTL_PWR_PD_HD_TIM:
+            return sysctl_pwr_set_pd_hd_tim(lpi_reg, tim_value);
+        case SYSCTL_PWR_SU_TIM:
+            return sysctl_pwr_set_pwr_su_tim(lpi_reg, tim_value);
+        case SYSCTL_PWR_WFI_TIM:
+            return sysctl_pwr_set_wfi_tim(wfi_reg,tim_value);
+        default:
+            return false;
+    }
+}
+
+/*****************************************************************************************
+*                                GET POWER DOMAIN'S TIME
+*   powerdomain:power domain
+*   timtype: idleReq_to_idleAck, idleAck_to_idle.....
+*   tim_value: ack_to_tim, idle_to_tim......
+*****************************************************************************************/
+
+/* ack timeout value, lpi idleReq to idleAck */
+bool sysctl_pwr_get_ack_to_tim(volatile uint32_t *reg, uint32_t *ack_to_tim)
+{
+    if((NULL == reg) || (NULL == ack_to_tim))
+        return false;
+
+    *ack_to_tim = ((*reg) >> 0) & 0x1F;
+    return true;
+}
+
+/* idle timeout value, lpi idleAck to idle */
+bool sysctl_pwr_get_idle_to_tim(volatile uint32_t *reg, uint32_t *idle_to_tim)
+{
+    if((NULL == reg) || (NULL == idle_to_tim))
+        return false;
+
+    *idle_to_tim = ((*reg) >> 8) & 0x1F;
+    return true;
+}
+
+/* NOC power controller in idle min time, idle to idelReq(inactive) */
+bool sysctl_pwr_get_idle_hd_tim(volatile uint32_t *reg, uint32_t *idle_hd_tim)
+{
+    if((NULL == reg) || (NULL == idle_hd_tim))
+        return false;
+
+    *idle_hd_tim = ((*reg) >> 16) & 0x3F;
+    return true;
+}
+
+/*
+ * After turning ISO on/off, you need to wait for a while to ensure that the
+ * isolation cells in the power domain are actually enabled/disabled.
+ */
+bool sysctl_pwr_get_iso_su_tim(volatile uint32_t *reg, uint32_t *iso_su_tim)
+{
+    if((NULL == reg) || (NULL == iso_su_tim))
+        return false;
+
+    *iso_su_tim = ((*reg) >> 0) & 0xF;
+    return true;
+}
+
+/*
+ * After powering off a power domain, it takes some time to exit the power-off
+ * state.
+ */
+bool sysctl_pwr_get_pd_hd_tim(volatile uint32_t *reg, uint32_t *pd_hd_tim)
+{
+    if((NULL == reg) || (NULL == pd_hd_tim))
+        return false;
+
+    *pd_hd_tim = ((*reg) >> 4) & 0xFF;
+    return true;
+}
+
+/*
+ * After restoring the power supply of a power domain (bringup), you need to
+ * wait for a period of time to ensure that the power supply of the power domain
+ * is fully restored.
+ */
+bool sysctl_pwr_get_pwr_su_tim(volatile uint32_t *reg, uint32_t *pwr_su_tim)
+{
+    if((NULL == reg) || (NULL == pwr_su_tim))
+        return false;
+
+    *pwr_su_tim = ((*reg) >> 12) & 0xFF;
+    return true;
+}
+
+/* cpu1 wait for interrupt time */
+bool sysctl_pwr_get_wfi_tim(volatile uint32_t *reg, uint32_t *wfi_tim)
+{
+    if((NULL == reg) || (NULL == wfi_tim))
+        return false;
+
+    *wfi_tim = (*reg >> 20) & 0xFFF;
+    return true;
+}
+
+bool sysctl_pwr_get_tim(sysctl_pwr_domain_e powerdomain, sysctl_pwr_tim_e timtype, uint32_t *tim_value)
+{
+    volatile uint32_t *pwr_reg = NULL;
+    volatile uint32_t *lpi_reg = NULL;
+    volatile uint32_t *wfi_reg = NULL;
+
+    if((powerdomain >= SYSCTL_PD_MAX) || (timtype >= SYSCTL_PWR_MAX_TIM))
+        return false;
+
+    switch(powerdomain)
+    {
+        case SYSCTL_PD_CPU1:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->cpu1_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->cpu1_lpi_tim;
+            wfi_reg = (volatile uint32_t *)&sysctl_pwr->cpu1_pwr_tim;
+            break;
+        }
+        case SYSCTL_PD_AI:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->ai_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->ai_lpi_tim;
+            break;
+        }
+        case SYSCTL_PD_DISP:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->disp_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->disp_lpi_tim;
+            break;
+        }
+        case SYSCTL_PD_VPU:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->vpu_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->vpu_lpi_tim;
+            break;
+        }
+        case SYSCTL_PD_DPU:
+        {
+            pwr_reg = (volatile uint32_t *)&sysctl_pwr->dpu_pwr_tim;
+            lpi_reg = (volatile uint32_t *)&sysctl_pwr->dpu_lpi_tim;
+            break;
+        }
+        default:
+            return false;
+    }
+
+    switch(timtype)
+    {
+        case SYSCTL_PWR_ACK_TO_TIM:
+            return sysctl_pwr_get_ack_to_tim(pwr_reg, tim_value);
+        case SYSCTL_PWR_IDLE_TO_TIM:
+            return sysctl_pwr_get_idle_to_tim(pwr_reg, tim_value);
+        case SYSCTL_PWR_IDLE_HD_TIM:
+            return sysctl_pwr_get_idle_hd_tim(pwr_reg, tim_value);
+        case SYSCTL_PWR_ISO_SU_TIM:
+            return sysctl_pwr_get_iso_su_tim(lpi_reg, tim_value);
+        case SYSCTL_PWR_PD_HD_TIM:
+            return sysctl_pwr_get_pd_hd_tim(lpi_reg, tim_value);
+        case SYSCTL_PWR_SU_TIM:
+            return sysctl_pwr_get_pwr_su_tim(lpi_reg, tim_value);
+        case SYSCTL_PWR_WFI_TIM:
+            return sysctl_pwr_get_wfi_tim(wfi_reg,tim_value);
+        default:
+            return false;
+    }
+}
+
+
+/*****************************************************************************************
+*                                CPU1 KEEP RESET IN POWEROFF MODE
+*   powerdomain: power domain
+*   enable: poweron, keep reset; poweroff, remove reset
+*****************************************************************************************/
+
+/* It will not be powered off when not working and can be in a reset state */
+bool sysctl_pwr_set_poweroff_keep_reset(sysctl_pwr_domain_e powerdomain, bool enable)
+{
+    volatile uint32_t ret;
+
+    if(SYSCTL_PD_CPU1 == powerdomain)
+    {
+        ret = sysctl_pwr->cpu1_pwr_lpi_ctl;
+        ret &= 0xfff7fff7;
+        if(true == enable)
+        {
+            sysctl_pwr->cpu1_pwr_lpi_ctl = ret | ((1 << 3) | (1 << 19));
+        }
+        else
+        {
+            sysctl_pwr->cpu1_pwr_lpi_ctl = ret | ((0 << 3) | (1 << 19));
+        }
+
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+bool sysctl_pwr_get_poweroff_keep_reset(sysctl_pwr_domain_e powerdomain, bool *enable)
+{
+    if(SYSCTL_PD_CPU1 == powerdomain)
+    {
+        if(sysctl_pwr->cpu1_pwr_lpi_ctl & (1 << 3))
+            *enable = true;
+        else
+            *enable = false;
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+/*****************************************************************************************
+*                                CPU1 AUTO POWERUP OR POWERDOWN
+*   powerdomain: power domain
+*   enable: poweron, enable power control unit auto control mode; poweroff, disable auto
+*****************************************************************************************/
+
+/*
+ * In MAIX3, CPU0 and CPU1 power domains support automatic power on and off
+ * management.
+ */
+bool sysctl_pwr_set_auto_pwr(sysctl_pwr_domain_e powerdomain, bool enable)
+{
+    volatile uint32_t ret;
+
+    if(SYSCTL_PD_CPU1 == powerdomain)
+    {
+        ret = sysctl_pwr->cpu1_pwr_lpi_ctl;
+        ret &= 0xfffbfffb;
+        if(true == enable)
+        {
+            sysctl_pwr->cpu1_pwr_lpi_ctl = ret | ((1 << 2) | (1 << 18));
+        }
+        else
+        {
+            sysctl_pwr->cpu1_pwr_lpi_ctl = ret | ((0 << 2) | (1 << 18));
+        }
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+bool sysctl_pwr_get_auto_pwr(sysctl_pwr_domain_e powerdomain, bool *enable)
+{
+    if(SYSCTL_PD_CPU1 == powerdomain)
+    {
+        if(sysctl_pwr->cpu1_pwr_lpi_ctl & (1 << 2))
+            *enable = true;
+        else
+            *enable = false;
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+/*****************************************************************************************
+*                                POWER DOMAIN REPAIR
+*   powerdomain: power domain
+*****************************************************************************************/
+
+/* When powering up, set the power domain to repair */
+bool sysctl_pwr_set_repair_enable(sysctl_pwr_domain_e powerdomain)
+{
+    switch(powerdomain)
+    {
+        case SYSCTL_PD_AI:
+            sysctl_pwr->ai_pwr_lpi_ctl |= (1 << 4) | (1 << 20);
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool sysctl_pwr_check_repair_done(sysctl_pwr_domain_e powerdomain)
+{
+    switch(powerdomain)
+    {
+        case SYSCTL_PD_AI:
+            return (sysctl_pwr->repair_status & (1 << 1)) ? true:false;
+        case SYSCTL_PD_MAX:
+            return (sysctl_pwr->repair_status & (1 << 2)) ? true:false;
+        default:
+            return false;
+    }
+}
+
+/*****************************************************************************************
+*                                NOC POWER CONTROLLER
+*   powerdomain: power domain
+*   enable: true, connect noc, exit idle mode; false, disconnect noc, go idle mode.
+*****************************************************************************************/
+
+/*
+ * Set different power domains to disconnect/connect to NOC and enter/leave
+ * idle state.
+ */
+bool sysctl_pwr_set_lpi(sysctl_pwr_domain_e powerdomain, bool enable)
+{
+    switch(powerdomain)
+    {
+        case SYSCTL_PD_CPU1:
+        {
+            sysctl_pwr->cpu1_pwr_lpi_ctl |= (true == enable) ? ((1 << 5) | (1 << 21)) : ((1 << 4) | (1 << 20));
+
+            /* usleep(500); */
+            rt_thread_delay(1);
+
+            if(true == enable)
+                return (sysctl_pwr->cpu1_pwr_lpi_state & (1 << 3)) ? true:false;
+            else
+                return (sysctl_pwr->cpu1_pwr_lpi_state & (1 << 2)) ? true:false;
+        }
+        case SYSCTL_PD_AI:
+        {
+            sysctl_pwr->ai_pwr_lpi_ctl |= (true == enable) ? ((1 << 3) | (1 << 19)) : ((1 << 2) | (1 << 18));
+
+            /* usleep(500); */
+            rt_thread_delay(1);
+
+            if(true == enable)
+                return (sysctl_pwr->ai_pwr_lpi_state & (1 << 3)) ? true:false;
+            else
+                return (sysctl_pwr->ai_pwr_lpi_state & (1 << 2)) ? true:false;
+        }
+        case SYSCTL_PD_DISP:
+        {
+            sysctl_pwr->disp_lpi_ctl |= (true == enable) ? ((1 << 3) | (1 << 19)) : ((1 << 2) | (1 << 18));
+
+            /* usleep(500); */
+            rt_thread_delay(1);
+
+            if(true == enable)
+                return (sysctl_pwr->disp_lpi_state & (1 << 3)) ? true:false;
+            else
+                return (sysctl_pwr->disp_lpi_state & (1 << 2)) ? true:false;
+        }
+        case SYSCTL_PD_VPU:
+        {
+            sysctl_pwr->vpu_pwr_lpi_ctl |= (true == enable) ? ((1 << 3) | (1 << 19)) : ((1 << 2) | (1 << 18));
+
+            /* usleep(500); */
+            rt_thread_delay(1);
+
+            if(true == enable)
+                return (sysctl_pwr->vpu_lpi_state & (1 << 3)) ? true:false;
+            else
+                return (sysctl_pwr->vpu_lpi_state & (1 << 2)) ? true:false;
+        }
+        case SYSCTL_PD_DPU:
+        {
+            sysctl_pwr->dpu_pwr_lpi_ctl |= (true == enable) ? ((1 << 3) | (1 << 19)) : ((1 << 2) | (1 << 18));
+
+            /* usleep(500); */
+            rt_thread_delay(1);
+
+            if(true == enable)
+                return (sysctl_pwr->dpu_pwr_lpi_state & (1 << 3)) ? true:false;
+            else
+                return (sysctl_pwr->dpu_pwr_lpi_state & (1 << 2)) ? true:false;
+        }
+        default:
+            return false;
+    }
+}
+
+/*****************************************************************************************
+*                                POWER DOMAIN ON OR OFF
+*   powerdomain: power domain
+*   enable: true for powerup, false for poweroff.
+*****************************************************************************************/
+
+bool sysctl_pwr_set_pwr_reg(volatile uint32_t *regctl, volatile uint32_t *regsta, bool enable)
+{
+    /* enable==true, power on; enable==false, power off */
+    uint32_t mask;
+
+    mask = enable ? 0x2 : 0x1;
+    if (*regsta & mask)
+        return true;
+
+    *regctl = (0x30000 | mask);
+
+    for (int i = 0; i < 100; i++)
+    {
+        if (*regsta & mask)
+            return true;
+        for (int j = 0; j < 5000; j++);
+    }
+
+    return false;
+}
+
+bool sysctl_pwr_set_power(sysctl_pwr_domain_e powerdomain, bool enable)
+{
+    volatile uint32_t *pwr_ctl_reg = NULL;
+    volatile uint32_t *pwr_sta_reg = NULL;
+
+    switch(powerdomain)
+    {
+        case SYSCTL_PD_CPU1:
+        {
+            pwr_ctl_reg = (volatile uint32_t *)&sysctl_pwr->cpu1_pwr_lpi_ctl;
+            pwr_sta_reg = (volatile uint32_t *)&sysctl_pwr->cpu1_pwr_lpi_state;
+            break;
+        }
+        case SYSCTL_PD_AI:
+        {
+            pwr_ctl_reg = (volatile uint32_t *)&sysctl_pwr->ai_pwr_lpi_ctl;
+            pwr_sta_reg = (volatile uint32_t *)&sysctl_pwr->ai_pwr_lpi_state;
+            break;
+        }
+        case SYSCTL_PD_DISP:
+        {
+            pwr_ctl_reg = (volatile uint32_t *)&sysctl_pwr->disp_lpi_ctl;
+            pwr_sta_reg = (volatile uint32_t *)&sysctl_pwr->disp_lpi_state;
+            break;
+        }
+        case SYSCTL_PD_VPU:
+        {
+            pwr_ctl_reg = (volatile uint32_t *)&sysctl_pwr->vpu_pwr_lpi_ctl;
+            pwr_sta_reg = (volatile uint32_t *)&sysctl_pwr->vpu_lpi_state;
+            break;
+        }
+        case SYSCTL_PD_DPU:
+        {
+            pwr_ctl_reg = (volatile uint32_t *)&sysctl_pwr->dpu_pwr_lpi_ctl;
+            pwr_sta_reg = (volatile uint32_t *)&sysctl_pwr->dpu_pwr_lpi_state;
+            break;
+        }
+        default:
+            return false;
+    }
+
+    /* repair powerdomain */
+    /* only powerup need repair */
+    if(true == enable)
+    {
+        (void)sysctl_pwr_set_repair_enable(powerdomain);
+    }
+
+    return sysctl_pwr_set_pwr_reg(pwr_ctl_reg, pwr_sta_reg, enable);
+}
+
+bool sysctl_pwr_set_power_multi(sysctl_pwr_domain_e powerdomain, bool enable)
+{
+    bool ret = true;
+    rt_base_t level;
+    static uint32_t ref_count[SYSCTL_PD_MAX];
+    /*
+    1. enable step for non-DISP power domains:
+        a. disable interrupt
+        b. judge ref_count, if == 0, execute sysctl_pwr_set_pwr_reg
+        c. ref_count++, limit UINT32_MAX
+        d. enable interrupt
+    2. disable step for non-DISP power domains:
+        a. disable interrupt
+        b. judge ref_count, if == 0, go step d
+        c. ref_count--, judge ref_count, if == 0, execute sysctl_pwr_set_pwr_reg
+        d. enable interrupt
+    3. enable step for DISP power domains:
+        a. disable interrupt
+        b. judge ref_count, if == 0, execute
+            b.1 get HARDLOCK_DISP
+            b.2 get HARDLOCK_DISP_CPU1
+            b.3 execute sysctl_pwr_set_pwr_reg
+            b.4 put HARDLOCK_DISP
+        c. ref_count++, limit UINT32_MAX
+        d. enable interrupt
+    4. disable step for DISP power domains:
+        a. disable interrupt
+        b. judge ref_count, if == 0, go step e
+        c. ref_count--, judge ref_count, if == 0, execute
+            c.1 get HARDLOCK_DISP
+            c.2 qeury HARDLOCK_DISP_CPU0, if no get, go step c.4
+            c.3 put HARDLOCK_DISP_CPU0, execute sysctl_pwr_set_pwr_reg
+            c.4 put HARDLOCK_DISP_CPU1
+            c.5 put HARDLOCK_DISP
+        d. enable interrupt
+    */
+    level = rt_hw_interrupt_disable();
+    if (enable == true)
+    {
+        if (ref_count[powerdomain] == 0)
+        {
+            if (powerdomain == SYSCTL_PD_DISP)
+            {
+                while (kd_hardlock_lock(HARDLOCK_DISP));
+                kd_hardlock_lock(HARDLOCK_DISP_CPU1);
+                ret = sysctl_pwr_set_power(powerdomain, enable);
+                kd_hardlock_unlock(HARDLOCK_DISP);
+            } else {
+                ret = sysctl_pwr_set_power(powerdomain, enable);
+            }
+        }
+        ref_count[powerdomain]++;
+        if (ref_count[powerdomain] == UINT32_MAX)
+            rt_kprintf("error: enable too many times\n");
+    } else if (ref_count[powerdomain])
+    {
+        ref_count[powerdomain]--;
+        if (ref_count[powerdomain] == 0)
+        {
+            if (powerdomain == SYSCTL_PD_DISP)
+            {
+                while (kd_hardlock_lock(HARDLOCK_DISP));
+                if (kd_hardlock_lock(HARDLOCK_DISP_CPU0) == 0)
+                {
+                    kd_hardlock_unlock(HARDLOCK_DISP_CPU0);
+                    ret = sysctl_pwr_set_power(powerdomain, enable);
+                }
+                kd_hardlock_unlock(HARDLOCK_DISP_CPU1);
+                kd_hardlock_unlock(HARDLOCK_DISP);
+            } else {
+                ret = sysctl_pwr_set_power(powerdomain, enable);
+            }
+        }
+    }
+    rt_hw_interrupt_enable(level);
+
+    return ret;
+}
+
+/* Power Domain Power-up */
+bool sysctl_pwr_up(sysctl_pwr_domain_e powerdomain)
+{
+    return sysctl_pwr_set_power_multi(powerdomain, true);
+}
+
+/* Power off a power domain */
+bool sysctl_pwr_off(sysctl_pwr_domain_e powerdomain)
+{
+    return sysctl_pwr_set_power_multi(powerdomain, false);
+}
+
+int rt_hw_sysctl_pwr_init(void)
+{
+    sysctl_pwr = rt_ioremap((void*)PWR_BASE_ADDR, PWR_IO_SIZE);
+    if(!sysctl_pwr)
+    {
+        rt_kprintf("sysctl_pwr ioremap error\n");
+        return -1;
+    }
+
+    return 0;
+}
+INIT_BOARD_EXPORT(rt_hw_sysctl_pwr_init);

+ 174 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_power/sysctl_pwr.h

@@ -0,0 +1,174 @@
+/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SYSCTL_PWR_H__
+#define __SYSCTL_PWR_H__
+
+/* created by yangfan */
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* See TRM 2.3.4 Table 2-3-3 */
+typedef struct
+{
+    volatile uint32_t cpu0_pwr_tim;         /* 0x00 */
+    volatile uint32_t cpu0_lpi_tim;         /* 0x04 */
+    volatile uint32_t cpu0_pwr_lpi_ctl;     /* 0x08 */
+    volatile uint32_t cpu0_pwr_lpi_state;   /* 0x0c */
+
+    volatile uint32_t cpu1_pwr_tim;         /* 0x10 */
+    volatile uint32_t cpu1_lpi_tim;         /* 0x14 */
+    volatile uint32_t cpu1_pwr_lpi_ctl;     /* 0x18 */
+    volatile uint32_t cpu1_pwr_lpi_state;   /* 0x1c */
+
+    volatile uint32_t ai_pwr_tim;           /* 0x20 */
+    volatile uint32_t ai_lpi_tim;           /* 0x24 */
+    volatile uint32_t ai_pwr_lpi_ctl;       /* 0x28 */
+    volatile uint32_t ai_pwr_lpi_state;     /* 0x2c */
+
+    volatile uint32_t disp_pwr_tim;         /* 0x30 */
+    volatile uint32_t disp_lpi_tim;         /* 0x34 */
+    volatile uint32_t disp_gpu_tim;         /* 0x38 */
+    volatile uint32_t disp_lpi_ctl;         /* 0x3c */
+    volatile uint32_t disp_lpi_state;       /* 0x40 */
+    volatile uint32_t disp_reserved[7];     /* 0x44-0x4c, 0x50-0x5c */
+
+    volatile uint32_t shrm_pwr_tim;         /* 0x60 */
+    volatile uint32_t shrm_lpi_tim;         /* 0x64 */
+    volatile uint32_t shrm_pwr_lpi_ctl;     /* 0x68 */
+    volatile uint32_t shrm_pwr_lpi_state;   /* 0x6c */
+
+    volatile uint32_t vpu_pwr_tim;          /* 0x70 */
+    volatile uint32_t vpu_lpi_tim;          /* 0x74 */
+    volatile uint32_t vpu_qch_tim;          /* 0x78 */
+    volatile uint32_t vpu_pwr_lpi_ctl;      /* 0x7c */
+    volatile uint32_t vpu_lpi_state;        /* 0x80 */
+    volatile uint32_t vpu_reserved[3];      /* 0x84-0x8c */
+
+    volatile uint32_t mctl_pwr_tim0;        /* 0x90 */
+    volatile uint32_t mctl_noc_lpi_tim;     /* 0x94 */
+    volatile uint32_t mctl_axi_lpi_tim;     /* 0x98 */
+    volatile uint32_t mctl_pwr_lpi_ctl;     /* 0x9c */
+    volatile uint32_t mctl_clock_switch;    /* 0xa0 */
+    volatile uint32_t mctl_lpi_state;       /* 0xa4 */
+    volatile uint32_t mctl_reserved[22];    /* 0xa8-0xac, 0xb0-0xbc, 0xc0-0xcc, 0xd0-0xdc, 0xe0-0xec, 0xf0-0xfc */
+
+    volatile uint32_t dpu_pwr_tim;          /* 0x100 */
+    volatile uint32_t dpu_lpi_tim;          /* 0x104 */
+    volatile uint32_t dpu_pwr_lpi_ctl;      /* 0x108 */
+    volatile uint32_t dpu_pwr_lpi_state;    /* 0x10c */
+
+    volatile uint32_t hi_pwr_tim;           /* 0x110 */
+    volatile uint32_t hi_lpi_tim;           /* 0x114 */
+    volatile uint32_t hi_pwr_lpi_ctl;       /* 0x118 */
+    volatile uint32_t hi_lpi_state;         /* 0x11c */
+
+    volatile uint32_t ls_pwr_tim;           /* 0x120 */
+    volatile uint32_t ls_lpi_tim;           /* 0x124 */
+    volatile uint32_t ls_pwr_lpi_ctl;       /* 0x128 */
+    volatile uint32_t ls_lpi_state;         /* 0x12c */
+
+    volatile uint32_t sec_pwr_tim;          /* 0x130 */
+    volatile uint32_t sec_lpi_tim;          /* 0x134 */
+    volatile uint32_t sec_pwr_lpi_ctl;      /* 0x138 */
+    volatile uint32_t sec_pwr_lpi_state;    /* 0x13c */
+
+    volatile uint32_t isp_pwr_tim;          /* 0x140 */
+    volatile uint32_t isp_lpi_tim;          /* 0x144 */
+    volatile uint32_t isp_pwr_lpi_ctl;      /* 0x148 */
+    volatile uint32_t isp_pwr_lpi_state;    /* 0x14c */
+
+    volatile uint32_t pmu_pwr_tim;          /* 0x150 */
+    volatile uint32_t pmu_lpi_tim;          /* 0x154 */
+    volatile uint32_t pmu_pwr_lpi_ctl;      /* 0x158 */
+    volatile uint32_t pmu_pwr_lpi_state;    /* 0x15c */
+
+    volatile uint32_t repair_status;        /* 0x160 */
+    volatile uint32_t sram0_repair_tim;     /* 0x164 */
+    volatile uint32_t ssys_ctl_gpio_ctl;    /* 0x168 */
+    volatile uint32_t ssys_reserved;        /* 0x16c */
+    volatile uint32_t ssys_ctl_gpio_en0;    /* 0x170 */
+    volatile uint32_t ssys_ctl_gpio_en1;    /* 0x174 */
+
+    volatile uint32_t cpu_repair_tim;       /* 0x178 */
+} sysctl_pwr_s;
+
+/* See TRM 2.3.1 Table 2-3-1 */
+typedef enum
+{
+    SYSCTL_PD_CPU1,
+    SYSCTL_PD_AI,
+    SYSCTL_PD_DISP,
+    SYSCTL_PD_VPU,
+    SYSCTL_PD_DPU,
+    SYSCTL_PD_MAX,
+} sysctl_pwr_domain_e;
+
+
+typedef enum
+{
+    SYSCTL_PWR_ACK_TO_TIM,  /* idleReq to idleAck max time */
+    SYSCTL_PWR_IDLE_TO_TIM, /* idleAck to idle max time */
+    SYSCTL_PWR_IDLE_HD_TIM, /* idle hold tim, from idle to cancel idleReq min time */
+    SYSCTL_PWR_ISO_SU_TIM,  /* isolation setup tim */
+    SYSCTL_PWR_PD_HD_TIM,   /* power done hardware tim */
+    SYSCTL_PWR_SU_TIM,      /* Power bringup tim */
+    SYSCTL_PWR_WFI_TIM,     /* wait for interrupt tim*/
+    SYSCTL_PWR_MAX_TIM,
+} sysctl_pwr_tim_e;
+
+
+bool sysctl_pwr_set_iso_su_tim(volatile uint32_t *reg, uint32_t iso_su_tim);
+bool sysctl_pwr_set_pd_hd_tim(volatile uint32_t *reg, uint32_t pd_hd_tim);
+bool sysctl_pwr_set_pwr_su_tim(volatile uint32_t *reg, uint32_t pwr_su_tim);
+bool sysctl_pwr_set_ack_to_tim(volatile uint32_t *reg, uint32_t ack_to_tim);
+bool sysctl_pwr_set_idle_to_tim(volatile uint32_t *reg, uint32_t idle_to_tim);
+bool sysctl_pwr_set_idle_hd_tim(volatile uint32_t *reg, uint32_t idle_hd_tim);
+bool sysctl_pwr_set_wfi_tim(volatile uint32_t *reg, uint32_t wfi_tim);
+bool sysctl_pwr_set_tim(sysctl_pwr_domain_e powerdomain, sysctl_pwr_tim_e timtype, uint32_t tim_value);
+bool sysctl_pwr_get_iso_su_tim(volatile uint32_t *reg, uint32_t *iso_su_tim);
+bool sysctl_pwr_get_pd_hd_tim(volatile uint32_t *reg, uint32_t *pd_hd_tim);
+bool sysctl_pwr_get_pwr_su_tim(volatile uint32_t *reg, uint32_t *pwr_su_tim);
+bool sysctl_pwr_get_ack_to_tim(volatile uint32_t *reg, uint32_t *ack_to_tim);
+bool sysctl_pwr_get_idle_to_tim(volatile uint32_t *reg, uint32_t *idle_to_tim);
+bool sysctl_pwr_get_idle_hd_tim(volatile uint32_t *reg, uint32_t *idle_hd_tim);
+bool sysctl_pwr_get_wfi_tim(volatile uint32_t *reg, uint32_t *wfi_tim);
+bool sysctl_pwr_get_tim(sysctl_pwr_domain_e powerdomain, sysctl_pwr_tim_e timtype, uint32_t *tim_value);
+bool sysctl_pwr_set_poweroff_keep_reset(sysctl_pwr_domain_e powerdomain, bool enable);
+bool sysctl_pwr_get_poweroff_keep_reset(sysctl_pwr_domain_e powerdomain, bool *enable);
+bool sysctl_pwr_set_auto_pwr(sysctl_pwr_domain_e powerdomain, bool enable);
+bool sysctl_pwr_get_auto_pwr(sysctl_pwr_domain_e powerdomain, bool *enable);
+bool sysctl_pwr_set_repair_enable(sysctl_pwr_domain_e powerdomain);
+bool sysctl_pwr_check_repair_done(sysctl_pwr_domain_e powerdomain);
+bool sysctl_pwr_set_lpi(sysctl_pwr_domain_e powerdomain, bool enable);
+bool sysctl_pwr_set_pwr_reg(volatile uint32_t *regctl, volatile uint32_t *regsta, bool enable);
+bool sysctl_pwr_set_power(sysctl_pwr_domain_e powerdomain, bool enable);
+
+/* Following two APIs are used to control the power on and off of the SOC power domain */
+bool sysctl_pwr_up(sysctl_pwr_domain_e powerdomain);
+bool sysctl_pwr_off(sysctl_pwr_domain_e powerdomain);
+
+#endif

+ 19 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_reset/SConscript

@@ -0,0 +1,19 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('Sysctl_reset', src, depend = [''], CPPPATH = CPPPATH)
+
+objs = [group]
+
+file_list = os.listdir(cwd)
+
+for item in file_list:
+    if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
+        objs = objs + SConscript(os.path.join(item, 'SConscript'))
+
+Return('objs')

+ 635 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_reset/sysctl_rst.c

@@ -0,0 +1,635 @@
+/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rtthread.h>
+#include <stdbool.h>
+#include "sysctl_rst.h"
+#include "ioremap.h"
+#include "board.h"
+
+volatile sysctl_rst_t* sysctl_rst = (volatile sysctl_rst_t*)RMU_BASE_ADDR;
+
+static bool sysctl_reset_cpu(volatile uint32_t *reset_reg, uint8_t reset_bit, uint8_t done_bit)
+{
+    /* clear done bit */
+    *reset_reg |= (1 << done_bit);
+    *reset_reg |= (1 << (done_bit + 0x10));  /* write enable */
+    /* usleep(100); */
+    rt_thread_delay(1);
+
+    /* set reset bit */
+    *reset_reg |= (1 << reset_bit);
+    *reset_reg |= (1 << (reset_bit + 0x10));  /* write enable */
+    /* usleep(100); */
+    rt_thread_delay(1);
+
+    /* clear reset bit */
+    if(0x9110100c == (uint64_t)reset_reg)
+    {
+        *reset_reg &= ~(1 << reset_bit);
+        *reset_reg |= (1 << (reset_bit + 0x10));   /* write enable */
+    }
+    /* usleep(100); */
+    rt_thread_delay(1);
+
+    /* check done bit */
+    if(*reset_reg & (1 << done_bit))
+        return true;
+    else
+        return false;
+}
+
+static bool sysctl_reset_hw_done(volatile uint32_t *reset_reg, uint8_t reset_bit, uint8_t done_bit)
+{
+    *reset_reg |= (1 << done_bit);      /* clear done bit */
+    /* usleep(100); */
+    rt_thread_delay(1);
+
+    *reset_reg |= (1 << reset_bit);     /* set reset bit */
+    /* usleep(100); */
+    rt_thread_delay(1);
+    /* check done bit */
+    if(*reset_reg & (1 << done_bit))
+        return true;
+    else
+        return false;
+}
+
+static bool sysctl_reset_sw_done(volatile uint32_t *reset_reg, uint8_t reset_bit, uint32_t reset_en)
+{
+    if(0 == reset_en)
+    {
+        if((0x91101020 == (uint64_t)reset_reg) || (0x91101024 == (uint64_t)reset_reg) || (0x91101080 == (uint64_t)reset_reg) || (0x91101064 == (uint64_t)reset_reg))
+        {
+            *reset_reg &= ~(1 << reset_bit);     /* set reset bit, 0 is assert */
+        }
+        else
+        {
+            *reset_reg |= (1 << reset_bit);     /* set reset bit, 1 is assert */
+        }
+    }
+    else
+    {
+        *reset_reg |= (1 << reset_bit) | (1 << reset_en);     /* set reset bit */
+    }
+    /* usleep(100); */
+    rt_thread_delay(1);
+
+    if((0x91101004 != (uint64_t)reset_reg) && (0x9110100c != (uint64_t)reset_reg))
+    {
+        if(0x911010a8 == (uint64_t)reset_reg)
+        {
+            *reset_reg &= ~(1 << reset_bit);    /* clear reset bit, 0 is clear */
+        }
+        else
+        {
+            *reset_reg |= (1 << reset_bit);    /* clear reset bit, 1 is clear */
+        }
+    }
+    /* usleep(100); */
+    rt_thread_delay(1);
+
+    return true;
+}
+
+bool sysctl_reset(sysctl_reset_e reset)
+{
+    switch(reset)
+    {
+        case SYSCTL_RESET_CPU0_CORE:
+            return sysctl_reset_cpu((volatile uint32_t *)&sysctl_rst->cpu0_rst_ctl, 0, 12);
+        case SYSCTL_RESET_CPU1_CORE:
+            return sysctl_reset_cpu((volatile uint32_t *)&sysctl_rst->cpu1_rst_ctl, 0, 12);
+
+        case SYSCTL_RESET_AI:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->ai_rst_ctl, 0, 31);
+        case SYSCTL_RESET_VPU:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->vpu_rst_ctl, 0, 31);
+        case SYSCTL_RESET_HS:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->hisys_rst_ctl, 0, 4);
+        case SYSCTL_RESET_HS_AHB:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->hisys_rst_ctl, 1, 5);
+        case SYSCTL_RESET_SDIO0:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->sdc_rst_ctl, 0, 28);
+        case SYSCTL_RESET_SDIO1:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->sdc_rst_ctl, 1, 29);
+        case SYSCTL_RESET_SDIO_AXI:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->sdc_rst_ctl, 2, 30);
+        case SYSCTL_RESET_USB0:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->usb_rst_ctl, 0, 28);
+        case SYSCTL_RESET_USB1:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->usb_rst_ctl, 1, 29);
+        case SYSCTL_RESET_USB0_AHB:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->usb_rst_ctl, 0, 30);
+        case SYSCTL_RESET_USB1_AHB:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->usb_rst_ctl, 1, 31);
+        case SYSCTL_RESET_SPI0:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->spi_rst_ctl, 0, 28);
+        case SYSCTL_RESET_SPI1:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->spi_rst_ctl, 1, 29);
+        case SYSCTL_RESET_SPI2:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->spi_rst_ctl, 2, 30);
+        case SYSCTL_RESET_SEC:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->sec_rst_ctl, 0, 31);
+        case SYSCTL_RESET_PDMA:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->dma_rst_ctl, 0, 28);
+        case SYSCTL_RESET_SDMA:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->dma_rst_ctl, 1, 29);
+        case SYSCTL_RESET_DECOMPRESS:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->decompress_rst_ctl, 0, 31);
+        case SYSCTL_RESET_SRAM:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->sram_rst_ctl, 0, 28);
+        case SYSCTL_RESET_SHRM_AXIM:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->sram_rst_ctl, 2, 30);
+        case SYSCTL_RESET_SHRM_AXIS:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->sram_rst_ctl, 3, 31);
+        case SYSCTL_RESET_NONAI2D:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->nonai2d_rst_ctl, 0, 31);
+        case SYSCTL_RESET_MCTL:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->mctl_rst_ctl, 0, 31);
+        case SYSCTL_RESET_ISP:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 6, 29);
+        case SYSCTL_RESET_ISP_DW:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 5, 28);
+        case SYSCTL_RESET_DPU:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->dpu_rst_ctl, 0, 31);
+        case SYSCTL_RESET_DISP:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->disp_rst_ctl, 0, 31);
+        case SYSCTL_RESET_GPU:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->v2p5d_rst_ctl, 0, 31);
+        case SYSCTL_RESET_AUDIO:
+            return sysctl_reset_hw_done((volatile uint32_t *)&sysctl_rst->audio_rst_ctl, 0, 31);
+
+        case SYSCTL_RESET_TIMER0:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 0, 0);
+        case SYSCTL_RESET_TIMER1:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 1, 0);
+        case SYSCTL_RESET_TIMER2:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 2, 0);
+        case SYSCTL_RESET_TIMER3:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 3, 0);
+        case SYSCTL_RESET_TIMER4:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 4, 0);
+        case SYSCTL_RESET_TIMER5:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 5, 0);
+        case SYSCTL_RESET_TIMER_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 6, 0);
+        case SYSCTL_RESET_HDI:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 7, 0);
+        case SYSCTL_RESET_WDT0:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 12, 0);
+        case SYSCTL_RESET_WDT1:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 13, 0);
+        case SYSCTL_RESET_WDT0_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 14, 0);
+        case SYSCTL_RESET_WDT1_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 15, 0);
+        case SYSCTL_RESET_TS_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 16, 0);
+        case SYSCTL_RESET_MAILBOX:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 17, 0);
+        case SYSCTL_RESET_STC:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 18, 0);
+        case SYSCTL_RESET_PMU:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->soc_ctl_rst_ctl, 19, 0);
+        case SYSCTL_RESET_LS_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 0, 0);
+        case SYSCTL_RESET_UART0:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 1, 0);
+        case SYSCTL_RESET_UART1:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 2, 0);
+        case SYSCTL_RESET_UART2:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 3, 0);
+        case SYSCTL_RESET_UART3:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 4, 0);
+        case SYSCTL_RESET_UART4:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 5, 0);
+        case SYSCTL_RESET_I2C0:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 6, 0);
+        case SYSCTL_RESET_I2C1:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 7, 0);
+        case SYSCTL_RESET_I2C2:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 8, 0);
+        case SYSCTL_RESET_I2C3:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 9, 0);
+        case SYSCTL_RESET_I2C4:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 10, 0);
+        case SYSCTL_RESET_JAMLINK0_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 11, 0);
+        case SYSCTL_RESET_JAMLINK1_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 12, 0);
+        case SYSCTL_RESET_JAMLINK2_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 13, 0);
+        case SYSCTL_RESET_JAMLINK3_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 14, 0);
+        case SYSCTL_RESET_CODEC_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 17, 0);
+        case SYSCTL_RESET_GPIO_DB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 18, 0);
+        case SYSCTL_RESET_GPIO_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 19, 0);
+        case SYSCTL_RESET_ADC:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 20, 0);
+        case SYSCTL_RESET_ADC_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 21, 0);
+        case SYSCTL_RESET_PWM_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->losys_rst_ctl, 22, 0);
+
+        case SYSCTL_RESET_CPU0_FLUSH:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->cpu0_rst_ctl, 4, 20);
+        case SYSCTL_RESET_CPU1_FLUSH:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->cpu1_rst_ctl, 4, 20);
+        case SYSCTL_RESET_SHRM_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->sram_rst_ctl, 1, 0);
+        case SYSCTL_RESET_CSI0_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 0, 0);
+        case SYSCTL_RESET_CSI1_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 1, 0);
+        case SYSCTL_RESET_CSI2_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 2, 0);
+        case SYSCTL_RESET_CSI_DPHY_APB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 3, 0);
+        case SYSCTL_RESET_ISP_AHB:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 4, 0);
+        case SYSCTL_RESET_M0:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 7, 0);
+        case SYSCTL_RESET_M1:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 8, 0);
+        case SYSCTL_RESET_M2:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->isp_rst_ctl, 9, 0);
+        case SYSCTL_RESET_SPI2AXI:
+            return sysctl_reset_sw_done((volatile uint32_t *)&sysctl_rst->spi2axi_rst_ctl, 0, 0);
+
+        default:
+            return false;
+    }
+}
+
+bool sysctl_set_reset_time(sysctl_reset_time_e reset, uint32_t tim0, uint32_t tim1, uint32_t tim2)
+{
+    volatile uint32_t ret;
+
+    switch(reset)
+    {
+        case SYSCTL_RESET_TIME_CPU0:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->cpu0_rst_tim;
+                ret &= 0xf0000fff;
+                sysctl_rst->cpu0_rst_tim = ret | ((tim1 << 12) | (tim2 << 20));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_CPU0_APB:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->cpu0_rst_tim;
+                ret &= 0xfffff00f;
+                sysctl_rst->cpu0_rst_tim = ret | ((tim1 << 4) | (tim2 << 8));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_CPU1:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->cpu1_rst_tim;
+                ret &= 0xfff00fff;
+                sysctl_rst->cpu1_rst_tim = ret | ((tim1 << 12) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_CPU1_APB:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->cpu1_rst_tim;
+                ret &= 0xfffff00f;
+                sysctl_rst->cpu1_rst_tim = ret | ((tim1 << 4) | (tim2 << 8));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_AI:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->ai_rst_tim;
+                ret &= 0xfffff00f;
+                sysctl_rst->ai_rst_tim = ret | ((tim1 << 4) | (tim2 << 8));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_VPU:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->vpu_rst_tim;
+                ret &= 0xfffff00f;
+                sysctl_rst->vpu_rst_tim = ret | ((tim1 << 4) | (tim2 << 8));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_HS_HCLK:
+        {
+            if((tim1 > 0x1F) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->hisys_hclk_tim;
+                ret &= 0xfff0f0ff;
+                sysctl_rst->hisys_hclk_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_SDCTL:
+        {
+            if((tim1 > 0x1F) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->sdctl_rst_tim;
+                ret &= 0xfff0f0ff;
+                sysctl_rst->sdctl_rst_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_USB:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->usb_rst_tim;
+                ret &= 0xffffff00;
+                sysctl_rst->usb_rst_tim = ret | ((tim1 << 0) | (tim2 << 4));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_USB_AHB:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->usb_rst_tim;
+                ret &= 0xff0000ff;
+                sysctl_rst->usb_rst_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_SPI:
+        {
+            if((tim1 > 0x3F) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->spi_rst_tim;
+                ret &= 0xfff0f0ff;
+                sysctl_rst->spi_rst_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_SEC_SYS:
+        {
+            if((tim1 > 0xFF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->sec_sys_rst_tim;
+                ret &= 0xfff0f0ff;
+                sysctl_rst->sec_sys_rst_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_DMAC:
+        {
+            if((tim1 > 0x7) || (tim2 > 0x7))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->dmac_rst_tim;
+                ret &= 0xfff0f0ff;
+                sysctl_rst->dmac_rst_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_DECOMPRESS:
+        {
+            if((tim1 > 0x7) || (tim2 > 0x7))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->decompress_rst_tim;
+                ret &= 0xfff0f0ff;
+                sysctl_rst->decompress_rst_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_SRAM:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->sram_rst_tim;
+                ret &= 0xfff0f0ff;
+                sysctl_rst->sram_rst_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_NONAI2D:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->nonai2d_rst_tim;
+                ret &= 0xfff0f0ff;
+                sysctl_rst->nonai2d_rst_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_MCTL:
+        {
+            if(tim0 > 0xF)
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->mctl_rst_tim;
+                ret &= 0xffffffc0;
+                sysctl_rst->mctl_rst_tim = ret | (tim0 << 0);
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_ISP:
+        {
+            if((tim0 > 0xFF) || (tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->isp_rst_tim;
+                ret &= 0xfff0f0f0;
+                sysctl_rst->isp_rst_tim = ret | ((tim0 << 0) | (tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_ISP_DW:
+        {
+            if((tim0 > 0xFF) || (tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->isp_dw_rst_tim;
+                ret &= 0xfff0f0f0;
+                sysctl_rst->isp_dw_rst_tim = ret | ((tim0 << 0) | (tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_DPU:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->dpu_rst_tim;
+                ret &= 0xfff0f0ff;
+                sysctl_rst->dpu_rst_tim = ret | ((tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_DISP_SYS:
+        {
+            if((tim0 > 0xFF) || (tim1 > 0xFF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->disp_sys_rst_tim;
+                ret &= 0xfff0f0f0;
+                sysctl_rst->disp_sys_rst_tim = ret | ((tim0 << 0) | (tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_V2P5D_SYS:
+        {
+            if((tim0 > 0xFF) || (tim1 > 0xFF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->v2p5d_sys_rst_tim;
+                ret &= 0xfff0f0f0;
+                sysctl_rst->v2p5d_sys_rst_tim = ret | ((tim0 << 0) | (tim1 << 8) | (tim2 << 16));
+                return true;
+            }
+        }
+        case SYSCTL_RESET_TIME_AUDIO:
+        {
+            if((tim1 > 0xF) || (tim2 > 0xF))
+            {
+                return false;
+            }
+            else
+            {
+                ret = sysctl_rst->audio_rst_tim;
+                ret &= 0xfffff00f;
+                sysctl_rst->audio_rst_tim = ret | ((tim1 << 4) | (tim2 << 8));
+                return true;
+            }
+        }
+
+        default:
+            return false;
+    }
+}
+
+int rt_hw_sysctl_rst_init(void)
+{
+    sysctl_rst = rt_ioremap((void*)RMU_BASE_ADDR, RMU_IO_SIZE);
+    if(!sysctl_rst)
+    {
+        rt_kprintf("sysctl_rst ioremap error\n");
+        return -1;
+    }
+
+    return 0;
+}
+INIT_BOARD_EXPORT(rt_hw_sysctl_rst_init);

+ 199 - 0
bsp/k230/drivers/interdrv/sysctl/sysctl_reset/sysctl_rst.h

@@ -0,0 +1,199 @@
+/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SYSCTL_RST_H__
+#define __SYSCTL_RST_H__
+
+/* created by yangfan */
+
+#include <stdint.h>
+#include "stdbool.h"
+
+typedef enum
+{
+    SYSCTL_RESET_CPU0_CORE,
+    /* SYSCTL_RESET_CPU0_APB, */
+    /* SYSCTL_RESET_CPU0_TDI, */
+    SYSCTL_RESET_CPU0_FLUSH,
+    SYSCTL_RESET_CPU1_CORE,
+    /* SYSCTL_RESET_CPU1_APB, */
+    SYSCTL_RESET_CPU1_FLUSH,
+    SYSCTL_RESET_AI,
+    SYSCTL_RESET_VPU,
+    SYSCTL_RESET_HS,
+    SYSCTL_RESET_HS_AHB,
+    SYSCTL_RESET_SDIO0,
+    SYSCTL_RESET_SDIO1,
+    SYSCTL_RESET_SDIO_AXI,
+    SYSCTL_RESET_USB0,
+    SYSCTL_RESET_USB1,
+    SYSCTL_RESET_USB0_AHB,
+    SYSCTL_RESET_USB1_AHB,
+    SYSCTL_RESET_SPI0,
+    SYSCTL_RESET_SPI1,
+    SYSCTL_RESET_SPI2,
+    SYSCTL_RESET_SEC,
+    SYSCTL_RESET_PDMA,
+    SYSCTL_RESET_SDMA,
+    SYSCTL_RESET_DECOMPRESS,
+    SYSCTL_RESET_SRAM,
+    SYSCTL_RESET_SHRM_AXIM,
+    SYSCTL_RESET_SHRM_AXIS,
+    SYSCTL_RESET_SHRM_APB,
+    SYSCTL_RESET_NONAI2D,
+    SYSCTL_RESET_MCTL,
+    SYSCTL_RESET_ISP,
+    SYSCTL_RESET_ISP_DW,
+    SYSCTL_RESET_CSI0_APB,
+    SYSCTL_RESET_CSI1_APB,
+    SYSCTL_RESET_CSI2_APB,
+    SYSCTL_RESET_CSI_DPHY_APB,
+    SYSCTL_RESET_ISP_AHB,
+    SYSCTL_RESET_M0,
+    SYSCTL_RESET_M1,
+    SYSCTL_RESET_M2,
+    SYSCTL_RESET_DPU,
+    SYSCTL_RESET_DISP,
+    SYSCTL_RESET_GPU,
+    SYSCTL_RESET_AUDIO,
+    SYSCTL_RESET_TIMER0,
+    SYSCTL_RESET_TIMER1,
+    SYSCTL_RESET_TIMER2,
+    SYSCTL_RESET_TIMER3,
+    SYSCTL_RESET_TIMER4,
+    SYSCTL_RESET_TIMER5,
+    SYSCTL_RESET_TIMER_APB,
+    SYSCTL_RESET_HDI,
+    SYSCTL_RESET_WDT0,
+    SYSCTL_RESET_WDT1,
+    SYSCTL_RESET_WDT0_APB,
+    SYSCTL_RESET_WDT1_APB,
+    SYSCTL_RESET_TS_APB,
+    SYSCTL_RESET_MAILBOX,
+    SYSCTL_RESET_STC,
+    SYSCTL_RESET_PMU,
+    SYSCTL_RESET_LS_APB,
+    SYSCTL_RESET_UART0,
+    SYSCTL_RESET_UART1,
+    SYSCTL_RESET_UART2,
+    SYSCTL_RESET_UART3,
+    SYSCTL_RESET_UART4,
+    SYSCTL_RESET_I2C0,
+    SYSCTL_RESET_I2C1,
+    SYSCTL_RESET_I2C2,
+    SYSCTL_RESET_I2C3,
+    SYSCTL_RESET_I2C4,
+    SYSCTL_RESET_JAMLINK0_APB,
+    SYSCTL_RESET_JAMLINK1_APB,
+    SYSCTL_RESET_JAMLINK2_APB,
+    SYSCTL_RESET_JAMLINK3_APB,
+    SYSCTL_RESET_CODEC_APB,
+    SYSCTL_RESET_GPIO_DB,
+    SYSCTL_RESET_GPIO_APB,
+    SYSCTL_RESET_ADC,
+    SYSCTL_RESET_ADC_APB,
+    SYSCTL_RESET_PWM_APB,
+    SYSCTL_RESET_SPI2AXI,
+} sysctl_reset_e;
+
+typedef enum
+{
+    SYSCTL_RESET_TIME_CPU0,
+    SYSCTL_RESET_TIME_CPU0_APB,
+    SYSCTL_RESET_TIME_CPU1,
+    SYSCTL_RESET_TIME_CPU1_APB,
+    SYSCTL_RESET_TIME_AI,
+    SYSCTL_RESET_TIME_VPU,
+    SYSCTL_RESET_TIME_HS_HCLK,
+    SYSCTL_RESET_TIME_SDCTL,
+    SYSCTL_RESET_TIME_USB,
+    SYSCTL_RESET_TIME_USB_AHB,
+    SYSCTL_RESET_TIME_SPI,
+    SYSCTL_RESET_TIME_SEC_SYS,
+    SYSCTL_RESET_TIME_DMAC,
+    SYSCTL_RESET_TIME_DECOMPRESS,
+    SYSCTL_RESET_TIME_SRAM,
+    SYSCTL_RESET_TIME_NONAI2D,
+    SYSCTL_RESET_TIME_MCTL,
+    SYSCTL_RESET_TIME_ISP,
+    SYSCTL_RESET_TIME_ISP_DW,
+    SYSCTL_RESET_TIME_DPU,
+    SYSCTL_RESET_TIME_DISP_SYS,
+    SYSCTL_RESET_TIME_V2P5D_SYS,
+    SYSCTL_RESET_TIME_AUDIO,
+} sysctl_reset_time_e;
+
+/* See TRM 2.1.4, Table 2-1-2 */
+typedef struct {
+    volatile uint32_t cpu0_rst_tim;         /* 0x00 */
+    volatile uint32_t cpu0_rst_ctl;         /* 0x04 */
+    volatile uint32_t cpu1_rst_tim;         /* 0x08 */
+    volatile uint32_t cpu1_rst_ctl;         /* 0x0c */
+    volatile uint32_t ai_rst_tim;           /* 0x10 */
+    volatile uint32_t ai_rst_ctl;           /* 0x14 */
+    volatile uint32_t vpu_rst_tim;          /* 0x18 */
+    volatile uint32_t vpu_rst_ctl;          /* 0x1c */
+    volatile uint32_t soc_ctl_rst_ctl;      /* 0x20 */
+    volatile uint32_t losys_rst_ctl;        /* 0x24 */
+    volatile uint32_t hisys_hclk_tim;       /* 0x28 */
+    volatile uint32_t hisys_rst_ctl;        /* 0x2c */
+    volatile uint32_t sdctl_rst_tim;        /* 0x30 */
+    volatile uint32_t sdc_rst_ctl;          /* 0x34 */
+    volatile uint32_t usb_rst_tim;          /* 0x38 */
+    volatile uint32_t usb_rst_ctl;          /* 0x3c */
+    volatile uint32_t spi_rst_tim;          /* 0x40 */
+    volatile uint32_t spi_rst_ctl;          /* 0x44 */
+    volatile uint32_t sec_sys_rst_tim;      /* 0x48 */
+    volatile uint32_t sec_rst_ctl;          /* 0x4c */
+    volatile uint32_t dmac_rst_tim;         /* 0x50 */
+    volatile uint32_t dma_rst_ctl;          /* 0x54 */
+    volatile uint32_t decompress_rst_tim;   /* 0x58 */
+    volatile uint32_t decompress_rst_ctl;   /* 0x5c */
+    volatile uint32_t sram_rst_tim;         /* 0x60 */
+    volatile uint32_t sram_rst_ctl;         /* 0x64 */
+    volatile uint32_t nonai2d_rst_tim;      /* 0x68 */
+    volatile uint32_t nonai2d_rst_ctl;      /* 0x6c */
+    volatile uint32_t mctl_rst_tim;         /* 0x70 */
+    volatile uint32_t mctl_rst_ctl;         /* 0x74 */
+    volatile uint32_t isp_rst_tim;          /* 0x78 */
+    volatile uint32_t isp_dw_rst_tim;       /* 0x7c */
+    volatile uint32_t isp_rst_ctl;          /* 0x80 */
+    volatile uint32_t dpu_rst_tim;          /* 0x84 */
+    volatile uint32_t dpu_rst_ctl;          /* 0x88 */
+    volatile uint32_t disp_sys_rst_tim;     /* 0x8c */
+    volatile uint32_t disp_rst_ctl;         /* 0x90 */
+    volatile uint32_t v2p5d_sys_rst_tim;    /* 0x94 */
+    volatile uint32_t v2p5d_rst_ctl;        /* 0x98 */
+    volatile uint32_t reserved;             /* 0x9c */
+    volatile uint32_t audio_rst_tim;        /* 0xa0 */
+    volatile uint32_t audio_rst_ctl;        /* 0xa4 */
+    volatile uint32_t spi2axi_rst_ctl;      /* 0xa8 */
+} sysctl_rst_t;
+
+/* Just call this API to reset */
+bool sysctl_reset(sysctl_reset_e reset);
+bool sysctl_set_reset_time(sysctl_reset_time_e reset, uint32_t tim0, uint32_t tim1, uint32_t tim2);
+
+#endif