diff --git a/bsp/k230/drivers/interdrv/sysctl/SConscript b/bsp/k230/drivers/interdrv/sysctl/SConscript new file mode 100644 index 00000000000..585f634c7b7 --- /dev/null +++ b/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') diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_boot/SConscript b/bsp/k230/drivers/interdrv/sysctl/sysctl_boot/SConscript new file mode 100644 index 00000000000..c0f36ac14a7 --- /dev/null +++ b/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') diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_boot/sysctl_boot.c b/bsp/k230/drivers/interdrv/sysctl/sysctl_boot/sysctl_boot.c new file mode 100644 index 00000000000..d272a2f5cba --- /dev/null +++ b/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 +#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); \ No newline at end of file diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_boot/sysctl_boot.h b/bsp/k230/drivers/interdrv/sysctl/sysctl_boot/sysctl_boot.h new file mode 100644 index 00000000000..eb3c725f60d --- /dev/null +++ b/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 +#include + +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 \ No newline at end of file diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_clock/SConscript b/bsp/k230/drivers/interdrv/sysctl/sysctl_clock/SConscript new file mode 100644 index 00000000000..5996ccf7cc2 --- /dev/null +++ b/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') diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_clock/sysctl_clk.c b/bsp/k230/drivers/interdrv/sysctl/sysctl_clock/sysctl_clk.c new file mode 100644 index 00000000000..b521540e3e8 --- /dev/null +++ b/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 +#include +#include +#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); \ No newline at end of file diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_clock/sysctl_clk.h b/bsp/k230/drivers/interdrv/sysctl/sysctl_clock/sysctl_clk.h new file mode 100644 index 00000000000..5dff8d0f69a --- /dev/null +++ b/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 +#include + +/* 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__ */ \ No newline at end of file diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_power/SConscript b/bsp/k230/drivers/interdrv/sysctl/sysctl_power/SConscript new file mode 100644 index 00000000000..503d98fd796 --- /dev/null +++ b/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') diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_power/sysctl_pwr.c b/bsp/k230/drivers/interdrv/sysctl/sysctl_power/sysctl_pwr.c new file mode 100644 index 00000000000..001660e5d94 --- /dev/null +++ b/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 +#include +#include +#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); \ No newline at end of file diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_power/sysctl_pwr.h b/bsp/k230/drivers/interdrv/sysctl/sysctl_power/sysctl_pwr.h new file mode 100644 index 00000000000..cf073940159 --- /dev/null +++ b/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 +#include + +/* 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 \ No newline at end of file diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_reset/SConscript b/bsp/k230/drivers/interdrv/sysctl/sysctl_reset/SConscript new file mode 100644 index 00000000000..802a920a671 --- /dev/null +++ b/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') diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_reset/sysctl_rst.c b/bsp/k230/drivers/interdrv/sysctl/sysctl_reset/sysctl_rst.c new file mode 100644 index 00000000000..9e38cab9d84 --- /dev/null +++ b/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 +#include +#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); \ No newline at end of file diff --git a/bsp/k230/drivers/interdrv/sysctl/sysctl_reset/sysctl_rst.h b/bsp/k230/drivers/interdrv/sysctl/sysctl_reset/sysctl_rst.h new file mode 100644 index 00000000000..f12c2516062 --- /dev/null +++ b/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 +#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 \ No newline at end of file