Skip to content

Commit 8b222b0

Browse files
committed
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>
1 parent b8880c4 commit 8b222b0

7 files changed

Lines changed: 1853 additions & 14 deletions

File tree

arch/risc-v/src/k210/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ list(APPEND SRCS k210_timerisr.c k210_allocateheap.c k210_clockconfig.c)
2626

2727
list(APPEND SRCS k210_lowputc.c k210_serial.c k210_fpioa.c k210_gpiohs.c)
2828

29+
list(APPEND SRCS k210_sysctl.c)
30+
2931
if(CONFIG_BUILD_PROTECTED)
3032
list(APPEND SRCS k210_userspace.c)
3133
endif()

arch/risc-v/src/k210/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ config K210_UART0
2727

2828
endmenu
2929

30+
config K210_CPU_FREQ
31+
int "K210 CPU target frequency (Hz)"
32+
default 400000000
33+
range 40000000 600000000
34+
depends on ARCH_CHIP_K210
35+
---help---
36+
Set the K210 CPU target frequency in Hz.
37+
Default is 400000000 (400 MHz).
38+
Valid range: 40000000-600000000 Hz (40-600 MHz).
39+
3040
menu "K210 Others"
3141

3242
config K210_WITH_QEMU

arch/risc-v/src/k210/Make.defs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ HEAD_ASRC = k210_head.S
3030
CHIP_CSRCS = k210_allocateheap.c k210_clockconfig.c
3131
CHIP_CSRCS += k210_irq.c k210_irq_dispatch.c
3232
CHIP_CSRCS += k210_lowputc.c k210_serial.c k210_fpioa.c
33-
CHIP_CSRCS += k210_start.c k210_timerisr.c k210_gpiohs.c
33+
CHIP_CSRCS += k210_start.c k210_timerisr.c k210_gpiohs.c k210_sysctl.c
3434

3535
ifeq ($(CONFIG_BUILD_PROTECTED),y)
3636
CHIP_CSRCS += k210_userspace.c

arch/risc-v/src/k210/hardware/k210_sysctl.h

Lines changed: 292 additions & 2 deletions
Large diffs are not rendered by default.

arch/risc-v/src/k210/k210_clockconfig.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
#include "riscv_internal.h"
3737
#include "k210_clockconfig.h"
38+
#include "k210_sysctl.h"
3839

3940
/****************************************************************************
4041
* Pre-processor Definitions
@@ -46,7 +47,7 @@
4647
* Private Data
4748
****************************************************************************/
4849

49-
static uint32_t g_cpu_clock = 416000000;
50+
static uint32_t g_cpu_clock = CONFIG_K210_CPU_FREQ;
5051

5152
/****************************************************************************
5253
* Public Functions
@@ -90,22 +91,43 @@ void k210_clockconfig(void)
9091
{
9192
#ifndef CONFIG_K210_WITH_QEMU
9293
uint32_t clksel0;
94+
uint32_t div;
9395

94-
/* Obtain clock selector for ACLK */
96+
/* Initialize sysctl driver */
9597

96-
clksel0 = getreg32(K210_SYSCTL_CLKSEL0);
98+
k210_sysctl_init();
9799

98-
if (1 == CLKSEL0_ACLK_SEL(clksel0))
99-
{
100-
/* PLL0 selected */
100+
/* Wait for PLL0 to lock before configuring clocks */
101101

102-
g_cpu_clock = k210_get_pll0clk() / 2;
103-
}
104-
else
102+
while (!k210_sysctl_pll_is_locked(K210_SYSCTL_PLL0))
105103
{
106-
/* OSC selected */
104+
up_mdelay(1);
105+
}
106+
107+
/* Enable essential system clocks */
107108

108-
g_cpu_clock = OSC_FREQ;
109+
k210_sysctl_clock_enable(K210_CLOCK_CPU);
110+
k210_sysctl_clock_enable(K210_CLOCK_SRAM0);
111+
k210_sysctl_clock_enable(K210_CLOCK_SRAM1);
112+
113+
/* Use new frequency API to update g_cpu_clock */
114+
115+
g_cpu_clock = k210_sysctl_clock_get_freq(K210_CLOCK_CPU);
116+
if (g_cpu_clock == 0)
117+
{
118+
/* Fallback to PLL frequency calculation if new API fails */
119+
120+
clksel0 = getreg32(K210_SYSCTL_CLKSEL0);
121+
122+
if (1 == CLKSEL0_ACLK_SEL(clksel0))
123+
{
124+
div = (clksel0 & CLKSEL0_ACLK_DIV_MASK) >> CLKSEL0_ACLK_DIV_SHIFT;
125+
g_cpu_clock = k210_get_pll0clk() / (2u << div);
126+
}
127+
else
128+
{
129+
g_cpu_clock = OSC_FREQ;
130+
}
109131
}
110132

111133
/* Workaround for stabilization */

0 commit comments

Comments
 (0)