hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/arch/arm/mach-rockchip/rv1106_pm.c
....@@ -15,6 +15,7 @@
1515 #include <asm/fiq_glue.h>
1616 #include <asm/tlbflush.h>
1717 #include <asm/suspend.h>
18
+#include <linux/irqchip/arm-gic.h>
1819
1920 #include "rkpm_gicv2.h"
2021 #include "rkpm_helpers.h"
....@@ -91,6 +92,7 @@
9192 static void __iomem *pmu_base;
9293 static void __iomem *nstimer_base;
9394 static void __iomem *stimer_base;
95
+static void __iomem *mbox_base;
9496 static void __iomem *ddrc_base;
9597 static void __iomem *ioc_base[5];
9698 static void __iomem *gpio_base[5];
....@@ -309,7 +311,10 @@
309311
310312 static void gic400_restore(void)
311313 {
312
- rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save);
314
+ if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP))
315
+ writel_relaxed(0x3, gicd_base + GIC_DIST_CTRL);
316
+ else
317
+ rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save);
313318 rkpm_gicv2_cpu_restore(gicd_base, gicc_base, &gicc_ctx_save);
314319 }
315320
....@@ -408,6 +413,87 @@
408413
409414 rkpm_bootdata_l2ctlr_f = 1;
410415 rkpm_bootdata_l2ctlr = rv1106_l2_config();
416
+}
417
+
418
+static void writel_clrset_bits(u32 clr, u32 set, void __iomem *addr)
419
+{
420
+ u32 val = readl_relaxed(addr);
421
+
422
+ val &= ~clr;
423
+ val |= set;
424
+ writel_relaxed(val, addr);
425
+}
426
+
427
+static void gic_irq_en(int irq)
428
+{
429
+ writel_clrset_bits(0xff << irq % 4 * 8, 0x1 << irq % 4 * 8,
430
+ gicd_base + GIC_DIST_TARGET + (irq >> 2 << 2));
431
+ writel_clrset_bits(0xff << irq % 4 * 8, 0xa0 << irq % 4 * 8,
432
+ gicd_base + GIC_DIST_PRI + (irq >> 2 << 2));
433
+ writel_clrset_bits(0x3 << irq % 16 * 2, 0x1 << irq % 16 * 2,
434
+ gicd_base + GIC_DIST_CONFIG + (irq >> 4 << 2));
435
+ writel_clrset_bits(BIT(irq % 32), BIT(irq % 32),
436
+ gicd_base + GIC_DIST_IGROUP + (irq >> 5 << 2));
437
+
438
+ dsb(sy);
439
+ writel_relaxed(0x1 << irq % 32, gicd_base + GIC_DIST_ENABLE_SET + (irq >> 5 << 2));
440
+ dsb(sy);
441
+}
442
+
443
+static int is_hpmcu_mbox_int(void)
444
+{
445
+ return !!(readl(mbox_base + RV1106_MBOX_B2A_STATUS) & BIT(0));
446
+}
447
+
448
+static void hpmcu_start(void)
449
+{
450
+ /* enable hpmcu mailbox AP irq */
451
+ gic_irq_en(RV1106_HPMCU_MBOX_IRQ_AP);
452
+
453
+ /* tell hpmcu that we are currently in system wake up. */
454
+ writel(RV1106_SYS_IS_WKUP, pmu_base + RV1106_PMU_SYS_REG(0));
455
+
456
+ /* set the mcu uncache area, usually set the devices address */
457
+ writel(0xff000, coregrf_base + RV1106_COREGRF_CACHE_PERI_ADDR_START);
458
+ writel(0xffc00, coregrf_base + RV1106_COREGRF_CACHE_PERI_ADDR_END);
459
+ /* Reset the hp mcu */
460
+ writel(0x1e001e, corecru_base + RV1106_COERCRU_SFTRST_CON(1));
461
+ /* set the mcu addr */
462
+ writel(RV1106_HPMCU_BOOT_ADDR,
463
+ coresgrf_base + RV1106_CORESGRF_HPMCU_BOOTADDR);
464
+ dsb(sy);
465
+
466
+ /* release the mcu */
467
+ writel(0x1e0000, corecru_base + RV1106_COERCRU_SFTRST_CON(1));
468
+ dsb(sy);
469
+}
470
+
471
+static int hpmcu_fast_wkup(void)
472
+{
473
+ u32 cmd;
474
+
475
+ hpmcu_start();
476
+
477
+ while (1) {
478
+ rkpm_printstr("-s-\n");
479
+ dsb(sy);
480
+ wfi();
481
+ rkpm_printstr("-w-\n");
482
+
483
+ if (is_hpmcu_mbox_int()) {
484
+ rkpm_printstr("-h-mbox-\n");
485
+ /* clear system wake up state */
486
+ writel(0, pmu_base + RV1106_PMU_SYS_REG(0));
487
+ writel(BIT(0), mbox_base + RV1106_MBOX_B2A_STATUS);
488
+ break;
489
+ }
490
+ }
491
+
492
+ cmd = readl(mbox_base + RV1106_MBOX_B2A_CMD_0);
493
+ if (cmd == RV1106_MBOX_CMD_AP_SUSPEND)
494
+ return 1;
495
+ else
496
+ return 0;
411497 }
412498
413499 static void clock_suspend(void)
....@@ -616,10 +702,11 @@
616702 ddr_data.ioc1_1a_iomux_l = readl_relaxed(ioc_base[1] + 0);
617703
618704 pmu_wkup_con =
619
- /* BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN) | */
620705 /* BIT(RV1106_PMU_WAKEUP_CPU_INT_EN) | */
621706 BIT(RV1106_PMU_WAKEUP_GPIO_INT_EN) |
622707 0;
708
+ if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP))
709
+ pmu_wkup_con |= BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN);
623710
624711 pmu_pwr_con =
625712 BIT(RV1106_PMU_PWRMODE_EN) |
....@@ -949,7 +1036,18 @@
9491036
9501037 cpu_do_idle();
9511038
952
- pr_err("%s: Failed to suspend\n", __func__);
1039
+#if RV1106_WAKEUP_TO_SYSTEM_RESET
1040
+ /* If reaches here, it means wakeup source cames before cpu enter wfi.
1041
+ * So we should do system reset if RV1106_WAKEUP_TO_SYSTEM_RESET.
1042
+ */
1043
+ writel_relaxed(0x000c000c, cru_base + RV1106_CRU_GLB_RST_CON);
1044
+ writel_relaxed(0xffff0000, pmugrf_base + RV1106_PMUGRF_SOC_CON(4));
1045
+ writel_relaxed(0xffff0000, pmugrf_base + RV1106_PMUGRF_SOC_CON(5));
1046
+ dsb(sy);
1047
+ writel_relaxed(0xfdb9, cru_base + RV1106_CRU_GLB_SRST_FST);
1048
+#endif
1049
+
1050
+ rkpm_printstr("Failed to suspend\n");
9531051
9541052 return 1;
9551053 }
....@@ -964,6 +1062,7 @@
9641062
9651063 rkpm_printch('-');
9661064
1065
+RE_ENTER_SLEEP:
9671066 clock_suspend();
9681067 rkpm_printch('0');
9691068
....@@ -1000,6 +1099,17 @@
10001099
10011100 clock_resume();
10021101 rkpm_printch('-');
1102
+
1103
+ /* Check whether it's time_out wakeup */
1104
+ if (IS_ENABLED(CONFIG_RV1106_HPMCU_FAST_WAKEUP) && ddr_data.pmu_wkup_int_st == 0) {
1105
+ if (hpmcu_fast_wkup()) {
1106
+ rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save);
1107
+ goto RE_ENTER_SLEEP;
1108
+ } else {
1109
+ rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save);
1110
+ rkpm_gicv2_cpu_restore(gicd_base, gicc_base, &gicc_ctx_save);
1111
+ }
1112
+ }
10031113
10041114 fiq_glue_resume();
10051115
....@@ -1062,6 +1172,7 @@
10621172 corecru_base = dev_reg_base + RV1106_CORECRU_OFFSET;
10631173 venccru_base = dev_reg_base + RV1106_VENCCRU_OFFSET;
10641174 vocru_base = dev_reg_base + RV1106_VOCRU_OFFSET;
1175
+ mbox_base = dev_reg_base + RV1106_MBOX_OFFSET;
10651176
10661177 ioc_base[0] = dev_reg_base + RV1106_GPIO0IOC_OFFSET;
10671178 ioc_base[1] = dev_reg_base + RV1106_GPIO1IOC_OFFSET;