arch/risc-v/k210: Add sysctl driver for clock and reset control

Add sysctl driver for K210 SoC providing clock and reset control:
- Clock enable/disable with two-stage APB/peripheral enable pattern
- Peripheral reset control with proper timing
- Clock frequency query for PLL, CPU, APB buses, and peripherals
- PLL frequency calculation and CPU frequency configuration

The sysctl driver is built unconditionally for K210 boards as it
provides essential clock and reset control functionality.

Add Kconfig option:
- K210_CPU_FREQ: Target CPU frequency in Hz (default 400MHz)

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
This commit is contained in:
Huang Qi
2026-03-14 11:59:35 +08:00
committed by simbit18
parent 11b4125170
commit a48936788a
8 changed files with 1873 additions and 14 deletions
@@ -2,6 +2,26 @@
Kendryte K210
=============
System Controller (sysctl)
==========================
The K210 System Controller (sysctl) driver provides essential clock and reset
control functionality for the K210 SoC. It is built unconditionally for all
K210 boards.
Clock Frequency Configuration
-----------------------------
The driver supports querying clock frequencies for:
* PLL frequencies (PLL0, PLL1, PLL2)
* CPU clock frequency
* APB bus frequencies (APB0, APB1, APB2)
* Individual peripheral clock frequencies
CPU frequency can be configured at build time using the ``K210_CPU_FREQ``
Kconfig option (default: 400 MHz, range: 40-600 MHz).
Supported Boards
================
+2
View File
@@ -26,6 +26,8 @@ list(APPEND SRCS k210_timerisr.c k210_allocateheap.c k210_clockconfig.c)
list(APPEND SRCS k210_lowputc.c k210_serial.c k210_fpioa.c k210_gpiohs.c)
list(APPEND SRCS k210_sysctl.c)
if(CONFIG_BUILD_PROTECTED)
list(APPEND SRCS k210_userspace.c)
endif()
+10
View File
@@ -27,6 +27,16 @@ config K210_UART0
endmenu
config K210_CPU_FREQ
int "K210 CPU target frequency (Hz)"
default 400000000
range 40000000 600000000
depends on ARCH_CHIP_K210
---help---
Set the K210 CPU target frequency in Hz.
Default is 400000000 (400 MHz).
Valid range: 40000000-600000000 Hz (40-600 MHz).
menu "K210 Others"
config K210_WITH_QEMU
+1 -1
View File
@@ -30,7 +30,7 @@ HEAD_ASRC = k210_head.S
CHIP_CSRCS = k210_allocateheap.c k210_clockconfig.c
CHIP_CSRCS += k210_irq.c k210_irq_dispatch.c
CHIP_CSRCS += k210_lowputc.c k210_serial.c k210_fpioa.c
CHIP_CSRCS += k210_start.c k210_timerisr.c k210_gpiohs.c
CHIP_CSRCS += k210_start.c k210_timerisr.c k210_gpiohs.c k210_sysctl.c
ifeq ($(CONFIG_BUILD_PROTECTED),y)
CHIP_CSRCS += k210_userspace.c
+292 -2
View File
@@ -33,13 +33,303 @@
* Pre-processor Definitions
****************************************************************************/
#define K210_SYSCTL_PLL0 (K210_SYSCTL_BASE + 0x08)
/* Sysctl Register Offsets */
#define K210_SYSCTL_GIT_ID (K210_SYSCTL_BASE + 0x00) /* Git short commit id */
#define K210_SYSCTL_CLK_FREQ (K210_SYSCTL_BASE + 0x04) /* System clock base frequency */
#define K210_SYSCTL_PLL0 (K210_SYSCTL_BASE + 0x08) /* PLL0 controller */
#define K210_SYSCTL_PLL1 (K210_SYSCTL_BASE + 0x0c) /* PLL1 controller */
#define K210_SYSCTL_PLL2 (K210_SYSCTL_BASE + 0x10) /* PLL2 controller */
/* 0x14: Reserved */
#define K210_SYSCTL_PLL_LOCK (K210_SYSCTL_BASE + 0x18) /* PLL lock tester */
#define K210_SYSCTL_ROM_ERROR (K210_SYSCTL_BASE + 0x1c) /* AXI ROM detector */
#define K210_SYSCTL_CLKSEL0 (K210_SYSCTL_BASE + 0x20) /* Clock select controller 0 */
#define K210_SYSCTL_CLKSEL1 (K210_SYSCTL_BASE + 0x24) /* Clock select controller 1 */
#define K210_SYSCTL_CLK_EN_CENT (K210_SYSCTL_BASE + 0x28) /* Central clock enable */
#define K210_SYSCTL_CLK_EN_PERI (K210_SYSCTL_BASE + 0x2c) /* Peripheral clock enable */
#define K210_SYSCTL_SOFT_RESET (K210_SYSCTL_BASE + 0x30) /* Soft reset control */
#define K210_SYSCTL_PERI_RESET (K210_SYSCTL_BASE + 0x34) /* Peripheral reset controller */
#define K210_SYSCTL_CLK_TH0 (K210_SYSCTL_BASE + 0x38) /* Clock threshold controller 0 */
#define K210_SYSCTL_CLK_TH1 (K210_SYSCTL_BASE + 0x3c) /* Clock threshold controller 1 */
#define K210_SYSCTL_CLK_TH2 (K210_SYSCTL_BASE + 0x40) /* Clock threshold controller 2 */
#define K210_SYSCTL_CLK_TH3 (K210_SYSCTL_BASE + 0x44) /* Clock threshold controller 3 */
#define K210_SYSCTL_CLK_TH4 (K210_SYSCTL_BASE + 0x48) /* Clock threshold controller 4 */
#define K210_SYSCTL_CLK_TH5 (K210_SYSCTL_BASE + 0x4c) /* Clock threshold controller 5 */
#define K210_SYSCTL_CLK_TH6 (K210_SYSCTL_BASE + 0x50) /* Clock threshold controller 6 */
#define K210_SYSCTL_MISC (K210_SYSCTL_BASE + 0x54) /* Miscellaneous controller */
#define K210_SYSCTL_PERI (K210_SYSCTL_BASE + 0x58) /* Peripheral controller */
#define K210_SYSCTL_SPI_SLEEP (K210_SYSCTL_BASE + 0x5c) /* SPI sleep controller */
#define K210_SYSCTL_RESET_STATUS (K210_SYSCTL_BASE + 0x60) /* Reset source status */
#define K210_SYSCTL_DMA_SEL0 (K210_SYSCTL_BASE + 0x64) /* DMA handshake selector 0 */
#define K210_SYSCTL_DMA_SEL1 (K210_SYSCTL_BASE + 0x68) /* DMA handshake selector 1 */
#define K210_SYSCTL_POWER_SEL (K210_SYSCTL_BASE + 0x6c) /* IO Power Mode Select */
/* PLL bit field extraction macros (legacy, kept for compatibility) */
#define PLL_CLK_R(n) (n & 0x00000f)
#define PLL_CLK_F(n) ((n & 0x0003f0) >> 4)
#define PLL_CLK_OD(n) ((n & 0x003c00) >> 10)
#define K210_SYSCTL_CLKSEL0 (K210_SYSCTL_BASE + 0x20)
/* PLL register bit field definitions */
#define PLL_CLKR_SHIFT (0) /* Reference clock divider */
#define PLL_CLKR_MASK (0xf << PLL_CLKR_SHIFT)
#define PLL_CLKF_SHIFT (4) /* Feedback divider */
#define PLL_CLKF_MASK (0x3f << PLL_CLKF_SHIFT)
#define PLL_CLKOD_SHIFT (10) /* Output divider */
#define PLL_CLKOD_MASK (0xf << PLL_CLKOD_SHIFT)
#define PLL_BWADJ_SHIFT (14) /* Bandwidth adjust */
#define PLL_BWADJ_MASK (0x3f << PLL_BWADJ_SHIFT)
#define PLL_RESET_SHIFT (20) /* PLL reset */
#define PLL_RESET_MASK (1 << PLL_RESET_SHIFT)
#define PLL_PWRD_SHIFT (21) /* Power down */
#define PLL_PWRD_MASK (1 << PLL_PWRD_SHIFT)
#define PLL_BYPASS_SHIFT (23) /* Bypass */
#define PLL_BYPASS_MASK (1 << PLL_BYPASS_SHIFT)
#define PLL_OUT_EN_SHIFT (25) /* Output enable */
#define PLL_OUT_EN_MASK (1 << PLL_OUT_EN_SHIFT)
/* CLK_EN_CENT register bit definitions (Central clock enable) */
#define CLK_EN_CENT_CPU_SHIFT (0) /* CPU clock enable */
#define CLK_EN_CENT_CPU_MASK (1 << CLK_EN_CENT_CPU_SHIFT)
#define CLK_EN_CENT_SRAM0_SHIFT (1) /* SRAM0 clock enable */
#define CLK_EN_CENT_SRAM0_MASK (1 << CLK_EN_CENT_SRAM0_SHIFT)
#define CLK_EN_CENT_SRAM1_SHIFT (2) /* SRAM1 clock enable */
#define CLK_EN_CENT_SRAM1_MASK (1 << CLK_EN_CENT_SRAM1_SHIFT)
#define CLK_EN_CENT_APB0_SHIFT (3) /* APB0 bus clock enable */
#define CLK_EN_CENT_APB0_MASK (1 << CLK_EN_CENT_APB0_SHIFT)
#define CLK_EN_CENT_APB1_SHIFT (4) /* APB1 bus clock enable */
#define CLK_EN_CENT_APB1_MASK (1 << CLK_EN_CENT_APB1_SHIFT)
#define CLK_EN_CENT_APB2_SHIFT (5) /* APB2 bus clock enable */
#define CLK_EN_CENT_APB2_MASK (1 << CLK_EN_CENT_APB2_SHIFT)
/* CLK_EN_PERI register bit definitions (Peripheral clock enable) */
#define CLK_EN_PERI_ROM_SHIFT (0) /* ROM clock enable */
#define CLK_EN_PERI_ROM_MASK (1 << CLK_EN_PERI_ROM_SHIFT)
#define CLK_EN_PERI_DMA_SHIFT (1) /* DMA clock enable */
#define CLK_EN_PERI_DMA_MASK (1 << CLK_EN_PERI_DMA_SHIFT)
#define CLK_EN_PERI_AI_SHIFT (2) /* AI accelerator clock enable */
#define CLK_EN_PERI_AI_MASK (1 << CLK_EN_PERI_AI_SHIFT)
#define CLK_EN_PERI_DVP_SHIFT (3) /* DVP camera interface clock enable */
#define CLK_EN_PERI_DVP_MASK (1 << CLK_EN_PERI_DVP_SHIFT)
#define CLK_EN_PERI_FFT_SHIFT (4) /* FFT accelerator clock enable */
#define CLK_EN_PERI_FFT_MASK (1 << CLK_EN_PERI_FFT_SHIFT)
#define CLK_EN_PERI_GPIO_SHIFT (5) /* GPIO clock enable */
#define CLK_EN_PERI_GPIO_MASK (1 << CLK_EN_PERI_GPIO_SHIFT)
#define CLK_EN_PERI_SPI0_SHIFT (6) /* SPI0 clock enable */
#define CLK_EN_PERI_SPI0_MASK (1 << CLK_EN_PERI_SPI0_SHIFT)
#define CLK_EN_PERI_SPI1_SHIFT (7) /* SPI1 clock enable */
#define CLK_EN_PERI_SPI1_MASK (1 << CLK_EN_PERI_SPI1_SHIFT)
#define CLK_EN_PERI_SPI2_SHIFT (8) /* SPI2 clock enable */
#define CLK_EN_PERI_SPI2_MASK (1 << CLK_EN_PERI_SPI2_SHIFT)
#define CLK_EN_PERI_SPI3_SHIFT (9) /* SPI3 clock enable */
#define CLK_EN_PERI_SPI3_MASK (1 << CLK_EN_PERI_SPI3_SHIFT)
#define CLK_EN_PERI_I2S0_SHIFT (10) /* I2S0 clock enable */
#define CLK_EN_PERI_I2S0_MASK (1 << CLK_EN_PERI_I2S0_SHIFT)
#define CLK_EN_PERI_I2S1_SHIFT (11) /* I2S1 clock enable */
#define CLK_EN_PERI_I2S1_MASK (1 << CLK_EN_PERI_I2S1_SHIFT)
#define CLK_EN_PERI_I2S2_SHIFT (12) /* I2S2 clock enable */
#define CLK_EN_PERI_I2S2_MASK (1 << CLK_EN_PERI_I2S2_SHIFT)
#define CLK_EN_PERI_I2C0_SHIFT (13) /* I2C0 clock enable */
#define CLK_EN_PERI_I2C0_MASK (1 << CLK_EN_PERI_I2C0_SHIFT)
#define CLK_EN_PERI_I2C1_SHIFT (14) /* I2C1 clock enable */
#define CLK_EN_PERI_I2C1_MASK (1 << CLK_EN_PERI_I2C1_SHIFT)
#define CLK_EN_PERI_I2C2_SHIFT (15) /* I2C2 clock enable */
#define CLK_EN_PERI_I2C2_MASK (1 << CLK_EN_PERI_I2C2_SHIFT)
#define CLK_EN_PERI_UART1_SHIFT (16) /* UART1 clock enable */
#define CLK_EN_PERI_UART1_MASK (1 << CLK_EN_PERI_UART1_SHIFT)
#define CLK_EN_PERI_UART2_SHIFT (17) /* UART2 clock enable */
#define CLK_EN_PERI_UART2_MASK (1 << CLK_EN_PERI_UART2_SHIFT)
#define CLK_EN_PERI_UART3_SHIFT (18) /* UART3 clock enable */
#define CLK_EN_PERI_UART3_MASK (1 << CLK_EN_PERI_UART3_SHIFT)
#define CLK_EN_PERI_AES_SHIFT (19) /* AES accelerator clock enable */
#define CLK_EN_PERI_AES_MASK (1 << CLK_EN_PERI_AES_SHIFT)
#define CLK_EN_PERI_FPIOA_SHIFT (20) /* FPIOA (GPIO multiplexer) clock enable */
#define CLK_EN_PERI_FPIOA_MASK (1 << CLK_EN_PERI_FPIOA_SHIFT)
#define CLK_EN_PERI_TIMER0_SHIFT (21) /* TIMER0 clock enable */
#define CLK_EN_PERI_TIMER0_MASK (1 << CLK_EN_PERI_TIMER0_SHIFT)
#define CLK_EN_PERI_TIMER1_SHIFT (22) /* TIMER1 clock enable */
#define CLK_EN_PERI_TIMER1_MASK (1 << CLK_EN_PERI_TIMER1_SHIFT)
#define CLK_EN_PERI_TIMER2_SHIFT (23) /* TIMER2 clock enable */
#define CLK_EN_PERI_TIMER2_MASK (1 << CLK_EN_PERI_TIMER2_SHIFT)
#define CLK_EN_PERI_WDT0_SHIFT (24) /* Watchdog timer 0 clock enable */
#define CLK_EN_PERI_WDT0_MASK (1 << CLK_EN_PERI_WDT0_SHIFT)
#define CLK_EN_PERI_WDT1_SHIFT (25) /* Watchdog timer 1 clock enable */
#define CLK_EN_PERI_WDT1_MASK (1 << CLK_EN_PERI_WDT1_SHIFT)
#define CLK_EN_PERI_SHA_SHIFT (26) /* SHA accelerator clock enable */
#define CLK_EN_PERI_SHA_MASK (1 << CLK_EN_PERI_SHA_SHIFT)
#define CLK_EN_PERI_OTP_SHIFT (27) /* OTP (One-Time Programmable) clock enable */
#define CLK_EN_PERI_OTP_MASK (1 << CLK_EN_PERI_OTP_SHIFT)
#define CLK_EN_PERI_RTC_SHIFT (29) /* RTC clock enable */
#define CLK_EN_PERI_RTC_MASK (1 << CLK_EN_PERI_RTC_SHIFT)
/* PERI_RESET register bit definitions (Peripheral reset control) */
#define PERI_RESET_ROM_SHIFT (0) /* ROM reset */
#define PERI_RESET_ROM_MASK (1 << PERI_RESET_ROM_SHIFT)
#define PERI_RESET_DMA_SHIFT (1) /* DMA reset */
#define PERI_RESET_DMA_MASK (1 << PERI_RESET_DMA_SHIFT)
#define PERI_RESET_AI_SHIFT (2) /* AI accelerator reset */
#define PERI_RESET_AI_MASK (1 << PERI_RESET_AI_SHIFT)
#define PERI_RESET_DVP_SHIFT (3) /* DVP camera interface reset */
#define PERI_RESET_DVP_MASK (1 << PERI_RESET_DVP_SHIFT)
#define PERI_RESET_FFT_SHIFT (4) /* FFT accelerator reset */
#define PERI_RESET_FFT_MASK (1 << PERI_RESET_FFT_SHIFT)
#define PERI_RESET_GPIO_SHIFT (5) /* GPIO reset */
#define PERI_RESET_GPIO_MASK (1 << PERI_RESET_GPIO_SHIFT)
#define PERI_RESET_SPI0_SHIFT (6) /* SPI0 reset */
#define PERI_RESET_SPI0_MASK (1 << PERI_RESET_SPI0_SHIFT)
#define PERI_RESET_SPI1_SHIFT (7) /* SPI1 reset */
#define PERI_RESET_SPI1_MASK (1 << PERI_RESET_SPI1_SHIFT)
#define PERI_RESET_SPI2_SHIFT (8) /* SPI2 reset */
#define PERI_RESET_SPI2_MASK (1 << PERI_RESET_SPI2_SHIFT)
#define PERI_RESET_SPI3_SHIFT (9) /* SPI3 reset */
#define PERI_RESET_SPI3_MASK (1 << PERI_RESET_SPI3_SHIFT)
#define PERI_RESET_I2S0_SHIFT (10) /* I2S0 reset */
#define PERI_RESET_I2S0_MASK (1 << PERI_RESET_I2S0_SHIFT)
#define PERI_RESET_I2S1_SHIFT (11) /* I2S1 reset */
#define PERI_RESET_I2S1_MASK (1 << PERI_RESET_I2S1_SHIFT)
#define PERI_RESET_I2S2_SHIFT (12) /* I2S2 reset */
#define PERI_RESET_I2S2_MASK (1 << PERI_RESET_I2S2_SHIFT)
#define PERI_RESET_I2C0_SHIFT (13) /* I2C0 reset */
#define PERI_RESET_I2C0_MASK (1 << PERI_RESET_I2C0_SHIFT)
#define PERI_RESET_I2C1_SHIFT (14) /* I2C1 reset */
#define PERI_RESET_I2C1_MASK (1 << PERI_RESET_I2C1_SHIFT)
#define PERI_RESET_I2C2_SHIFT (15) /* I2C2 reset */
#define PERI_RESET_I2C2_MASK (1 << PERI_RESET_I2C2_SHIFT)
#define PERI_RESET_UART1_SHIFT (16) /* UART1 reset */
#define PERI_RESET_UART1_MASK (1 << PERI_RESET_UART1_SHIFT)
#define PERI_RESET_UART2_SHIFT (17) /* UART2 reset */
#define PERI_RESET_UART2_MASK (1 << PERI_RESET_UART2_SHIFT)
#define PERI_RESET_UART3_SHIFT (18) /* UART3 reset */
#define PERI_RESET_UART3_MASK (1 << PERI_RESET_UART3_SHIFT)
#define PERI_RESET_AES_SHIFT (19) /* AES accelerator reset */
#define PERI_RESET_AES_MASK (1 << PERI_RESET_AES_SHIFT)
#define PERI_RESET_FPIOA_SHIFT (20) /* FPIOA (GPIO multiplexer) reset */
#define PERI_RESET_FPIOA_MASK (1 << PERI_RESET_FPIOA_SHIFT)
#define PERI_RESET_TIMER0_SHIFT (21) /* TIMER0 reset */
#define PERI_RESET_TIMER0_MASK (1 << PERI_RESET_TIMER0_SHIFT)
#define PERI_RESET_TIMER1_SHIFT (22) /* TIMER1 reset */
#define PERI_RESET_TIMER1_MASK (1 << PERI_RESET_TIMER1_SHIFT)
#define PERI_RESET_TIMER2_SHIFT (23) /* TIMER2 reset */
#define PERI_RESET_TIMER2_MASK (1 << PERI_RESET_TIMER2_SHIFT)
#define PERI_RESET_WDT0_SHIFT (24) /* Watchdog timer 0 reset */
#define PERI_RESET_WDT0_MASK (1 << PERI_RESET_WDT0_SHIFT)
#define PERI_RESET_WDT1_SHIFT (25) /* Watchdog timer 1 reset */
#define PERI_RESET_WDT1_MASK (1 << PERI_RESET_WDT1_SHIFT)
#define PERI_RESET_SHA_SHIFT (26) /* SHA accelerator reset */
#define PERI_RESET_SHA_MASK (1 << PERI_RESET_SHA_SHIFT)
#define PERI_RESET_RTC_SHIFT (29) /* RTC reset */
#define PERI_RESET_RTC_MASK (1 << PERI_RESET_RTC_SHIFT)
/* RESET_STATUS register bit definitions (Reset source status) */
#define RESET_STATUS_CLR_SHIFT (0) /* Reset status clear */
#define RESET_STATUS_CLR_MASK (1 << RESET_STATUS_CLR_SHIFT)
#define RESET_STATUS_PIN_SHIFT (1) /* Pin reset status */
#define RESET_STATUS_PIN_MASK (1 << RESET_STATUS_PIN_SHIFT)
#define RESET_STATUS_WDT0_SHIFT (2) /* Watchdog timer 0 reset status */
#define RESET_STATUS_WDT0_MASK (1 << RESET_STATUS_WDT0_SHIFT)
#define RESET_STATUS_WDT1_SHIFT (3) /* Watchdog timer 1 reset status */
#define RESET_STATUS_WDT1_MASK (1 << RESET_STATUS_WDT1_SHIFT)
#define RESET_STATUS_SOFT_SHIFT (4) /* Soft reset status */
#define RESET_STATUS_SOFT_MASK (1 << RESET_STATUS_SOFT_SHIFT)
/* CLKSEL0 register bit definitions (Clock select controller 0) */
#define CLKSEL0_ACLK_SEL_SHIFT (0)
#define CLKSEL0_ACLK_SEL_MASK (1 << CLKSEL0_ACLK_SEL_SHIFT)
#define CLKSEL0_ACLK_DIV_SHIFT (1)
#define CLKSEL0_ACLK_DIV_MASK (3 << CLKSEL0_ACLK_DIV_SHIFT)
#define CLKSEL0_APB0_DIV_SHIFT (3)
#define CLKSEL0_APB0_DIV_MASK (7 << CLKSEL0_APB0_DIV_SHIFT)
#define CLKSEL0_APB1_DIV_SHIFT (6)
#define CLKSEL0_APB1_DIV_MASK (7 << CLKSEL0_APB1_DIV_SHIFT)
#define CLKSEL0_APB2_DIV_SHIFT (9)
#define CLKSEL0_APB2_DIV_MASK (7 << CLKSEL0_APB2_DIV_SHIFT)
/* CLK_TH0 register bit definitions (Clock threshold controller 0) */
#define CLK_TH0_SRAM0_SHIFT (0)
#define CLK_TH0_SRAM0_MASK (0xf << CLK_TH0_SRAM0_SHIFT)
#define CLK_TH0_SRAM1_SHIFT (4)
#define CLK_TH0_SRAM1_MASK (0xf << CLK_TH0_SRAM1_SHIFT)
#define CLK_TH0_AI_SHIFT (8)
#define CLK_TH0_AI_MASK (0xf << CLK_TH0_AI_SHIFT)
#define CLK_TH0_DVP_SHIFT (12)
#define CLK_TH0_DVP_MASK (0xf << CLK_TH0_DVP_SHIFT)
#define CLK_TH0_ROM_SHIFT (16)
#define CLK_TH0_ROM_MASK (0xf << CLK_TH0_ROM_SHIFT)
/* CLK_TH1 register bit definitions (Clock threshold controller 1) */
#define CLK_TH1_SPI0_SHIFT (0)
#define CLK_TH1_SPI0_MASK (0xff << CLK_TH1_SPI0_SHIFT)
#define CLK_TH1_SPI1_SHIFT (8)
#define CLK_TH1_SPI1_MASK (0xff << CLK_TH1_SPI1_SHIFT)
#define CLK_TH1_SPI2_SHIFT (16)
#define CLK_TH1_SPI2_MASK (0xff << CLK_TH1_SPI2_SHIFT)
#define CLK_TH1_SPI3_SHIFT (24)
#define CLK_TH1_SPI3_MASK (0xff << CLK_TH1_SPI3_SHIFT)
/* CLK_TH2 register bit definitions (Clock threshold controller 2) */
#define CLK_TH2_TIMER0_SHIFT (0)
#define CLK_TH2_TIMER0_MASK (0xff << CLK_TH2_TIMER0_SHIFT)
#define CLK_TH2_TIMER1_SHIFT (8)
#define CLK_TH2_TIMER1_MASK (0xff << CLK_TH2_TIMER1_SHIFT)
#define CLK_TH2_TIMER2_SHIFT (16)
#define CLK_TH2_TIMER2_MASK (0xff << CLK_TH2_TIMER2_SHIFT)
/* CLK_TH3 register bit definitions (Clock threshold controller 3) */
#define CLK_TH3_I2S0_SHIFT (0)
#define CLK_TH3_I2S0_MASK (0xffff << CLK_TH3_I2S0_SHIFT)
#define CLK_TH3_I2S1_SHIFT (16)
#define CLK_TH3_I2S1_MASK (0xffff << CLK_TH3_I2S1_SHIFT)
/* CLK_TH4 register bit definitions (Clock threshold controller 4) */
#define CLK_TH4_I2S2_SHIFT (0)
#define CLK_TH4_I2S2_MASK (0xffff << CLK_TH4_I2S2_SHIFT)
/* CLK_TH5 register bit definitions (Clock threshold controller 5) */
#define CLK_TH5_I2C0_SHIFT (8)
#define CLK_TH5_I2C0_MASK (0xff << CLK_TH5_I2C0_SHIFT)
#define CLK_TH5_I2C1_SHIFT (16)
#define CLK_TH5_I2C1_MASK (0xff << CLK_TH5_I2C1_SHIFT)
#define CLK_TH5_I2C2_SHIFT (24)
#define CLK_TH5_I2C2_MASK (0xff << CLK_TH5_I2C2_SHIFT)
/* CLK_TH6 register bit definitions (Clock threshold controller 6) */
#define CLK_TH6_WDT0_SHIFT (0)
#define CLK_TH6_WDT0_MASK (0xff << CLK_TH6_WDT0_SHIFT)
#define CLK_TH6_WDT1_SHIFT (8)
#define CLK_TH6_WDT1_MASK (0xff << CLK_TH6_WDT1_SHIFT)
/* PLL_LOCK register bit definitions (PLL lock tester) */
#define PLL_LOCK_PLL0_SHIFT (0)
#define PLL_LOCK_PLL0_MASK (0x3 << PLL_LOCK_PLL0_SHIFT)
#define PLL_LOCK_PLL0_SLIP_CLR (1 << 2)
#define PLL_LOCK_PLL1_SHIFT (8)
#define PLL_LOCK_PLL1_MASK (0x1 << PLL_LOCK_PLL1_SHIFT)
#define PLL_LOCK_PLL1_SLIP_CLR (1 << 10)
#define PLL_LOCK_PLL2_SHIFT (16)
#define PLL_LOCK_PLL2_MASK (0x1 << PLL_LOCK_PLL2_SHIFT)
#define PLL_LOCK_PLL2_SLIP_CLR (1 << 18)
#define PLL_LOCK_PLL0_LOCKED (0x3 << PLL_LOCK_PLL0_SHIFT)
#define PLL_LOCK_PLL1_LOCKED (0x1 << PLL_LOCK_PLL1_SHIFT)
#define PLL_LOCK_PLL2_LOCKED (0x1 << PLL_LOCK_PLL2_SHIFT)
/* Clock select macros */
#define CLKSEL0_ACLK_SEL(n) (n & 0x00000001)
+33 -11
View File
@@ -35,6 +35,7 @@
#include "riscv_internal.h"
#include "k210_clockconfig.h"
#include "k210_sysctl.h"
/****************************************************************************
* Pre-processor Definitions
@@ -46,7 +47,7 @@
* Private Data
****************************************************************************/
static uint32_t g_cpu_clock = 416000000;
static uint32_t g_cpu_clock = CONFIG_K210_CPU_FREQ;
/****************************************************************************
* Public Functions
@@ -90,22 +91,43 @@ void k210_clockconfig(void)
{
#ifndef CONFIG_K210_WITH_QEMU
uint32_t clksel0;
uint32_t div;
/* Obtain clock selector for ACLK */
/* Initialize sysctl driver */
clksel0 = getreg32(K210_SYSCTL_CLKSEL0);
k210_sysctl_init();
if (1 == CLKSEL0_ACLK_SEL(clksel0))
/* Wait for PLL0 to lock before configuring clocks */
while (!k210_sysctl_pll_is_locked(K210_SYSCTL_PLL0))
{
/* PLL0 selected */
g_cpu_clock = k210_get_pll0clk() / 2;
up_mdelay(1);
}
else
{
/* OSC selected */
g_cpu_clock = OSC_FREQ;
/* Enable essential system clocks */
k210_sysctl_clock_enable(K210_CLOCK_CPU);
k210_sysctl_clock_enable(K210_CLOCK_SRAM0);
k210_sysctl_clock_enable(K210_CLOCK_SRAM1);
/* Use new frequency API to update g_cpu_clock */
g_cpu_clock = k210_sysctl_clock_get_freq(K210_CLOCK_CPU);
if (g_cpu_clock == 0)
{
/* Fallback to PLL frequency calculation if new API fails */
clksel0 = getreg32(K210_SYSCTL_CLKSEL0);
if (1 == CLKSEL0_ACLK_SEL(clksel0))
{
div = (clksel0 & CLKSEL0_ACLK_DIV_MASK) >> CLKSEL0_ACLK_DIV_SHIFT;
g_cpu_clock = k210_get_pll0clk() / (2u << div);
}
else
{
g_cpu_clock = OSC_FREQ;
}
}
/* Workaround for stabilization */
File diff suppressed because it is too large Load Diff
+239
View File
@@ -0,0 +1,239 @@
/****************************************************************************
* arch/risc-v/src/k210/k210_sysctl.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_RISCV_SRC_K210_K210_SYSCTL_H
#define __ARCH_RISCV_SRC_K210_K210_SYSCTL_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/**
* @brief K210 peripheral clock ID enumeration
*
* This enumeration defines all clock IDs for K210 peripherals.
* These IDs are used to enable/disable clocks and get clock frequencies.
*/
typedef enum
{
K210_CLOCK_PLL0 = 0, /* PLL0 clock */
K210_CLOCK_PLL1, /* PLL1 clock */
K210_CLOCK_PLL2, /* PLL2 clock */
K210_CLOCK_CPU, /* CPU clock */
K210_CLOCK_SRAM0, /* SRAM0 clock */
K210_CLOCK_SRAM1, /* SRAM1 clock */
K210_CLOCK_APB0, /* APB0 bus clock */
K210_CLOCK_APB1, /* APB1 bus clock */
K210_CLOCK_APB2, /* APB2 bus clock */
K210_CLOCK_ROM, /* ROM clock */
K210_CLOCK_DMA, /* DMA clock */
K210_CLOCK_AI, /* AI accelerator clock */
K210_CLOCK_DVP, /* DVP camera interface clock */
K210_CLOCK_FFT, /* FFT accelerator clock */
K210_CLOCK_GPIO, /* GPIO clock */
K210_CLOCK_SPI0, /* SPI0 clock */
K210_CLOCK_SPI1, /* SPI1 clock */
K210_CLOCK_SPI2, /* SPI2 clock */
K210_CLOCK_SPI3, /* SPI3 clock */
K210_CLOCK_I2S0, /* I2S0 clock */
K210_CLOCK_I2S1, /* I2S1 clock */
K210_CLOCK_I2S2, /* I2S2 clock */
K210_CLOCK_I2C0, /* I2C0 clock */
K210_CLOCK_I2C1, /* I2C1 clock */
K210_CLOCK_I2C2, /* I2C2 clock */
K210_CLOCK_UART1, /* UART1 clock */
K210_CLOCK_UART2, /* UART2 clock */
K210_CLOCK_UART3, /* UART3 clock */
K210_CLOCK_AES, /* AES accelerator clock */
K210_CLOCK_FPIOA, /* FPIOA (GPIO mux) clock */
K210_CLOCK_TIMER0, /* TIMER0 clock */
K210_CLOCK_TIMER1, /* TIMER1 clock */
K210_CLOCK_TIMER2, /* TIMER2 clock */
K210_CLOCK_WDT0, /* Watchdog timer 0 clock */
K210_CLOCK_WDT1, /* Watchdog timer 1 clock */
K210_CLOCK_SHA, /* SHA accelerator clock */
K210_CLOCK_OTP, /* OTP (one-time programmable) clock */
K210_CLOCK_RTC, /* RTC clock */
K210_CLOCK_MAX /* Boundary check value */
} k210_clockid_t;
/**
* @brief K210 peripheral reset ID enumeration
*
* This enumeration defines all reset IDs for K210 peripherals.
* These IDs are used to reset individual peripherals.
*/
typedef enum
{
K210_RESET_SOC = 0, /* SOC reset */
K210_RESET_ROM, /* ROM reset */
K210_RESET_DMA, /* DMA reset */
K210_RESET_AI, /* AI accelerator reset */
K210_RESET_DVP, /* DVP camera interface reset */
K210_RESET_FFT, /* FFT accelerator reset */
K210_RESET_GPIO, /* GPIO reset */
K210_RESET_SPI0, /* SPI0 reset */
K210_RESET_SPI1, /* SPI1 reset */
K210_RESET_SPI2, /* SPI2 reset */
K210_RESET_SPI3, /* SPI3 reset */
K210_RESET_I2S0, /* I2S0 reset */
K210_RESET_I2S1, /* I2S1 reset */
K210_RESET_I2S2, /* I2S2 reset */
K210_RESET_I2C0, /* I2C0 reset */
K210_RESET_I2C1, /* I2C1 reset */
K210_RESET_I2C2, /* I2C2 reset */
K210_RESET_UART1, /* UART1 reset */
K210_RESET_UART2, /* UART2 reset */
K210_RESET_UART3, /* UART3 reset */
K210_RESET_AES, /* AES accelerator reset */
K210_RESET_FPIOA, /* FPIOA reset */
K210_RESET_TIMER0, /* TIMER0 reset */
K210_RESET_TIMER1, /* TIMER1 reset */
K210_RESET_TIMER2, /* TIMER2 reset */
K210_RESET_WDT0, /* Watchdog timer 0 reset */
K210_RESET_WDT1, /* Watchdog timer 1 reset */
K210_RESET_SHA, /* SHA accelerator reset */
K210_RESET_RTC, /* RTC reset */
K210_RESET_MAX /* Boundary check value */
} k210_rstidx_t;
#ifndef __ASSEMBLY__
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/**
* @brief Initialize the system controller
*
* This function initializes the K210 system controller, including
* PLL configuration and clock tree setup.
*/
EXTERN void k210_sysctl_init(void);
/**
* @brief Enable a peripheral clock
*
* @param clkid Clock ID of the peripheral
* @return 0 on success, negative error code on failure
*/
EXTERN int k210_sysctl_clock_enable(k210_clockid_t clkid);
/**
* @brief Disable a peripheral clock
*
* @param clkid Clock ID of the peripheral
* @return 0 on success, negative error code on failure
*/
EXTERN int k210_sysctl_clock_disable(k210_clockid_t clkid);
/**
* @brief Get the frequency of a peripheral clock
*
* @param clkid Clock ID of the peripheral
* @return Clock frequency in Hz, 0 on error
*/
EXTERN uint32_t k210_sysctl_clock_get_freq(k210_clockid_t clkid);
/**
* @brief Get current CPU clock frequency
*
* @return CPU clock frequency in Hz
*/
EXTERN uint32_t k210_sysctl_cpu_get_freq(void);
/**
* @brief Set CPU clock frequency (SDK-like)
*
* This function adjusts PLL0 and keeps current ACLK divider setting.
* The final frequency may be near the target due to integer PLL factors.
*
* @param freq Target CPU frequency in Hz
* @return Actual CPU clock frequency in Hz, 0 on failure
*/
EXTERN uint32_t k210_sysctl_cpu_set_freq(uint32_t freq);
/**
* @brief Reset a peripheral
*
* @param rstidx Reset ID of the peripheral
* @return 0 on success, negative error code on failure
*/
EXTERN int k210_sysctl_reset(k210_rstidx_t rstidx);
/**
* @brief Initialize a peripheral (enable clock and deassert reset)
*
* This is a convenience function that enables the clock and releases
* the peripheral from reset state.
*
* @param clkid Clock ID of the peripheral
* @param rstidx Reset ID of the peripheral
* @return 0 on success, negative error code on failure
*/
EXTERN int k210_sysctl_init_peripheral(k210_clockid_t clkid,
k210_rstidx_t rstidx);
/**
* @brief Check if a PLL is locked
*
* @param pll_offset PLL register offset (K210_SYSCTL_PLL0/PLL1/PLL2)
* @return true if PLL is locked, false otherwise
*/
EXTERN bool k210_sysctl_pll_is_locked(uint32_t pll_offset);
#if defined(__cplusplus)
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_RISCV_SRC_K210_K210_SYSCTL_H */