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