mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
ARM: rockchip: rv1106: sleep: support hpmcu fast wakeup
Signed-off-by: XiaoDong Huang <derrick.huang@rock-chips.com> Change-Id: I4a34e33fd267a54c4df0a5b158e28837e3a28051
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include <asm/fiq_glue.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/suspend.h>
|
||||
#include <linux/irqchip/arm-gic.h>
|
||||
|
||||
#include "rkpm_gicv2.h"
|
||||
#include "rkpm_helpers.h"
|
||||
@@ -91,6 +92,7 @@ static void __iomem *firewall_syssram_base;
|
||||
static void __iomem *pmu_base;
|
||||
static void __iomem *nstimer_base;
|
||||
static void __iomem *stimer_base;
|
||||
static void __iomem *mbox_base;
|
||||
static void __iomem *ddrc_base;
|
||||
static void __iomem *ioc_base[5];
|
||||
static void __iomem *gpio_base[5];
|
||||
@@ -309,7 +311,10 @@ static void gic400_save(void)
|
||||
|
||||
static void gic400_restore(void)
|
||||
{
|
||||
rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save);
|
||||
if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP))
|
||||
writel_relaxed(0x3, gicd_base + GIC_DIST_CTRL);
|
||||
else
|
||||
rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save);
|
||||
rkpm_gicv2_cpu_restore(gicd_base, gicc_base, &gicc_ctx_save);
|
||||
}
|
||||
|
||||
@@ -410,6 +415,87 @@ static void __init rv1106_config_bootdata(void)
|
||||
rkpm_bootdata_l2ctlr = rv1106_l2_config();
|
||||
}
|
||||
|
||||
static void writel_clrset_bits(u32 clr, u32 set, void __iomem *addr)
|
||||
{
|
||||
u32 val = readl_relaxed(addr);
|
||||
|
||||
val &= ~clr;
|
||||
val |= set;
|
||||
writel_relaxed(val, addr);
|
||||
}
|
||||
|
||||
static void gic_irq_en(int irq)
|
||||
{
|
||||
writel_clrset_bits(0xff << irq % 4 * 8, 0x1 << irq % 4 * 8,
|
||||
gicd_base + GIC_DIST_TARGET + (irq >> 2 << 2));
|
||||
writel_clrset_bits(0xff << irq % 4 * 8, 0xa0 << irq % 4 * 8,
|
||||
gicd_base + GIC_DIST_PRI + (irq >> 2 << 2));
|
||||
writel_clrset_bits(0x3 << irq % 16 * 2, 0x1 << irq % 16 * 2,
|
||||
gicd_base + GIC_DIST_CONFIG + (irq >> 4 << 2));
|
||||
writel_clrset_bits(BIT(irq % 32), BIT(irq % 32),
|
||||
gicd_base + GIC_DIST_IGROUP + (irq >> 5 << 2));
|
||||
|
||||
dsb(sy);
|
||||
writel_relaxed(0x1 << irq % 32, gicd_base + GIC_DIST_ENABLE_SET + (irq >> 5 << 2));
|
||||
dsb(sy);
|
||||
}
|
||||
|
||||
static int is_hpmcu_mbox_int(void)
|
||||
{
|
||||
return !!(readl(mbox_base + RV1106_MBOX_B2A_STATUS) & BIT(0));
|
||||
}
|
||||
|
||||
static void hpmcu_start(void)
|
||||
{
|
||||
/* enable hpmcu mailbox AP irq */
|
||||
gic_irq_en(RV1106_HPMCU_MBOX_IRQ_AP);
|
||||
|
||||
/* tell hpmcu that we are currently in system wake up. */
|
||||
writel(RV1106_SYS_IS_WKUP, pmu_base + RV1106_PMU_SYS_REG(0));
|
||||
|
||||
/* set the mcu uncache area, usually set the devices address */
|
||||
writel(0xff000, coregrf_base + RV1106_COREGRF_CACHE_PERI_ADDR_START);
|
||||
writel(0xffc00, coregrf_base + RV1106_COREGRF_CACHE_PERI_ADDR_END);
|
||||
/* Reset the hp mcu */
|
||||
writel(0x1e001e, corecru_base + RV1106_COERCRU_SFTRST_CON(1));
|
||||
/* set the mcu addr */
|
||||
writel(RV1106_HPMCU_BOOT_ADDR,
|
||||
coresgrf_base + RV1106_CORESGRF_HPMCU_BOOTADDR);
|
||||
dsb(sy);
|
||||
|
||||
/* release the mcu */
|
||||
writel(0x1e0000, corecru_base + RV1106_COERCRU_SFTRST_CON(1));
|
||||
dsb(sy);
|
||||
}
|
||||
|
||||
static int hpmcu_fast_wkup(void)
|
||||
{
|
||||
u32 cmd;
|
||||
|
||||
hpmcu_start();
|
||||
|
||||
while (1) {
|
||||
rkpm_printstr("-s-\n");
|
||||
dsb(sy);
|
||||
wfi();
|
||||
rkpm_printstr("-w-\n");
|
||||
|
||||
if (is_hpmcu_mbox_int()) {
|
||||
rkpm_printstr("-h-mbox-\n");
|
||||
/* clear system wake up state */
|
||||
writel(0, pmu_base + RV1106_PMU_SYS_REG(0));
|
||||
writel(BIT(0), mbox_base + RV1106_MBOX_B2A_STATUS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cmd = readl(mbox_base + RV1106_MBOX_B2A_CMD_0);
|
||||
if (cmd == RV1106_MBOX_CMD_AP_SUSPEND)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clock_suspend(void)
|
||||
{
|
||||
int i;
|
||||
@@ -616,10 +702,11 @@ static void pmu_sleep_config(void)
|
||||
ddr_data.ioc1_1a_iomux_l = readl_relaxed(ioc_base[1] + 0);
|
||||
|
||||
pmu_wkup_con =
|
||||
/* BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN) | */
|
||||
/* BIT(RV1106_PMU_WAKEUP_CPU_INT_EN) | */
|
||||
BIT(RV1106_PMU_WAKEUP_GPIO_INT_EN) |
|
||||
0;
|
||||
if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP))
|
||||
pmu_wkup_con |= BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN);
|
||||
|
||||
pmu_pwr_con =
|
||||
BIT(RV1106_PMU_PWRMODE_EN) |
|
||||
@@ -964,6 +1051,7 @@ static int rv1106_suspend_enter(suspend_state_t state)
|
||||
|
||||
rkpm_printch('-');
|
||||
|
||||
RE_ENTER_SLEEP:
|
||||
clock_suspend();
|
||||
rkpm_printch('0');
|
||||
|
||||
@@ -1001,6 +1089,17 @@ static int rv1106_suspend_enter(suspend_state_t state)
|
||||
clock_resume();
|
||||
rkpm_printch('-');
|
||||
|
||||
/* Check whether it's time_out wakeup */
|
||||
if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP) && ddr_data.pmu_wkup_int_st == 0) {
|
||||
if (hpmcu_fast_wkup()) {
|
||||
rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save);
|
||||
goto RE_ENTER_SLEEP;
|
||||
} else {
|
||||
rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save);
|
||||
rkpm_gicv2_cpu_restore(gicd_base, gicc_base, &gicc_ctx_save);
|
||||
}
|
||||
}
|
||||
|
||||
fiq_glue_resume();
|
||||
|
||||
rv1106_dbg_irq_finish();
|
||||
@@ -1062,6 +1161,7 @@ static int __init rv1106_suspend_init(struct device_node *np)
|
||||
corecru_base = dev_reg_base + RV1106_CORECRU_OFFSET;
|
||||
venccru_base = dev_reg_base + RV1106_VENCCRU_OFFSET;
|
||||
vocru_base = dev_reg_base + RV1106_VOCRU_OFFSET;
|
||||
mbox_base = dev_reg_base + RV1106_MBOX_OFFSET;
|
||||
|
||||
ioc_base[0] = dev_reg_base + RV1106_GPIO0IOC_OFFSET;
|
||||
ioc_base[1] = dev_reg_base + RV1106_GPIO1IOC_OFFSET;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define __MACH_ROCKCHIP_RV1106_PM_H
|
||||
|
||||
#define RV1106_WAKEUP_TO_SYSTEM_RESET 0
|
||||
#define RV1106_HPMCU_FAST_WKUP_TIMEOUT 2000 /* ms */
|
||||
|
||||
#define RV1106_PERIGRF_OFFSET 0x0
|
||||
#define RV1106_VENCGRF_OFFSET 0x10000
|
||||
@@ -54,6 +55,7 @@
|
||||
|
||||
#define RV1106_NSTIMER_OFFSET 0x580000
|
||||
#define RV1106_STIMER_OFFSET 0x590000
|
||||
#define RV1106_MBOX_OFFSET 0x5c0000
|
||||
#define RV1106_PMUSRAM_OFFSET 0x670000
|
||||
#define RV1106_DDRC_OFFSET 0x800000
|
||||
#define RV1106_FW_DDR_OFFSET 0x900000
|
||||
@@ -101,6 +103,7 @@
|
||||
#define RV1106_CORECRU_GATE_CON(i) (0x800 + (i) * 4)
|
||||
#define RV1106_COERCRU_CLKSEL_CON(i) (0x300 + (i) * 4)
|
||||
#define RV1106_CORECRU_GATE_CON_NUM 2
|
||||
#define RV1106_COERCRU_SFTRST_CON(i) (0xa00 + (i) * 4)
|
||||
|
||||
/* grf */
|
||||
#define RV1106_PMUGRF_SOC_CON(i) ((i) * 4)
|
||||
@@ -110,6 +113,11 @@
|
||||
|
||||
#define RV1106_DDRGRF_CON(i) ((i) * 0x4)
|
||||
|
||||
#define RV1106_CORESGRF_HPMCU_BOOTADDR 0x44
|
||||
|
||||
#define RV1106_COREGRF_CACHE_PERI_ADDR_START 0x24
|
||||
#define RV1106_COREGRF_CACHE_PERI_ADDR_END 0x28
|
||||
|
||||
/* pvmt */
|
||||
#define RV1106_PVTM_CON(i) (0x4 + (i) * 4)
|
||||
#define RV1106_PVTM_INTEN 0x70
|
||||
@@ -177,6 +185,17 @@
|
||||
#define PMU_SUSPEND_MAGIC 0x02468ace
|
||||
#define PMU_RESUME_MAGIC 0x13579bdf
|
||||
|
||||
/* mcu */
|
||||
#define RV1106_MBOX_B2A_STATUS 0x2c
|
||||
#define RV1106_MBOX_B2A_CMD_0 0x30
|
||||
|
||||
#define RV1106_HPMCU_MBOX_IRQ_AP 33
|
||||
|
||||
#define RV1106_HPMCU_BOOT_ADDR 0x40000
|
||||
#define RV1106_MBOX_CMD_AP_SUSPEND 0x12345600
|
||||
#define RV1106_MBOX_CMD_AP_RESUME 0x12345601
|
||||
#define RV1106_SYS_IS_WKUP 0x87654300
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
extern unsigned long rkpm_bootdata_cpusp;
|
||||
extern unsigned long rkpm_bootdata_cpu_code;
|
||||
|
||||
Reference in New Issue
Block a user