From 6778948f9de86c3cfaf36725a7c87dcff9ba247f Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 08:20:59 +0000 Subject: [PATCH] kernel_5.10 no rt --- kernel/arch/arm/mach-rockchip/rv1106_pm.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 114 insertions(+), 3 deletions(-) diff --git a/kernel/arch/arm/mach-rockchip/rv1106_pm.c b/kernel/arch/arm/mach-rockchip/rv1106_pm.c index a4d1c0f..7767b44 100644 --- a/kernel/arch/arm/mach-rockchip/rv1106_pm.c +++ b/kernel/arch/arm/mach-rockchip/rv1106_pm.c @@ -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 *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_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); } @@ -408,6 +413,87 @@ rkpm_bootdata_l2ctlr_f = 1; 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) @@ -616,10 +702,11 @@ 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) | @@ -949,7 +1036,18 @@ cpu_do_idle(); - pr_err("%s: Failed to suspend\n", __func__); +#if RV1106_WAKEUP_TO_SYSTEM_RESET + /* If reaches here, it means wakeup source cames before cpu enter wfi. + * So we should do system reset if RV1106_WAKEUP_TO_SYSTEM_RESET. + */ + writel_relaxed(0x000c000c, cru_base + RV1106_CRU_GLB_RST_CON); + writel_relaxed(0xffff0000, pmugrf_base + RV1106_PMUGRF_SOC_CON(4)); + writel_relaxed(0xffff0000, pmugrf_base + RV1106_PMUGRF_SOC_CON(5)); + dsb(sy); + writel_relaxed(0xfdb9, cru_base + RV1106_CRU_GLB_SRST_FST); +#endif + + rkpm_printstr("Failed to suspend\n"); return 1; } @@ -964,6 +1062,7 @@ rkpm_printch('-'); +RE_ENTER_SLEEP: clock_suspend(); rkpm_printch('0'); @@ -1000,6 +1099,17 @@ 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(); @@ -1062,6 +1172,7 @@ 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; -- Gitblit v1.6.2