k1pro:cpuidle: support cpuidle
Change-Id: I586ebcec8e3b03cec44a1845b1bee36b79c14d0e
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user