feat(rk3576): support rk3576

rk3576 is an Octa-core soc with Cortex-a53/a72 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

Change-Id: I67a019822bd4af13e4a3cdd09cf06202f4922cc4
Signed-off-by: XiaoDong Huang <derrick.huang@rock-chips.com>
diff --git a/plat/rockchip/rk3576/drivers/secure/firewall.c b/plat/rockchip/rk3576/drivers/secure/firewall.c
new file mode 100644
index 0000000..5da9ea8
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/secure/firewall.c
@@ -0,0 +1,693 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include <firewall.h>
+#include <soc.h>
+
+enum {
+	FW_NS_A_S_A = 0x0,
+	FW_NS_A_S_NA = 0x1,
+	FW_NS_NA_S_A = 0x2,
+	FW_NS_NA_S_NA = 0x3,
+};
+
+/* group type */
+enum {
+	FW_GRP_TYPE_INV = 0,
+	FW_GRP_TYPE_DDR_RGN = 1,
+	FW_GRP_TYPE_SYSMEM_RGN = 2,
+	FW_GRP_TYPE_CBUF_RGN = 3,
+	FW_GRP_TYPE_SLV = 4,
+	FW_GRP_TYPE_DM = 5,
+};
+
+enum {
+	FW_SLV_TYPE_INV = 0,
+	FW_MST_TYPE_INV = 0,
+	FW_SLV_TYPE_BUS = 1,
+	FW_SLV_TYPE_TOP = 2,
+	FW_SLV_TYPE_CENTER = 3,
+	FW_SLV_TYPE_CCI = 4,
+	FW_SLV_TYPE_PHP = 5,
+	FW_SLV_TYPE_GPU = 6,
+	FW_SLV_TYPE_NPU = 7,
+	FW_SLV_TYPE_PMU = 8,
+	FW_MST_TYPE_SYS = 9,
+	FW_MST_TYPE_PMU = 10,
+};
+
+#define FW_ID(type, id)			\
+	((((type) & 0xff) << 16) | ((id) & 0xffff))
+
+#define FW_MST_ID(type, id)		FW_ID(type, id)
+#define FW_SLV_ID(type, id)		FW_ID(type, id)
+#define FW_GRP_ID(type, id)		FW_ID(type, id)
+
+/* group id */
+#define FW_GRP_ID_DDR_RGN(id)		FW_GRP_ID(FW_GRP_TYPE_DDR_RGN, id)
+#define FW_GRP_ID_SYSMEM_RGN(id)	FW_GRP_ID(FW_GRP_TYPE_SYSMEM_RGN, id)
+#define FW_GRP_ID_CBUF(id)		FW_GRP_ID(FW_GRP_TYPE_CBUF_RGN, id)
+#define FW_GRP_ID_SLV(id)		FW_GRP_ID(FW_GRP_TYPE_SLV, id)
+#define FW_GRP_ID_DM(id)		FW_GRP_ID(FW_GRP_TYPE_DM, id)
+
+#define FW_GRP_ID_SLV_CNT		8
+#define FW_GRP_ID_DM_CNT		8
+
+#define FW_GET_ID(id)			((id) & 0xffff)
+#define FW_GET_TYPE(id)			(((id) >> 16) & 0xff)
+
+#define FW_INVLID_MST_ID		FW_MST_ID(FW_MST_TYPE_INV, 0)
+#define FW_INVLID_SLV_ID		FW_SLV_ID(FW_SLV_TYPE_INV, 0)
+
+typedef struct {
+	uint32_t domain[FW_SGRF_MST_DOMAIN_CON_CNT];
+	uint32_t pmu_domain;
+	uint32_t bus_slv_grp[FW_SGRF_BUS_SLV_CON_CNT];
+	uint32_t top_slv_grp[FW_SGRF_TOP_SLV_CON_CNT];
+	uint32_t center_slv_grp[FW_SGRF_CENTER_SLV_CON_CNT];
+	uint32_t cci_slv_grp[FW_SGRF_CCI_SLV_CON_CNT];
+	uint32_t php_slv_grp[FW_SGRF_PHP_SLV_CON_CNT];
+	uint32_t gpu_slv_grp;
+	uint32_t npu_slv_grp[FW_SGRF_NPU_SLV_CON_CNT];
+	uint32_t pmu_slv_grp[FW_PMU_SGRF_SLV_CON_CNT];
+	uint32_t ddr_rgn[FW_SGRF_DDR_RGN_CNT];
+	uint32_t ddr_size;
+	uint32_t ddr_con;
+	uint32_t sysmem_rgn[FW_SGRF_SYSMEM_RGN_CNT];
+	uint32_t sysmem_con;
+	uint32_t cbuf_rgn[FW_SGRF_CBUF_RGN_CNT];
+	uint32_t cbuf_con;
+	uint32_t ddr_lookup[FW_SGRF_DDR_LOOKUP_CNT];
+	uint32_t sysmem_lookup[FW_SGRF_SYSMEM_LOOKUP_CNT];
+	uint32_t cbuf_lookup[FW_SGRF_CBUF_LOOKUP_CNT];
+	uint32_t slv_lookup[FW_SGRF_SLV_LOOKUP_CNT];
+	uint32_t pmu_slv_lookup[FW_PMU_SGRF_SLV_LOOKUP_CNT];
+} fw_config_t;
+
+static fw_config_t fw_config_buf;
+
+/****************************************************************************
+ * Access rights between domains and groups are as follows:
+ *
+ * 00: NS access,     S access
+ * 01: NS access,     S not access
+ * 10: NS not access, S access
+ * 11: NS not access, S not access
+ * |---------------------------------------------------------|
+ * |                 | d0 | d1 | d2 | d3 | d4 | d5 | d6 | d7 |
+ * |---------------------------------------------------------|
+ * | slave g0        | 00 | 00 | 11 | 11 | 11 | 11 | 11 | 00 |
+ * |---------------------------------------------------------|
+ * | slave g1        | 10 | 11 | 11 | 11 | 11 | 11 | 11 | 10 |
+ * |---------------------------------------------------------|
+ * | slave g2~7      | 11 | 11 | 11 | 11 | 11 | 11 | 11 | 11 |
+ * |---------------------------------------------------------|
+ * | ddr region 0~15 | 10 | 11 | 11 | 11 | 11 | 11 | 11 | 10 |
+ * |---------------------------------------------------------|
+ * | sram region 0~3 | 10 | 11 | 11 | 11 | 11 | 11 | 11 | 10 |
+ * |---------------------------------------------------------|
+ * | cbuf region 0~7 | 10 | 11 | 11 | 11 | 11 | 11 | 11 | 10 |
+ * |---------------------------------------------------------|
+ *
+ * PS:
+ * Domain 0/1/7 NS/S can access group 0.
+ * Domain 0/1/7 NS and Domain1 NS/S can't access group 1, domain 0/7 S can access.
+ * Other domains NS/S can't access all groups.
+ *
+ * Domain 0/7 NS can't access ddr/sram/cbuf region and Domain 0/7 S can access.
+ * Other domains NS/S can't access ddr/sram/cbuf region.
+ *
+ ******************************************************************************/
+
+/* Masters in dm1 */
+static const int dm1_mst[] = {
+	FW_MST_ID(FW_MST_TYPE_SYS, 1), /* keylad_apbm */
+	FW_MST_ID(FW_MST_TYPE_SYS, 2), /* dft2apbm */
+	FW_MST_ID(FW_MST_TYPE_SYS, 11), /* dma2ddr */
+	FW_MST_ID(FW_MST_TYPE_SYS, 12), /* dmac0 */
+	FW_MST_ID(FW_MST_TYPE_SYS, 13), /* dmac1 */
+	FW_MST_ID(FW_MST_TYPE_SYS, 14), /* dmac2 */
+	FW_MST_ID(FW_MST_TYPE_SYS, 19), /* gpu */
+	FW_MST_ID(FW_MST_TYPE_SYS, 31), /* vop_m0 */
+	FW_MST_ID(FW_MST_TYPE_SYS, 32), /* vop_m1 */
+	FW_MST_ID(FW_MST_TYPE_SYS, 36), /* bus_mcu */
+	FW_MST_ID(FW_MST_TYPE_SYS, 38), /* npu_mcu */
+	FW_MST_ID(FW_MST_TYPE_SYS, 56), /* dap_lite */
+
+	FW_INVLID_MST_ID
+};
+
+/* Slaves in group1 */
+static const int sec_slv[] = {
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 28), /* crypto_s */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 29), /* keyladder_s */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 30), /* rkrng_s */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 33), /* jtag_lock */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 34), /* otp_s */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 35), /* otpmsk */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 37), /* scru_s */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 38), /* sys_sgrf */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 39), /* bootrom */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 41), /* wdts */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 44), /* sevice_secure */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 61), /* timers0_ch0~5 */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 62),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 63),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 64),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 65),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 66),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 67), /* timers1_ch0~5 */
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 68),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 69),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 70),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 71),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 72),
+	FW_SLV_ID(FW_SLV_TYPE_TOP, 73), /* sys_fw */
+
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 3),  /* ddr grf */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 4),  /* ddr ctl0 */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 5),  /* ddr ctl1 */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 6),  /* ddr phy0 */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 7),  /* ddr0 cru */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 8),  /* ddr phy1 */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 9),  /* ddr1 cru */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 15), /* ddr wdt */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 19), /* service ddr */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 58), /* ddr timer ch0 */
+	FW_SLV_ID(FW_SLV_TYPE_CENTER, 59), /* ddr timer ch1 */
+
+	FW_SLV_ID(FW_SLV_TYPE_PMU, 1),	/* pmu mem */
+	FW_SLV_ID(FW_SLV_TYPE_PMU, 15), /* pmu1_scru */
+	FW_SLV_ID(FW_SLV_TYPE_PMU, 30), /* osc chk */
+	FW_SLV_ID(FW_SLV_TYPE_PMU, 31), /* pmu0_sgrf */
+	FW_SLV_ID(FW_SLV_TYPE_PMU, 32), /* pmu1_sgrf */
+	FW_SLV_ID(FW_SLV_TYPE_PMU, 34), /* scramble key */
+	FW_SLV_ID(FW_SLV_TYPE_PMU, 36), /* pmu remap */
+	FW_SLV_ID(FW_SLV_TYPE_PMU, 43), /* pmu fw */
+
+	FW_INVLID_SLV_ID
+};
+
+static void fw_buf_sys_mst_dm_cfg(int mst_id, uint32_t dm_id)
+{
+	int sft = (mst_id & 0x7) << 2;
+
+	fw_config_buf.domain[mst_id >> 3] &= ~(0xf << sft);
+	fw_config_buf.domain[mst_id >> 3] |= (dm_id & 0xf) << sft;
+}
+
+static void fw_buf_pmu_mst_dm_cfg(int mst_id, uint32_t dm_id)
+{
+	int sft = (mst_id & 0x7) << 2;
+
+	fw_config_buf.pmu_domain &= ~(0xf << sft);
+	fw_config_buf.pmu_domain |= (dm_id & 0xf) << sft;
+}
+
+void fw_buf_mst_dm_cfg(int mst_id, uint32_t dm_id)
+{
+	int type = FW_GET_TYPE(mst_id);
+
+	mst_id = FW_GET_ID(mst_id);
+
+	switch (type) {
+	case FW_MST_TYPE_SYS:
+		fw_buf_sys_mst_dm_cfg(mst_id, dm_id);
+		break;
+	case FW_MST_TYPE_PMU:
+		fw_buf_pmu_mst_dm_cfg(mst_id, dm_id);
+		break;
+
+	default:
+		ERROR("%s: unknown FW_DOMAIN_TYPE (0x%x)\n", __func__, type);
+		break;
+	}
+}
+
+static void fw_buf_ddr_lookup_cfg(int rgn_id, int dm_id, uint32_t priv)
+{
+	int sft = (dm_id << 1) + (rgn_id & 0x1) * 16;
+
+	fw_config_buf.ddr_lookup[rgn_id >> 1] &= ~(0x3 << sft);
+	fw_config_buf.ddr_lookup[rgn_id >> 1] |= (priv & 0x3) << sft;
+}
+
+static void fw_buf_sysmem_lookup_cfg(int rgn_id, int dm_id, uint32_t priv)
+{
+	int sft = (dm_id << 1) + (rgn_id & 0x1) * 16;
+
+	fw_config_buf.sysmem_lookup[rgn_id >> 1] &= ~(0x3 << sft);
+	fw_config_buf.sysmem_lookup[rgn_id >> 1] |= (priv & 0x3) << sft;
+}
+
+static void fw_buf_cbuf_lookup_cfg(int rgn_id, int dm_id, uint32_t priv)
+{
+	int sft = (dm_id << 1) + (rgn_id & 0x1) * 16;
+
+	fw_config_buf.cbuf_lookup[rgn_id >> 1] &= ~(0x3 << sft);
+	fw_config_buf.cbuf_lookup[rgn_id >> 1] |= (priv & 0x3) << sft;
+}
+
+static void fw_buf_slv_lookup_cfg(int grp_id, int dm_id, uint32_t priv)
+{
+	int sft = (dm_id << 1) + (grp_id & 0x1) * 16;
+
+	fw_config_buf.slv_lookup[grp_id >> 1] &= ~(0x3 << sft);
+	fw_config_buf.slv_lookup[grp_id >> 1] |= (priv & 0x3) << sft;
+}
+
+static void fw_buf_pmu_slv_lookup_cfg(int grp_id, int dm_id, uint32_t priv)
+{
+	int sft = (dm_id << 1) + (grp_id & 0x1) * 16;
+
+	fw_config_buf.pmu_slv_lookup[grp_id >> 1] &= ~(0x3 << sft);
+	fw_config_buf.pmu_slv_lookup[grp_id >> 1] |= (priv & 0x3) << sft;
+}
+
+void fw_buf_grp_lookup_cfg(int grp_id, int dm_id, uint32_t priv)
+{
+	uint32_t type = FW_GET_TYPE(grp_id);
+
+	grp_id = FW_GET_ID(grp_id);
+
+	switch (type) {
+	case FW_GRP_TYPE_DDR_RGN:
+		fw_buf_ddr_lookup_cfg(grp_id, dm_id, priv);
+		break;
+	case FW_GRP_TYPE_SYSMEM_RGN:
+		fw_buf_sysmem_lookup_cfg(grp_id, dm_id, priv);
+		break;
+	case FW_GRP_TYPE_CBUF_RGN:
+		fw_buf_cbuf_lookup_cfg(grp_id, dm_id, priv);
+		break;
+	case FW_GRP_TYPE_SLV:
+		fw_buf_slv_lookup_cfg(grp_id, dm_id, priv);
+		fw_buf_pmu_slv_lookup_cfg(grp_id, dm_id, priv);
+		break;
+
+	default:
+		ERROR("%s: unknown FW_LOOKUP_TYPE (0x%x)\n", __func__, type);
+		break;
+	}
+}
+
+static void fw_buf_bus_slv_grp_cfg(int slv_id, int grp_id)
+{
+	int sft = slv_id % 5 << 2;
+
+	fw_config_buf.bus_slv_grp[slv_id / 5] &= ~(0xf << sft);
+	fw_config_buf.bus_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_top_slv_grp_cfg(int slv_id, int grp_id)
+{
+	int sft = slv_id % 5 << 2;
+
+	fw_config_buf.top_slv_grp[slv_id / 5] &= ~(0xf << sft);
+	fw_config_buf.top_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_center_slv_grp_cfg(int slv_id, int grp_id)
+{
+	int sft = slv_id % 5 << 2;
+
+	fw_config_buf.center_slv_grp[slv_id / 5] &= ~(0xf << sft);
+	fw_config_buf.center_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_cci_slv_grp_cfg(int slv_id, int grp_id)
+{
+	int sft = slv_id % 5 << 2;
+
+	fw_config_buf.cci_slv_grp[slv_id / 5] &= ~(0xf << sft);
+	fw_config_buf.cci_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_php_slv_grp_cfg(int slv_id, int grp_id)
+{
+	int sft = slv_id % 5 << 2;
+
+	fw_config_buf.php_slv_grp[slv_id / 5] &= ~(0xf << sft);
+	fw_config_buf.php_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_gpu_slv_grp_cfg(int slv_id, int grp_id)
+{
+	int sft = slv_id % 5 << 2;
+
+	fw_config_buf.gpu_slv_grp &= ~(0xf << sft);
+	fw_config_buf.gpu_slv_grp |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_npu_slv_grp_cfg(int slv_id, int grp_id)
+{
+	int sft = slv_id % 5 << 2;
+
+	fw_config_buf.npu_slv_grp[slv_id / 5] &= ~(0xf << sft);
+	fw_config_buf.npu_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_pmu_slv_grp_cfg(int slv_id, int grp_id)
+{
+	int sft = slv_id % 5 << 2;
+
+	fw_config_buf.pmu_slv_grp[slv_id / 5] &= ~(0xf << sft);
+	fw_config_buf.pmu_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+void fw_buf_slv_grp_cfg(int slv_id, int grp_id)
+{
+	int type = FW_GET_TYPE(slv_id);
+
+	slv_id = FW_GET_ID(slv_id);
+	grp_id = FW_GET_ID(grp_id);
+
+	switch (type) {
+	case FW_SLV_TYPE_BUS:
+		fw_buf_bus_slv_grp_cfg(slv_id, grp_id);
+		break;
+	case FW_SLV_TYPE_TOP:
+		fw_buf_top_slv_grp_cfg(slv_id, grp_id);
+		break;
+	case FW_SLV_TYPE_CENTER:
+		fw_buf_center_slv_grp_cfg(slv_id, grp_id);
+		break;
+	case FW_SLV_TYPE_CCI:
+		fw_buf_cci_slv_grp_cfg(slv_id, grp_id);
+		break;
+	case FW_SLV_TYPE_PHP:
+		fw_buf_php_slv_grp_cfg(slv_id, grp_id);
+		break;
+	case FW_SLV_TYPE_GPU:
+		fw_buf_gpu_slv_grp_cfg(slv_id, grp_id);
+		break;
+	case FW_SLV_TYPE_NPU:
+		fw_buf_npu_slv_grp_cfg(slv_id, grp_id);
+		break;
+	case FW_SLV_TYPE_PMU:
+		fw_buf_pmu_slv_grp_cfg(slv_id, grp_id);
+		break;
+
+	default:
+		ERROR("%s: unknown FW_SLV_TYPE (0x%x)\n", __func__, type);
+		break;
+	}
+}
+
+void fw_buf_add_msts(const int *mst_ids, int dm_id)
+{
+	int i;
+
+	for (i = 0; FW_GET_TYPE(mst_ids[i]) != FW_INVLID_SLV_ID; i++)
+		fw_buf_mst_dm_cfg(mst_ids[i], dm_id);
+}
+
+void fw_buf_add_slvs(const int *slv_ids, int grp_id)
+{
+	int i;
+
+	for (i = 0; FW_GET_TYPE(slv_ids[i]) != FW_INVLID_SLV_ID; i++)
+		fw_buf_slv_grp_cfg(slv_ids[i], grp_id);
+}
+
+/* unit: Mb */
+void fw_buf_ddr_size_cfg(uint64_t base_mb, uint64_t top_mb, int id)
+{
+	fw_config_buf.ddr_size = RG_MAP_SECURE(top_mb, base_mb);
+	fw_config_buf.ddr_con |= BIT(16);
+}
+
+/* unit: Mb */
+void fw_buf_ddr_rgn_cfg(uint64_t base_mb, uint64_t top_mb, int rgn_id)
+{
+	fw_config_buf.ddr_rgn[rgn_id] = RG_MAP_SECURE(top_mb, base_mb);
+	fw_config_buf.ddr_con |= BIT(rgn_id);
+}
+
+/* Unit: kb */
+void fw_buf_sysmem_rgn_cfg(uint64_t base_kb, uint64_t top_kb, int rgn_id)
+{
+	fw_config_buf.sysmem_rgn[rgn_id] = RG_MAP_SRAM_SECURE(top_kb, base_kb);
+	fw_config_buf.sysmem_con |= BIT(rgn_id);
+}
+
+static void fw_domain_init(void)
+{
+	int i;
+
+	/* select to domain0 by default */
+	for (i = 0; i < FW_SGRF_MST_DOMAIN_CON_CNT; i++)
+		fw_config_buf.domain[i] = 0x0;
+
+	/* select to domain0 by default */
+	fw_config_buf.pmu_domain = 0x0;
+}
+
+static void fw_slv_grp_init(void)
+{
+	int i;
+
+	/* select to group0 by default */
+	for (i = 0; i < FW_SGRF_BUS_SLV_CON_CNT; i++)
+		fw_config_buf.bus_slv_grp[i] = 0x0;
+
+	for (i = 0; i < FW_SGRF_TOP_SLV_CON_CNT; i++)
+		fw_config_buf.top_slv_grp[i] = 0x0;
+
+	for (i = 0; i < FW_SGRF_CENTER_SLV_CON_CNT; i++)
+		fw_config_buf.center_slv_grp[i] = 0x0;
+
+	for (i = 0; i < FW_SGRF_CCI_SLV_CON_CNT; i++)
+		fw_config_buf.cci_slv_grp[i] = 0x0;
+
+	for (i = 0; i < FW_SGRF_PHP_SLV_CON_CNT; i++)
+		fw_config_buf.php_slv_grp[i] = 0x0;
+
+	fw_config_buf.gpu_slv_grp = 0x0;
+
+	for (i = 0; i < FW_SGRF_NPU_SLV_CON_CNT; i++)
+		fw_config_buf.npu_slv_grp[i] = 0x0;
+}
+
+static void fw_region_init(void)
+{
+	/* Use FW_DDR_RGN0_REG to config 1024~1025M space to secure */
+	fw_buf_ddr_rgn_cfg(1024, 1025, 0);
+
+	/* Use FW_SYSMEM_RGN0_REG to config 0~32k space to secure */
+	fw_buf_sysmem_rgn_cfg(0, 32, 0);
+}
+
+static void fw_lookup_init(void)
+{
+	int i;
+
+	/*
+	 * Domain 0/7 NS can't access ddr/sram/cbuf region and Domain 0/7 S can access.
+	 * Other domains NS/S can't access ddr/sram/cbuf region.
+	 */
+	for (i = 0; i < FW_SGRF_DDR_LOOKUP_CNT; i++)
+		fw_config_buf.ddr_lookup[i] = 0xbffebffe;
+
+	for (i = 0; i < FW_SGRF_SYSMEM_LOOKUP_CNT; i++)
+		fw_config_buf.sysmem_lookup[i] = 0xbffebffe;
+
+	for (i = 0; i < FW_SGRF_CBUF_LOOKUP_CNT; i++)
+		fw_config_buf.cbuf_lookup[i] = 0xbffebffe;
+
+	/*
+	 * Domain 0/1/7 NS/S can access group 0.
+	 * Domain 0/1/7 NS and Domain1 NS/S can't access group 1, domain 0/7 S can access.
+	 * Other domains NS/S can't access all groups.
+	 */
+	fw_config_buf.slv_lookup[0] = 0xbffe3ff0;
+	fw_config_buf.slv_lookup[1] = 0xffffffff;
+	fw_config_buf.slv_lookup[2] = 0xffffffff;
+	fw_config_buf.slv_lookup[3] = 0xffffffff;
+
+	/*
+	 * Domain 0/1/7 NS/S can access group 0.
+	 * Domain 0/1/7 NS and Domain1 NS/S can't access group 1, domain 0/7 S can access.
+	 * Other domains NS/S can't access all groups.
+	 */
+	fw_config_buf.pmu_slv_lookup[0] = 0xbffe3ff0;
+	fw_config_buf.pmu_slv_lookup[1] = 0xffffffff;
+	fw_config_buf.pmu_slv_lookup[2] = 0xffffffff;
+	fw_config_buf.pmu_slv_lookup[3] = 0xffffffff;
+}
+
+static void fw_config_buf_flush(void)
+{
+	int i;
+
+	/* domain */
+	for (i = 0; i < FW_SGRF_MST_DOMAIN_CON_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_MST_DOMAIN_CON(i),
+			      fw_config_buf.domain[i]);
+
+	mmio_write_32(PMU1SGRF_FW_BASE + FW_PMU_SGRF_DOMAIN_CON,
+		      fw_config_buf.pmu_domain);
+
+	/* slave group */
+	for (i = 0; i < FW_SGRF_BUS_SLV_CON_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_BUS_SLV_CON(i),
+			      fw_config_buf.bus_slv_grp[i]);
+
+	for (i = 0; i < FW_SGRF_TOP_SLV_CON_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_TOP_SLV_CON(i),
+			      fw_config_buf.top_slv_grp[i]);
+
+	for (i = 0; i < FW_SGRF_CENTER_SLV_CON_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CENTER_SLV_CON(i),
+			      fw_config_buf.center_slv_grp[i]);
+
+	for (i = 0; i < FW_SGRF_CCI_SLV_CON_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CCI_SLV_CON(i),
+			      fw_config_buf.cci_slv_grp[i]);
+
+	for (i = 0; i < FW_SGRF_PHP_SLV_CON_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_PHP_SLV_CON(i),
+			      fw_config_buf.php_slv_grp[i]);
+
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_GPU_SLV_CON,
+		      fw_config_buf.gpu_slv_grp);
+
+	for (i = 0; i < FW_SGRF_NPU_SLV_CON_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_NPU_SLV_CON(i),
+			      fw_config_buf.npu_slv_grp[i]);
+
+	for (i = 0; i < FW_PMU_SGRF_SLV_CON_CNT; i++)
+		mmio_write_32(PMU1SGRF_FW_BASE + FW_PMU_SGRF_SLV_CON(i),
+			      fw_config_buf.pmu_slv_grp[i]);
+
+	/* region */
+	for (i = 0; i < FW_SGRF_DDR_RGN_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_RGN(i),
+			      fw_config_buf.ddr_rgn[i]);
+
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_SIZE, fw_config_buf.ddr_size);
+
+	for (i = 0; i < FW_SGRF_SYSMEM_RGN_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_RGN(i),
+			      fw_config_buf.sysmem_rgn[i]);
+
+	for (i = 0; i < FW_SGRF_CBUF_RGN_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_RGN(i),
+			      fw_config_buf.cbuf_rgn[i]);
+
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_CON, fw_config_buf.ddr_con);
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_CON, fw_config_buf.sysmem_con);
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_CON, fw_config_buf.cbuf_con);
+
+	dsb();
+	isb();
+
+	/* lookup */
+	for (i = 0; i < FW_SGRF_DDR_LOOKUP_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_LOOKUP(i),
+			      fw_config_buf.ddr_lookup[i]);
+
+	for (i = 0; i < FW_SGRF_SYSMEM_LOOKUP_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_LOOKUP(i),
+			      fw_config_buf.sysmem_lookup[i]);
+
+	for (i = 0; i < FW_SGRF_CBUF_LOOKUP_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_LOOKUP(i),
+			      fw_config_buf.cbuf_lookup[i]);
+
+	for (i = 0; i < FW_SGRF_SLV_LOOKUP_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SLV_LOOKUP(i),
+			      fw_config_buf.slv_lookup[i]);
+
+	for (i = 0; i < FW_PMU_SGRF_SLV_LOOKUP_CNT; i++)
+		mmio_write_32(PMU1SGRF_FW_BASE + FW_PMU_SGRF_SLV_LOOKUP(i),
+			      fw_config_buf.pmu_slv_lookup[i]);
+
+	dsb();
+	isb();
+}
+
+static __pmusramfunc void pmusram_udelay(uint32_t us)
+{
+	uint64_t orig;
+	uint64_t to_wait;
+
+	orig = read_cntpct_el0();
+	to_wait = read_cntfrq_el0() * us / 1000000;
+
+	while (read_cntpct_el0() - orig <= to_wait)
+		;
+}
+
+__pmusramfunc void pmusram_fw_update_msk(uint32_t msk)
+{
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_KEYUPD_CON0,
+		      BITS_WITH_WMASK(0, 0x3ff, 0));
+	dsb();
+
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_KEYUPD_CON0,
+		      BITS_WITH_WMASK(msk, msk, 0));
+	dsb();
+	isb();
+	pmusram_udelay(20);
+	dsb();
+	isb();
+}
+
+__pmusramfunc void pmusram_all_fw_bypass(void)
+{
+	int i;
+
+	/* disable regions */
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_CON, 0);
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_CON, 0);
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_CON, 0);
+
+	for (i = 0; i < FW_SGRF_DDR_LOOKUP_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_LOOKUP(i), 0x0);
+
+	for (i = 0; i < FW_SGRF_SYSMEM_LOOKUP_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_LOOKUP(i), 0x0);
+
+	for (i = 0; i < FW_SGRF_CBUF_LOOKUP_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_LOOKUP(i), 0x0);
+
+	for (i = 0; i < FW_SGRF_SLV_LOOKUP_CNT; i++)
+		mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SLV_LOOKUP(i), 0x0);
+
+	for (i = 0; i < FW_PMU_SGRF_SLV_LOOKUP_CNT; i++)
+		mmio_write_32(PMU1SGRF_FW_BASE + FW_PMU_SGRF_SLV_LOOKUP(i), 0x0);
+
+	dsb();
+
+	pmusram_fw_update_msk(0x3ff);
+}
+
+void fw_init(void)
+{
+	/* Enable all fw auto-update */
+	mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_KEYUPD_CON1, 0x03ff03ff);
+
+	pmusram_all_fw_bypass();
+
+	fw_domain_init();
+	fw_slv_grp_init();
+	fw_region_init();
+
+	fw_buf_add_slvs(sec_slv, 1);
+	fw_buf_add_msts(dm1_mst, 1);
+
+	fw_lookup_init();
+
+	fw_config_buf_flush();
+	pmusram_fw_update_msk(0x3ff);
+}