4063 lines
120 KiB
Diff
4063 lines
120 KiB
Diff
From 19f8e52d2c8795bbde80dcd13dff517b96735855 Mon Sep 17 00:00:00 2001
|
|
From: XiaoDong Huang <derrick.huang@rock-chips.com>
|
|
Date: Mon, 26 Jun 2023 16:43:30 +0800
|
|
Subject: [PATCH] feat(rk3588): support rk3588
|
|
|
|
rk3588 is an Octa-core soc with Cortex-a55/a76 inside.
|
|
This patch supports the following functions:
|
|
1. basic platform setup
|
|
2. power up/off cpus
|
|
3. suspend/resume cpus
|
|
4. suspend/resume system
|
|
5. reset system
|
|
6. power off system
|
|
|
|
Signed-off-by: XiaoDong Huang <derrick.huang@rock-chips.com>
|
|
Change-Id: I598109f15a2efd5b33aedd176cf708c08cb1dcf4
|
|
---
|
|
|
|
diff --git a/docs/plat/rockchip.rst b/docs/plat/rockchip.rst
|
|
index 53f63b5..384cd73 100644
|
|
--- a/docs/plat/rockchip.rst
|
|
+++ b/docs/plat/rockchip.rst
|
|
@@ -11,6 +11,7 @@
|
|
- rk3368: Octa-Core Cortex-A53
|
|
- rk3399: Hexa-Core Cortex-A53/A72
|
|
- rk3566/rk3568: Quad-Core Cortex-A55
|
|
+- rk3588: Octa-Core Cortex-A55/A76
|
|
|
|
|
|
Boot Sequence
|
|
diff --git a/plat/rockchip/common/include/plat_pm_helpers.h b/plat/rockchip/common/include/plat_pm_helpers.h
|
|
new file mode 100644
|
|
index 0000000..2204a65
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/common/include/plat_pm_helpers.h
|
|
@@ -0,0 +1,51 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef PLAT_PM_HELPERS_H
|
|
+#define PLAT_PM_HELPERS_H
|
|
+
|
|
+#include <stdint.h>
|
|
+
|
|
+/**
|
|
+ * Use this macro to define a register region.
|
|
+ * start: start offset from the base address.
|
|
+ * end: end offset from the base address.
|
|
+ * stride: stride of registers in region.
|
|
+ * base: base address of registers in region.
|
|
+ * wmsk: write mask of registers in region.
|
|
+ */
|
|
+#define REG_REGION(_start, _end, _stride, _base, _wmsk) \
|
|
+{ \
|
|
+ .start = (_base) + (_start), \
|
|
+ .end = (_base) + (_end), \
|
|
+ .stride = _stride, \
|
|
+ .wmsk = _wmsk \
|
|
+}
|
|
+
|
|
+struct reg_region {
|
|
+ /* Start address of region */
|
|
+ uint32_t start;
|
|
+ /* End address of region */
|
|
+ uint32_t end;
|
|
+ /* Stride of registers in region */
|
|
+ uint32_t stride;
|
|
+ /* Write mask of registers in region */
|
|
+ uint32_t wmsk;
|
|
+ /* Buffer to save/restore registers in region */
|
|
+ uint32_t *buf;
|
|
+};
|
|
+
|
|
+void rockchip_alloc_region_mem(struct reg_region *rgns, uint32_t rgn_num);
|
|
+void rockchip_reg_rgn_save(struct reg_region *rgns, uint32_t rgn_num);
|
|
+void rockchip_reg_rgn_restore(struct reg_region *rgns, uint32_t rgn_num);
|
|
+void rockchip_reg_rgn_restore_reverse(struct reg_region *rgns, uint32_t rgn_num);
|
|
+void rockchip_regs_dump(uint32_t base,
|
|
+ uint32_t start_offset,
|
|
+ uint32_t end_offset,
|
|
+ uint32_t stride);
|
|
+void rockchip_dump_reg_rgns(struct reg_region *rgns, uint32_t rgn_num);
|
|
+
|
|
+#endif /* PLAT_PM_HELPERS_H */
|
|
diff --git a/plat/rockchip/common/plat_pm_helpers.c b/plat/rockchip/common/plat_pm_helpers.c
|
|
new file mode 100644
|
|
index 0000000..191b0ca
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/common/plat_pm_helpers.c
|
|
@@ -0,0 +1,213 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <assert.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include <arch_helpers.h>
|
|
+#include <bl31/bl31.h>
|
|
+#include <common/debug.h>
|
|
+#include <drivers/console.h>
|
|
+#include <drivers/delay_timer.h>
|
|
+#include <lib/mmio.h>
|
|
+#include <plat/common/platform.h>
|
|
+#include <platform_def.h>
|
|
+
|
|
+#include <plat_pm_helpers.h>
|
|
+
|
|
+#define ROCKCHIP_PM_REG_REGION_MEM_LEN (ROCKCHIP_PM_REG_REGION_MEM_SIZE / sizeof(uint32_t))
|
|
+
|
|
+/* REG region */
|
|
+#define RGN_LEN(_rgn) (((_rgn)->end - (_rgn)->start) / (_rgn)->stride + 1)
|
|
+
|
|
+#ifndef ROCKCHIP_PM_REG_REGION_MEM_SIZE
|
|
+#define ROCKCHIP_PM_REG_REGION_MEM_SIZE 0
|
|
+#endif
|
|
+
|
|
+#ifdef ROCKCHIP_REG_RGN_MEM_BASE
|
|
+static uint32_t *region_mem = (uint32_t *)ROCKCHIP_REG_RGN_MEM_BASE;
|
|
+#else
|
|
+static uint32_t region_mem[ROCKCHIP_PM_REG_REGION_MEM_LEN];
|
|
+#endif
|
|
+
|
|
+static int region_mem_idx;
|
|
+
|
|
+static int alloc_region_mem(uint32_t *buf, int max_len,
|
|
+ struct reg_region *rgns, uint32_t rgn_num)
|
|
+{
|
|
+ int i;
|
|
+ int total_len = 0, len = 0;
|
|
+ struct reg_region *r = rgns;
|
|
+
|
|
+ assert(buf && rgns && rgn_num);
|
|
+
|
|
+ for (i = 0; i < rgn_num; i++, r++) {
|
|
+ if (total_len < max_len)
|
|
+ r->buf = &buf[total_len];
|
|
+
|
|
+ len = RGN_LEN(r);
|
|
+ total_len += len;
|
|
+ }
|
|
+
|
|
+ if (total_len > max_len) {
|
|
+ ERROR("%s The buffer remain length:%d is too small for region:0x%x, at least %d\n",
|
|
+ __func__, max_len, rgns[0].start, total_len);
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ return total_len;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Alloc memory to reg_region->buf from region_mem.
|
|
+ * @rgns - struct reg_region array.
|
|
+ * @rgn_num - struct reg_region array length.
|
|
+ */
|
|
+void rockchip_alloc_region_mem(struct reg_region *rgns, uint32_t rgn_num)
|
|
+{
|
|
+ int max_len = 0, len;
|
|
+
|
|
+ assert(rgns && rgn_num);
|
|
+
|
|
+ max_len = ROCKCHIP_PM_REG_REGION_MEM_LEN - region_mem_idx;
|
|
+
|
|
+ len = alloc_region_mem(region_mem + region_mem_idx, max_len,
|
|
+ rgns, rgn_num);
|
|
+
|
|
+ region_mem_idx += len;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Save (reg_region->start ~ reg_region->end) to reg_region->buf.
|
|
+ * @rgns - struct reg_region array.
|
|
+ * @rgn_num - struct reg_region array length.
|
|
+ */
|
|
+void rockchip_reg_rgn_save(struct reg_region *rgns, uint32_t rgn_num)
|
|
+{
|
|
+ struct reg_region *r;
|
|
+ uint32_t addr;
|
|
+ int i, j;
|
|
+
|
|
+ assert(rgns && rgn_num);
|
|
+
|
|
+ for (i = 0; i < rgn_num; i++) {
|
|
+ r = &rgns[i];
|
|
+ for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
|
|
+ r->buf[j] = mmio_read_32(addr);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Restore reg_region->buf to (reg_region->start ~ reg_region->end).
|
|
+ * @rgns - struct reg_region array.
|
|
+ * @rgn_num - struct reg_region array length.
|
|
+ */
|
|
+void rockchip_reg_rgn_restore(struct reg_region *rgns, uint32_t rgn_num)
|
|
+{
|
|
+ struct reg_region *r;
|
|
+ uint32_t addr;
|
|
+ int i, j;
|
|
+
|
|
+ assert(rgns && rgn_num);
|
|
+
|
|
+ for (i = 0; i < rgn_num; i++) {
|
|
+ r = &rgns[i];
|
|
+ for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
|
|
+ mmio_write_32(addr, r->buf[j] | r->wmsk);
|
|
+
|
|
+ dsb();
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Restore reg_region->buf to (reg_region->start ~ reg_region->end) reversely.
|
|
+ * @rgns - struct reg_region array.
|
|
+ * @rgn_num - struct reg_region array length.
|
|
+ */
|
|
+void rockchip_reg_rgn_restore_reverse(struct reg_region *rgns, uint32_t rgn_num)
|
|
+{
|
|
+ struct reg_region *r;
|
|
+ uint32_t addr;
|
|
+ int i, j;
|
|
+
|
|
+ assert(rgns && rgn_num);
|
|
+
|
|
+ for (i = rgn_num - 1; i >= 0; i--) {
|
|
+ r = &rgns[i];
|
|
+ j = RGN_LEN(r) - 1;
|
|
+ for (addr = r->end; addr >= r->start; addr -= r->stride, j--)
|
|
+ mmio_write_32(addr, r->buf[j] | r->wmsk);
|
|
+
|
|
+ dsb();
|
|
+ }
|
|
+}
|
|
+
|
|
+static void rockchip_print_hex(uint32_t val)
|
|
+{
|
|
+ int i;
|
|
+ unsigned char tmp;
|
|
+
|
|
+ putchar('0');
|
|
+ putchar('x');
|
|
+ for (i = 0; i < 8; val <<= 4, ++i) {
|
|
+ tmp = (val & 0xf0000000) >> 28;
|
|
+ if (tmp < 10)
|
|
+ putchar('0' + tmp);
|
|
+ else
|
|
+ putchar('a' + tmp - 10);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Dump registers (base + start_offset ~ base + end_offset)
|
|
+ * @base - the base addr of the register.
|
|
+ * @start_offset - the start offset to dump.
|
|
+ * @end_offset - the end offset to dump.
|
|
+ * @stride - the stride of the registers.
|
|
+ */
|
|
+void rockchip_regs_dump(uint32_t base,
|
|
+ uint32_t start_offset,
|
|
+ uint32_t end_offset,
|
|
+ uint32_t stride)
|
|
+{
|
|
+ uint32_t i;
|
|
+
|
|
+ for (i = start_offset; i <= end_offset; i += stride) {
|
|
+ if ((i - start_offset) % 16 == 0) {
|
|
+ putchar('\n');
|
|
+ rockchip_print_hex(base + i);
|
|
+ putchar(':');
|
|
+ putchar(' ');
|
|
+ putchar(' ');
|
|
+ putchar(' ');
|
|
+ putchar(' ');
|
|
+ }
|
|
+ rockchip_print_hex(mmio_read_32(base + i));
|
|
+ putchar(' ');
|
|
+ putchar(' ');
|
|
+ putchar(' ');
|
|
+ putchar(' ');
|
|
+ }
|
|
+ putchar('\n');
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Dump reg regions
|
|
+ * @rgns - struct reg_region array.
|
|
+ * @rgn_num - struct reg_region array length.
|
|
+ */
|
|
+void rockchip_dump_reg_rgns(struct reg_region *rgns, uint32_t rgn_num)
|
|
+{
|
|
+ struct reg_region *r;
|
|
+ int i;
|
|
+
|
|
+ assert(rgns && rgn_num);
|
|
+
|
|
+ for (i = 0; i < rgn_num; i++) {
|
|
+ r = &rgns[i];
|
|
+ rockchip_regs_dump(0x0, r->start, r->end, r->stride);
|
|
+ }
|
|
+}
|
|
diff --git a/plat/rockchip/rk3588/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3588/drivers/pmu/plat_pmu_macros.S
|
|
new file mode 100644
|
|
index 0000000..c278899
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/drivers/pmu/plat_pmu_macros.S
|
|
@@ -0,0 +1,21 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <arch.h>
|
|
+#include <asm_macros.S>
|
|
+#include <platform_def.h>
|
|
+
|
|
+.globl clst_warmboot_data
|
|
+
|
|
+.macro func_rockchip_clst_warmboot
|
|
+.endm
|
|
+
|
|
+.macro rockchip_clst_warmboot_data
|
|
+clst_warmboot_data:
|
|
+ .rept PLATFORM_CLUSTER_COUNT
|
|
+ .word 0
|
|
+ .endr
|
|
+.endm
|
|
diff --git a/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.c b/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.c
|
|
new file mode 100644
|
|
index 0000000..78e8500
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.c
|
|
@@ -0,0 +1,555 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <assert.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include <arch_helpers.h>
|
|
+#include <bl31/bl31.h>
|
|
+#include <common/debug.h>
|
|
+#include <drivers/console.h>
|
|
+#include <drivers/delay_timer.h>
|
|
+#include <lib/mmio.h>
|
|
+#include <platform.h>
|
|
+#include <platform_def.h>
|
|
+#include <pmu.h>
|
|
+
|
|
+#include <plat_pm_helpers.h>
|
|
+#include <plat_private.h>
|
|
+#include <pm_pd_regs.h>
|
|
+#include <soc.h>
|
|
+
|
|
+#define WMSK_VAL 0xffff0000
|
|
+
|
|
+static struct reg_region qos_reg_rgns[] = {
|
|
+ [QOS_ISP0_MWO] = REG_REGION(0x08, 0x18, 4, 0xfdf40500, 0),
|
|
+ [QOS_ISP0_MRO] = REG_REGION(0x08, 0x18, 4, 0xfdf40400, 0),
|
|
+ [QOS_ISP1_MWO] = REG_REGION(0x08, 0x18, 4, 0xfdf41000, 0),
|
|
+ [QOS_ISP1_MRO] = REG_REGION(0x08, 0x18, 4, 0xfdf41100, 0),
|
|
+ [QOS_VICAP_M0] = REG_REGION(0x08, 0x18, 4, 0xfdf40600, 0),
|
|
+ [QOS_VICAP_M1] = REG_REGION(0x08, 0x18, 4, 0xfdf40800, 0),
|
|
+ [QOS_FISHEYE0] = REG_REGION(0x08, 0x18, 4, 0xfdf40000, 0),
|
|
+ [QOS_FISHEYE1] = REG_REGION(0x08, 0x18, 4, 0xfdf40200, 0),
|
|
+ [QOS_VOP_M0] = REG_REGION(0x08, 0x18, 4, 0xfdf82000, 0),
|
|
+ [QOS_VOP_M1] = REG_REGION(0x08, 0x18, 4, 0xfdf82200, 0),
|
|
+ [QOS_RKVDEC0] = REG_REGION(0x08, 0x18, 4, 0xfdf62000, 0),
|
|
+ [QOS_RKVDEC1] = REG_REGION(0x08, 0x18, 4, 0xfdf63000, 0),
|
|
+ [QOS_AV1] = REG_REGION(0x08, 0x18, 4, 0xfdf64000, 0),
|
|
+ [QOS_RKVENC0_M0RO] = REG_REGION(0x08, 0x18, 4, 0xfdf60000, 0),
|
|
+ [QOS_RKVENC0_M1RO] = REG_REGION(0x08, 0x18, 4, 0xfdf60200, 0),
|
|
+ [QOS_RKVENC0_M2WO] = REG_REGION(0x08, 0x18, 4, 0xfdf60400, 0),
|
|
+ [QOS_RKVENC1_M0RO] = REG_REGION(0x08, 0x18, 4, 0xfdf61000, 0),
|
|
+ [QOS_RKVENC1_M1RO] = REG_REGION(0x08, 0x18, 4, 0xfdf61200, 0),
|
|
+ [QOS_RKVENC1_M2WO] = REG_REGION(0x08, 0x18, 4, 0xfdf61400, 0),
|
|
+ [QOS_DSU_M0] = REG_REGION(0x08, 0x18, 4, 0xfe008000, 0),
|
|
+ [QOS_DSU_M1] = REG_REGION(0x08, 0x18, 4, 0xfe008800, 0),
|
|
+ [QOS_DSU_MP] = REG_REGION(0x08, 0x18, 4, 0xfdf34200, 0),
|
|
+ [QOS_DEBUG] = REG_REGION(0x08, 0x18, 4, 0xfdf34400, 0),
|
|
+ [QOS_GPU_M0] = REG_REGION(0x08, 0x18, 4, 0xfdf35000, 0),
|
|
+ [QOS_GPU_M1] = REG_REGION(0x08, 0x18, 4, 0xfdf35200, 0),
|
|
+ [QOS_GPU_M2] = REG_REGION(0x08, 0x18, 4, 0xfdf35400, 0),
|
|
+ [QOS_GPU_M3] = REG_REGION(0x08, 0x18, 4, 0xfdf35600, 0),
|
|
+ [QOS_NPU1] = REG_REGION(0x08, 0x18, 4, 0xfdf70000, 0),
|
|
+ [QOS_NPU0_MRO] = REG_REGION(0x08, 0x18, 4, 0xfdf72200, 0),
|
|
+ [QOS_NPU2] = REG_REGION(0x08, 0x18, 4, 0xfdf71000, 0),
|
|
+ [QOS_NPU0_MWR] = REG_REGION(0x08, 0x18, 4, 0xfdf72000, 0),
|
|
+ [QOS_MCU_NPU] = REG_REGION(0x08, 0x18, 4, 0xfdf72400, 0),
|
|
+ [QOS_JPEG_DEC] = REG_REGION(0x08, 0x18, 4, 0xfdf66200, 0),
|
|
+ [QOS_JPEG_ENC0] = REG_REGION(0x08, 0x18, 4, 0xfdf66400, 0),
|
|
+ [QOS_JPEG_ENC1] = REG_REGION(0x08, 0x18, 4, 0xfdf66600, 0),
|
|
+ [QOS_JPEG_ENC2] = REG_REGION(0x08, 0x18, 4, 0xfdf66800, 0),
|
|
+ [QOS_JPEG_ENC3] = REG_REGION(0x08, 0x18, 4, 0xfdf66a00, 0),
|
|
+ [QOS_RGA2_MRO] = REG_REGION(0x08, 0x18, 4, 0xfdf66c00, 0),
|
|
+ [QOS_RGA2_MWO] = REG_REGION(0x08, 0x18, 4, 0xfdf66e00, 0),
|
|
+ [QOS_RGA3_0] = REG_REGION(0x08, 0x18, 4, 0xfdf67000, 0),
|
|
+ [QOS_RGA3_1] = REG_REGION(0x08, 0x18, 4, 0xfdf36000, 0),
|
|
+ [QOS_VDPU] = REG_REGION(0x08, 0x18, 4, 0xfdf67200, 0),
|
|
+ [QOS_IEP] = REG_REGION(0x08, 0x18, 4, 0xfdf66000, 0),
|
|
+ [QOS_HDCP0] = REG_REGION(0x08, 0x18, 4, 0xfdf80000, 0),
|
|
+ [QOS_HDCP1] = REG_REGION(0x08, 0x18, 4, 0xfdf81000, 0),
|
|
+ [QOS_HDMIRX] = REG_REGION(0x08, 0x18, 4, 0xfdf81200, 0),
|
|
+ [QOS_GIC600_M0] = REG_REGION(0x08, 0x18, 4, 0xfdf3a000, 0),
|
|
+ [QOS_GIC600_M1] = REG_REGION(0x08, 0x18, 4, 0xfdf3a200, 0),
|
|
+ [QOS_MMU600PCIE_TCU] = REG_REGION(0x08, 0x18, 4, 0xfdf3a400, 0),
|
|
+ [QOS_MMU600PHP_TBU] = REG_REGION(0x08, 0x18, 4, 0xfdf3a600, 0),
|
|
+ [QOS_MMU600PHP_TCU] = REG_REGION(0x08, 0x18, 4, 0xfdf3a800, 0),
|
|
+ [QOS_USB3_0] = REG_REGION(0x08, 0x18, 4, 0xfdf3e200, 0),
|
|
+ [QOS_USB3_1] = REG_REGION(0x08, 0x18, 4, 0xfdf3e000, 0),
|
|
+ [QOS_USBHOST_0] = REG_REGION(0x08, 0x18, 4, 0xfdf3e400, 0),
|
|
+ [QOS_USBHOST_1] = REG_REGION(0x08, 0x18, 4, 0xfdf3e600, 0),
|
|
+ [QOS_EMMC] = REG_REGION(0x08, 0x18, 4, 0xfdf38200, 0),
|
|
+ [QOS_FSPI] = REG_REGION(0x08, 0x18, 4, 0xfdf38000, 0),
|
|
+ [QOS_SDIO] = REG_REGION(0x08, 0x18, 4, 0xfdf39000, 0),
|
|
+ [QOS_DECOM] = REG_REGION(0x08, 0x18, 4, 0xfdf32000, 0),
|
|
+ [QOS_DMAC0] = REG_REGION(0x08, 0x18, 4, 0xfdf32200, 0),
|
|
+ [QOS_DMAC1] = REG_REGION(0x08, 0x18, 4, 0xfdf32400, 0),
|
|
+ [QOS_DMAC2] = REG_REGION(0x08, 0x18, 4, 0xfdf32600, 0),
|
|
+ [QOS_GIC600M] = REG_REGION(0x08, 0x18, 4, 0xfdf32800, 0),
|
|
+ [QOS_DMA2DDR] = REG_REGION(0x08, 0x18, 4, 0xfdf52000, 0),
|
|
+ [QOS_MCU_DDR] = REG_REGION(0x08, 0x18, 4, 0xfdf52200, 0),
|
|
+ [QOS_VAD] = REG_REGION(0x08, 0x18, 4, 0xfdf3b200, 0),
|
|
+ [QOS_MCU_PMU] = REG_REGION(0x08, 0x18, 4, 0xfdf3b000, 0),
|
|
+ [QOS_CRYPTOS] = REG_REGION(0x08, 0x18, 4, 0xfdf3d200, 0),
|
|
+ [QOS_CRYPTONS] = REG_REGION(0x08, 0x18, 4, 0xfdf3d000, 0),
|
|
+ [QOS_DCF] = REG_REGION(0x08, 0x18, 4, 0xfdf3d400, 0),
|
|
+ [QOS_SDMMC] = REG_REGION(0x08, 0x18, 4, 0xfdf3d800, 0),
|
|
+};
|
|
+
|
|
+static struct reg_region pd_crypto_reg_rgns[] = {
|
|
+ /* SECURE CRU */
|
|
+ REG_REGION(0x300, 0x30c, 4, SCRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x800, 0x80c, 4, SCRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xa00, 0xa0c, 4, SCRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xd00, 0xd20, 8, SCRU_BASE, 0),
|
|
+ REG_REGION(0xd04, 0xd24, 8, SCRU_BASE, WMSK_VAL),
|
|
+
|
|
+ /* S TIMER0 6 channel */
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x00, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x00, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x20, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x20, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x40, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x40, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x60, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x60, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x80, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x80, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0xa0, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0xa0, 0),
|
|
+
|
|
+ /* S TIMER1 6 channel */
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x00, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x00, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x20, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x20, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x40, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x40, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x60, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x60, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x80, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x80, 0),
|
|
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0xa0, 0),
|
|
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0xa0, 0),
|
|
+
|
|
+ /* wdt_s */
|
|
+ REG_REGION(0x04, 0x04, 4, WDT_S_BASE, 0),
|
|
+ REG_REGION(0x00, 0x00, 4, WDT_S_BASE, 0),
|
|
+};
|
|
+
|
|
+static struct reg_region pd_dsu_reg_rgns[] = {
|
|
+ /* dsucru */
|
|
+ REG_REGION(0x040, 0x054, 4, DSUCRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x300, 0x31c, 4, DSUCRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x800, 0x80c, 4, DSUCRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xa00, 0xa0c, 4, DSUCRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xd00, 0xd20, 8, DSUCRU_BASE, 0),
|
|
+ REG_REGION(0xd04, 0xd24, 8, DSUCRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xf00, 0xf00, 4, DSUCRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xf10, 0xf1c, 4, DSUCRU_BASE, 0),
|
|
+
|
|
+ /* bcore0cru */
|
|
+ REG_REGION(0x000, 0x014, 4, BIGCORE0CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x300, 0x304, 4, BIGCORE0CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x800, 0x804, 4, BIGCORE0CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xa00, 0xa04, 4, BIGCORE0CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xcc0, 0xcc4, 4, BIGCORE0CRU_BASE, 0),
|
|
+ REG_REGION(0xd00, 0xd00, 4, BIGCORE0CRU_BASE, 0),
|
|
+ REG_REGION(0xd04, 0xd04, 4, BIGCORE0CRU_BASE, WMSK_VAL),
|
|
+
|
|
+ /* bcore1cru */
|
|
+ REG_REGION(0x020, 0x034, 4, BIGCORE1CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x300, 0x304, 4, BIGCORE1CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x800, 0x804, 4, BIGCORE1CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xa00, 0xa04, 4, BIGCORE1CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xcc0, 0xcc4, 4, BIGCORE1CRU_BASE, 0),
|
|
+ REG_REGION(0xd00, 0xd00, 4, BIGCORE1CRU_BASE, 0),
|
|
+ REG_REGION(0xd04, 0xd04, 4, BIGCORE1CRU_BASE, WMSK_VAL),
|
|
+
|
|
+ /* dsugrf */
|
|
+ REG_REGION(0x00, 0x18, 4, DSUGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x20, 0x20, 4, DSUGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x28, 0x30, 4, DSUGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x38, 0x38, 4, DSUGRF_BASE, WMSK_VAL),
|
|
+
|
|
+ /* lcore_grf */
|
|
+ REG_REGION(0x20, 0x20, 4, LITCOREGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x28, 0x30, 4, LITCOREGRF_BASE, WMSK_VAL),
|
|
+
|
|
+ /* bcore0_grf */
|
|
+ REG_REGION(0x20, 0x20, 4, BIGCORE0GRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x28, 0x30, 4, BIGCORE0GRF_BASE, WMSK_VAL),
|
|
+
|
|
+ /* bcore1_grf */
|
|
+ REG_REGION(0x20, 0x20, 4, BIGCORE1GRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x28, 0x28, 4, BIGCORE1GRF_BASE, WMSK_VAL),
|
|
+};
|
|
+
|
|
+static struct reg_region pd_php_reg_rgns[] = {
|
|
+ /* php_grf */
|
|
+ REG_REGION(0x000, 0x008, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x014, 0x024, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x028, 0x02c, 4, PHPGRF_BASE, 0),
|
|
+ REG_REGION(0x030, 0x03c, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x05c, 0x060, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x064, 0x068, 4, PHPGRF_BASE, 0),
|
|
+ REG_REGION(0x070, 0x070, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x074, 0x0d0, 4, PHPGRF_BASE, 0),
|
|
+ REG_REGION(0x0d4, 0x0d4, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x0e0, 0x0e0, 4, PHPGRF_BASE, 0),
|
|
+ REG_REGION(0x0e4, 0x0ec, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x100, 0x104, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x10c, 0x130, 4, PHPGRF_BASE, 0),
|
|
+ REG_REGION(0x138, 0x138, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x144, 0x168, 4, PHPGRF_BASE, 0),
|
|
+ REG_REGION(0x16c, 0x174, 4, PHPGRF_BASE, WMSK_VAL),
|
|
+
|
|
+ /* php_cru */
|
|
+ REG_REGION(0x200, 0x218, 4, PHP_CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0x800, 0x800, 4, PHP_CRU_BASE, WMSK_VAL),
|
|
+ REG_REGION(0xa00, 0xa00, 4, PHP_CRU_BASE, WMSK_VAL),
|
|
+
|
|
+ /* pcie3phy_grf_cmn_con0 */
|
|
+ REG_REGION(0x00, 0x00, 4, PCIE3PHYGRF_BASE, WMSK_VAL),
|
|
+};
|
|
+
|
|
+void qos_save(void)
|
|
+{
|
|
+ uint32_t pmu_pd_st0 = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0));
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_GPU)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GPU_M0], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GPU_M1], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GPU_M2], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GPU_M3], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_NPU1)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_NPU1], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_NPU2)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_NPU2], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_NPUTOP)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_NPU0_MRO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_NPU0_MWR], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_MCU_NPU], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_RKVDEC1)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVDEC1], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_RKVDEC0)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVDEC0], 1);
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_VENC1)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC1_M0RO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC1_M1RO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC1_M2WO], 1);
|
|
+ }
|
|
+ if ((pmu_pd_st0 & BIT(PD_VENC0)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC0_M0RO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC0_M1RO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC0_M2WO], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_RGA30)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RGA3_0], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_AV1)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_AV1], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_VDPU)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_DEC], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_ENC0], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_ENC1], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_ENC2], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_ENC3], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RGA2_MRO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RGA2_MWO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VDPU], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_IEP], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_VO0)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_HDCP0], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_VO1)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_HDCP1], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_HDMIRX], 1);
|
|
+ }
|
|
+ if ((pmu_pd_st0 & BIT(PD_VOP)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VOP_M0], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VOP_M1], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_FEC)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_FISHEYE0], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_FISHEYE1], 1);
|
|
+ }
|
|
+ if ((pmu_pd_st0 & BIT(PD_ISP1)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_ISP1_MWO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_ISP1_MRO], 1);
|
|
+ }
|
|
+ if ((pmu_pd_st0 & BIT(PD_VI)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_ISP0_MWO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_ISP0_MRO], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VICAP_M0], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VICAP_M1], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_RGA31)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RGA3_1], 1);
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_USB)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_USB3_0], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_USB3_1], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_USBHOST_0], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_USBHOST_1], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_PHP)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GIC600_M0], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GIC600_M1], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_MMU600PCIE_TCU], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_MMU600PHP_TBU], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_MMU600PHP_TCU], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_SDIO)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_SDIO], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_NVM0)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_FSPI], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_EMMC], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_SDMMC)) == 0)
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_SDMMC], 1);
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_CRYPTO)) == 0) {
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_CRYPTONS], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_CRYPTOS], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DCF], 1);
|
|
+ }
|
|
+
|
|
+ /* PD_DSU */
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DSU_M0], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DSU_M1], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DSU_MP], 1);
|
|
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DEBUG], 1);
|
|
+}
|
|
+
|
|
+void qos_restore(void)
|
|
+{
|
|
+ uint32_t pmu_pd_st0 = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0));
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_GPU)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GPU_M0], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GPU_M1], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GPU_M2], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GPU_M3], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_NPU1)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_NPU1], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_NPU2)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_NPU2], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_NPUTOP)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_NPU0_MRO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_NPU0_MWR], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_MCU_NPU], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_RKVDEC1)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVDEC1], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_RKVDEC0)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVDEC0], 1);
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_VENC1)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC1_M0RO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC1_M1RO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC1_M2WO], 1);
|
|
+ }
|
|
+ if ((pmu_pd_st0 & BIT(PD_VENC0)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC0_M0RO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC0_M1RO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC0_M2WO], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_RGA30)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RGA3_0], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_AV1)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_AV1], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_VDPU)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_DEC], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_ENC0], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_ENC1], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_ENC2], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_ENC3], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RGA2_MRO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RGA2_MWO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VDPU], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_IEP], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_VO0)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_HDCP0], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_VO1)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_HDCP1], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_HDMIRX], 1);
|
|
+ }
|
|
+ if ((pmu_pd_st0 & BIT(PD_VOP)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VOP_M0], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VOP_M1], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_FEC)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_FISHEYE0], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_FISHEYE1], 1);
|
|
+ }
|
|
+ if ((pmu_pd_st0 & BIT(PD_ISP1)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_ISP1_MWO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_ISP1_MRO], 1);
|
|
+ }
|
|
+ if ((pmu_pd_st0 & BIT(PD_VI)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_ISP0_MWO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_ISP0_MRO], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VICAP_M0], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VICAP_M1], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_RGA31)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RGA3_1], 1);
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_USB)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_USB3_0], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_USB3_1], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_USBHOST_0], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_USBHOST_1], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_PHP)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GIC600_M0], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GIC600_M1], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_MMU600PCIE_TCU], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_MMU600PHP_TBU], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_MMU600PHP_TCU], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_SDIO)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_SDIO], 1);
|
|
+ if ((pmu_pd_st0 & BIT(PD_NVM0)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_FSPI], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_EMMC], 1);
|
|
+ }
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_SDMMC)) == 0)
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_SDMMC], 1);
|
|
+
|
|
+ if ((pmu_pd_st0 & BIT(PD_CRYPTO)) == 0) {
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_CRYPTONS], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_CRYPTOS], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DCF], 1);
|
|
+ }
|
|
+
|
|
+ /* PD_DSU */
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DSU_M0], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DSU_M1], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DSU_MP], 1);
|
|
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DEBUG], 1);
|
|
+}
|
|
+
|
|
+void pd_crypto_save(void)
|
|
+{
|
|
+ rockchip_reg_rgn_save(pd_crypto_reg_rgns, ARRAY_SIZE(pd_crypto_reg_rgns));
|
|
+}
|
|
+
|
|
+void pd_crypto_restore(void)
|
|
+{
|
|
+ rockchip_reg_rgn_restore(pd_crypto_reg_rgns, ARRAY_SIZE(pd_crypto_reg_rgns));
|
|
+}
|
|
+
|
|
+static uint32_t b0_cru_mode;
|
|
+static uint32_t b1_cru_mode;
|
|
+static uint32_t dsu_cru_mode;
|
|
+static uint32_t bcore0_cru_sel_con2, bcore1_cru_sel_con2;
|
|
+
|
|
+void pd_dsu_core_save(void)
|
|
+{
|
|
+ b0_cru_mode = mmio_read_32(BIGCORE0CRU_BASE + 0x280);
|
|
+ b1_cru_mode = mmio_read_32(BIGCORE1CRU_BASE + 0x280);
|
|
+ dsu_cru_mode = mmio_read_32(DSUCRU_BASE + 0x280);
|
|
+ bcore0_cru_sel_con2 = mmio_read_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(2));
|
|
+ bcore1_cru_sel_con2 = mmio_read_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(2));
|
|
+
|
|
+ rockchip_reg_rgn_save(pd_dsu_reg_rgns, ARRAY_SIZE(pd_dsu_reg_rgns));
|
|
+}
|
|
+
|
|
+void pd_dsu_core_restore(void)
|
|
+{
|
|
+ /* switch bcore0/1 pclk root to 24M */
|
|
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(2),
|
|
+ BITS_WITH_WMASK(2, 0x3, 0));
|
|
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(2),
|
|
+ BITS_WITH_WMASK(2, 0x3, 0));
|
|
+
|
|
+ /* slow mode */
|
|
+ mmio_write_32(BIGCORE0CRU_BASE + 0x280, 0x00030000);
|
|
+ mmio_write_32(BIGCORE1CRU_BASE + 0x280, 0x00030000);
|
|
+ mmio_write_32(DSUCRU_BASE + 0x280, 0x00030000);
|
|
+
|
|
+ rockchip_reg_rgn_restore(pd_dsu_reg_rgns, ARRAY_SIZE(pd_dsu_reg_rgns));
|
|
+
|
|
+ /* trigger dsu/lcore/bcore mem_cfg */
|
|
+ mmio_write_32(DSUGRF_BASE + 0x18, BITS_WITH_WMASK(1, 0x1, 14));
|
|
+ mmio_write_32(LITCOREGRF_BASE + 0x30, BITS_WITH_WMASK(1, 0x1, 5));
|
|
+ mmio_write_32(BIGCORE0GRF_BASE + 0x30, BITS_WITH_WMASK(1, 0x1, 5));
|
|
+ mmio_write_32(BIGCORE1GRF_BASE + 0x30, BITS_WITH_WMASK(1, 0x1, 5));
|
|
+ udelay(1);
|
|
+ mmio_write_32(DSUGRF_BASE + 0x18, BITS_WITH_WMASK(0, 0x1, 14));
|
|
+ mmio_write_32(LITCOREGRF_BASE + 0x30, BITS_WITH_WMASK(0, 0x1, 5));
|
|
+ mmio_write_32(BIGCORE0GRF_BASE + 0x30, BITS_WITH_WMASK(0, 0x1, 5));
|
|
+ mmio_write_32(BIGCORE1GRF_BASE + 0x30, BITS_WITH_WMASK(0, 0x1, 5));
|
|
+
|
|
+ /* wait lock */
|
|
+ pm_pll_wait_lock(BIGCORE0CRU_BASE + 0x00);
|
|
+ pm_pll_wait_lock(BIGCORE1CRU_BASE + 0x20);
|
|
+ pm_pll_wait_lock(DSUCRU_BASE + 0x40);
|
|
+
|
|
+ /* restore mode */
|
|
+ mmio_write_32(BIGCORE0CRU_BASE + 0x280, WITH_16BITS_WMSK(b0_cru_mode));
|
|
+ mmio_write_32(BIGCORE1CRU_BASE + 0x280, WITH_16BITS_WMSK(b1_cru_mode));
|
|
+ mmio_write_32(DSUCRU_BASE + 0x280, WITH_16BITS_WMSK(dsu_cru_mode));
|
|
+
|
|
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(2),
|
|
+ WITH_16BITS_WMSK(bcore0_cru_sel_con2));
|
|
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(2),
|
|
+ WITH_16BITS_WMSK(bcore1_cru_sel_con2));
|
|
+}
|
|
+
|
|
+static uint32_t php_ppll_con0;
|
|
+
|
|
+void pd_php_save(void)
|
|
+{
|
|
+ php_ppll_con0 = mmio_read_32(PHP_CRU_BASE + 0x200);
|
|
+
|
|
+ /* php_ppll bypass */
|
|
+ mmio_write_32(PHP_CRU_BASE + 0x200, BITS_WITH_WMASK(1u, 1u, 15));
|
|
+ dsb();
|
|
+ isb();
|
|
+ rockchip_reg_rgn_save(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
|
|
+}
|
|
+
|
|
+void pd_php_restore(void)
|
|
+{
|
|
+ rockchip_reg_rgn_restore(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
|
|
+
|
|
+ pm_pll_wait_lock(PHP_CRU_BASE + 0x200);
|
|
+
|
|
+ /* restore php_ppll bypass */
|
|
+ mmio_write_32(PHP_CRU_BASE + 0x200, WITH_16BITS_WMSK(php_ppll_con0));
|
|
+}
|
|
+
|
|
+void pm_reg_rgns_init(void)
|
|
+{
|
|
+ rockchip_alloc_region_mem(qos_reg_rgns, ARRAY_SIZE(qos_reg_rgns));
|
|
+ rockchip_alloc_region_mem(pd_crypto_reg_rgns, ARRAY_SIZE(pd_crypto_reg_rgns));
|
|
+ rockchip_alloc_region_mem(pd_dsu_reg_rgns, ARRAY_SIZE(pd_dsu_reg_rgns));
|
|
+ rockchip_alloc_region_mem(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
|
|
+}
|
|
diff --git a/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.h b/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.h
|
|
new file mode 100644
|
|
index 0000000..8baf69a
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.h
|
|
@@ -0,0 +1,23 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef PM_PD_REGS_H
|
|
+#define PM_PD_REGS_H
|
|
+
|
|
+#include <stdint.h>
|
|
+
|
|
+void qos_save(void);
|
|
+void qos_restore(void);
|
|
+void pd_crypto_save(void);
|
|
+void pd_crypto_restore(void);
|
|
+void pd_dsu_core_save(void);
|
|
+void pd_dsu_core_restore(void);
|
|
+void pd_php_save(void);
|
|
+void pd_php_restore(void);
|
|
+
|
|
+void pm_reg_rgns_init(void);
|
|
+
|
|
+#endif
|
|
diff --git a/plat/rockchip/rk3588/drivers/pmu/pmu.c b/plat/rockchip/rk3588/drivers/pmu/pmu.c
|
|
new file mode 100644
|
|
index 0000000..445cf8d
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/drivers/pmu/pmu.c
|
|
@@ -0,0 +1,1436 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <assert.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include <arch_helpers.h>
|
|
+#include <bl31/bl31.h>
|
|
+#include <common/debug.h>
|
|
+#include <drivers/arm/gicv3.h>
|
|
+#include <drivers/console.h>
|
|
+#include <drivers/delay_timer.h>
|
|
+#include <drivers/ti/uart/uart_16550.h>
|
|
+#include <lib/mmio.h>
|
|
+#include <plat/common/platform.h>
|
|
+#include <platform_def.h>
|
|
+#include <pmu.h>
|
|
+
|
|
+#include <cpus_on_fixed_addr.h>
|
|
+#include <plat_pm_helpers.h>
|
|
+#include <plat_private.h>
|
|
+#include <pm_pd_regs.h>
|
|
+#include <rockchip_sip_svc.h>
|
|
+#include <secure.h>
|
|
+#include <soc.h>
|
|
+
|
|
+#define PSRAM_SP_TOP ((PMUSRAM_BASE + PMUSRAM_RSIZE) & ~0xf)
|
|
+#define NONBOOT_CPUS_OFF_LOOP (500000)
|
|
+
|
|
+#define DSUGRF_REG_CNT (0x78 / 4 + 1)
|
|
+#define BCORE_GRF_REG_CNT (0x30 / 4 + 1)
|
|
+#define LCORE_GRF_REG_CNT (0x30 / 4 + 1)
|
|
+
|
|
+#define CENTER_GRF_REG_CNT (0x20 / 4 + 1)
|
|
+
|
|
+static struct psram_data_t *psram_sleep_cfg =
|
|
+ (struct psram_data_t *)&sys_sleep_flag_sram;
|
|
+
|
|
+static int8_t pd_repair_map[] = {
|
|
+ [PD_GPU] = PD_RPR_GPU,
|
|
+ [PD_NPU] = -1,
|
|
+ [PD_VCODEC] = -1,
|
|
+ [PD_NPUTOP] = PD_RPR_NPUTOP,
|
|
+ [PD_NPU1] = PD_RPR_NPU1,
|
|
+ [PD_NPU2] = PD_RPR_NPU2,
|
|
+ [PD_VENC0] = PD_RPR_VENC0,
|
|
+ [PD_VENC1] = PD_RPR_VENC1,
|
|
+ [PD_RKVDEC0] = PD_RPR_RKVDEC0,
|
|
+ [PD_RKVDEC1] = PD_RPR_RKVDEC1,
|
|
+ [PD_VDPU] = PD_RPR_VDPU,
|
|
+ [PD_RGA30] = PD_RPR_RGA30,
|
|
+ [PD_AV1] = PD_RPR_AV1,
|
|
+ [PD_VI] = PD_RPR_VI,
|
|
+ [PD_FEC] = PD_RPR_FEC,
|
|
+ [PD_ISP1] = PD_RPR_ISP1,
|
|
+ [PD_RGA31] = PD_RPR_RGA31,
|
|
+ [PD_VOP] = PD_RPR_VOP,
|
|
+ [PD_VO0] = PD_RPR_VO0,
|
|
+ [PD_VO1] = PD_RPR_VO1,
|
|
+ [PD_AUDIO] = PD_RPR_AUDIO,
|
|
+ [PD_PHP] = PD_RPR_PHP,
|
|
+ [PD_GMAC] = PD_RPR_GMAC,
|
|
+ [PD_PCIE] = PD_RPR_PCIE,
|
|
+ [PD_NVM] = -1,
|
|
+ [PD_NVM0] = PD_RPR_NVM0,
|
|
+ [PD_SDIO] = PD_RPR_SDIO,
|
|
+ [PD_USB] = PD_RPR_USB,
|
|
+ [PD_SECURE] = -1,
|
|
+ [PD_SDMMC] = PD_RPR_SDMMC,
|
|
+ [PD_CRYPTO] = PD_RPR_CRYPTO,
|
|
+ [PD_CENTER] = PD_RPR_CENTER,
|
|
+ [PD_DDR01] = PD_RPR_DDR01,
|
|
+ [PD_DDR23] = PD_RPR_DDR23,
|
|
+};
|
|
+
|
|
+struct rk3588_sleep_ddr_data {
|
|
+ uint32_t gpio0a_iomux_l, gpio0a_iomux_h, gpio0b_iomux_l;
|
|
+ uint32_t pmu_pd_st0, bus_idle_st0, qch_pwr_st;
|
|
+ uint32_t pmu2_vol_gate_con[3], pmu2_submem_gate_sft_con0;
|
|
+ uint32_t pmu2_bisr_con0;
|
|
+ uint32_t cpll_con0;
|
|
+ uint32_t cru_mode_con, busscru_mode_con;
|
|
+ uint32_t bussgrf_soc_con7;
|
|
+ uint32_t pmu0grf_soc_con0, pmu0grf_soc_con1, pmu0grf_soc_con3;
|
|
+ uint32_t pmu1grf_soc_con2, pmu1grf_soc_con7, pmu1grf_soc_con8, pmu1grf_soc_con9;
|
|
+ uint32_t pmu0sgrf_soc_con1;
|
|
+ uint32_t pmu1sgrf_soc_con14;
|
|
+ uint32_t ddrgrf_chn_con0[4], ddrgrf_chn_con1[4],
|
|
+ ddrgrf_chn_con2[4], pmu1_ddr_pwr_sft_con[4];
|
|
+ uint32_t pmu1cru_clksel_con1;
|
|
+};
|
|
+
|
|
+static struct rk3588_sleep_ddr_data ddr_data;
|
|
+
|
|
+struct rk3588_sleep_pmusram_data {
|
|
+ uint32_t dsusgrf_soc_con[DSUSGRF_SOC_CON_CNT],
|
|
+ dsusgrf_ddr_hash_con[DSUSGRF_DDR_HASH_CON_CNT];
|
|
+ uint32_t dsu_ddr_fw_rgn_reg[FIREWALL_DSU_RGN_CNT],
|
|
+ dsu_ddr_fw_mst_reg[FIREWALL_DSU_MST_CNT],
|
|
+ dsu_ddr_fw_con_reg[FIREWALL_DSU_CON_CNT];
|
|
+ uint32_t busioc_gpio0b_iomux_h;
|
|
+};
|
|
+
|
|
+static __pmusramdata struct rk3588_sleep_pmusram_data pmusram_data;
|
|
+
|
|
+static __pmusramfunc void dsu_restore_early(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ /* dsusgrf */
|
|
+ for (i = 0; i < DSUSGRF_SOC_CON_CNT; i++)
|
|
+ mmio_write_32(DSUSGRF_BASE + DSUSGRF_SOC_CON(i),
|
|
+ WITH_16BITS_WMSK(pmusram_data.dsusgrf_soc_con[i]));
|
|
+
|
|
+ for (i = 0; i < DSUSGRF_DDR_HASH_CON_CNT; i++)
|
|
+ mmio_write_32(DSUSGRF_BASE + DSUSGRF_DDR_HASH_CON(i),
|
|
+ pmusram_data.dsusgrf_ddr_hash_con[i]);
|
|
+
|
|
+ /* dsu ddr firewall */
|
|
+ for (i = 0; i < FIREWALL_DSU_RGN_CNT; i++)
|
|
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(i),
|
|
+ pmusram_data.dsu_ddr_fw_rgn_reg[i]);
|
|
+
|
|
+ for (i = 0; i < FIREWALL_DSU_MST_CNT; i++)
|
|
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(i),
|
|
+ pmusram_data.dsu_ddr_fw_mst_reg[i]);
|
|
+
|
|
+ for (i = 0; i < FIREWALL_DSU_CON_CNT; i++)
|
|
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i),
|
|
+ pmusram_data.dsu_ddr_fw_con_reg[i]);
|
|
+}
|
|
+
|
|
+static __pmusramfunc void ddr_resume(void)
|
|
+{
|
|
+ dsu_restore_early();
|
|
+}
|
|
+
|
|
+static void dsu_core_save(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ /* dsusgrf */
|
|
+ for (i = 0; i < DSUSGRF_SOC_CON_CNT; i++)
|
|
+ pmusram_data.dsusgrf_soc_con[i] =
|
|
+ mmio_read_32(DSUSGRF_BASE + DSUSGRF_SOC_CON(i));
|
|
+
|
|
+ for (i = 0; i < DSUSGRF_DDR_HASH_CON_CNT; i++)
|
|
+ pmusram_data.dsusgrf_ddr_hash_con[i] =
|
|
+ mmio_read_32(DSUSGRF_BASE + DSUSGRF_DDR_HASH_CON(i));
|
|
+
|
|
+ /* dsu ddr firewall */
|
|
+ for (i = 0; i < FIREWALL_DSU_RGN_CNT; i++)
|
|
+ pmusram_data.dsu_ddr_fw_rgn_reg[i] =
|
|
+ mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(i));
|
|
+
|
|
+ for (i = 0; i < FIREWALL_DSU_MST_CNT; i++)
|
|
+ pmusram_data.dsu_ddr_fw_mst_reg[i] =
|
|
+ mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(i));
|
|
+
|
|
+ for (i = 0; i < FIREWALL_DSU_CON_CNT; i++)
|
|
+ pmusram_data.dsu_ddr_fw_con_reg[i] =
|
|
+ mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i));
|
|
+
|
|
+ pd_dsu_core_save();
|
|
+}
|
|
+
|
|
+static void dsu_core_restore(void)
|
|
+{
|
|
+ pd_dsu_core_restore();
|
|
+}
|
|
+
|
|
+static uint32_t clk_save[CRU_CLKGATE_CON_CNT + PHPCRU_CLKGATE_CON_CNT +
|
|
+ SECURECRU_CLKGATE_CON_CNT + PMU1CRU_CLKGATE_CON_CNT];
|
|
+
|
|
+void clk_gate_con_save(void)
|
|
+{
|
|
+ int i, j = 0;
|
|
+
|
|
+ for (i = 0; i < CRU_CLKGATE_CON_CNT; i++, j++)
|
|
+ clk_save[j] = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(i));
|
|
+
|
|
+ clk_save[j] = mmio_read_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON);
|
|
+
|
|
+ for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++, j++)
|
|
+ clk_save[j] = mmio_read_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i));
|
|
+
|
|
+ for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++)
|
|
+ clk_save[j] = mmio_read_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i));
|
|
+}
|
|
+
|
|
+void clk_gate_con_disable(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < CRU_CLKGATE_CON_CNT; i++)
|
|
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i), 0xffff0000);
|
|
+
|
|
+ mmio_write_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON, 0xffff0000);
|
|
+
|
|
+ for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++)
|
|
+ mmio_write_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i), 0xffff0000);
|
|
+
|
|
+ for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++)
|
|
+ mmio_write_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i), 0xffff0000);
|
|
+}
|
|
+
|
|
+void clk_gate_con_restore(void)
|
|
+{
|
|
+ int i, j = 0;
|
|
+
|
|
+ for (i = 0; i < CRU_CLKGATE_CON_CNT; i++, j++)
|
|
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i),
|
|
+ WITH_16BITS_WMSK(clk_save[j]));
|
|
+
|
|
+ mmio_write_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON,
|
|
+ WITH_16BITS_WMSK(clk_save[j]));
|
|
+
|
|
+ for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++, j++)
|
|
+ mmio_write_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i),
|
|
+ WITH_16BITS_WMSK(clk_save[j]));
|
|
+
|
|
+ for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++)
|
|
+ mmio_write_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i),
|
|
+ WITH_16BITS_WMSK(clk_save[j]));
|
|
+}
|
|
+
|
|
+static void pmu_bus_idle_req(uint32_t bus, uint32_t state)
|
|
+{
|
|
+ uint32_t wait_cnt = 0;
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_SFTCON(bus / 16),
|
|
+ BITS_WITH_WMASK(state, 0x1, bus % 16));
|
|
+
|
|
+ while (pmu_bus_idle_st(bus) != state ||
|
|
+ pmu_bus_idle_ack(bus) != state) {
|
|
+ if (++wait_cnt > BUS_IDLE_LOOP)
|
|
+ break;
|
|
+ udelay(1);
|
|
+ }
|
|
+
|
|
+ if (wait_cnt > BUS_IDLE_LOOP)
|
|
+ WARN("%s: can't wait state %d for bus %d (0x%x)\n",
|
|
+ __func__, state, bus,
|
|
+ mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST(bus / 32)));
|
|
+}
|
|
+
|
|
+static void pmu_qch_pwr_ctlr(uint32_t msk, uint32_t state)
|
|
+{
|
|
+ uint32_t wait_cnt = 0;
|
|
+
|
|
+ if (state != 0)
|
|
+ state = msk;
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_QCHANNEL_PWR_SFTCON,
|
|
+ BITS_WITH_WMASK(state, msk, 0));
|
|
+
|
|
+ while ((mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS) & msk) != state) {
|
|
+ if (++wait_cnt > QCH_PWR_LOOP)
|
|
+ break;
|
|
+ udelay(1);
|
|
+ }
|
|
+
|
|
+ if (wait_cnt > BUS_IDLE_LOOP)
|
|
+ WARN("%s: can't wait qch:0x%x to state:0x%x (0x%x)\n",
|
|
+ __func__, msk, state,
|
|
+ mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS));
|
|
+}
|
|
+
|
|
+static inline uint32_t pmu_power_domain_chain_st(uint32_t pd)
|
|
+{
|
|
+ return mmio_read_32(PMU_BASE + PMU2_PWR_CHAIN1_ST(pd / 32)) & BIT(pd % 32) ?
|
|
+ pmu_pd_on :
|
|
+ pmu_pd_off;
|
|
+}
|
|
+
|
|
+static inline uint32_t pmu_power_domain_mem_st(uint32_t pd)
|
|
+{
|
|
+ return mmio_read_32(PMU_BASE + PMU2_PWR_MEM_ST(pd / 32)) & BIT(pd % 32) ?
|
|
+ pmu_pd_off :
|
|
+ pmu_pd_on;
|
|
+}
|
|
+
|
|
+static inline uint32_t pmu_power_domain_st(uint32_t pd)
|
|
+{
|
|
+ int8_t pd_repair = pd_repair_map[pd];
|
|
+
|
|
+ if (pd_repair >= 0)
|
|
+ return mmio_read_32(PMU_BASE + PMU2_BISR_STATUS(4)) & BIT(pd_repair) ?
|
|
+ pmu_pd_on :
|
|
+ pmu_pd_off;
|
|
+ else
|
|
+ return mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(pd / 32)) & BIT(pd % 32) ?
|
|
+ pmu_pd_off :
|
|
+ pmu_pd_on;
|
|
+}
|
|
+
|
|
+static int pmu_power_domain_pd_to_mem_st(uint32_t pd, uint32_t *pd_mem_st)
|
|
+{
|
|
+ uint32_t mem_st;
|
|
+
|
|
+ switch (pd) {
|
|
+ case PD_NPUTOP:
|
|
+ mem_st = PD_NPU_TOP_MEM_ST;
|
|
+ break;
|
|
+ case PD_NPU1:
|
|
+ mem_st = PD_NPU1_MEM_ST;
|
|
+ break;
|
|
+ case PD_NPU2:
|
|
+ mem_st = PD_NPU2_MEM_ST;
|
|
+ break;
|
|
+ case PD_VENC0:
|
|
+ mem_st = PD_VENC0_MEM_ST;
|
|
+ break;
|
|
+ case PD_VENC1:
|
|
+ mem_st = PD_VENC1_MEM_ST;
|
|
+ break;
|
|
+ case PD_RKVDEC0:
|
|
+ mem_st = PD_RKVDEC0_MEM_ST;
|
|
+ break;
|
|
+ case PD_RKVDEC1:
|
|
+ mem_st = PD_RKVDEC1_MEM_ST;
|
|
+ break;
|
|
+ case PD_RGA30:
|
|
+ mem_st = PD_RGA30_MEM_ST;
|
|
+ break;
|
|
+ case PD_AV1:
|
|
+ mem_st = PD_AV1_MEM_ST;
|
|
+ break;
|
|
+ case PD_VI:
|
|
+ mem_st = PD_VI_MEM_ST;
|
|
+ break;
|
|
+ case PD_FEC:
|
|
+ mem_st = PD_FEC_MEM_ST;
|
|
+ break;
|
|
+ case PD_ISP1:
|
|
+ mem_st = PD_ISP1_MEM_ST;
|
|
+ break;
|
|
+ case PD_RGA31:
|
|
+ mem_st = PD_RGA31_MEM_ST;
|
|
+ break;
|
|
+ case PD_VOP:
|
|
+ mem_st = PD_VOP_MEM_ST;
|
|
+ break;
|
|
+ case PD_VO0:
|
|
+ mem_st = PD_VO0_MEM_ST;
|
|
+ break;
|
|
+ case PD_VO1:
|
|
+ mem_st = PD_VO1_MEM_ST;
|
|
+ break;
|
|
+ case PD_AUDIO:
|
|
+ mem_st = PD_AUDIO_MEM_ST;
|
|
+ break;
|
|
+ case PD_PHP:
|
|
+ mem_st = PD_PHP_MEM_ST;
|
|
+ break;
|
|
+ case PD_GMAC:
|
|
+ mem_st = PD_GMAC_MEM_ST;
|
|
+ break;
|
|
+ case PD_PCIE:
|
|
+ mem_st = PD_PCIE_MEM_ST;
|
|
+ break;
|
|
+ case PD_NVM0:
|
|
+ mem_st = PD_NVM0_MEM_ST;
|
|
+ break;
|
|
+ case PD_SDIO:
|
|
+ mem_st = PD_SDIO_MEM_ST;
|
|
+ break;
|
|
+ case PD_USB:
|
|
+ mem_st = PD_USB_MEM_ST;
|
|
+ break;
|
|
+ case PD_SDMMC:
|
|
+ mem_st = PD_SDMMC_MEM_ST;
|
|
+ break;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ *pd_mem_st = mem_st;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int pmu_power_domain_reset_mem(uint32_t pd, uint32_t pd_mem_st)
|
|
+{
|
|
+ uint32_t loop = 0;
|
|
+ int ret = 0;
|
|
+
|
|
+ while (pmu_power_domain_chain_st(pd_mem_st) != pmu_pd_on) {
|
|
+ udelay(1);
|
|
+ loop++;
|
|
+ if (loop >= PD_CTR_LOOP) {
|
|
+ WARN("%s: %d chain up time out\n", __func__, pd);
|
|
+ ret = -EINVAL;
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ udelay(60);
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_MEMPWR_GATE_SFTCON(pd / 16),
|
|
+ BITS_WITH_WMASK(pmu_pd_off, 0x1, pd % 16));
|
|
+ dsb();
|
|
+
|
|
+ loop = 0;
|
|
+ while (pmu_power_domain_mem_st(pd_mem_st) != pmu_pd_off) {
|
|
+ udelay(1);
|
|
+ loop++;
|
|
+ if (loop >= PD_CTR_LOOP) {
|
|
+ WARN("%s: %d mem down time out\n", __func__, pd);
|
|
+ ret = -EINVAL;
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_MEMPWR_GATE_SFTCON(pd / 16),
|
|
+ BITS_WITH_WMASK(pmu_pd_on, 0x1, pd % 16));
|
|
+ dsb();
|
|
+
|
|
+ loop = 0;
|
|
+ while (pmu_power_domain_mem_st(pd_mem_st) != pmu_pd_on) {
|
|
+ udelay(1);
|
|
+ loop++;
|
|
+ if (loop >= PD_CTR_LOOP) {
|
|
+ WARN("%s: %d mem up time out\n", __func__, pd);
|
|
+ ret = -EINVAL;
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+error:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
|
|
+{
|
|
+ uint32_t loop = 0;
|
|
+ uint32_t is_mem_on = pmu_pd_off;
|
|
+ uint32_t pd_mem_st;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (pd_state == pmu_pd_on) {
|
|
+ ret = pmu_power_domain_pd_to_mem_st(pd, &pd_mem_st);
|
|
+ if (ret == 0) {
|
|
+ is_mem_on = pmu_power_domain_mem_st(pd_mem_st);
|
|
+ if (is_mem_on == pmu_pd_on)
|
|
+ WARN("%s: %d mem is up\n", __func__, pd);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_SFTCON(pd / 16),
|
|
+ BITS_WITH_WMASK(pd_state, 0x1, pd % 16));
|
|
+ dsb();
|
|
+
|
|
+ if (is_mem_on == pmu_pd_on) {
|
|
+ ret = pmu_power_domain_reset_mem(pd, pd_mem_st);
|
|
+ if (ret != 0)
|
|
+ goto out;
|
|
+ WARN("%s: %d mem reset ok\n", __func__, pd);
|
|
+ }
|
|
+
|
|
+ while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) {
|
|
+ udelay(1);
|
|
+ loop++;
|
|
+ }
|
|
+
|
|
+ if (pmu_power_domain_st(pd) != pd_state) {
|
|
+ WARN("%s: %d, %d, (0x%x, 0x%x) error!\n", __func__, pd, pd_state,
|
|
+ mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0)),
|
|
+ mmio_read_32(PMU_BASE + PMU2_BISR_STATUS(4)));
|
|
+ ret = -EINVAL;
|
|
+ }
|
|
+
|
|
+out:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state)
|
|
+{
|
|
+ uint32_t state;
|
|
+
|
|
+ if (pmu_power_domain_st(pd_id) == pd_state)
|
|
+ goto out;
|
|
+
|
|
+ if (pd_state == pmu_pd_on)
|
|
+ pmu_power_domain_ctr(pd_id, pd_state);
|
|
+
|
|
+ state = (pd_state == pmu_pd_off) ? bus_idle : bus_active;
|
|
+
|
|
+ switch (pd_id) {
|
|
+ case PD_GPU:
|
|
+ pmu_bus_idle_req(BUS_ID_GPU, state);
|
|
+ break;
|
|
+ case PD_NPUTOP:
|
|
+ pmu_bus_idle_req(BUS_ID_NPUTOP, state);
|
|
+ break;
|
|
+ case PD_NPU1:
|
|
+ pmu_bus_idle_req(BUS_ID_NPU1, state);
|
|
+ break;
|
|
+ case PD_NPU2:
|
|
+ pmu_bus_idle_req(BUS_ID_NPU2, state);
|
|
+ break;
|
|
+ case PD_VENC0:
|
|
+ pmu_bus_idle_req(BUS_ID_RKVENC0, state);
|
|
+ break;
|
|
+ case PD_VENC1:
|
|
+ pmu_bus_idle_req(BUS_ID_RKVENC1, state);
|
|
+ break;
|
|
+ case PD_RKVDEC0:
|
|
+ pmu_bus_idle_req(BUS_ID_RKVDEC0, state);
|
|
+ break;
|
|
+ case PD_RKVDEC1:
|
|
+ pmu_bus_idle_req(BUS_ID_RKVDEC1, state);
|
|
+ break;
|
|
+ case PD_VDPU:
|
|
+ pmu_bus_idle_req(BUS_ID_VDPU, state);
|
|
+ break;
|
|
+ case PD_AV1:
|
|
+ pmu_bus_idle_req(BUS_ID_AV1, state);
|
|
+ break;
|
|
+ case PD_VI:
|
|
+ pmu_bus_idle_req(BUS_ID_VI, state);
|
|
+ break;
|
|
+ case PD_ISP1:
|
|
+ pmu_bus_idle_req(BUS_ID_ISP, state);
|
|
+ break;
|
|
+ case PD_RGA31:
|
|
+ pmu_bus_idle_req(BUS_ID_RGA31, state);
|
|
+ break;
|
|
+ case PD_VOP:
|
|
+ pmu_bus_idle_req(BUS_ID_VOP_CHANNEL, state);
|
|
+ pmu_bus_idle_req(BUS_ID_VOP, state);
|
|
+ break;
|
|
+ case PD_VO0:
|
|
+ pmu_bus_idle_req(BUS_ID_VO0, state);
|
|
+ break;
|
|
+ case PD_VO1:
|
|
+ pmu_bus_idle_req(BUS_ID_VO1, state);
|
|
+ break;
|
|
+ case PD_AUDIO:
|
|
+ pmu_bus_idle_req(BUS_ID_AUDIO, state);
|
|
+ break;
|
|
+ case PD_PHP:
|
|
+ pmu_bus_idle_req(BUS_ID_PHP, state);
|
|
+ break;
|
|
+ case PD_NVM:
|
|
+ pmu_bus_idle_req(BUS_ID_NVM, state);
|
|
+ break;
|
|
+ case PD_SDIO:
|
|
+ pmu_bus_idle_req(BUS_ID_SDIO, state);
|
|
+ break;
|
|
+ case PD_USB:
|
|
+ pmu_bus_idle_req(BUS_ID_USB, state);
|
|
+ break;
|
|
+ case PD_SECURE:
|
|
+ pmu_bus_idle_req(BUS_ID_SECURE, state);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (pd_state == pmu_pd_off)
|
|
+ pmu_power_domain_ctr(pd_id, pd_state);
|
|
+
|
|
+out:
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void pmu_power_domains_suspend(void)
|
|
+{
|
|
+ ddr_data.qch_pwr_st =
|
|
+ mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS) & PMU2_QCH_PWR_MSK;
|
|
+ ddr_data.pmu_pd_st0 = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0));
|
|
+ ddr_data.bus_idle_st0 = mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST(0));
|
|
+
|
|
+ qos_save();
|
|
+
|
|
+ if ((ddr_data.pmu_pd_st0 & BIT(PD_PHP)) == 0)
|
|
+ pd_php_save();
|
|
+
|
|
+ if ((ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)) == 0)
|
|
+ pd_crypto_save();
|
|
+
|
|
+ pmu_qch_pwr_ctlr(0x20, 1);
|
|
+ pmu_qch_pwr_ctlr(0x40, 1);
|
|
+ pmu_qch_pwr_ctlr(0x1, 1);
|
|
+ pmu_qch_pwr_ctlr(0x2, 1);
|
|
+ pmu_qch_pwr_ctlr(0x4, 1);
|
|
+ pmu_qch_pwr_ctlr(0x8, 1);
|
|
+ pmu_qch_pwr_ctlr(0x10, 1);
|
|
+
|
|
+ pmu_bus_idle_req(BUS_ID_VO1USBTOP, bus_idle);
|
|
+ pmu_bus_idle_req(BUS_ID_SECURE_VO1USB_CHANNEL, bus_idle);
|
|
+
|
|
+ pmu_bus_idle_req(BUS_ID_USB, bus_idle);
|
|
+
|
|
+ pmu_set_power_domain(PD_GPU, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_NPU1, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_NPU2, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_NPUTOP, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_NPU, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_RKVDEC1, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_RKVDEC0, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_VENC1, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_VENC0, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_VCODEC, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_RGA30, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_AV1, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_VDPU, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_VO0, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_VO1, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_VOP, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_FEC, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_ISP1, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_VI, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_RGA31, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_AUDIO, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_GMAC, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_PCIE, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_PHP, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_SDIO, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_NVM0, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_NVM, pmu_pd_off);
|
|
+
|
|
+ pmu_set_power_domain(PD_SDMMC, pmu_pd_off);
|
|
+ pmu_set_power_domain(PD_CRYPTO, pmu_pd_off);
|
|
+}
|
|
+
|
|
+static void pmu_power_domains_resume(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ pmu_set_power_domain(PD_CRYPTO, !!(ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)));
|
|
+ pmu_set_power_domain(PD_SDMMC, !!(ddr_data.pmu_pd_st0 & BIT(PD_SDMMC)));
|
|
+
|
|
+ pmu_set_power_domain(PD_NVM, !!(ddr_data.pmu_pd_st0 & BIT(PD_NVM)));
|
|
+ pmu_set_power_domain(PD_NVM0, !!(ddr_data.pmu_pd_st0 & BIT(PD_NVM0)));
|
|
+
|
|
+ pmu_set_power_domain(PD_SDIO, !!(ddr_data.pmu_pd_st0 & BIT(PD_SDIO)));
|
|
+
|
|
+ pmu_set_power_domain(PD_PHP, !!(ddr_data.pmu_pd_st0 & BIT(PD_PHP)));
|
|
+ pmu_set_power_domain(PD_PCIE, !!(ddr_data.pmu_pd_st0 & BIT(PD_PCIE)));
|
|
+ pmu_set_power_domain(PD_GMAC, !!(ddr_data.pmu_pd_st0 & BIT(PD_GMAC)));
|
|
+
|
|
+ pmu_set_power_domain(PD_AUDIO, !!(ddr_data.pmu_pd_st0 & BIT(PD_AUDIO)));
|
|
+
|
|
+ pmu_set_power_domain(PD_USB, !!(ddr_data.pmu_pd_st0 & BIT(PD_USB)));
|
|
+
|
|
+ pmu_set_power_domain(PD_RGA31, !!(ddr_data.pmu_pd_st0 & BIT(PD_RGA31)));
|
|
+
|
|
+ pmu_set_power_domain(PD_VI, !!(ddr_data.pmu_pd_st0 & BIT(PD_VI)));
|
|
+ pmu_set_power_domain(PD_ISP1, !!(ddr_data.pmu_pd_st0 & BIT(PD_ISP1)));
|
|
+ pmu_set_power_domain(PD_FEC, !!(ddr_data.pmu_pd_st0 & BIT(PD_FEC)));
|
|
+
|
|
+ pmu_set_power_domain(PD_VOP, !!(ddr_data.pmu_pd_st0 & BIT(PD_VOP)));
|
|
+
|
|
+ pmu_set_power_domain(PD_VO1, !!(ddr_data.pmu_pd_st0 & BIT(PD_VO1)));
|
|
+
|
|
+ pmu_set_power_domain(PD_VO0, !!(ddr_data.pmu_pd_st0 & BIT(PD_VO0)));
|
|
+
|
|
+ pmu_set_power_domain(PD_VDPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_VDPU)));
|
|
+ pmu_set_power_domain(PD_AV1, !!(ddr_data.pmu_pd_st0 & BIT(PD_AV1)));
|
|
+ pmu_set_power_domain(PD_RGA30, !!(ddr_data.pmu_pd_st0 & BIT(PD_RGA30)));
|
|
+
|
|
+ pmu_set_power_domain(PD_VCODEC, !!(ddr_data.pmu_pd_st0 & BIT(PD_VCODEC)));
|
|
+ pmu_set_power_domain(PD_VENC0, !!(ddr_data.pmu_pd_st0 & BIT(PD_VENC0)));
|
|
+ pmu_set_power_domain(PD_VENC1, !!(ddr_data.pmu_pd_st0 & BIT(PD_VENC1)));
|
|
+ pmu_set_power_domain(PD_RKVDEC0, !!(ddr_data.pmu_pd_st0 & BIT(PD_RKVDEC0)));
|
|
+ pmu_set_power_domain(PD_RKVDEC1, !!(ddr_data.pmu_pd_st0 & BIT(PD_RKVDEC1)));
|
|
+
|
|
+ pmu_set_power_domain(PD_NPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU)));
|
|
+ pmu_set_power_domain(PD_NPUTOP, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPUTOP)));
|
|
+ pmu_set_power_domain(PD_NPU2, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU2)));
|
|
+ pmu_set_power_domain(PD_NPU1, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU1)));
|
|
+
|
|
+ pmu_set_power_domain(PD_GPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_GPU)));
|
|
+
|
|
+ for (i = 0; i < 32; i++)
|
|
+ pmu_bus_idle_req(i, !!(ddr_data.bus_idle_st0 & BIT(i)));
|
|
+
|
|
+ pmu_qch_pwr_ctlr(0x10, !!(ddr_data.qch_pwr_st & 0x10));
|
|
+ pmu_qch_pwr_ctlr(0x8, !!(ddr_data.qch_pwr_st & 0x8));
|
|
+ pmu_qch_pwr_ctlr(0x4, !!(ddr_data.qch_pwr_st & 0x4));
|
|
+ pmu_qch_pwr_ctlr(0x2, !!(ddr_data.qch_pwr_st & 0x2));
|
|
+ pmu_qch_pwr_ctlr(0x1, !!(ddr_data.qch_pwr_st & 0x1));
|
|
+ pmu_qch_pwr_ctlr(0x40, !!(ddr_data.qch_pwr_st & 0x40));
|
|
+ pmu_qch_pwr_ctlr(0x20, !!(ddr_data.qch_pwr_st & 0x20));
|
|
+
|
|
+ if ((ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)) == 0)
|
|
+ pd_crypto_restore();
|
|
+
|
|
+ if ((ddr_data.pmu_pd_st0 & BIT(PD_PHP)) == 0)
|
|
+ pd_php_restore();
|
|
+
|
|
+ qos_restore();
|
|
+}
|
|
+
|
|
+static int cpus_power_domain_on(uint32_t cpu_id)
|
|
+{
|
|
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
|
|
+ BITS_WITH_WMASK(0, 0x1, core_pm_en));
|
|
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
|
|
+ BITS_WITH_WMASK(1, 0x1, core_pm_sft_wakeup_en));
|
|
+ dsb();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
|
|
+{
|
|
+ uint32_t apm_value = BIT(core_pm_en);
|
|
+
|
|
+ if (pd_cfg == core_pwr_wfi_int)
|
|
+ apm_value |= BIT(core_pm_int_wakeup_en);
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
|
|
+ BITS_WITH_WMASK(apm_value, 0x3, 0));
|
|
+ dsb();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline void cpus_pd_req_enter_wfi(void)
|
|
+{
|
|
+ /* CORTEX_A55_CPUACTLR_EL1 */
|
|
+ __asm__ volatile ("msr DBGPRCR_EL1, xzr\n"
|
|
+ "mrs x0, S3_0_C15_C2_7\n"
|
|
+ "orr x0, x0, #0x1\n"
|
|
+ "msr S3_0_C15_C2_7, x0\n"
|
|
+ "wfi_loop:\n"
|
|
+ "isb\n"
|
|
+ "wfi\n"
|
|
+ "b wfi_loop\n");
|
|
+}
|
|
+
|
|
+static void nonboot_cpus_off(void)
|
|
+{
|
|
+ uint32_t boot_cpu, cpu, tmp;
|
|
+ uint32_t exp_st;
|
|
+ uint32_t bcore0_rst_msk = 0, bcore1_rst_msk = 0;
|
|
+ int wait_cnt;
|
|
+
|
|
+ bcore0_rst_msk = CRU_BIGCPU02_RST_MSK | CRU_BIGCPU13_RST_MSK;
|
|
+ bcore1_rst_msk = CRU_BIGCPU02_RST_MSK | CRU_BIGCPU13_RST_MSK;
|
|
+
|
|
+ mmio_write_32(BIGCORE0CRU_BASE + 0xa00, BITS_WITH_WMASK(0, bcore0_rst_msk, 0));
|
|
+ mmio_write_32(BIGCORE1CRU_BASE + 0xa00, BITS_WITH_WMASK(0, bcore1_rst_msk, 0));
|
|
+
|
|
+ wait_cnt = NONBOOT_CPUS_OFF_LOOP;
|
|
+ exp_st = SYS_GRF_BIG_CPUS_WFE;
|
|
+ do {
|
|
+ wait_cnt--;
|
|
+ tmp = mmio_read_32(SYSGRF_BASE + SYS_GRF_SOC_STATUS(3));
|
|
+ tmp &= SYS_GRF_BIG_CPUS_WFE;
|
|
+ } while (tmp != exp_st && wait_cnt);
|
|
+
|
|
+ boot_cpu = plat_my_core_pos();
|
|
+
|
|
+ /* turn off noboot cpus */
|
|
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
|
|
+ if (cpu == boot_cpu)
|
|
+ continue;
|
|
+ cpus_power_domain_off(cpu, core_pwr_wfi);
|
|
+ }
|
|
+
|
|
+ mmio_write_32(SRAM_BASE + 0x08, (uintptr_t)&cpus_pd_req_enter_wfi);
|
|
+ mmio_write_32(SRAM_BASE + 0x04, 0xdeadbeaf);
|
|
+
|
|
+ dsb();
|
|
+ isb();
|
|
+
|
|
+ sev();
|
|
+
|
|
+ wait_cnt = NONBOOT_CPUS_OFF_LOOP;
|
|
+ do {
|
|
+ wait_cnt--;
|
|
+ tmp = mmio_read_32(PMU_BASE + PMU2_CLUSTER_ST);
|
|
+ tmp &= CLUSTER_STS_NONBOOT_CPUS_DWN;
|
|
+ } while (tmp != CLUSTER_STS_NONBOOT_CPUS_DWN && wait_cnt);
|
|
+
|
|
+ if (tmp != CLUSTER_STS_NONBOOT_CPUS_DWN)
|
|
+ ERROR("nonboot cpus status(%x) error!\n", tmp);
|
|
+}
|
|
+
|
|
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr,
|
|
+ uint64_t entrypoint)
|
|
+{
|
|
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
|
|
+
|
|
+ assert(cpu_id < PLATFORM_CORE_COUNT);
|
|
+ assert(cpuson_flags[cpu_id] == 0);
|
|
+ cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
|
|
+ cpuson_entry_point[cpu_id] = entrypoint;
|
|
+ dsb();
|
|
+
|
|
+ flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags));
|
|
+ flush_dcache_range((uintptr_t)cpuson_entry_point,
|
|
+ sizeof(cpuson_entry_point));
|
|
+ dsb();
|
|
+ isb();
|
|
+
|
|
+ cpus_power_domain_on(cpu_id);
|
|
+
|
|
+ return PSCI_E_SUCCESS;
|
|
+}
|
|
+
|
|
+int rockchip_soc_cores_pwr_dm_on_finish(void)
|
|
+{
|
|
+ uint32_t cpu_id = plat_my_core_pos();
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
|
|
+ BITS_WITH_WMASK(0, 0xf, 0));
|
|
+
|
|
+ return PSCI_E_SUCCESS;
|
|
+}
|
|
+
|
|
+int rockchip_soc_cores_pwr_dm_off(void)
|
|
+{
|
|
+ uint32_t cpu_id = plat_my_core_pos();
|
|
+
|
|
+ cpus_power_domain_off(cpu_id, core_pwr_wfi);
|
|
+
|
|
+ return PSCI_E_SUCCESS;
|
|
+}
|
|
+
|
|
+int rockchip_soc_cores_pwr_dm_suspend(void)
|
|
+{
|
|
+ uint32_t cpu_id = plat_my_core_pos();
|
|
+
|
|
+ assert(cpu_id < PLATFORM_CORE_COUNT);
|
|
+
|
|
+ cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
|
|
+ cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint();
|
|
+ dsb();
|
|
+ flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags));
|
|
+ flush_dcache_range((uintptr_t)cpuson_entry_point,
|
|
+ sizeof(cpuson_entry_point));
|
|
+ dsb();
|
|
+ isb();
|
|
+
|
|
+ cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
|
|
+
|
|
+ __asm__ volatile ("msr DBGPRCR_EL1, xzr\n"
|
|
+ "mrs x0, S3_0_C15_C2_7\n"
|
|
+ "orr x0, x0, #0x1\n"
|
|
+ "msr S3_0_C15_C2_7, x0\n");
|
|
+
|
|
+ return PSCI_E_SUCCESS;
|
|
+}
|
|
+
|
|
+int rockchip_soc_cores_pwr_dm_resume(void)
|
|
+{
|
|
+ uint32_t cpu_id = plat_my_core_pos();
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
|
|
+ BITS_WITH_WMASK(0, 0x3, 0));
|
|
+
|
|
+ dsb();
|
|
+
|
|
+ return PSCI_E_SUCCESS;
|
|
+}
|
|
+
|
|
+static void ddr_sleep_config(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ if (pmu_power_domain_st(PD_DDR01) == 0) {
|
|
+ ddr_data.ddrgrf_chn_con0[0] =
|
|
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0));
|
|
+ ddr_data.ddrgrf_chn_con0[1] =
|
|
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0));
|
|
+ ddr_data.ddrgrf_chn_con1[0] =
|
|
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1));
|
|
+ ddr_data.ddrgrf_chn_con1[1] =
|
|
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1));
|
|
+ ddr_data.ddrgrf_chn_con2[0] =
|
|
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2));
|
|
+ ddr_data.ddrgrf_chn_con2[1] =
|
|
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2));
|
|
+
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2), 0x20002000);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2), 0x20002000);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2), 0x08000000);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2), 0x08000000);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0), 0x00200020);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0), 0x00200020);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1), 0x00400040);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1), 0x00400040);
|
|
+ }
|
|
+
|
|
+ if (pmu_power_domain_st(PD_DDR23) == 0) {
|
|
+ ddr_data.ddrgrf_chn_con0[2] =
|
|
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0));
|
|
+ ddr_data.ddrgrf_chn_con0[3] =
|
|
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0));
|
|
+ ddr_data.ddrgrf_chn_con1[2] =
|
|
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1));
|
|
+ ddr_data.ddrgrf_chn_con1[3] =
|
|
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1));
|
|
+ ddr_data.ddrgrf_chn_con2[2] =
|
|
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2));
|
|
+ ddr_data.ddrgrf_chn_con2[3] =
|
|
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2));
|
|
+
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2), 0x20002000);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2), 0x20002000);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2), 0x08000000);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2), 0x08000000);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0), 0x00200020);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0), 0x00200020);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1), 0x00400040);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1), 0x00400040);
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < DDR_CHN_CNT; i++) {
|
|
+ ddr_data.pmu1_ddr_pwr_sft_con[i] =
|
|
+ mmio_read_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i));
|
|
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i), 0x0fff0900);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void ddr_sleep_config_restore(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < DDR_CHN_CNT; i++) {
|
|
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i),
|
|
+ 0x0fff0000 | ddr_data.pmu1_ddr_pwr_sft_con[i]);
|
|
+ }
|
|
+
|
|
+ if (pmu_power_domain_st(PD_DDR01) == 0) {
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1),
|
|
+ 0x00400000 | ddr_data.ddrgrf_chn_con1[0]);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1),
|
|
+ 0x00400000 | ddr_data.ddrgrf_chn_con1[1]);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0),
|
|
+ 0x00200000 | ddr_data.ddrgrf_chn_con0[0]);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0),
|
|
+ 0x00200000 | ddr_data.ddrgrf_chn_con0[1]);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2),
|
|
+ 0x28000000 | ddr_data.ddrgrf_chn_con2[0]);
|
|
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2),
|
|
+ 0x28000000 | ddr_data.ddrgrf_chn_con2[1]);
|
|
+ }
|
|
+
|
|
+ if (pmu_power_domain_st(PD_DDR23) == 0) {
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1),
|
|
+ 0x00400000 | ddr_data.ddrgrf_chn_con1[2]);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1),
|
|
+ 0x00400000 | ddr_data.ddrgrf_chn_con1[3]);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0),
|
|
+ 0x00200000 | ddr_data.ddrgrf_chn_con0[2]);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0),
|
|
+ 0x00200000 | ddr_data.ddrgrf_chn_con0[3]);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2),
|
|
+ 0x28000000 | ddr_data.ddrgrf_chn_con2[2]);
|
|
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2),
|
|
+ 0x28000000 | ddr_data.ddrgrf_chn_con2[3]);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void pmu_sleep_config(void)
|
|
+{
|
|
+ uint32_t pmu1_pwr_con, pmu1_wkup_int_con, pmu1_cru_pwr_con;
|
|
+ uint32_t pmu1_ddr_pwr_con, pmu1_pll_pd_con[2] = {0};
|
|
+ uint32_t pmu2_dsu_pwr_con, pmu2_core_pwr_con, pmu2_clst_idle_con;
|
|
+ uint32_t pmu2_bus_idle_con[3] = {0}, pmu2_pwr_gate_con[3] = {0};
|
|
+ uint32_t pmu2_vol_gate_con[3] = {0}, pmu2_qch_pwr_con = 0;
|
|
+ int i;
|
|
+
|
|
+ ddr_data.pmu1grf_soc_con7 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(7));
|
|
+ ddr_data.pmu1grf_soc_con8 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(8));
|
|
+ ddr_data.pmu1grf_soc_con9 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(9));
|
|
+ ddr_data.pmu1sgrf_soc_con14 = mmio_read_32(PMU1SGRF_BASE + PMU1_SGRF_SOC_CON(14));
|
|
+ ddr_data.pmu0sgrf_soc_con1 = mmio_read_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(1));
|
|
+ ddr_data.pmu0grf_soc_con1 = mmio_read_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(1));
|
|
+
|
|
+ ddr_data.pmu2_vol_gate_con[0] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(0));
|
|
+ ddr_data.pmu2_vol_gate_con[1] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(1));
|
|
+ ddr_data.pmu2_vol_gate_con[2] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(2));
|
|
+
|
|
+ ddr_data.pmu2_submem_gate_sft_con0 =
|
|
+ mmio_read_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0));
|
|
+
|
|
+ /* save pmic_sleep iomux gpio0_a4 */
|
|
+ ddr_data.gpio0a_iomux_l = mmio_read_32(PMU0IOC_BASE + 0);
|
|
+ ddr_data.gpio0a_iomux_h = mmio_read_32(PMU0IOC_BASE + 4);
|
|
+ ddr_data.pmu0grf_soc_con3 = mmio_read_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3));
|
|
+
|
|
+ /* PMU1 repair disable */
|
|
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(0), 0x00010000);
|
|
+
|
|
+ /* set pmic_sleep iomux */
|
|
+ mmio_write_32(PMU0IOC_BASE + 0,
|
|
+ BITS_WITH_WMASK(1, 0xf, 8) |
|
|
+ BITS_WITH_WMASK(1, 0xfu, 12));
|
|
+
|
|
+ /* set tsadc_shut_m0 pin iomux to gpio */
|
|
+ mmio_write_32(PMU0IOC_BASE + 0,
|
|
+ BITS_WITH_WMASK(0, 0xf, 4));
|
|
+
|
|
+ /* set spi2_cs0/1 pin iomux to gpio */
|
|
+ mmio_write_32(PMU0IOC_BASE + 8,
|
|
+ BITS_WITH_WMASK(0, 0xff, 0));
|
|
+
|
|
+ /* sleep 1~2 src select */
|
|
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3),
|
|
+ BITS_WITH_WMASK(0x8, 0xf, 0) |
|
|
+ BITS_WITH_WMASK(0x8, 0xf, 4) |
|
|
+ BITS_WITH_WMASK(0x0, 0x3, 8));
|
|
+
|
|
+ pmu1_wkup_int_con = BIT(WAKEUP_GPIO0_INT_EN) |
|
|
+ BIT(WAKEUP_CPU0_INT_EN);
|
|
+
|
|
+ pmu1_pwr_con = BIT(powermode_en);
|
|
+
|
|
+ pmu1_cru_pwr_con =
|
|
+ BIT(alive_osc_mode_en) |
|
|
+ BIT(power_off_en) |
|
|
+ BIT(pd_clk_src_gate_en);
|
|
+
|
|
+ pmu1_ddr_pwr_con = 0;
|
|
+
|
|
+ pmu2_dsu_pwr_con =
|
|
+ BIT(DSU_PWRDN_EN) |
|
|
+ BIT(DSU_PWROFF_EN);
|
|
+
|
|
+ pmu2_core_pwr_con = BIT(CORE_PWRDN_EN);
|
|
+
|
|
+ pmu2_clst_idle_con =
|
|
+ BIT(IDLE_REQ_BIGCORE0_EN) |
|
|
+ BIT(IDLE_REQ_BIGCORE1_EN) |
|
|
+ BIT(IDLE_REQ_DSU_EN) |
|
|
+ BIT(IDLE_REQ_LITDSU_EN) |
|
|
+ BIT(IDLE_REQ_ADB400_CORE_QCH_EN);
|
|
+
|
|
+ pmu1_pll_pd_con[0] =
|
|
+ BIT(B0PLL_PD_EN) |
|
|
+ BIT(B1PLL_PD_EN) |
|
|
+ BIT(LPLL_PD_EN) |
|
|
+ BIT(V0PLL_PD_EN) |
|
|
+ BIT(AUPLL_PD_EN) |
|
|
+ BIT(GPLL_PD_EN) |
|
|
+ BIT(CPLL_PD_EN) |
|
|
+ BIT(NPLL_PD_EN);
|
|
+
|
|
+ pmu1_pll_pd_con[1] =
|
|
+ BIT(PPLL_PD_EN) |
|
|
+ BIT(SPLL_PD_EN);
|
|
+
|
|
+ pmu2_bus_idle_con[0] = 0;
|
|
+
|
|
+ pmu2_bus_idle_con[1] =
|
|
+ BIT(BUS_ID_SECURE - 16) |
|
|
+ BIT(BUS_ID_SECURE_CENTER_CHANNEL - 16) |
|
|
+ BIT(BUS_ID_CENTER_CHANNEL - 16);
|
|
+
|
|
+ pmu2_bus_idle_con[2] =
|
|
+ BIT(BUS_ID_MSCH - 32) |
|
|
+ BIT(BUS_ID_BUS - 32) |
|
|
+ BIT(BUS_ID_TOP - 32);
|
|
+
|
|
+ pmu2_pwr_gate_con[0] = 0;
|
|
+ pmu2_pwr_gate_con[1] = BIT(PD_SECURE - 16);
|
|
+ pmu2_pwr_gate_con[2] = 0;
|
|
+
|
|
+ pmu2_qch_pwr_con = 0;
|
|
+
|
|
+ pmu2_vol_gate_con[0] = 0x7;
|
|
+ pmu2_vol_gate_con[2] = 0;
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE_AUTO_PWR_CON(0), 0x00030000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE_AUTO_PWR_CON(1), 0x00030000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(0),
|
|
+ WITH_16BITS_WMSK(pmu2_core_pwr_con));
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(1),
|
|
+ WITH_16BITS_WMSK(pmu2_core_pwr_con));
|
|
+ mmio_write_32(PMU_BASE + PMU2_CLUSTER_IDLE_CON,
|
|
+ WITH_16BITS_WMSK(pmu2_clst_idle_con));
|
|
+ mmio_write_32(PMU_BASE + PMU2_DSU_AUTO_PWR_CON, 0x00030000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_DSU_PWR_CON,
|
|
+ WITH_16BITS_WMSK(pmu2_dsu_pwr_con));
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU1_OSC_STABLE_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU1_STABLE_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU1_WAKEUP_RST_CLR_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU1_PLL_LOCK_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU1_PWM_SWITCH_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE0_STABLE_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE0_PWRUP_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE0_PWRDN_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE1_STABLE_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE1_PWRUP_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE1_PWRDN_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_DSU_STABLE_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_DSU_PWRUP_CNT_THRESH, 24000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_DSU_PWRDN_CNT_THRESH, 24000);
|
|
+
|
|
+ /* Config pmu power mode and pmu wakeup source */
|
|
+ mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON,
|
|
+ BITS_WITH_WMASK(1, 0x1, 0));
|
|
+
|
|
+ /* pmu1_pwr_con */
|
|
+ mmio_write_32(PMU_BASE + PMU1_PWR_CON,
|
|
+ WITH_16BITS_WMSK(pmu1_pwr_con));
|
|
+
|
|
+ /* cru_pwr_con */
|
|
+ mmio_write_32(PMU_BASE + PMU1_CRU_PWR_CON,
|
|
+ WITH_16BITS_WMSK(pmu1_cru_pwr_con));
|
|
+
|
|
+ /* wakeup source */
|
|
+ mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, pmu1_wkup_int_con);
|
|
+
|
|
+ /* ddr pwr con */
|
|
+ for (i = 0; i < DDR_CHN_CNT; i++) {
|
|
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_CON(i),
|
|
+ WITH_16BITS_WMSK(pmu1_ddr_pwr_con));
|
|
+ pmu2_bus_idle_con[1] |=
|
|
+ BIT(BUS_ID_MSCH0 - 16 + i);
|
|
+ }
|
|
+
|
|
+ /* pll_pd */
|
|
+ mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(0),
|
|
+ WITH_16BITS_WMSK(pmu1_pll_pd_con[0]));
|
|
+ mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(1),
|
|
+ WITH_16BITS_WMSK(pmu1_pll_pd_con[1]));
|
|
+
|
|
+ /* bypass cpu1~7*/
|
|
+ mmio_write_32(PMU_BASE + PMU2_PWR_CON1, 0x00ff00fe);
|
|
+
|
|
+ /* bus idle */
|
|
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(0),
|
|
+ WITH_16BITS_WMSK(pmu2_bus_idle_con[0]));
|
|
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(1),
|
|
+ WITH_16BITS_WMSK(pmu2_bus_idle_con[1]));
|
|
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(2),
|
|
+ WITH_16BITS_WMSK(pmu2_bus_idle_con[2]));
|
|
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(2),
|
|
+ 0xf000f000);
|
|
+ /* power gate */
|
|
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(0),
|
|
+ WITH_16BITS_WMSK(pmu2_pwr_gate_con[0]));
|
|
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(1),
|
|
+ WITH_16BITS_WMSK(pmu2_pwr_gate_con[1]));
|
|
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(2),
|
|
+ WITH_16BITS_WMSK(pmu2_pwr_gate_con[2]));
|
|
+ /* vol gate */
|
|
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(0),
|
|
+ BITS_WITH_WMASK(pmu2_vol_gate_con[0], 0x7, 0));
|
|
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(1), 0);
|
|
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(2),
|
|
+ BITS_WITH_WMASK(pmu2_vol_gate_con[2], 0x3, 0));
|
|
+ /* qch */
|
|
+ mmio_write_32(PMU_BASE + PMU2_QCHANNEL_PWR_CON,
|
|
+ BITS_WITH_WMASK(pmu2_qch_pwr_con, 0x7f, 0));
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0),
|
|
+ 0x000f000f);
|
|
+}
|
|
+
|
|
+static void pmu_sleep_restore(void)
|
|
+{
|
|
+ mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(7),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con7));
|
|
+ mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(8),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con8));
|
|
+ mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(9),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con9));
|
|
+ mmio_write_32(PMU1SGRF_BASE + PMU1_SGRF_SOC_CON(14),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu1sgrf_soc_con14));
|
|
+
|
|
+ mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(1),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu0sgrf_soc_con1));
|
|
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(1),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con1));
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(0), 0xffff0000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(1), 0xffff0000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_CLUSTER_IDLE_CON, 0xffff0000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_DSU_PWR_CON, 0xffff0000);
|
|
+ mmio_write_32(PMU_BASE + PMU2_PWR_CON1, 0xffff0000);
|
|
+
|
|
+ /* Must clear PMU1_WAKEUP_INT_CON because the wakeup source
|
|
+ * in PMU1_WAKEUP_INT_CON will wakeup cpus in cpu_auto_pd state.
|
|
+ */
|
|
+ mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, 0);
|
|
+ mmio_write_32(PMU_BASE + PMU1_PWR_CON, 0xffff0000);
|
|
+ mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON, 0x00010000);
|
|
+ mmio_write_32(PMU_BASE + PMU0_WAKEUP_INT_CON, 0x00010000);
|
|
+ mmio_write_32(PMU_BASE + PMU0_PWR_CON, 0xffff0000);
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(0),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[0]));
|
|
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(1),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[1]));
|
|
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(2),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[2]));
|
|
+
|
|
+ mmio_write_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu2_submem_gate_sft_con0));
|
|
+
|
|
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con3));
|
|
+ mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(2),
|
|
+ WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con2));
|
|
+
|
|
+ mmio_write_32(PMU0IOC_BASE + 0x4,
|
|
+ WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_h));
|
|
+ mmio_write_32(PMU0IOC_BASE + 0,
|
|
+ WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_l));
|
|
+}
|
|
+
|
|
+static void soc_sleep_config(void)
|
|
+{
|
|
+ ddr_data.gpio0b_iomux_l = mmio_read_32(PMU0IOC_BASE + 0x8);
|
|
+
|
|
+ pmu_sleep_config();
|
|
+ ddr_sleep_config();
|
|
+}
|
|
+
|
|
+static void soc_sleep_restore(void)
|
|
+{
|
|
+ ddr_sleep_config_restore();
|
|
+ pmu_sleep_restore();
|
|
+
|
|
+ mmio_write_32(PMU0IOC_BASE + 0x8, WITH_16BITS_WMSK(ddr_data.gpio0b_iomux_l));
|
|
+}
|
|
+
|
|
+static void pm_pll_suspend(void)
|
|
+{
|
|
+ ddr_data.cru_mode_con = mmio_read_32(CRU_BASE + 0x280);
|
|
+ ddr_data.busscru_mode_con = mmio_read_32(BUSSCRU_BASE + 0x280);
|
|
+ ddr_data.pmu2_bisr_con0 = mmio_read_32(PMU_BASE + PMU2_BISR_CON(0));
|
|
+ ddr_data.cpll_con0 = mmio_read_32(CRU_BASE + CRU_PLLS_CON(2, 0));
|
|
+ ddr_data.pmu1cru_clksel_con1 = mmio_read_32(PMU1CRU_BASE + CRU_CLKSEL_CON(1));
|
|
+
|
|
+ /* disable bisr_init */
|
|
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(0), BITS_WITH_WMASK(0, 0x1, 0));
|
|
+ /* cpll bypass */
|
|
+ mmio_write_32(CRU_BASE + CRU_PLLS_CON(2, 0), BITS_WITH_WMASK(1u, 1u, 15));
|
|
+}
|
|
+
|
|
+static void pm_pll_restore(void)
|
|
+{
|
|
+ pm_pll_wait_lock(CRU_BASE + CRU_PLLS_CON(2, 0));
|
|
+
|
|
+ mmio_write_32(CRU_BASE + 0x280, WITH_16BITS_WMSK(ddr_data.cru_mode_con));
|
|
+ mmio_write_32(BUSSCRU_BASE + 0x280, WITH_16BITS_WMSK(ddr_data.busscru_mode_con));
|
|
+ mmio_write_32(CRU_BASE + CRU_PLLS_CON(2, 0), WITH_16BITS_WMSK(ddr_data.cpll_con0));
|
|
+ dsb();
|
|
+ isb();
|
|
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(0), WITH_16BITS_WMSK(ddr_data.pmu2_bisr_con0));
|
|
+}
|
|
+
|
|
+int rockchip_soc_sys_pwr_dm_suspend(void)
|
|
+{
|
|
+ clk_gate_con_save();
|
|
+ clk_gate_con_disable();
|
|
+
|
|
+ psram_sleep_cfg->pm_flag &= ~PM_WARM_BOOT_BIT;
|
|
+
|
|
+ pmu_power_domains_suspend();
|
|
+ soc_sleep_config();
|
|
+ dsu_core_save();
|
|
+ pm_pll_suspend();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int rockchip_soc_sys_pwr_dm_resume(void)
|
|
+{
|
|
+ pm_pll_restore();
|
|
+ dsu_core_restore();
|
|
+ soc_sleep_restore();
|
|
+ pmu_power_domains_resume();
|
|
+ plat_rockchip_gic_cpuif_enable();
|
|
+
|
|
+ psram_sleep_cfg->pm_flag |= PM_WARM_BOOT_BIT;
|
|
+
|
|
+ clk_gate_con_restore();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(const
|
|
+ psci_power_state_t *target_state)
|
|
+{
|
|
+ psci_power_down_wfi();
|
|
+}
|
|
+
|
|
+void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
|
|
+{
|
|
+ cpus_pd_req_enter_wfi();
|
|
+ psci_power_down_wfi();
|
|
+}
|
|
+
|
|
+void __dead2 rockchip_soc_soft_reset(void)
|
|
+{
|
|
+ /* pll slow mode */
|
|
+ mmio_write_32(CRU_BASE + 0x280, 0x03ff0000);
|
|
+ mmio_write_32(BIGCORE0CRU_BASE + 0x280, 0x00030000);
|
|
+ mmio_write_32(BIGCORE0CRU_BASE + 0x300, 0x60000000);
|
|
+ mmio_write_32(BIGCORE0CRU_BASE + 0x304, 0x00600000);
|
|
+ mmio_write_32(BIGCORE1CRU_BASE + 0x280, 0x00030000);
|
|
+ mmio_write_32(BIGCORE1CRU_BASE + 0x300, 0x60000000);
|
|
+ mmio_write_32(BIGCORE1CRU_BASE + 0x304, 0x00600000);
|
|
+ mmio_write_32(DSUCRU_BASE + 0x280, 0x00030000);
|
|
+ mmio_write_32(DSUCRU_BASE + 0x318, 0x30600000);
|
|
+ mmio_write_32(DSUCRU_BASE + 0x31c, 0x30600000);
|
|
+ mmio_write_32(DSUCRU_BASE + 0x304, 0x00010000);
|
|
+ mmio_write_32(BUSSCRU_BASE + 0x280, 0x0003000);
|
|
+ dsb();
|
|
+ isb();
|
|
+
|
|
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL);
|
|
+
|
|
+ /*
|
|
+ * Maybe the HW needs some times to reset the system,
|
|
+ * so we do not hope the core to execute valid codes.
|
|
+ */
|
|
+ psci_power_down_wfi();
|
|
+}
|
|
+
|
|
+void __dead2 rockchip_soc_system_off(void)
|
|
+{
|
|
+ /* set pmic_sleep pin(gpio0_a2) to gpio mode */
|
|
+ mmio_write_32(PMU0IOC_BASE + 0, BITS_WITH_WMASK(0, 0xf, 8));
|
|
+
|
|
+ /* config output */
|
|
+ mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DDR_L,
|
|
+ BITS_WITH_WMASK(1, 0x1, 2));
|
|
+
|
|
+ /* config output high level */
|
|
+ mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DR_L,
|
|
+ BITS_WITH_WMASK(1, 0x1, 2));
|
|
+ dsb();
|
|
+
|
|
+ /*
|
|
+ * Maybe the HW needs some times to reset the system,
|
|
+ * so we do not hope the core to execute valid codes.
|
|
+ */
|
|
+ psci_power_down_wfi();
|
|
+}
|
|
+
|
|
+static void rockchip_pmu_pd_init(void)
|
|
+{
|
|
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(1), 0xffffffff);
|
|
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(2), 0xffffffff);
|
|
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(3), 0xffffffff);
|
|
+
|
|
+ pmu_set_power_domain(PD_PHP, pmu_pd_on);
|
|
+ pmu_set_power_domain(PD_PCIE, pmu_pd_on);
|
|
+ pmu_set_power_domain(PD_GMAC, pmu_pd_on);
|
|
+ pmu_set_power_domain(PD_SECURE, pmu_pd_on);
|
|
+ pmu_set_power_domain(PD_VOP, pmu_pd_on);
|
|
+ pmu_set_power_domain(PD_VO0, pmu_pd_on);
|
|
+ pmu_set_power_domain(PD_VO1, pmu_pd_on);
|
|
+}
|
|
+
|
|
+#define PLL_LOCKED_TIMEOUT 600000U
|
|
+
|
|
+void pm_pll_wait_lock(uint32_t pll_base)
|
|
+{
|
|
+ int delay = PLL_LOCKED_TIMEOUT;
|
|
+
|
|
+ if ((mmio_read_32(pll_base + CRU_PLL_CON(1)) & CRU_PLLCON1_PWRDOWN) != 0)
|
|
+ return;
|
|
+
|
|
+ while (delay-- >= 0) {
|
|
+ if (mmio_read_32(pll_base + CRU_PLL_CON(6)) &
|
|
+ CRU_PLLCON6_LOCK_STATUS)
|
|
+ break;
|
|
+ udelay(1);
|
|
+ }
|
|
+
|
|
+ if (delay <= 0)
|
|
+ ERROR("Can't wait pll(0x%x) lock\n", pll_base);
|
|
+}
|
|
+
|
|
+void rockchip_plat_mmu_el3(void)
|
|
+{
|
|
+ /* Nothing todo */
|
|
+}
|
|
+
|
|
+void plat_rockchip_pmu_init(void)
|
|
+{
|
|
+ int cpu;
|
|
+
|
|
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
|
|
+ cpuson_flags[cpu] = 0;
|
|
+
|
|
+ psram_sleep_cfg->sp = PSRAM_SP_TOP;
|
|
+ psram_sleep_cfg->ddr_func = (uint64_t)ddr_resume;
|
|
+ psram_sleep_cfg->ddr_data = 0;
|
|
+ psram_sleep_cfg->ddr_flag = 0;
|
|
+ psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
|
|
+ psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT;
|
|
+
|
|
+ nonboot_cpus_off();
|
|
+
|
|
+ /*
|
|
+ * When perform idle operation, corresponding clock can be
|
|
+ * opened or gated automatically.
|
|
+ */
|
|
+ mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(0), 0xffffffff);
|
|
+ mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(1), 0xffffffff);
|
|
+ mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(2), 0x00070007);
|
|
+
|
|
+ rockchip_pmu_pd_init();
|
|
+
|
|
+ /* grf_con_pmic_sleep_sel
|
|
+ * pmic sleep function selection
|
|
+ * 1'b0: From reset pulse generator, can reset external PMIC
|
|
+ * 1'b1: From pmu block, only support sleep function for external PMIC
|
|
+ */
|
|
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3), 0x03ff0000);
|
|
+
|
|
+ /* pmusram remap to 0xffff0000 */
|
|
+ mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(2), 0x00030001);
|
|
+
|
|
+ pm_reg_rgns_init();
|
|
+}
|
|
diff --git a/plat/rockchip/rk3588/drivers/pmu/pmu.h b/plat/rockchip/rk3588/drivers/pmu/pmu.h
|
|
new file mode 100644
|
|
index 0000000..7d8288c
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/drivers/pmu/pmu.h
|
|
@@ -0,0 +1,589 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef __PMU_H__
|
|
+#define __PMU_H__
|
|
+
|
|
+#include <lib/mmio.h>
|
|
+
|
|
+#define PMU0_PWR_CON 0x0000
|
|
+#define PMU0_WAKEUP_INT_CON 0x0008
|
|
+#define PMU0_WAKEUP_INT_ST 0x000c
|
|
+#define PMU0_PMIC_STABLE_CNT_THRES 0x0010
|
|
+#define PMU0_WAKEUP_RST_CLR_CNT_THRES 0x0014
|
|
+#define PMU0_OSC_STABLE_CNT_THRES 0x0018
|
|
+#define PMU0_PWR_CHAIN_STABLE_CON 0x001c
|
|
+#define PMU0_DDR_RET_CON(i) (0x0020 + (i) * 4)
|
|
+#define PMU0_INFO_TX_CON 0x0030
|
|
+
|
|
+#define PMU1_VERSION_ID 0x4000
|
|
+#define PMU1_PWR_CON 0x4004
|
|
+#define PMU1_PWR_FSM 0x4008
|
|
+#define PMU1_INT_MASK_CON 0x400c
|
|
+#define PMU1_WAKEUP_INT_CON 0x4010
|
|
+#define PMU1_WAKEUP_INT_ST 0x4014
|
|
+#define PMU1_WAKEUP_EDGE_CON 0x4018
|
|
+#define PMU1_WAKEUP_EDGE_ST 0x401c
|
|
+#define PMU1_DDR_PWR_CON(i) (0x4020 + (i) * 4)
|
|
+#define PMU1_DDR_PWR_SFTCON(i) (0x4030 + (i) * 4)
|
|
+#define PMU1_DDR_PWR_FSM 0x4040
|
|
+#define PMU1_DDR_PWR_ST 0x4044
|
|
+#define PMU1_CRU_PWR_CON 0x4050
|
|
+#define PMU1_CRU_PWR_SFTCON 0x4054
|
|
+#define PMU1_CRU_PWR_FSM 0x4058
|
|
+#define PMU1_PLLPD_CON(i) (0x4060 + (i) * 4)
|
|
+#define PMU1_PLLPD_SFTCON(i) (0x4068 + (i) * 4)
|
|
+#define PMU1_STABLE_CNT_THRESH 0x4080
|
|
+#define PMU1_OSC_STABLE_CNT_THRESH 0x4084
|
|
+#define PMU1_WAKEUP_RST_CLR_CNT_THRESH 0x4088
|
|
+#define PMU1_PLL_LOCK_CNT_THRESH 0x408c
|
|
+#define PMU1_WAKEUP_TIMEOUT_THRESH 0x4094
|
|
+#define PMU1_PWM_SWITCH_CNT_THRESH 0x4098
|
|
+#define PMU1_SYS_REG(i) (0x4100 + (i) * 4)
|
|
+
|
|
+#define PMU2_PWR_CON1 0x8000
|
|
+#define PMU2_DSU_PWR_CON 0x8004
|
|
+#define PMU2_DSU_PWR_SFTCON 0x8008
|
|
+#define PMU2_DSU_AUTO_PWR_CON 0x800c
|
|
+#define PMU2_CPU_AUTO_PWR_CON(i) (0x8010 + (i) * 4)
|
|
+#define PMU2_CPU_PWR_SFTCON(i) (0x8030 + (i) * 4)
|
|
+#define PMU2_CORE_PWR_CON(i) (0x8050 + (i) * 4)
|
|
+#define PMU2_CORE_PWR_SFTCON(i) (0x8058 + (i) * 4)
|
|
+#define PMU2_CORE_AUTO_PWR_CON(i) (0x8060 + (i) * 4)
|
|
+#define PMU2_CLUSTER_NOC_AUTO_CON 0x8068
|
|
+#define PMU2_CLUSTER_DBG_PWR_CON 0x806c
|
|
+#define PMU2_CLUSTER_IDLE_CON 0x8070
|
|
+#define PMU2_CLUSTER_IDLE_SFTCON 0x8074
|
|
+#define PMU2_CLUSTER_IDLE_ACK 0x8078
|
|
+#define PMU2_CLUSTER_IDLE_ST 0x807c
|
|
+#define PMU2_CLUSTER_ST 0x8080
|
|
+#define PMU2_SCU_PWR_FSM_STATUS(i) (0x8084 + (i) * 4)
|
|
+#define PMU2_CORE_PCHANNEL_STATUS(i) (0x808c + (i) * 4)
|
|
+#define PMU2_CPU_PWR_CHAIN_STABLE_CON 0x8098
|
|
+#define PMU2_CLUSTER_MEMPWR_GATE_SFTCON 0x809c
|
|
+#define PMU2_DSU_STABLE_CNT_THRESH 0x80b0
|
|
+#define PMU2_DSU_PWRUP_CNT_THRESH 0x80b4
|
|
+#define PMU2_DSU_PWRDN_CNT_THRESH 0x80b8
|
|
+#define PMU2_CORE0_STABLE_CNT_THRESH 0x80bc
|
|
+#define PMU2_CORE0_PWRUP_CNT_THRESH 0x80c0
|
|
+#define PMU2_CORE0_PWRDN_CNT_THRESH 0x80c4
|
|
+#define PMU2_CORE1_STABLE_CNT_THRESH 0x80c8
|
|
+#define PMU2_CORE1_PWRUP_CNT_THRESH 0x80cc
|
|
+#define PMU2_CORE1_PWRDN_CNT_THRESH 0x80d0
|
|
+#define PMU2_DBG_RST_CNT_THRESH(i) (0x80d4 + (i) * 4)
|
|
+#define PMU2_BUS_IDLE_CON(i) (0x8100 + (i) * 4)
|
|
+#define PMU2_BUS_IDLE_SFTCON(i) (0x810c + (i) * 4)
|
|
+#define PMU2_BUS_IDLE_ACK(i) (0x8118 + (i) * 4)
|
|
+#define PMU2_BUS_IDLE_ST(i) (0x8120 + (i) * 4)
|
|
+#define PMU2_BIU_AUTO_CON(i) (0x8128 + (i) * 4)
|
|
+#define PMU2_PWR_GATE_CON(i) (0x8140 + (i) * 4)
|
|
+#define PMU2_PWR_GATE_SFTCON(i) (0x814c + (i) * 4)
|
|
+#define PMU2_VOL_GATE_CON(i) (0x8158 + (i) * 4)
|
|
+#define PMU2_PWR_UP_CHAIN_STABLE_CON(i) (0x8164 + (i) * 4)
|
|
+#define PMU2_PWR_DWN_CHAIN_STABLE_CON(i)(0x8170 + (i) * 4)
|
|
+#define PMU2_PWR_STABLE_CHAIN_CNT_THRES 0x817c
|
|
+#define PMU2_PWR_GATE_ST(i) (0x8180 + (i) * 4)
|
|
+#define PMU2_PWR_GATE_FSM 0x8188
|
|
+#define PMU2_VOL_GATE_FAST_CON 0x818c
|
|
+#define PMU2_GPU_PWRUP_CNT 0x8190
|
|
+#define PMU2_GPU_PWRDN_CNT 0x8194
|
|
+#define PMU2_NPU_PWRUP_CNT 0x8198
|
|
+#define PMU2_NPU_PWRDN_CNT 0x819c
|
|
+#define PMU2_MEMPWR_GATE_SFTCON(i) (0x81a0 + (i) * 4)
|
|
+#define PMU2_MEMPWR_MD_GATE_SFTCON(i) (0x81b0 + (i) * 4)
|
|
+#define PMU2_MEMPWR_MD_GATE_STATUS 0x81bc
|
|
+#define PMU2_SUBMEM_PWR_ACK_BYPASS(i) (0x81c0 + (i) * 4)
|
|
+#define PMU2_QCHANNEL_PWR_CON 0x81d0
|
|
+#define PMU2_QCHANNEL_PWR_SFTCON 0x81d4
|
|
+#define PMU2_QCHANNEL_STATUS 0x81d8
|
|
+#define PMU2_DEBUG_INFO_SEL 0x81e0
|
|
+#define PMU2_VOP_SUBPD_STATE 0x81e4
|
|
+#define PMU2_PWR_CHAIN0_ST(i) (0x81e8 + (i) * 4)
|
|
+#define PMU2_PWR_CHAIN1_ST(i) (0x81f0 + (i) * 4)
|
|
+#define PMU2_PWR_MEM_ST(i) (0x81f8 + (i) * 4)
|
|
+#define PMU2_BISR_CON(i) (0x8200 + (i) * 4)
|
|
+#define PMU2_BISR_STATUS(i) (0x8280 + (i) * 4)
|
|
+
|
|
+#define PMU2_QCH_PWR_MSK 0x7f
|
|
+
|
|
+#define PD_CTR_LOOP 500
|
|
+#define PD_CHECK_LOOP 500
|
|
+#define WFEI_CHECK_LOOP 500
|
|
+#define BUS_IDLE_LOOP 1000
|
|
+#define QCH_PWR_LOOP 5000
|
|
+
|
|
+/* PMU1SCRU */
|
|
+#define PMU1SCRU_GATE_CON(i) (0x800 + (i) * 4)
|
|
+
|
|
+/* PMU_GRF */
|
|
+#define PMU0_GRF_SOC_CON(i) ((i) * 4)
|
|
+#define PMU0_GRF_OS_REGS(i) (0x80 + ((i) - 8) * 4)
|
|
+#define PMU1_GRF_SOC_CON(i) ((i) * 4)
|
|
+#define PMU0_GRF_IO_RET_CON(i) (0x20 + (i) * 4)
|
|
+
|
|
+/* PMU_SGRF */
|
|
+#define PMU0_SGRF_SOC_CON(i) ((i) * 4)
|
|
+#define PMU1_SGRF_SOC_CON(i) ((i) * 4)
|
|
+
|
|
+/* sys grf */
|
|
+#define GRF_CPU_STATUS0 0x0420
|
|
+
|
|
+#define CORES_PM_DISABLE 0x0
|
|
+#define PD_CHECK_LOOP 500
|
|
+#define WFEI_CHECK_LOOP 500
|
|
+
|
|
+/* The ways of cores power domain contorlling */
|
|
+enum cores_pm_ctr_mode {
|
|
+ core_pwr_pd = 0,
|
|
+ core_pwr_wfi = 1,
|
|
+ core_pwr_wfi_int = 2
|
|
+};
|
|
+
|
|
+/* PMU0_PWR_CON */
|
|
+enum pmu0_pwr_con {
|
|
+ pmu0_powermode_en = 0,
|
|
+ pmu0_pmu1_pwr_bypass = 1,
|
|
+ pmu0_pmu1_bus_bypass = 2,
|
|
+ pmu0_wkup_bypass = 3,
|
|
+ pmu0_pmic_bypass = 4,
|
|
+ pmu0_reset_bypass = 5,
|
|
+ pmu0_freq_sw_bypass = 6,
|
|
+ pmu0_osc_dis_bypass = 7,
|
|
+ pmu0_pmu1_pwr_gt_en = 8,
|
|
+ pmu0_pmu1_pwr_gt_sft_en = 9,
|
|
+ pmu0_pmu1_mem_gt_sft_en = 10,
|
|
+ pmu0_pmu1_bus_idle_en = 11,
|
|
+ pmu0_pmu1_bus_idle_sft_en = 12,
|
|
+ pmu0_pmu1_biu_auto_en = 13,
|
|
+ pmu0_pwr_off_io_en = 14,
|
|
+};
|
|
+
|
|
+/* PMU1_PWR_CON */
|
|
+enum pmu1_pwr_con {
|
|
+ powermode_en = 0,
|
|
+ dsu_bypass = 1,
|
|
+ bus_bypass = 4,
|
|
+ ddr_bypass = 5,
|
|
+ pwrdn_bypass = 6,
|
|
+ cru_bypass = 7,
|
|
+ qch_bypass = 8,
|
|
+ core_bypass = 9,
|
|
+ cpu_sleep_wfi_dis = 12,
|
|
+};
|
|
+
|
|
+/* PMU1_DDR_PWR_CON */
|
|
+enum pmu1_ddr_pwr_con {
|
|
+ ddr_sref_en = 0,
|
|
+ ddr_sref_a_en = 1,
|
|
+ ddrio_ret_en = 2,
|
|
+ ddrio_ret_exit_en = 5,
|
|
+ ddrio_rstiov_en = 6,
|
|
+ ddrio_rstiov_exit_en = 7,
|
|
+ ddr_gating_a_en = 8,
|
|
+ ddr_gating_c_en = 9,
|
|
+ ddr_gating_p_en = 10,
|
|
+};
|
|
+
|
|
+/* PMU_CRU_PWR_CON */
|
|
+enum pmu1_cru_pwr_con {
|
|
+ alive_32k_en = 0,
|
|
+ osc_dis_en = 1,
|
|
+ wakeup_rst_en = 2,
|
|
+ input_clamp_en = 3,
|
|
+ alive_osc_mode_en = 4,
|
|
+ power_off_en = 5,
|
|
+ pwm_switch_en = 6,
|
|
+ pwm_gpio_ioe_en = 7,
|
|
+ pwm_switch_io = 8,
|
|
+ pd_clk_src_gate_en = 9,
|
|
+};
|
|
+
|
|
+/* PMU_PLLPD_CON */
|
|
+enum pmu1_pllpd_con {
|
|
+ B0PLL_PD_EN,
|
|
+ B1PLL_PD_EN,
|
|
+ LPLL_PD_EN,
|
|
+ D0APLL_PD_EN,
|
|
+ D0BPLL_PD_EN,
|
|
+ D1APLL_PD_EN,
|
|
+ D1BPLL_PD_EN,
|
|
+ D2APLL_PD_EN,
|
|
+ D2BPLL_PD_EN,
|
|
+ D3APLL_PD_EN,
|
|
+ D3BPLL_PD_EN,
|
|
+ V0PLL_PD_EN,
|
|
+ AUPLL_PD_EN,
|
|
+ GPLL_PD_EN,
|
|
+ CPLL_PD_EN,
|
|
+ NPLL_PD_EN,
|
|
+ PPLL_PD_EN = 0,
|
|
+ SPLL_PD_EN = 1,
|
|
+};
|
|
+
|
|
+enum pmu1_wakeup_int {
|
|
+ WAKEUP_CPU0_INT_EN,
|
|
+ WAKEUP_CPU1_INT_EN,
|
|
+ WAKEUP_CPU2_INT_EN,
|
|
+ WAKEUP_CPU3_INT_EN,
|
|
+ WAKEUP_CPU4_INT_EN,
|
|
+ WAKEUP_CPU5_INT_EN,
|
|
+ WAKEUP_CPU6_INT_EN,
|
|
+ WAKEUP_CPU7_INT_EN,
|
|
+ WAKEUP_GPIO0_INT_EN,
|
|
+ WAKEUP_SDMMC_EN,
|
|
+ WAKEUP_SDIO_EN,
|
|
+ WAKEUP_USBDEV_EN,
|
|
+ WAKEUP_UART0_EN,
|
|
+ WAKEUP_VAD_EN,
|
|
+ WAKEUP_TIMER_EN,
|
|
+ WAKEUP_SOC_INT_EN,
|
|
+ WAKEUP_TIMEROUT_EN,
|
|
+ WAKEUP_PMUMCU_CEC_EN = 20,
|
|
+};
|
|
+
|
|
+enum pmu2_dsu_auto_pwr_con {
|
|
+ dsu_pm_en = 0,
|
|
+ dsu_pm_int_wakeup_en = 1,
|
|
+ dsu_pm_sft_wakeup_en = 3,
|
|
+};
|
|
+
|
|
+enum pmu2_cpu_auto_pwr_con {
|
|
+ cpu_pm_en = 0,
|
|
+ cpu_pm_int_wakeup_en = 1,
|
|
+ cpu_pm_sft_wakeup_en = 3,
|
|
+};
|
|
+
|
|
+enum pmu2_core_auto_pwr_con {
|
|
+ core_pm_en = 0,
|
|
+ core_pm_int_wakeup_en = 1,
|
|
+ core_pm_int_wakeup_glb_msk = 2,
|
|
+ core_pm_sft_wakeup_en = 3,
|
|
+};
|
|
+
|
|
+enum pmu2_dsu_power_con {
|
|
+ DSU_PWRDN_EN,
|
|
+ DSU_PWROFF_EN,
|
|
+ BIT_FULL_EN,
|
|
+ DSU_RET_EN,
|
|
+ CLUSTER_CLK_SRC_GT_EN,
|
|
+};
|
|
+
|
|
+enum pmu2_core_power_con {
|
|
+ CORE_PWRDN_EN,
|
|
+ CORE_PWROFF_EN,
|
|
+ CORE_CPU_PWRDN_EN,
|
|
+ CORE_PWR_CNT_EN,
|
|
+};
|
|
+
|
|
+enum pmu2_cluster_idle_con {
|
|
+ IDLE_REQ_BIGCORE0_EN = 0,
|
|
+ IDLE_REQ_BIGCORE1_EN = 2,
|
|
+ IDLE_REQ_DSU_EN = 4,
|
|
+ IDLE_REQ_LITDSU_EN = 5,
|
|
+ IDLE_REQ_ADB400_CORE_QCH_EN = 6,
|
|
+};
|
|
+
|
|
+enum qos_id {
|
|
+ QOS_ISP0_MWO = 0,
|
|
+ QOS_ISP0_MRO = 1,
|
|
+ QOS_ISP1_MWO = 2,
|
|
+ QOS_ISP1_MRO = 3,
|
|
+ QOS_VICAP_M0 = 4,
|
|
+ QOS_VICAP_M1 = 5,
|
|
+ QOS_FISHEYE0 = 6,
|
|
+ QOS_FISHEYE1 = 7,
|
|
+ QOS_VOP_M0 = 8,
|
|
+ QOS_VOP_M1 = 9,
|
|
+ QOS_RKVDEC0 = 10,
|
|
+ QOS_RKVDEC1 = 11,
|
|
+ QOS_AV1 = 12,
|
|
+ QOS_RKVENC0_M0RO = 13,
|
|
+ QOS_RKVENC0_M1RO = 14,
|
|
+ QOS_RKVENC0_M2WO = 15,
|
|
+ QOS_RKVENC1_M0RO = 16,
|
|
+ QOS_RKVENC1_M1RO = 17,
|
|
+ QOS_RKVENC1_M2WO = 18,
|
|
+ QOS_DSU_M0 = 19,
|
|
+ QOS_DSU_M1 = 20,
|
|
+ QOS_DSU_MP = 21,
|
|
+ QOS_DEBUG = 22,
|
|
+ QOS_GPU_M0 = 23,
|
|
+ QOS_GPU_M1 = 24,
|
|
+ QOS_GPU_M2 = 25,
|
|
+ QOS_GPU_M3 = 26,
|
|
+ QOS_NPU1 = 27,
|
|
+ QOS_NPU0_MRO = 28,
|
|
+ QOS_NPU2 = 29,
|
|
+ QOS_NPU0_MWR = 30,
|
|
+ QOS_MCU_NPU = 31,
|
|
+ QOS_JPEG_DEC = 32,
|
|
+ QOS_JPEG_ENC0 = 33,
|
|
+ QOS_JPEG_ENC1 = 34,
|
|
+ QOS_JPEG_ENC2 = 35,
|
|
+ QOS_JPEG_ENC3 = 36,
|
|
+ QOS_RGA2_MRO = 37,
|
|
+ QOS_RGA2_MWO = 38,
|
|
+ QOS_RGA3_0 = 39,
|
|
+ QOS_RGA3_1 = 40,
|
|
+ QOS_VDPU = 41,
|
|
+ QOS_IEP = 42,
|
|
+ QOS_HDCP0 = 43,
|
|
+ QOS_HDCP1 = 44,
|
|
+ QOS_HDMIRX = 45,
|
|
+ QOS_GIC600_M0 = 46,
|
|
+ QOS_GIC600_M1 = 47,
|
|
+ QOS_MMU600PCIE_TCU = 48,
|
|
+ QOS_MMU600PHP_TBU = 49,
|
|
+ QOS_MMU600PHP_TCU = 50,
|
|
+ QOS_USB3_0 = 51,
|
|
+ QOS_USB3_1 = 52,
|
|
+ QOS_USBHOST_0 = 53,
|
|
+ QOS_USBHOST_1 = 54,
|
|
+ QOS_EMMC = 55,
|
|
+ QOS_FSPI = 56,
|
|
+ QOS_SDIO = 57,
|
|
+ QOS_DECOM = 58,
|
|
+ QOS_DMAC0 = 59,
|
|
+ QOS_DMAC1 = 60,
|
|
+ QOS_DMAC2 = 61,
|
|
+ QOS_GIC600M = 62,
|
|
+ QOS_DMA2DDR = 63,
|
|
+ QOS_MCU_DDR = 64,
|
|
+ QOS_VAD = 65,
|
|
+ QOS_MCU_PMU = 66,
|
|
+ QOS_CRYPTOS = 67,
|
|
+ QOS_CRYPTONS = 68,
|
|
+ QOS_DCF = 69,
|
|
+ QOS_SDMMC = 70,
|
|
+};
|
|
+
|
|
+enum pmu2_pdid {
|
|
+ PD_GPU = 0,
|
|
+ PD_NPU = 1,
|
|
+ PD_VCODEC = 2,
|
|
+ PD_NPUTOP = 3,
|
|
+ PD_NPU1 = 4,
|
|
+ PD_NPU2 = 5,
|
|
+ PD_VENC0 = 6,
|
|
+ PD_VENC1 = 7,
|
|
+ PD_RKVDEC0 = 8,
|
|
+ PD_RKVDEC1 = 9,
|
|
+ PD_VDPU = 10,
|
|
+ PD_RGA30 = 11,
|
|
+ PD_AV1 = 12,
|
|
+ PD_VI = 13,
|
|
+ PD_FEC = 14,
|
|
+ PD_ISP1 = 15,
|
|
+ PD_RGA31 = 16,
|
|
+ PD_VOP = 17,
|
|
+ PD_VO0 = 18,
|
|
+ PD_VO1 = 19,
|
|
+ PD_AUDIO = 20,
|
|
+ PD_PHP = 21,
|
|
+ PD_GMAC = 22,
|
|
+ PD_PCIE = 23,
|
|
+ PD_NVM = 24,
|
|
+ PD_NVM0 = 25,
|
|
+ PD_SDIO = 26,
|
|
+ PD_USB = 27,
|
|
+ PD_SECURE = 28,
|
|
+ PD_SDMMC = 29,
|
|
+ PD_CRYPTO = 30,
|
|
+ PD_CENTER = 31,
|
|
+ PD_DDR01 = 32,
|
|
+ PD_DDR23 = 33,
|
|
+};
|
|
+
|
|
+enum pmu2_pd_repair_id {
|
|
+ PD_RPR_PMU = 0,
|
|
+ PD_RPR_GPU = 1,
|
|
+ PD_RPR_NPUTOP = 2,
|
|
+ PD_RPR_NPU1 = 3,
|
|
+ PD_RPR_NPU2 = 4,
|
|
+ PD_RPR_VENC0 = 5,
|
|
+ PD_RPR_VENC1 = 6,
|
|
+ PD_RPR_RKVDEC0 = 7,
|
|
+ PD_RPR_RKVDEC1 = 8,
|
|
+ PD_RPR_VDPU = 9,
|
|
+ PD_RPR_RGA30 = 10,
|
|
+ PD_RPR_AV1 = 11,
|
|
+ PD_RPR_VI = 12,
|
|
+ PD_RPR_FEC = 13,
|
|
+ PD_RPR_ISP1 = 14,
|
|
+ PD_RPR_RGA31 = 15,
|
|
+ PD_RPR_VOP = 16,
|
|
+ PD_RPR_VO0 = 17,
|
|
+ PD_RPR_VO1 = 18,
|
|
+ PD_RPR_AUDIO = 19,
|
|
+ PD_RPR_PHP = 20,
|
|
+ PD_RPR_GMAC = 21,
|
|
+ PD_RPR_PCIE = 22,
|
|
+ PD_RPR_NVM0 = 23,
|
|
+ PD_RPR_SDIO = 24,
|
|
+ PD_RPR_USB = 25,
|
|
+ PD_RPR_SDMMC = 26,
|
|
+ PD_RPR_CRYPTO = 27,
|
|
+ PD_RPR_CENTER = 28,
|
|
+ PD_RPR_DDR01 = 29,
|
|
+ PD_RPR_DDR23 = 30,
|
|
+ PD_RPR_BUS = 31,
|
|
+};
|
|
+
|
|
+enum pmu2_bus_id {
|
|
+ BUS_ID_GPU = 0,
|
|
+ BUS_ID_NPUTOP = 1,
|
|
+ BUS_ID_NPU1 = 2,
|
|
+ BUS_ID_NPU2 = 3,
|
|
+ BUS_ID_RKVENC0 = 4,
|
|
+ BUS_ID_RKVENC1 = 5,
|
|
+ BUS_ID_RKVDEC0 = 6,
|
|
+ BUS_ID_RKVDEC1 = 7,
|
|
+ BUS_ID_VDPU = 8,
|
|
+ BUS_ID_AV1 = 9,
|
|
+ BUS_ID_VI = 10,
|
|
+ BUS_ID_ISP = 11,
|
|
+ BUS_ID_RGA31 = 12,
|
|
+ BUS_ID_VOP = 13,
|
|
+ BUS_ID_VOP_CHANNEL = 14,
|
|
+ BUS_ID_VO0 = 15,
|
|
+ BUS_ID_VO1 = 16,
|
|
+ BUS_ID_AUDIO = 17,
|
|
+ BUS_ID_NVM = 18,
|
|
+ BUS_ID_SDIO = 19,
|
|
+ BUS_ID_USB = 20,
|
|
+ BUS_ID_PHP = 21,
|
|
+ BUS_ID_VO1USBTOP = 22,
|
|
+ BUS_ID_SECURE = 23,
|
|
+ BUS_ID_SECURE_CENTER_CHANNEL = 24,
|
|
+ BUS_ID_SECURE_VO1USB_CHANNEL = 25,
|
|
+ BUS_ID_CENTER = 26,
|
|
+ BUS_ID_CENTER_CHANNEL = 27,
|
|
+ BUS_ID_MSCH0 = 28,
|
|
+ BUS_ID_MSCH1 = 29,
|
|
+ BUS_ID_MSCH2 = 30,
|
|
+ BUS_ID_MSCH3 = 31,
|
|
+ BUS_ID_MSCH = 32,
|
|
+ BUS_ID_BUS = 33,
|
|
+ BUS_ID_TOP = 34,
|
|
+};
|
|
+
|
|
+enum pmu2_mem_st {
|
|
+ PD_NPU_TOP_MEM_ST = 11,
|
|
+ PD_NPU1_MEM_ST = 12,
|
|
+ PD_NPU2_MEM_ST = 13,
|
|
+ PD_VENC0_MEM_ST = 14,
|
|
+ PD_VENC1_MEM_ST = 15,
|
|
+ PD_RKVDEC0_MEM_ST = 16,
|
|
+ PD_RKVDEC1_MEM_ST = 17,
|
|
+ PD_RGA30_MEM_ST = 19,
|
|
+ PD_AV1_MEM_ST = 20,
|
|
+ PD_VI_MEM_ST = 21,
|
|
+ PD_FEC_MEM_ST = 22,
|
|
+ PD_ISP1_MEM_ST = 23,
|
|
+ PD_RGA31_MEM_ST = 24,
|
|
+ PD_VOP_MEM_ST = 25,
|
|
+ PD_VO0_MEM_ST = 26,
|
|
+ PD_VO1_MEM_ST = 27,
|
|
+ PD_AUDIO_MEM_ST = 28,
|
|
+ PD_PHP_MEM_ST = 29,
|
|
+ PD_GMAC_MEM_ST = 30,
|
|
+ PD_PCIE_MEM_ST = 31,
|
|
+ PD_NVM0_MEM_ST = 33,
|
|
+ PD_SDIO_MEM_ST = 34,
|
|
+ PD_USB_MEM_ST = 35,
|
|
+ PD_SDMMC_MEM_ST = 37,
|
|
+};
|
|
+
|
|
+enum pmu2_qid {
|
|
+ QID_PHPMMU_TBU = 0,
|
|
+ QID_PHPMMU_TCU = 1,
|
|
+ QID_PCIEMMU_TBU0 = 2,
|
|
+ QID_PCIEMU_TCU = 3,
|
|
+ QID_PHP_GICITS = 4,
|
|
+ QID_BUS_GICITS0 = 5,
|
|
+ QID_BUS_GICITS1 = 6,
|
|
+};
|
|
+
|
|
+/* PMU_DSU_PWR_CON */
|
|
+enum pmu_dsu_pwr_con {
|
|
+ DSU_PWRDN_ENA = 2,
|
|
+ DSU_PWROFF_ENA,
|
|
+ DSU_RET_ENA = 6,
|
|
+ CLUSTER_CLK_SRC_GATE_ENA,
|
|
+ DSU_PWR_CON_END
|
|
+};
|
|
+
|
|
+enum cpu_power_state {
|
|
+ CPU_POWER_ON,
|
|
+ CPU_POWER_OFF,
|
|
+ CPU_EMULATION_OFF,
|
|
+ CPU_RETENTION,
|
|
+ CPU_DEBUG
|
|
+};
|
|
+
|
|
+enum dsu_power_state {
|
|
+ DSU_POWER_ON,
|
|
+ CLUSTER_TRANSFER_IDLE,
|
|
+ DSU_POWER_DOWN,
|
|
+ DSU_OFF,
|
|
+ DSU_WAKEUP,
|
|
+ DSU_POWER_UP,
|
|
+ CLUSTER_TRANSFER_RESUME,
|
|
+ DSU_FUNCTION_RETENTION
|
|
+};
|
|
+
|
|
+/* PMU2_CLUSTER_STS 0x8080 */
|
|
+enum pmu2_cluster_sts_bits {
|
|
+ pd_cpu0_dwn = 0,
|
|
+ pd_cpu1_dwn,
|
|
+ pd_cpu2_dwn,
|
|
+ pd_cpu3_dwn,
|
|
+ pd_cpu4_dwn,
|
|
+ pd_cpu5_dwn,
|
|
+ pd_cpu6_dwn,
|
|
+ pd_cpu7_dwn,
|
|
+ pd_core0_dwn,
|
|
+ pd_core1_dwn
|
|
+};
|
|
+
|
|
+#define CLUSTER_STS_NONBOOT_CPUS_DWN 0xfe
|
|
+
|
|
+enum cpu_off_trigger {
|
|
+ CPU_OFF_TRIGGER_WFE = 0,
|
|
+ CPU_OFF_TRIGGER_REQ_EML,
|
|
+ CPU_OFF_TRIGGER_REQ_WFI,
|
|
+ CPU_OFF_TRIGGER_REQ_WFI_NBT_CPU,
|
|
+ CPU_OFF_TRIGGER_REQ_WFI_NBT_CPU_SRAM
|
|
+};
|
|
+
|
|
+/*****************************************************************************
|
|
+ * power domain on or off
|
|
+ *****************************************************************************/
|
|
+enum pmu_pd_state {
|
|
+ pmu_pd_on = 0,
|
|
+ pmu_pd_off = 1
|
|
+};
|
|
+
|
|
+enum bus_state {
|
|
+ bus_active,
|
|
+ bus_idle,
|
|
+};
|
|
+
|
|
+#define RK_CPU_STATUS_OFF 0
|
|
+#define RK_CPU_STATUS_ON 1
|
|
+#define RK_CPU_STATUS_BUSY -1
|
|
+
|
|
+#define PD_CTR_LOOP 500
|
|
+#define MAX_WAIT_COUNT 500
|
|
+
|
|
+#define pmu_bus_idle_st(id) \
|
|
+ (!!(mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST((id) / 32)) & BIT((id) % 32)))
|
|
+
|
|
+#define pmu_bus_idle_ack(id) \
|
|
+ (!!(mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ACK((id) / 32)) & BIT((id) % 32)))
|
|
+
|
|
+void pm_pll_wait_lock(uint32_t pll_base);
|
|
+#endif /* __PMU_H__ */
|
|
diff --git a/plat/rockchip/rk3588/drivers/secure/secure.c b/plat/rockchip/rk3588/drivers/secure/secure.c
|
|
new file mode 100644
|
|
index 0000000..fc9f211
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/drivers/secure/secure.c
|
|
@@ -0,0 +1,188 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <assert.h>
|
|
+#include <lib/mmio.h>
|
|
+
|
|
+#include <platform_def.h>
|
|
+
|
|
+#include <secure.h>
|
|
+#include <soc.h>
|
|
+
|
|
+static void secure_fw_master_init(void)
|
|
+{
|
|
+ uint32_t i;
|
|
+
|
|
+ /* ddr_mcu can access all ddr-regions */
|
|
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_MST(1), 0x0000ffff);
|
|
+ /* dcf/crypto_s can access all ddr-regions */
|
|
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_MST(14), 0x00000000);
|
|
+ /* dsu_mp_sec can access all ddr-regions.
|
|
+ * DSU access memory [f000_0000~ff00_0000] through MP in firewall_ddr.
|
|
+ */
|
|
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_MST(36), 0xffff0000);
|
|
+
|
|
+ /* all other ns-master can't access all ddr-regions */
|
|
+ for (i = 0; i < FIREWALL_DDR_MST_CNT; i++) {
|
|
+ if (i == 1 || i == 14 || i == 36)
|
|
+ continue;
|
|
+
|
|
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_MST(i), 0xffffffff);
|
|
+ }
|
|
+
|
|
+ /* mcu_pmu can access all sram-regions */
|
|
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_MST(19), 0x000000ff);
|
|
+ /* dsu mp-sec can access all sram-regions */
|
|
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_MST(38), 0x000000ff);
|
|
+ /* nsp_dsu2main_sec can access all sram-regions */
|
|
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_MST(41), 0x00000000);
|
|
+
|
|
+ /* all ns-master can't access all sram-regions */
|
|
+ for (i = 0; i < FIREWALL_SYSMEM_MST_CNT; i++) {
|
|
+ if (i == 19 || i == 38 || i == 41)
|
|
+ continue;
|
|
+
|
|
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_MST(i),
|
|
+ 0x00ff00ff);
|
|
+ }
|
|
+
|
|
+ /* dsu-ns can't access all ddr-regions, dsu-s can access all ddr-regions */
|
|
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(0), 0xffffffff);
|
|
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(1), 0x00000000);
|
|
+ dsb();
|
|
+ isb();
|
|
+}
|
|
+
|
|
+/* unit: Mb */
|
|
+static void dsu_fw_rgn_config(uint64_t base_mb, uint64_t top_mb, int rgn_id)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ if (rgn_id >= FIREWALL_DSU_RGN_CNT || rgn_id < 0) {
|
|
+ ERROR("%s regions-id:%d is invalid!\n", __func__, rgn_id);
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(rgn_id),
|
|
+ RG_MAP_SECURE(top_mb, base_mb));
|
|
+
|
|
+ for (i = 0; i < DDR_CHN_CNT; i++)
|
|
+ mmio_setbits_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i),
|
|
+ BIT(rgn_id));
|
|
+}
|
|
+
|
|
+/* unit: Mb */
|
|
+static void ddr_fw_rgn_config(uint64_t base_mb, uint64_t top_mb, int rgn_id)
|
|
+{
|
|
+ if (rgn_id >= FIREWALL_DDR_RGN_CNT || rgn_id < 0) {
|
|
+ ERROR("%s regions-id:%d is invalid!\n", __func__, rgn_id);
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_RGN(rgn_id),
|
|
+ RG_MAP_SECURE(top_mb, base_mb));
|
|
+
|
|
+ /* enable region */
|
|
+ mmio_setbits_32(FIREWALL_DDR_BASE + FIREWALL_DDR_CON,
|
|
+ BIT(rgn_id));
|
|
+}
|
|
+
|
|
+/* Unit: Kb */
|
|
+static void sram_fw_rgn_config(uint64_t base_kb, uint64_t top_kb, int rgn_id)
|
|
+{
|
|
+ if (rgn_id >= FIREWALL_SYSMEM_RGN_CNT || rgn_id < 0) {
|
|
+ ERROR("%s regions-id:%d is invalid!\n", __func__, rgn_id);
|
|
+ panic();
|
|
+ }
|
|
+
|
|
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_RGN(rgn_id),
|
|
+ RG_MAP_SRAM_SECURE(top_kb, base_kb));
|
|
+
|
|
+ /* enable region */
|
|
+ mmio_setbits_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_CON, BIT(rgn_id));
|
|
+}
|
|
+
|
|
+static void secure_region_init(void)
|
|
+{
|
|
+ uint32_t i;
|
|
+
|
|
+ /* disable all region first except region0 */
|
|
+ mmio_clrbits_32(FIREWALL_DDR_BASE + FIREWALL_DDR_CON, 0xfffe);
|
|
+ for (i = 0; i < FIREWALL_DSU_CON_CNT; i++)
|
|
+ mmio_clrbits_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i), 0xfffe);
|
|
+ mmio_clrbits_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_CON, 0xfe);
|
|
+
|
|
+ secure_fw_master_init();
|
|
+
|
|
+ /* Use FW_DDR_RGN0_REG to config 0~1M space to secure */
|
|
+ dsu_fw_rgn_config(0, 1, 0);
|
|
+ ddr_fw_rgn_config(0, 1, 0);
|
|
+
|
|
+ /* Use FIREWALL_SYSMEM_RGN0 to config SRAM_ENTRY code(0~4k of sram) to secure */
|
|
+ sram_fw_rgn_config(0, 4, 0);
|
|
+ /* For 0xffff0000~0xffffffff, use FIREWALL_SYSMEM_RGN7 to config
|
|
+ * 960~1024k of sram to secure.
|
|
+ */
|
|
+ sram_fw_rgn_config(960, 1024, 7);
|
|
+}
|
|
+
|
|
+void secure_timer_init(void)
|
|
+{
|
|
+ /* gpu's cntvalue comes from stimer1 channel_5 */
|
|
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG,
|
|
+ TIMER_DIS);
|
|
+
|
|
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_LOAD_COUNT0, 0xffffffff);
|
|
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_LOAD_COUNT1, 0xffffffff);
|
|
+
|
|
+ /* auto reload & enable the timer */
|
|
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG,
|
|
+ TIMER_EN | TIMER_FMODE);
|
|
+}
|
|
+
|
|
+void sgrf_init(void)
|
|
+{
|
|
+ uint32_t i;
|
|
+
|
|
+ secure_region_init();
|
|
+
|
|
+ /* config master ddr_mcu_prot|dcf_wr|dcf_rd as secure */
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(14), 0x001f0011);
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(15), 0xffffffff);
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(16), 0x03ff03ff);
|
|
+
|
|
+ /* config slave mailbox_mcu_ddr as secure */
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(4), 0xffff2000);
|
|
+ /* config slave int256mux4_mcu_ddr|int256mux4_mcu_pmu as secure */
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(5), 0xffff0060);
|
|
+ /* config slave ddrgrf*|dma2ddr|ddrphy*_cru|umctl* as secure */
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(24), 0xffff0fbf);
|
|
+ /* config slave ddrphy*|ddr_stanby*|ddr_mcu_timer|ddr_mcu_wdt as secure */
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(25), 0xffff03ff);
|
|
+
|
|
+ /* config all other slave as ns */
|
|
+ for (i = 0; i < SGRF_FIREWALL_CON_CNT; i++) {
|
|
+ if (i == 4 || i == 5 || i == 24 || i == 25)
|
|
+ continue;
|
|
+
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(i), 0xffff0000);
|
|
+ }
|
|
+
|
|
+ /* config vad_hprot non-secure, pmu_mcu_hprot as secure */
|
|
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(0), 0x00180010);
|
|
+ /* config pmu1, pmu0, pmu_sram as secure */
|
|
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(1), 0xefbe6020);
|
|
+ /* config remap_pmu_mem, h_pmu_mem as secure */
|
|
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(2), 0x01f900c0);
|
|
+
|
|
+ /* disable dp encryption */
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(13), 0x00180018);
|
|
+
|
|
+ /* select grf config for pcie ats */
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(17), 0x11111111);
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(18), 0x11111111);
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(19), 0x00110011);
|
|
+}
|
|
diff --git a/plat/rockchip/rk3588/drivers/secure/secure.h b/plat/rockchip/rk3588/drivers/secure/secure.h
|
|
new file mode 100644
|
|
index 0000000..d9c234f
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/drivers/secure/secure.h
|
|
@@ -0,0 +1,54 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef SECURE_H
|
|
+#define SECURE_H
|
|
+
|
|
+/* DSUSGRF */
|
|
+#define DSU_SGRF_SOC_CON(i) ((i) * 4)
|
|
+#define DSUSGRF_SOC_CON(i) ((i) * 4)
|
|
+#define DSUSGRF_SOC_CON_CNT 13
|
|
+#define DSUSGRF_DDR_HASH_CON(i) (0x240 + (i) * 4)
|
|
+#define DSUSGRF_DDR_HASH_CON_CNT 8
|
|
+
|
|
+/* PMUSGRF */
|
|
+#define PMU1SGRF_SOC_CON(n) ((n) * 4)
|
|
+
|
|
+/* SGRF */
|
|
+#define SGRF_SOC_CON(i) ((i) * 4)
|
|
+#define SGRF_FIREWALL_CON(i) (0x240 + (i) * 4)
|
|
+#define SGRF_FIREWALL_CON_CNT 32
|
|
+
|
|
+/* ddr firewall */
|
|
+#define FIREWALL_DDR_RGN(i) ((i) * 0x4)
|
|
+#define FIREWALL_DDR_RGN_CNT 16
|
|
+#define FIREWALL_DDR_MST(i) (0x40 + (i) * 0x4)
|
|
+#define FIREWALL_DDR_MST_CNT 42
|
|
+#define FIREWALL_DDR_CON 0xf0
|
|
+
|
|
+#define FIREWALL_SYSMEM_RGN(i) ((i) * 0x4)
|
|
+#define FIREWALL_SYSMEM_RGN_CNT 8
|
|
+#define FIREWALL_SYSMEM_MST(i) (0x40 + (i) * 0x4)
|
|
+#define FIREWALL_SYSMEM_MST_CNT 43
|
|
+#define FIREWALL_SYSMEM_CON 0xf0
|
|
+
|
|
+#define FIREWALL_DSU_RGN(i) ((i) * 0x4)
|
|
+#define FIREWALL_DSU_RGN_CNT 16
|
|
+#define FIREWALL_DSU_MST(i) (0x40 + (i) * 0x4)
|
|
+#define FIREWALL_DSU_MST_CNT 2
|
|
+#define FIREWALL_DSU_CON(i) (0xf0 + (i) * 4)
|
|
+#define FIREWALL_DSU_CON_CNT 4
|
|
+
|
|
+#define PLAT_MAX_DDR_CAPACITY_MB 0x8000 /* for 32Gb */
|
|
+#define RG_MAP_SECURE(top, base) \
|
|
+ (((((top) - 1) & 0x7fff) << 16) | ((base) & 0x7fff))
|
|
+#define RG_MAP_SRAM_SECURE(top_kb, base_kb) \
|
|
+ (((((top_kb) / 4 - 1) & 0xff) << 16) | ((base_kb) / 4 & 0xff))
|
|
+
|
|
+void secure_timer_init(void);
|
|
+void sgrf_init(void);
|
|
+
|
|
+#endif /* SECURE_H */
|
|
diff --git a/plat/rockchip/rk3588/drivers/soc/soc.c b/plat/rockchip/rk3588/drivers/soc/soc.c
|
|
new file mode 100644
|
|
index 0000000..a276859
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/drivers/soc/soc.c
|
|
@@ -0,0 +1,96 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <assert.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include <arch_helpers.h>
|
|
+#include <bl31/bl31.h>
|
|
+#include <common/debug.h>
|
|
+#include <drivers/console.h>
|
|
+#include <drivers/delay_timer.h>
|
|
+#include <lib/mmio.h>
|
|
+#include <lib/xlat_tables/xlat_tables_compat.h>
|
|
+#include <platform.h>
|
|
+#include <platform_def.h>
|
|
+#include <pmu.h>
|
|
+
|
|
+#include <plat_private.h>
|
|
+#include <secure.h>
|
|
+#include <soc.h>
|
|
+
|
|
+#define RK3588_DEV_RNG0_BASE 0xf0000000
|
|
+#define RK3588_DEV_RNG0_SIZE 0x0ffff000
|
|
+
|
|
+const mmap_region_t plat_rk_mmap[] = {
|
|
+ MAP_REGION_FLAT(RK3588_DEV_RNG0_BASE, RK3588_DEV_RNG0_SIZE,
|
|
+ MT_DEVICE | MT_RW | MT_SECURE),
|
|
+ MAP_REGION_FLAT(DDR_SHARE_MEM, DDR_SHARE_SIZE,
|
|
+ MT_DEVICE | MT_RW | MT_NS),
|
|
+ { 0 }
|
|
+};
|
|
+
|
|
+/* The RockChip power domain tree descriptor */
|
|
+const unsigned char rockchip_power_domain_tree_desc[] = {
|
|
+ /* No of root nodes */
|
|
+ PLATFORM_SYSTEM_COUNT,
|
|
+ /* No of children for the root node */
|
|
+ PLATFORM_CLUSTER_COUNT,
|
|
+ /* No of children for the first cluster node */
|
|
+ PLATFORM_CLUSTER0_CORE_COUNT,
|
|
+ /* No of children for the second cluster node */
|
|
+ PLATFORM_CLUSTER1_CORE_COUNT
|
|
+};
|
|
+
|
|
+void timer_hp_init(void)
|
|
+{
|
|
+ if ((mmio_read_32(TIMER_HP_BASE + TIMER_HP_CTRL) & 0x1) != 0)
|
|
+ return;
|
|
+
|
|
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_CTRL, 0x0);
|
|
+ dsb();
|
|
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_LOAD_COUNT0, 0xffffffff);
|
|
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_LOAD_COUNT1, 0xffffffff);
|
|
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_INT_EN, 0);
|
|
+ dsb();
|
|
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_CTRL, 0x1);
|
|
+}
|
|
+
|
|
+static void system_reset_init(void)
|
|
+{
|
|
+ /* enable wdt_ns0~4 trigger global reset and select first reset.
|
|
+ * enable tsadc trigger global reset and select first reset.
|
|
+ * enable global reset and wdt trigger pmu reset.
|
|
+ * select first reset trigger pmu reset.s
|
|
+ */
|
|
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, 0xffdf);
|
|
+
|
|
+ /* enable wdt_s, wdt_ns reset */
|
|
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(2), 0x0c000c00);
|
|
+
|
|
+ /* reset width = 0xffff */
|
|
+ mmio_write_32(PMU1GRF_BASE + PMU1GRF_SOC_CON(1), 0xffffffff);
|
|
+
|
|
+ /* enable first/tsadc/wdt reset output */
|
|
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(0), 0x00070007);
|
|
+
|
|
+ /* pmu1_grf pmu1_ioc hold */
|
|
+ mmio_write_32(PMU1GRF_BASE + PMU1GRF_SOC_CON(7), 0x30003000);
|
|
+
|
|
+ /* pmu1sgrf hold */
|
|
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(14), 0x00200020);
|
|
+
|
|
+ /* select tsadc_shut_m0 ionmux*/
|
|
+ mmio_write_32(PMU0IOC_BASE + 0x0, 0x00f00020);
|
|
+}
|
|
+
|
|
+void plat_rockchip_soc_init(void)
|
|
+{
|
|
+ secure_timer_init();
|
|
+ timer_hp_init();
|
|
+ system_reset_init();
|
|
+ sgrf_init();
|
|
+}
|
|
diff --git a/plat/rockchip/rk3588/drivers/soc/soc.h b/plat/rockchip/rk3588/drivers/soc/soc.h
|
|
new file mode 100644
|
|
index 0000000..9af179a
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/drivers/soc/soc.h
|
|
@@ -0,0 +1,198 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef __SOC_H__
|
|
+#define __SOC_H__
|
|
+
|
|
+enum pll_id {
|
|
+ APLL_ID,
|
|
+ DPLL_ID,
|
|
+ GPLL_ID,
|
|
+ CPLL_ID,
|
|
+ NPLL_ID,
|
|
+ VPLL_ID,
|
|
+};
|
|
+
|
|
+enum pmu_pll_id {
|
|
+ PPLL_ID = 0,
|
|
+ HPLL_ID
|
|
+};
|
|
+
|
|
+enum cru_mode_con00 {
|
|
+ CLK_APLL,
|
|
+ CLK_DPLL,
|
|
+ CLK_CPLL,
|
|
+ CLK_GPLL,
|
|
+ CLK_REVSERVED,
|
|
+ CLK_NPLL,
|
|
+ CLK_VPLL,
|
|
+ CLK_USBPLL,
|
|
+};
|
|
+
|
|
+#define KHz 1000
|
|
+#define MHz (1000 * KHz)
|
|
+#define OSC_HZ (24 * MHz)
|
|
+
|
|
+/* CRU */
|
|
+#define GLB_SRST_FST_CFG_VAL 0xfdb9
|
|
+
|
|
+#define CRU_PLLS_CON(pll_id, i) (0x160 + (pll_id) * 0x20 + (i) * 0x4)
|
|
+#define CRU_PLL_CON(i) ((i) * 0x4)
|
|
+#define CRU_MODE_CON0 0x280
|
|
+#define CRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
|
|
+#define CRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
|
|
+#define CRU_CLKGATE_CON_CNT 78
|
|
+#define CRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
|
|
+#define CRU_GLB_CNT_TH 0xc00
|
|
+#define CRU_GLB_SRST_FST 0xc08
|
|
+#define CRU_GLB_SRST_SND 0xc0c
|
|
+#define CRU_GLB_RST_CON 0xc10
|
|
+#define CRU_GLB_RST_ST 0xc04
|
|
+#define CRU_SDIO_CON0 0xc24
|
|
+#define CRU_SDIO_CON1 0xc28
|
|
+#define CRU_SDMMC_CON0 0xc30
|
|
+#define CRU_SDMMC_CON1 0xc34
|
|
+#define CRU_AUTOCS_CON0(id) (0xd00 + (id) * 8)
|
|
+#define CRU_AUTOCS_CON1(id) (0xd04 + (id) * 8)
|
|
+
|
|
+#define CRU_AUTOCS_ID_CNT 74
|
|
+
|
|
+#define CRU_PLLCON0_M_MASK 0x3ff
|
|
+#define CRU_PLLCON0_M_SHIFT 0
|
|
+#define CRU_PLLCON1_P_MASK 0x3f
|
|
+#define CRU_PLLCON1_P_SHIFT 0
|
|
+#define CRU_PLLCON1_S_MASK 0x7
|
|
+#define CRU_PLLCON1_S_SHIFT 6
|
|
+#define CRU_PLLCON2_K_MASK 0xffff
|
|
+#define CRU_PLLCON2_K_SHIFT 0
|
|
+#define CRU_PLLCON1_PWRDOWN BIT(13)
|
|
+#define CRU_PLLCON6_LOCK_STATUS BIT(15)
|
|
+
|
|
+#define CRU_BIGCPU02_RST_MSK 0x30
|
|
+#define CRU_BIGCPU13_RST_MSK 0x300
|
|
+
|
|
+#define PHPCRU_CLKGATE_CON 0x800
|
|
+#define PHPCRU_CLKGATE_CON_CNT 1
|
|
+
|
|
+#define SECURECRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
|
|
+#define SECURECRU_CLKGATE_CON_CNT 4
|
|
+
|
|
+#define PMU1CRU_CLKGATE_CON_CNT 6
|
|
+
|
|
+/* CENTER GRF */
|
|
+#define CENTER_GRF_CON(i) ((i) * 4)
|
|
+
|
|
+/* PMU1GRF */
|
|
+#define PMU1GRF_SOC_CON(n) ((n) * 4)
|
|
+#define PMU1GRF_SOC_ST 0x60
|
|
+#define PMU1GRF_OS_REG(n) (0x200 + ((n) * 4))
|
|
+
|
|
+#define PMU_MCU_HALT BIT(7)
|
|
+#define PMU_MCU_SLEEP BIT(9)
|
|
+#define PMU_MCU_DEEPSLEEP BIT(10)
|
|
+#define PMU_MCU_STOP_MSK \
|
|
+ (PMU_MCU_HALT | PMU_MCU_SLEEP | PMU_MCU_DEEPSLEEP)
|
|
+
|
|
+/* SYSGRF */
|
|
+#define SYS_GRF_NOC_CON(n) (0x100 + (n) * 4)
|
|
+#define SYS_GRF_SOC_CON(n) (0x300 + (n) * 4)
|
|
+#define SYS_GRF_SOC_STATUS(n) (0x380 + (n) * 4)
|
|
+
|
|
+#define SYS_GRF_LITTLE_CPUS_WFE 0xf
|
|
+#define SYS_GRF_CORE0_CPUS_WFE 0x30
|
|
+#define SYS_GRF_CORE1_CPUS_WFE 0xc0
|
|
+#define SYS_GRF_BIG_CPUS_WFE 0xf0
|
|
+#define SYS_GRF_LITTLE_CPUS_WFI 0xf00
|
|
+#define SYS_GRF_CORE0_CPUS_WFI 0x3000
|
|
+#define SYS_GRF_CORE1_CPUS_WFI 0xc000
|
|
+
|
|
+/* pvtm */
|
|
+#define PVTM_CON(i) (0x4 + (i) * 4)
|
|
+#define PVTM_INTEN 0x70
|
|
+#define PVTM_INTSTS 0x74
|
|
+#define PVTM_STATUS(i) (0x80 + (i) * 4)
|
|
+#define PVTM_CALC_CNT 0x200
|
|
+
|
|
+enum pvtm_con0 {
|
|
+ pvtm_start = 0,
|
|
+ pvtm_osc_en = 1,
|
|
+ pvtm_osc_sel = 2,
|
|
+ pvtm_rnd_seed_en = 5,
|
|
+};
|
|
+
|
|
+/* timer */
|
|
+#define TIMER_LOAD_COUNT0 0x00
|
|
+#define TIMER_LOAD_COUNT1 0x04
|
|
+#define TIMER_CURRENT_VALUE0 0x08
|
|
+#define TIMER_CURRENT_VALUE1 0x0c
|
|
+#define TIMER_CONTROL_REG 0x10
|
|
+#define TIMER_INTSTATUS 0x18
|
|
+
|
|
+#define TIMER_DIS 0x0
|
|
+#define TIMER_EN 0x1
|
|
+
|
|
+#define TIMER_FMODE (0x0 << 1)
|
|
+#define TIMER_RMODE (0x1 << 1)
|
|
+
|
|
+#define STIMER0_CHN_BASE(n) (STIMER0_BASE + 0x20 * (n))
|
|
+#define STIMER1_CHN_BASE(n) (STIMER1_BASE + 0x20 * (n))
|
|
+
|
|
+/* cpu timer */
|
|
+#define TIMER_HP_REVISION 0x0
|
|
+#define TIMER_HP_CTRL 0x4
|
|
+#define TIMER_HP_INT_EN 0x8
|
|
+#define TIMER_HP_T24_GCD 0xc
|
|
+#define TIMER_HP_T32_GCD 0x10
|
|
+#define TIMER_HP_LOAD_COUNT0 0x14
|
|
+#define TIMER_HP_LOAD_COUNT1 0x18
|
|
+#define TIMER_HP_T24_DELAT_COUNT0 0x1c
|
|
+#define TIMER_HP_T24_DELAT_COUNT1 0x20
|
|
+#define TIMER_HP_CURR_32K_VALUE0 0x24
|
|
+#define TIMER_HP_CURR_32K_VALUE1 0x28
|
|
+#define TIMER_HP_CURR_TIMER_VALUE0 0x2c
|
|
+#define TIMER_HP_CURR_TIMER_VALUE1 0x30
|
|
+#define TIMER_HP_T24_32BEGIN0 0x34
|
|
+#define TIMER_HP_T24_32BEGIN1 0x38
|
|
+#define TIMER_HP_T32_24END0 0x3c
|
|
+#define TIMER_HP_T32_24END1 0x40
|
|
+#define TIMER_HP_BEGIN_END_VALID 0x44
|
|
+#define TIMER_HP_SYNC_REQ 0x48
|
|
+#define TIMER_HP_INTR_STATUS 0x4c
|
|
+
|
|
+ /* GPIO */
|
|
+#define GPIO_SWPORT_DR_L 0x0000
|
|
+#define GPIO_SWPORT_DR_H 0x0004
|
|
+#define GPIO_SWPORT_DDR_L 0x0008
|
|
+#define GPIO_SWPORT_DDR_H 0x000c
|
|
+#define GPIO_INT_EN_L 0x0010
|
|
+#define GPIO_INT_EN_H 0x0014
|
|
+#define GPIO_INT_MASK_L 0x0018
|
|
+#define GPIO_INT_MASK_H 0x001c
|
|
+#define GPIO_INT_TYPE_L 0x0020
|
|
+#define GPIO_INT_TYPE_H 0x0024
|
|
+#define GPIO_INT_POLARITY_L 0x0028
|
|
+#define GPIO_INT_POLARITY_H 0x002c
|
|
+#define GPIO_INT_BOTHEDGE_L 0x0030
|
|
+#define GPIO_INT_BOTHEDGE_H 0x0034
|
|
+#define GPIO_DEBOUNCE_L 0x0038
|
|
+#define GPIO_DEBOUNCE_H 0x003c
|
|
+#define GPIO_DBCLK_DIV_EN_L 0x0040
|
|
+#define GPIO_DBCLK_DIV_EN_H 0x0044
|
|
+#define GPIO_DBCLK_DIV_CON 0x0048
|
|
+#define GPIO_INT_STATUS 0x0050
|
|
+#define GPIO_INT_RAWSTATUS 0x0058
|
|
+#define GPIO_PORT_EOI_L 0x0060
|
|
+#define GPIO_PORT_EOI_H 0x0064
|
|
+#define GPIO_EXT_PORT 0x0070
|
|
+#define GPIO_VER_ID 0x0078
|
|
+
|
|
+/* DDRGRF */
|
|
+#define DDRGRF_CHA_CON(i) ((i) * 4)
|
|
+#define DDRGRF_CHB_CON(i) (0x30 + (i) * 4)
|
|
+
|
|
+#define DDR_CHN_CNT 4
|
|
+
|
|
+#endif /* __SOC_H__ */
|
|
diff --git a/plat/rockchip/rk3588/include/plat.ld.S b/plat/rockchip/rk3588/include/plat.ld.S
|
|
new file mode 100644
|
|
index 0000000..e3ea9cc
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/include/plat.ld.S
|
|
@@ -0,0 +1,42 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef ROCKCHIP_PLAT_LD_S
|
|
+#define ROCKCHIP_PLAT_LD_S
|
|
+
|
|
+MEMORY {
|
|
+ PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
|
|
+}
|
|
+
|
|
+SECTIONS
|
|
+{
|
|
+ . = PMUSRAM_BASE;
|
|
+
|
|
+ /*
|
|
+ * pmu_cpuson_entrypoint request address
|
|
+ * align 64K when resume, so put it in the
|
|
+ * start of pmusram
|
|
+ */
|
|
+ .text_pmusram : {
|
|
+ ASSERT(. == ALIGN(64 * 1024),
|
|
+ ".pmusram.entry request 64K aligned.");
|
|
+ KEEP(*(.pmusram.entry))
|
|
+ __bl31_pmusram_text_start = .;
|
|
+ *(.pmusram.text)
|
|
+ *(.pmusram.rodata)
|
|
+ . = ALIGN(PAGE_SIZE);
|
|
+ __bl31_pmusram_text_end = .;
|
|
+ __bl31_pmusram_data_start = .;
|
|
+ *(.pmusram.data)
|
|
+ . = ALIGN(PAGE_SIZE);
|
|
+ __bl31_pmusram_data_end = .;
|
|
+
|
|
+ ASSERT(__bl31_pmusram_data_end <= PMUSRAM_BASE + PMUSRAM_RSIZE,
|
|
+ ".pmusram has exceeded its limit.");
|
|
+ } >PMUSRAM
|
|
+}
|
|
+
|
|
+#endif /* ROCKCHIP_PLAT_LD_S */
|
|
diff --git a/plat/rockchip/rk3588/include/plat_sip_calls.h b/plat/rockchip/rk3588/include/plat_sip_calls.h
|
|
new file mode 100644
|
|
index 0000000..bc4455f
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/include/plat_sip_calls.h
|
|
@@ -0,0 +1,12 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef __PLAT_SIP_CALLS_H__
|
|
+#define __PLAT_SIP_CALLS_H__
|
|
+
|
|
+#define RK_PLAT_SIP_NUM_CALLS 0
|
|
+
|
|
+#endif /* __PLAT_SIP_CALLS_H__ */
|
|
diff --git a/plat/rockchip/rk3588/include/platform_def.h b/plat/rockchip/rk3588/include/platform_def.h
|
|
new file mode 100644
|
|
index 0000000..5946af0
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/include/platform_def.h
|
|
@@ -0,0 +1,119 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef __PLATFORM_DEF_H__
|
|
+#define __PLATFORM_DEF_H__
|
|
+
|
|
+#include <arch.h>
|
|
+#include <plat/common/common_def.h>
|
|
+
|
|
+#include <rk3588_def.h>
|
|
+
|
|
+#define DEBUG_XLAT_TABLE 0
|
|
+
|
|
+/*******************************************************************************
|
|
+ * Platform binary types for linking
|
|
+ ******************************************************************************/
|
|
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
|
|
+#define PLATFORM_LINKER_ARCH aarch64
|
|
+
|
|
+/*******************************************************************************
|
|
+ * Generic platform constants
|
|
+ ******************************************************************************/
|
|
+
|
|
+/* Size of cacheable stacks */
|
|
+#if DEBUG_XLAT_TABLE
|
|
+#define PLATFORM_STACK_SIZE 0x800
|
|
+#elif IMAGE_BL1
|
|
+#define PLATFORM_STACK_SIZE 0x440
|
|
+#elif IMAGE_BL2
|
|
+#define PLATFORM_STACK_SIZE 0x400
|
|
+#elif IMAGE_BL31
|
|
+#define PLATFORM_STACK_SIZE 0x800
|
|
+#elif IMAGE_BL32
|
|
+#define PLATFORM_STACK_SIZE 0x440
|
|
+#endif
|
|
+
|
|
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
|
|
+
|
|
+#define PLATFORM_SYSTEM_COUNT 1
|
|
+#define PLATFORM_CLUSTER_COUNT 1
|
|
+#define PLATFORM_CLUSTER0_CORE_COUNT 8
|
|
+#define PLATFORM_CLUSTER1_CORE_COUNT 0
|
|
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
|
|
+ PLATFORM_CLUSTER0_CORE_COUNT)
|
|
+
|
|
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
|
|
+ PLATFORM_CLUSTER_COUNT + \
|
|
+ PLATFORM_CORE_COUNT)
|
|
+
|
|
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
|
|
+
|
|
+#define PLAT_RK_CLST_TO_CPUID_SHIFT 8
|
|
+
|
|
+/*
|
|
+ * This macro defines the deepest retention state possible. A higher state
|
|
+ * id will represent an invalid or a power down state.
|
|
+ */
|
|
+#define PLAT_MAX_RET_STATE 1
|
|
+
|
|
+/*
|
|
+ * This macro defines the deepest power down states possible. Any state ID
|
|
+ * higher than this is invalid.
|
|
+ */
|
|
+#define PLAT_MAX_OFF_STATE 2
|
|
+/*******************************************************************************
|
|
+ * Platform memory map related constants
|
|
+ ******************************************************************************/
|
|
+/* TF txet, ro, rw, Size: 512KB */
|
|
+#define TZRAM_BASE (0x0)
|
|
+#define TZRAM_SIZE (0x100000)
|
|
+
|
|
+/*******************************************************************************
|
|
+ * BL31 specific defines.
|
|
+ ******************************************************************************/
|
|
+/*
|
|
+ * Put BL3-1 at the top of the Trusted RAM
|
|
+ */
|
|
+#define BL31_BASE (TZRAM_BASE + 0x40000)
|
|
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
|
|
+
|
|
+/*******************************************************************************
|
|
+ * Platform specific page table and MMU setup constants
|
|
+ ******************************************************************************/
|
|
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
|
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
|
+
|
|
+#define ADDR_SPACE_SIZE (1ULL << 32)
|
|
+#define MAX_XLAT_TABLES 18
|
|
+#define MAX_MMAP_REGIONS 27
|
|
+
|
|
+/*******************************************************************************
|
|
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
|
|
+ * aligned on the biggest cache line size in the platform. This is known only
|
|
+ * to the platform as it might have a combination of integrated and external
|
|
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
|
|
+ * line at any cache level. They could belong to different cpus/clusters &
|
|
+ * get written while being protected by different locks causing corruption of
|
|
+ * a valid mailbox address.
|
|
+ ******************************************************************************/
|
|
+#define CACHE_WRITEBACK_SHIFT 6
|
|
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
|
+
|
|
+/*
|
|
+ * Define GICD and GICC and GICR base
|
|
+ */
|
|
+#define PLAT_RK_GICD_BASE PLAT_GICD_BASE
|
|
+#define PLAT_RK_GICC_BASE PLAT_GICC_BASE
|
|
+#define PLAT_RK_GICR_BASE PLAT_GICR_BASE
|
|
+
|
|
+#define PLAT_RK_UART_BASE RK_DBG_UART_BASE
|
|
+#define PLAT_RK_UART_CLOCK RK_DBG_UART_CLOCK
|
|
+#define PLAT_RK_UART_BAUDRATE RK_DBG_UART_BAUDRATE
|
|
+
|
|
+#define PLAT_RK_PRIMARY_CPU 0x0
|
|
+
|
|
+#endif /* __PLATFORM_DEF_H__ */
|
|
diff --git a/plat/rockchip/rk3588/plat_sip_calls.c b/plat/rockchip/rk3588/plat_sip_calls.c
|
|
new file mode 100644
|
|
index 0000000..57f5de5
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/plat_sip_calls.c
|
|
@@ -0,0 +1,27 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <common/debug.h>
|
|
+#include <common/runtime_svc.h>
|
|
+
|
|
+#include <plat_sip_calls.h>
|
|
+#include <rockchip_sip_svc.h>
|
|
+
|
|
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
|
|
+ u_register_t x1,
|
|
+ u_register_t x2,
|
|
+ u_register_t x3,
|
|
+ u_register_t x4,
|
|
+ void *cookie,
|
|
+ void *handle,
|
|
+ u_register_t flags)
|
|
+{
|
|
+ switch (smc_fid) {
|
|
+ default:
|
|
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
|
|
+ SMC_RET1(handle, SMC_UNK);
|
|
+ }
|
|
+}
|
|
diff --git a/plat/rockchip/rk3588/platform.mk b/plat/rockchip/rk3588/platform.mk
|
|
new file mode 100644
|
|
index 0000000..f987815
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/platform.mk
|
|
@@ -0,0 +1,85 @@
|
|
+#
|
|
+# Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+#
|
|
+# SPDX-License-Identifier: BSD-3-Clause
|
|
+#
|
|
+
|
|
+RK_PLAT := plat/rockchip
|
|
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
|
|
+RK_PLAT_COMMON := ${RK_PLAT}/common
|
|
+
|
|
+DISABLE_BIN_GENERATION := 1
|
|
+include lib/libfdt/libfdt.mk
|
|
+include lib/xlat_tables_v2/xlat_tables.mk
|
|
+
|
|
+# GIC-600 configuration
|
|
+GICV3_IMPL := GIC600
|
|
+GICV3_SUPPORT_GIC600 := 1
|
|
+
|
|
+# Include GICv3 driver files
|
|
+include drivers/arm/gic/v3/gicv3.mk
|
|
+
|
|
+PLAT_INCLUDES := -Iinclude/plat/common \
|
|
+ -Idrivers/arm/gic/v3/ \
|
|
+ -I${RK_PLAT_COMMON}/ \
|
|
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
|
|
+ -I${RK_PLAT_COMMON}/drivers/parameter/ \
|
|
+ -I${RK_PLAT_COMMON}/include/ \
|
|
+ -I${RK_PLAT_COMMON}/pmusram/ \
|
|
+ -I${RK_PLAT_SOC}/ \
|
|
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
|
|
+ -I${RK_PLAT_SOC}/drivers/secure/ \
|
|
+ -I${RK_PLAT_SOC}/drivers/soc/ \
|
|
+ -I${RK_PLAT_SOC}/include/
|
|
+
|
|
+RK_GIC_SOURCES := ${GICV3_SOURCES} \
|
|
+ plat/common/plat_gicv3.c \
|
|
+ ${RK_PLAT}/common/rockchip_gicv3.c
|
|
+
|
|
+PLAT_BL_COMMON_SOURCES := ${XLAT_TABLES_LIB_SRCS} \
|
|
+ common/desc_image_load.c \
|
|
+ plat/common/aarch64/crash_console_helpers.S \
|
|
+ lib/bl_aux_params/bl_aux_params.c \
|
|
+ plat/common/plat_psci_common.c
|
|
+
|
|
+ifneq (${ENABLE_STACK_PROTECTOR},0)
|
|
+PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c
|
|
+endif
|
|
+
|
|
+BL31_SOURCES += ${RK_GIC_SOURCES} \
|
|
+ drivers/ti/uart/aarch64/16550_console.S \
|
|
+ drivers/delay_timer/delay_timer.c \
|
|
+ drivers/delay_timer/generic_delay_timer.c \
|
|
+ lib/cpus/aarch64/cortex_a55.S \
|
|
+ lib/cpus/aarch64/cortex_a76.S \
|
|
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
|
|
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
|
|
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
|
|
+ ${RK_PLAT_COMMON}/plat_pm.c \
|
|
+ ${RK_PLAT_COMMON}/plat_pm_helpers.c \
|
|
+ ${RK_PLAT_COMMON}/plat_topology.c \
|
|
+ ${RK_PLAT_COMMON}/params_setup.c \
|
|
+ ${RK_PLAT_COMMON}/pmusram/cpus_on_fixed_addr.S \
|
|
+ ${RK_PLAT_COMMON}/rockchip_sip_svc.c \
|
|
+ ${RK_PLAT_SOC}/plat_sip_calls.c \
|
|
+ ${RK_PLAT_SOC}/drivers/secure/secure.c \
|
|
+ ${RK_PLAT_SOC}/drivers/soc/soc.c \
|
|
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
|
|
+ ${RK_PLAT_SOC}/drivers/pmu/pm_pd_regs.c
|
|
+
|
|
+CTX_INCLUDE_AARCH32_REGS := 0
|
|
+ENABLE_PLAT_COMPAT := 0
|
|
+MULTI_CONSOLE_API := 1
|
|
+ERRATA_A55_1530923 := 1
|
|
+
|
|
+# System coherency is managed in hardware
|
|
+HW_ASSISTED_COHERENCY := 1
|
|
+
|
|
+# When building for systems with hardware-assisted coherency, there's no need to
|
|
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
|
|
+USE_COHERENT_MEM := 0
|
|
+
|
|
+ENABLE_SPE_FOR_LOWER_ELS := 0
|
|
+
|
|
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
|
|
+$(eval $(call add_define,PLAT_SKIP_DFS_TLB_DCACHE_MAINTENANCE))
|
|
diff --git a/plat/rockchip/rk3588/rk3588_def.h b/plat/rockchip/rk3588/rk3588_def.h
|
|
new file mode 100644
|
|
index 0000000..75b685a
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3588/rk3588_def.h
|
|
@@ -0,0 +1,221 @@
|
|
+/*
|
|
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#ifndef __PLAT_DEF_H__
|
|
+#define __PLAT_DEF_H__
|
|
+
|
|
+#define SIZE_K(n) ((n) * 1024)
|
|
+
|
|
+#define WITH_16BITS_WMSK(bits) (0xffff0000 | (bits))
|
|
+
|
|
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
|
|
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
|
|
+
|
|
+#define UMCTL0_BASE 0xf7000000
|
|
+#define UMCTL1_BASE 0xf8000000
|
|
+#define UMCTL2_BASE 0xf9000000
|
|
+#define UMCTL3_BASE 0xfa000000
|
|
+
|
|
+#define GIC600_BASE 0xfe600000
|
|
+#define GIC600_SIZE SIZE_K(64)
|
|
+
|
|
+#define DAPLITE_BASE 0xfd100000
|
|
+#define PMU0SGRF_BASE 0xfd580000
|
|
+#define PMU1SGRF_BASE 0xfd582000
|
|
+#define BUSSGRF_BASE 0xfd586000
|
|
+#define DSUSGRF_BASE 0xfd587000
|
|
+#define PMU0GRF_BASE 0xfd588000
|
|
+#define PMU1GRF_BASE 0xfd58a000
|
|
+
|
|
+#define SYSGRF_BASE 0xfd58c000
|
|
+#define BIGCORE0GRF_BASE 0xfd590000
|
|
+#define BIGCORE1GRF_BASE 0xfd592000
|
|
+#define LITCOREGRF_BASE 0xfd594000
|
|
+#define DSUGRF_BASE 0xfd598000
|
|
+#define DDR01GRF_BASE 0xfd59c000
|
|
+#define DDR23GRF_BASE 0xfd59d000
|
|
+#define CENTERGRF_BASE 0xfd59e000
|
|
+#define GPUGRF_BASE 0xfd5a0000
|
|
+#define NPUGRF_BASE 0xfd5a2000
|
|
+#define USBGRF_BASE 0xfd5ac000
|
|
+#define PHPGRF_BASE 0xfd5b0000
|
|
+#define PCIE3PHYGRF_BASE 0xfd5b8000
|
|
+#define USB2PHY0_GRF_BASE 0xfd5d0000
|
|
+#define USB2PHY1_GRF_BASE 0xfd5d4000
|
|
+#define USB2PHY2_GRF_BASE 0xfd5d8000
|
|
+#define USB2PHY3_GRF_BASE 0xfd5dc000
|
|
+
|
|
+#define PMU0IOC_BASE 0xfd5f0000
|
|
+#define PMU1IOC_BASE 0xfd5f4000
|
|
+#define BUSIOC_BASE 0xfd5f8000
|
|
+#define VCCIO1_4_IOC_BASE 0xfd5f9000
|
|
+#define VCCIO3_5_IOC_BASE 0xfd5fa000
|
|
+#define VCCIO2_IOC_BASE 0xfd5fb000
|
|
+#define VCCIO6_IOC_BASE 0xfd5fc000
|
|
+
|
|
+#define SRAM_BASE 0xff000000
|
|
+#define PMUSRAM_BASE 0xff100000
|
|
+#define PMUSRAM_SIZE SIZE_K(128)
|
|
+#define PMUSRAM_RSIZE SIZE_K(64)
|
|
+
|
|
+#define CRU_BASE 0xfd7c0000
|
|
+#define PHP_CRU_BASE 0xfd7c8000
|
|
+#define SCRU_BASE 0xfd7d0000
|
|
+#define BUSSCRU_BASE 0xfd7d8000
|
|
+#define PMU1SCRU_BASE 0xfd7e0000
|
|
+#define PMU1CRU_BASE 0xfd7f0000
|
|
+
|
|
+#define DDR0CRU_BASE 0xfd800000
|
|
+#define DDR1CRU_BASE 0xfd804000
|
|
+#define DDR2CRU_BASE 0xfd808000
|
|
+#define DDR3CRU_BASE 0xfd80c000
|
|
+
|
|
+#define BIGCORE0CRU_BASE 0xfd810000
|
|
+#define BIGCORE1CRU_BASE 0xfd812000
|
|
+#define LITCRU_BASE 0xfd814000
|
|
+#define DSUCRU_BASE 0xfd818000
|
|
+
|
|
+#define I2C0_BASE 0xfd880000
|
|
+#define UART0_BASE 0xfd890000
|
|
+#define GPIO0_BASE 0xfd8a0000
|
|
+#define PWM0_BASE 0xfd8b0000
|
|
+#define PMUPVTM_BASE 0xfd8c0000
|
|
+#define TIMER_HP_BASE 0xfd8c8000
|
|
+#define PMU0_BASE 0xfd8d0000
|
|
+#define PMU1_BASE 0xfd8d4000
|
|
+#define PMU2_BASE 0xfd8d8000
|
|
+#define PMU_BASE PMU0_BASE
|
|
+#define PMUWDT_BASE 0xfd8e0000
|
|
+#define PMUTIMER_BASE 0xfd8f0000
|
|
+#define OSC_CHK_BASE 0xfd9b0000
|
|
+#define VOP_BASE 0xfdd90000
|
|
+#define HDMIRX_BASE 0xfdee0000
|
|
+
|
|
+#define MSCH0_BASE 0xfe000000
|
|
+#define MSCH1_BASE 0xfe002000
|
|
+#define MSCH2_BASE 0xfe004000
|
|
+#define MSCH3_BASE 0xfe006000
|
|
+#define FIREWALL_DSU_BASE 0xfe010000
|
|
+#define FIREWALL_DDR_BASE 0xfe030000
|
|
+#define FIREWALL_SYSMEM_BASE 0xfe038000
|
|
+#define DDRPHY0_BASE 0xfe0c0000
|
|
+#define DDRPHY1_BASE 0xfe0d0000
|
|
+#define DDRPHY2_BASE 0xfe0e0000
|
|
+#define DDRPHY3_BASE 0xfe0f0000
|
|
+#define TIMER_DDR_BASE 0xfe118000
|
|
+#define KEYLADDER_BASE 0xfe380000
|
|
+#define CRYPTO_S_BASE 0xfe390000
|
|
+#define OTP_S_BASE 0xfe3a0000
|
|
+#define DCF_BASE 0xfe3c0000
|
|
+#define STIMER0_BASE 0xfe3d0000
|
|
+#define WDT_S_BASE 0xfe3e0000
|
|
+#define CRYPTO_S_BY_KEYLAD_BASE 0xfe420000
|
|
+#define NSTIMER0_BASE 0xfeae0000
|
|
+#define NSTIMER1_BASE 0xfeae8000
|
|
+#define WDT_NS_BASE 0xfeaf0000
|
|
+
|
|
+#define UART1_BASE 0xfeb40000
|
|
+#define UART2_BASE 0xfeb50000
|
|
+#define UART3_BASE 0xfeb60000
|
|
+#define UART4_BASE 0xfeb70000
|
|
+#define UART5_BASE 0xfeb80000
|
|
+#define UART6_BASE 0xfeb90000
|
|
+#define UART7_BASE 0xfeba0000
|
|
+#define UART8_BASE 0xfebb0000
|
|
+#define UART9_BASE 0xfebc0000
|
|
+
|
|
+#define GPIO1_BASE 0xfec20000
|
|
+#define GPIO2_BASE 0xfec30000
|
|
+#define GPIO3_BASE 0xfec40000
|
|
+#define GPIO4_BASE 0xfec50000
|
|
+
|
|
+#define MAILBOX1_BASE 0xfec70000
|
|
+#define OTP_NS_BASE 0xfecc0000
|
|
+#define INTMUX0_DDR_BASE 0Xfecf8000
|
|
+#define INTMUX1_DDR_BASE 0Xfecfc000
|
|
+#define STIMER1_BASE 0xfed30000
|
|
+
|
|
+/**************************************************************************
|
|
+ * sys sram allocation
|
|
+ **************************************************************************/
|
|
+#define SRAM_ENTRY_BASE SRAM_BASE
|
|
+#define SRAM_PMUM0_SHMEM_BASE (SRAM_ENTRY_BASE + SIZE_K(3))
|
|
+#define SRAM_LD_BASE (SRAM_ENTRY_BASE + SIZE_K(4))
|
|
+#define SRAM_LD_SIZE SIZE_K(64)
|
|
+
|
|
+#define SRAM_LD_SP (SRAM_LD_BASE + SRAM_LD_SIZE -\
|
|
+ 128)
|
|
+
|
|
+/**************************************************************************
|
|
+ * share mem region allocation: 1M~2M
|
|
+ **************************************************************************/
|
|
+#define DDR_SHARE_MEM SIZE_K(1024)
|
|
+#define DDR_SHARE_SIZE SIZE_K(64)
|
|
+
|
|
+#define SHARE_MEM_BASE DDR_SHARE_MEM
|
|
+#define SHARE_MEM_PAGE_NUM 15
|
|
+#define SHARE_MEM_SIZE SIZE_K(SHARE_MEM_PAGE_NUM * 4)
|
|
+
|
|
+#define SCMI_SHARE_MEM_BASE (SHARE_MEM_BASE + SHARE_MEM_SIZE)
|
|
+#define SCMI_SHARE_MEM_SIZE SIZE_K(4)
|
|
+
|
|
+/**************************************************************************
|
|
+ * UART related constants
|
|
+ **************************************************************************/
|
|
+#define RK_DBG_UART_BASE UART2_BASE
|
|
+#define RK_DBG_UART_BAUDRATE 1500000
|
|
+#define RK_DBG_UART_CLOCK 24000000
|
|
+
|
|
+/******************************************************************************
|
|
+ * System counter frequency related constants
|
|
+ ******************************************************************************/
|
|
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
|
|
+#define SYS_COUNTER_FREQ_IN_MHZ 24
|
|
+
|
|
+/******************************************************************************
|
|
+ * GIC-600 & interrupt handling related constants
|
|
+ ******************************************************************************/
|
|
+
|
|
+/* Base rk_platform compatible GIC memory map */
|
|
+#define PLAT_GICD_BASE GIC600_BASE
|
|
+#define PLAT_GICC_BASE 0
|
|
+#define PLAT_GICR_BASE (GIC600_BASE + 0x80000)
|
|
+#define PLAT_GICITS0_BASE 0xfe640000
|
|
+#define PLAT_GICITS1_BASE 0xfe660000
|
|
+
|
|
+/******************************************************************************
|
|
+ * sgi, ppi
|
|
+ ******************************************************************************/
|
|
+#define RK_IRQ_SEC_SGI_0 8
|
|
+#define RK_IRQ_SEC_SGI_1 9
|
|
+#define RK_IRQ_SEC_SGI_2 10
|
|
+#define RK_IRQ_SEC_SGI_3 11
|
|
+#define RK_IRQ_SEC_SGI_4 12
|
|
+#define RK_IRQ_SEC_SGI_5 13
|
|
+#define RK_IRQ_SEC_SGI_6 14
|
|
+#define RK_IRQ_SEC_SGI_7 15
|
|
+#define RK_IRQ_SEC_PHY_TIMER 29
|
|
+
|
|
+/*
|
|
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
|
|
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
|
|
+ * as Group 0 interrupts.
|
|
+ */
|
|
+
|
|
+#define PLAT_RK_GICV3_G1S_IRQS \
|
|
+ INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
|
|
+ INTR_GROUP1S, GIC_INTR_CFG_LEVEL)
|
|
+
|
|
+#define PLAT_RK_GICV3_G0_IRQS \
|
|
+ INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
|
|
+ INTR_GROUP0, GIC_INTR_CFG_LEVEL)
|
|
+
|
|
+/******************************************************************************
|
|
+ * pm reg region memory
|
|
+ ******************************************************************************/
|
|
+#define ROCKCHIP_PM_REG_REGION_MEM_SIZE SIZE_K(4)
|
|
+
|
|
+#endif /* __PLAT_DEF_H__ */
|