k1pro:cpuidle: support cpuidle

Change-Id: I586ebcec8e3b03cec44a1845b1bee36b79c14d0e
This commit is contained in:
Nell
2023-09-23 12:38:00 +08:00
committed by zhangmeng
parent a21ef18c58
commit 69b5206e18
5 changed files with 109 additions and 51 deletions

View File

@@ -145,6 +145,7 @@ choice
config SOC_SPACEMIT_K1PRO
bool "k1-pro"
select DW_APB_TIMER_OF
help
This enables support for Spacemit k1-pro Platform Hardware.

View File

@@ -27,7 +27,7 @@
reg = <0>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt";
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc";
riscv,cbom-block-size = <64>;
mmu-type = "riscv,sv39";
cpu-freq = "1.848Ghz";
@@ -51,7 +51,7 @@
reg = <1>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt";
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc";
riscv,cbom-block-size = <64>;
mmu-type = "riscv,sv39";
cpu-freq = "1.848Ghz";
@@ -75,7 +75,7 @@
reg = <2>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt";
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc";
riscv,cbom-block-size = <64>;
mmu-type = "riscv,sv39";
cpu-freq = "1.848Ghz";
@@ -99,7 +99,7 @@
reg = <3>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt";
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc";
riscv,cbom-block-size = <64>;
mmu-type = "riscv,sv39";
cpu-freq = "1.848Ghz";
@@ -119,97 +119,84 @@
};
};
cpu-map {
cluster0 {
core0 {
cpu = <&cpu_0>;
};
core1 {
cpu = <&cpu_1>;
};
core2 {
cpu = <&cpu_2>;
};
core3 {
cpu = <&cpu_3>;
};
};
};
idle-states {
CPU_RET: cpu-ret {
compatible = "riscv,idle-state", "domain-idle-state";
idle-state-name = "riscv,cpu-ret";
riscv,sbi-suspend-param = <0x10000000>;
entry-latency-us = <20>;
exit-latency-us = <40>;
min-residency-us = <80>;
local-timer-stop;
entry-latency-us = <100>;
exit-latency-us = <120>;
min-residency-us = <160>;
};
CPU_NONRET: cpu-nonret {
compatible = "riscv,idle-state", "domain-idle-state";
idle-state-name = "riscv,cpu-nonret";
riscv,sbi-suspend-param = <0x90000000>;
entry-latency-us = <250>;
local-timer-stop;
entry-latency-us = <200>;
exit-latency-us = <500>;
min-residency-us = <950>;
local-timer-stop;
};
CLUSTER_RET: cluster-ret {
compatible = "domain-idle-state";
idle-state-name = "riscv,cluster-ret";
riscv,sbi-suspend-param = <0x11000000>;
entry-latency-us = <50>;
exit-latency-us = <100>;
min-residency-us = <250>;
wakeup-latency-us = <130>;
local-timer-stop;
};
/**
* CLUSTER_RET: cluster-ret {
* compatible = "domain-idle-state";
* idle-state-name = "riscv,cluster-ret";
* riscv,sbi-suspend-param = <0x11000000>;
* local-timer-stop;
* entry-latency-us = <50>;
* exit-latency-us = <100>;
* min-residency-us = <250>;
* wakeup-latency-us = <130>;
* };
*/
CLUSTER_NONRET: cluster-nonret {
compatible = "domain-idle-state";
idle-state-name = "riscv,cluster-nonret";
riscv,sbi-suspend-param = <0x91000000>;
local-timer-stop;
entry-latency-us = <600>;
exit-latency-us = <1100>;
min-residency-us = <2700>;
wakeup-latency-us = <1500>;
local-timer-stop;
};
};
power-domains {
CPU_PD0: cpu0 {
#power-domain-cells = <0>;
power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_RET>, <&CPU_NONRET>;
power-domains = <&CLUSTER_PD0>;
domain-idle-states = <&CPU_RET>, <&CPU_NONRET>;
};
CPU_PD1: cpu1 {
#power-domain-cells = <0>;
power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_RET>, <&CPU_NONRET>;
power-domains = <&CLUSTER_PD0>;
domain-idle-states = <&CPU_RET>, <&CPU_NONRET>;
};
CPU_PD2: cpu2 {
#power-domain-cells = <0>;
power-domains = <&CLUSTER_PD>;
power-domains = <&CLUSTER_PD1>;
domain-idle-states = <&CPU_RET>, <&CPU_NONRET>;
};
CPU_PD3: cpu3 {
#power-domain-cells = <0>;
power-domains = <&CLUSTER_PD>;
domain-idle-states = <&CPU_RET>, <&CPU_NONRET>;
power-domains = <&CLUSTER_PD1>;
domain-idle-states = <&CPU_RET>, <&CPU_NONRET>;
};
CLUSTER_PD: cpu-cluster0 {
CLUSTER_PD0: cpu-cluster0 {
#power-domain-cells = <0>;
domain-idle-states = <&CLUSTER_RET>, <&CLUSTER_NONRET>;
domain-idle-states = /* <&CLUSTER_RET>, */ <&CLUSTER_NONRET>;
};
CLUSTER_PD1: cpu-cluster1 {
#power-domain-cells = <0>;
domain-idle-states = /* <&CLUSTER_RET>, */ <&CLUSTER_NONRET>;
};
};
};
@@ -342,6 +329,16 @@
riscv,ndev = <159>;
};
broadcast_timer: broadcast_timer@2cfa0000 {
compatible = "snps,dw-apb-timer";
reg = <0x0 0x2cfa0000 0x0 0x14>;
interrupt-parent = <&intc>;
interrupts = <16>;
clock-frequency = "50000000";
resets = <&reset RESET_TIMER>;
status = "okay";
};
/* Normal serial, log */
uart0: serial@2cea0000 {
compatible = "snps,dw-apb-uart";

View File

@@ -94,6 +94,7 @@ static void apbt_eoi(struct dw_apb_timer *timer)
static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
{
u32 ctrl;
struct clock_event_device *evt = data;
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
@@ -105,6 +106,15 @@ static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
if (dw_ced->eoi)
dw_ced->eoi(&dw_ced->timer);
/* disable the timer & interrupt in one-shot mode */
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
if (!(ctrl & APBTMR_CONTROL_MODE_PERIODIC)) {
ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL);
ctrl &= ~APBTMR_CONTROL_ENABLE;
ctrl |= APBTMR_CONTROL_INT;
apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
}
evt->event_handler(evt);
return IRQ_HANDLED;
}
@@ -211,9 +221,14 @@ static int apbt_next_event(unsigned long delta,
ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL);
ctrl &= ~APBTMR_CONTROL_ENABLE;
apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
/* clear the pending */
apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_EOI);
/* write new count */
apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
ctrl |= APBTMR_CONTROL_ENABLE;
ctrl &= ~APBTMR_CONTROL_INT;
apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
return 0;

View File

@@ -35,8 +35,46 @@ static int riscv_clock_next_event(unsigned long delta,
struct clock_event_device *ce)
{
u64 next_tval = get_cycles64() + delta;
csr_set(CSR_IE, IE_TIE);
if (static_branch_likely(&riscv_sstc_available)) {
#if defined(CONFIG_32BIT)
csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
csr_write(CSR_STIMECMPH, next_tval >> 32);
#else
csr_write(CSR_STIMECMP, next_tval);
#endif
} else
sbi_set_timer(next_tval);
return 0;
}
static int riscv_set_state_shutdown(struct clock_event_device *ce)
{
csr_clear(CSR_IE, IE_TIE);
u64 next_tval = 0xffffffffffffffff;
if (static_branch_likely(&riscv_sstc_available)) {
#if defined(CONFIG_32BIT)
csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
csr_write(CSR_STIMECMPH, next_tval >> 32);
#else
csr_write(CSR_STIMECMP, next_tval);
#endif
} else
sbi_set_timer(next_tval);
return 0;
}
static int riscv_set_state_oneshot(struct clock_event_device *ce)
{
u64 next_tval = 0xffffffffffffffff;
csr_set(CSR_IE, IE_TIE);
if (static_branch_likely(&riscv_sstc_available)) {
#if defined(CONFIG_32BIT)
csr_write(CSR_STIMECMP, next_tval & 0xFFFFFFFF);
@@ -53,9 +91,12 @@ static int riscv_clock_next_event(unsigned long delta,
static unsigned int riscv_clock_event_irq;
static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = {
.name = "riscv_timer_clockevent",
.features = CLOCK_EVT_FEAT_ONESHOT,
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP,
.rating = 100,
.set_next_event = riscv_clock_next_event,
.set_state_shutdown = riscv_set_state_shutdown,
.set_state_oneshot_stopped = riscv_set_state_shutdown,
.set_state_oneshot = riscv_set_state_oneshot,
};
/*

View File

@@ -80,6 +80,10 @@ static int sbi_suspend_finisher(unsigned long suspend_type,
{
struct sbiret ret;
#if defined(CONFIG_SOC_SPACEMIT_K1PRO) || defined(CONFIG_SOC_SPACEMIT_K1X)
/* flush the local cache */
sbi_flush_local_dcache_all();
#endif
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_SUSPEND,
suspend_type, resume_addr, opaque, 0, 0, 0);