From 9a520d63a6b97dceb59aff8a8e659dc3325520ec Mon Sep 17 00:00:00 2001
From: CTCaer <ctcaer@gmail.com>
Date: Wed, 13 Mar 2024 01:54:46 +0200
Subject: [PATCH] bdk: smmu: refactor driver and allow other asid

---
 bdk/mem/mc_t210.h | 29 +++++++++++++++++++------
 bdk/mem/smmu.c    | 47 ++++++++++++++++++++++++++++-------------
 bdk/mem/smmu.h    | 54 ++++++++---------------------------------------
 bdk/memory_map.h  |  4 +++-
 bdk/sec/tsec.c    | 22 +++++++++----------
 bdk/soc/irq.c     |  2 +-
 6 files changed, 79 insertions(+), 79 deletions(-)

diff --git a/bdk/mem/mc_t210.h b/bdk/mem/mc_t210.h
index ed96852..ff96b9d 100644
--- a/bdk/mem/mc_t210.h
+++ b/bdk/mem/mc_t210.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2014, NVIDIA Corporation.
+ * Copyright (c) 2018-2023, CTCaer
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -14,6 +15,22 @@
 #ifndef _MC_T210_H_
 #define _MC_T210_H_
 
+/*! MC SMMU registers */
+#define MC_SMMU_CONFIG               0x10
+#define MC_SMMU_TLB_CONFIG           0x14
+#define MC_SMMU_PTC_CONFIG           0x18
+#define MC_SMMU_PTB_ASID             0x1c
+#define MC_SMMU_PTB_DATA             0x20
+#define MC_SMMU_TLB_FLUSH            0x30
+#define MC_SMMU_PTC_FLUSH            0x34
+#define MC_SMMU_ASID_SECURITY        0x38
+#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
+#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
+#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
+#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
+#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
+
+/*! MC General registers */
 #define MC_INTSTATUS                                            0x0
 #define MC_INTMASK                                              0x4
 #define MC_ERR_STATUS                                           0x8
@@ -464,7 +481,7 @@
 #define MC_UNTRANSLATED_REGION_CHECK                            0x948
 #define MC_DA_CONFIG0                                           0x9dc
 
-/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS0 */
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS0 */
 #define SEC_CARVEOUT_CA0_R_PTCR       BIT(0)
 #define SEC_CARVEOUT_CA0_R_DISPLAY0A  BIT(1)
 #define SEC_CARVEOUT_CA0_R_DISPLAY0AB BIT(2)
@@ -484,7 +501,7 @@
 #define SEC_CARVEOUT_CA0_R_PPCSAHBSLV BIT(30)
 #define SEC_CARVEOUT_CA0_R_SATAR      BIT(31)
 
-/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS1 */
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS1 */
 #define SEC_CARVEOUT_CA1_R_VDEBSEV    BIT(2)
 #define SEC_CARVEOUT_CA1_R_VDEMBE     BIT(3)
 #define SEC_CARVEOUT_CA1_R_VDEMCE     BIT(4)
@@ -504,7 +521,7 @@
 #define SEC_CARVEOUT_CA1_W_VDEBSEV    BIT(30)
 #define SEC_CARVEOUT_CA1_W_VDEDBG     BIT(31)
 
-/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS2 */
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS2 */
 #define SEC_CARVEOUT_CA2_W_VDEMBE    BIT(0)
 #define SEC_CARVEOUT_CA2_W_VDETPM    BIT(1)
 #define SEC_CARVEOUT_CA2_R_ISPRA     BIT(4)
@@ -524,7 +541,7 @@
 #define SEC_CARVEOUT_CA2_W_GPU       BIT(25)
 #define SEC_CARVEOUT_CA2_R_DISPLAYT  BIT(26)
 
-/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS3 */
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS3 */
 #define SEC_CARVEOUT_CA3_R_SDMMCA   BIT(0)
 #define SEC_CARVEOUT_CA3_R_SDMMCAA  BIT(1)
 #define SEC_CARVEOUT_CA3_R_SDMMC    BIT(2)
@@ -544,7 +561,7 @@
 #define SEC_CARVEOUT_CA3_R_NVJPG    BIT(30)
 #define SEC_CARVEOUT_CA3_W_NVJPG    BIT(31)
 
-/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS4 */
+/*! MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS4 */
 #define SEC_CARVEOUT_CA4_R_SE    BIT(0)
 #define SEC_CARVEOUT_CA4_W_SE    BIT(1)
 #define SEC_CARVEOUT_CA4_R_AXIAP BIT(2)
diff --git a/bdk/mem/smmu.c b/bdk/mem/smmu.c
index 048203f..0128103 100644
--- a/bdk/mem/smmu.c
+++ b/bdk/mem/smmu.c
@@ -23,6 +23,23 @@
 #include <soc/t210.h>
 #include <mem/mc_t210.h>
 #include <mem/smmu.h>
+#include <memory_map.h>
+
+#define SMMU_PAGE_SHIFT 12
+#define SMMU_PAGE_SIZE  (1 << SMMU_PAGE_SHIFT)
+#define SMMU_PDIR_COUNT 1024
+#define SMMU_PDIR_SIZE  (sizeof(u32) * SMMU_PDIR_COUNT)
+#define SMMU_PTBL_COUNT 1024
+#define SMMU_PTBL_SIZE  (sizeof(u32) * SMMU_PTBL_COUNT)
+#define SMMU_PDIR_SHIFT 12
+#define SMMU_PDE_SHIFT  12
+#define SMMU_PTE_SHIFT  12
+#define SMMU_PFN_MASK   0x000FFFFF
+#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
+#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
+#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22)
+#define SMMU_MK_PDIR(page, attr) (((page) >> SMMU_PDIR_SHIFT) | (attr))
+#define SMMU_MK_PDE(page, attr)  (((page) >> SMMU_PDE_SHIFT) | (attr))
 
 u8 *_pageheap = (u8 *)SMMU_HEAP_ADDR;
 
@@ -37,7 +54,7 @@ u8 smmu_payload[] __attribute__((aligned(16))) = {
 	0x10, 0x90, 0x01, 0x70, // 0x18: MC_SMMU_CONFIG
 };
 
-void *page_alloc(u32 num)
+void *smmu_page_zalloc(u32 num)
 {
 	u8 *res = _pageheap;
 	_pageheap += SZ_PAGE * num;
@@ -45,15 +62,15 @@ void *page_alloc(u32 num)
 	return res;
 }
 
-u32 *smmu_alloc_pdir()
+static u32 *_smmu_pdir_alloc()
 {
-	u32 *pdir = (u32 *)page_alloc(1);
+	u32 *pdir = (u32 *)smmu_page_zalloc(1);
 	for (int pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++)
 		pdir[pdn] = _PDE_VACANT(pdn);
 	return pdir;
 }
 
-void smmu_flush_regs()
+static void _smmu_flush_regs()
 {
 	(void)MC(MC_SMMU_PTB_DATA);
 }
@@ -61,10 +78,10 @@ void smmu_flush_regs()
 void smmu_flush_all()
 {
 	MC(MC_SMMU_PTC_FLUSH) = 0;
-	smmu_flush_regs();
+	_smmu_flush_regs();
 
 	MC(MC_SMMU_TLB_FLUSH) = 0;
-	smmu_flush_regs();
+	_smmu_flush_regs();
 }
 
 void smmu_init()
@@ -95,14 +112,14 @@ void smmu_enable()
 
 u32 *smmu_init_domain4(u32 dev_base, u32 asid)
 {
-	u32 *pdir = smmu_alloc_pdir();
+	u32 *pdir = _smmu_pdir_alloc();
 
 	MC(MC_SMMU_PTB_ASID) = asid;
 	MC(MC_SMMU_PTB_DATA) = SMMU_MK_PDIR((u32)pdir, _PDIR_ATTR);
-	smmu_flush_regs();
+	_smmu_flush_regs();
 
 	MC(dev_base) = 0x80000000 | (asid << 24) | (asid << 16) | (asid << 8) | (asid);
-	smmu_flush_regs();
+	_smmu_flush_regs();
 
 	return pdir;
 }
@@ -117,7 +134,7 @@ u32 *smmu_get_pte(u32 *pdir, u32 iova)
 		ptbl = (u32 *)((pdir[pdn] & SMMU_PFN_MASK) << SMMU_PDIR_SHIFT);
 	else
 	{
-		ptbl = (u32 *)page_alloc(1);
+		ptbl = (u32 *)smmu_page_zalloc(1);
 		u32 addr = SMMU_PDN_TO_ADDR(pdn);
 		for (int pn = 0; pn < SMMU_PTBL_COUNT; pn++, addr += SMMU_PAGE_SIZE)
 			ptbl[pn] = _PTE_VACANT(addr);
@@ -140,16 +157,16 @@ void smmu_map(u32 *pdir, u32 addr, u32 page, int cnt, u32 attr)
 	smmu_flush_all();
 }
 
-u32 *smmu_init_for_tsec()
+u32 *smmu_init_domain(u32 asid)
 {
-	return smmu_init_domain4(MC_SMMU_TSEC_ASID, 1);
+	return smmu_init_domain4(asid, 1);
 }
 
-void smmu_deinit_for_tsec()
+void smmu_deinit_domain(u32 asid)
 {
 	MC(MC_SMMU_PTB_ASID)  = 1;
 	MC(MC_SMMU_PTB_DATA)  = 0;
-	MC(MC_SMMU_TSEC_ASID) = 0;
-	smmu_flush_regs();
+	MC(asid)              = 0;
+	_smmu_flush_regs();
 }
 
diff --git a/bdk/mem/smmu.h b/bdk/mem/smmu.h
index 80ef66f..c0c765c 100644
--- a/bdk/mem/smmu.h
+++ b/bdk/mem/smmu.h
@@ -17,45 +17,13 @@
 
 #include <utils/types.h>
 
-#define SMMU_HEAP_ADDR 0xA0000000
-
-#define MC_INTSTATUS                 0x0
-#define MC_INTMASK                   0x4
-#define MC_ERR_STATUS                0x8
-#define MC_ERR_ADR                   0xc
-#define MC_SMMU_CONFIG               0x10
-#define MC_SMMU_TLB_CONFIG           0x14
-#define MC_SMMU_PTC_CONFIG           0x18
-#define MC_SMMU_PTB_ASID             0x1c
-#define MC_SMMU_PTB_DATA             0x20
-#define MC_SMMU_TLB_FLUSH            0x30
-#define MC_SMMU_PTC_FLUSH            0x34
-#define MC_SMMU_ASID_SECURITY        0x38
 #define MC_SMMU_AVPC_ASID            0x23C
 #define MC_SMMU_TSEC_ASID            0x294
-#define MC_SMMU_TRANSLATION_ENABLE_0 0x228
-#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c
-#define MC_SMMU_TRANSLATION_ENABLE_2 0x230
-#define MC_SMMU_TRANSLATION_ENABLE_3 0x234
-#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98
 
 #define SMMU_PDE_NEXT_SHIFT 28
 #define MC_SMMU_PTB_DATA_0_ASID_NONSECURE_SHIFT 29
 #define MC_SMMU_PTB_DATA_0_ASID_WRITABLE_SHIFT  30
 #define MC_SMMU_PTB_DATA_0_ASID_READABLE_SHIFT  31
-#define SMMU_PAGE_SHIFT 12
-#define SMMU_PAGE_SIZE  (1 << SMMU_PAGE_SHIFT)
-#define SMMU_PDIR_COUNT 1024
-#define SMMU_PDIR_SIZE  (sizeof(u32) * SMMU_PDIR_COUNT)
-#define SMMU_PTBL_COUNT 1024
-#define SMMU_PTBL_SIZE  (sizeof(u32) * SMMU_PTBL_COUNT)
-#define SMMU_PDIR_SHIFT 12
-#define SMMU_PDE_SHIFT  12
-#define SMMU_PTE_SHIFT  12
-#define SMMU_PFN_MASK   0x000FFFFF
-#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
-#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
-#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22)
 #define _READABLE  (1 << MC_SMMU_PTB_DATA_0_ASID_READABLE_SHIFT)
 #define _WRITABLE  (1 << MC_SMMU_PTB_DATA_0_ASID_WRITABLE_SHIFT)
 #define _NONSECURE (1 << MC_SMMU_PTB_DATA_0_ASID_NONSECURE_SHIFT)
@@ -66,17 +34,13 @@
 #define _PDE_VACANT(pdn) (((pdn) << 10) | _PDE_ATTR)
 #define _PTE_ATTR  (_READABLE | _WRITABLE | _NONSECURE)
 #define _PTE_VACANT(addr) (((addr) >> SMMU_PAGE_SHIFT) | _PTE_ATTR)
-#define SMMU_MK_PDIR(page, attr) (((page) >> SMMU_PDIR_SHIFT) | (attr))
-#define SMMU_MK_PDE(page, attr)  (((page) >> SMMU_PDE_SHIFT) | (attr))
 
-void *page_alloc(u32 num);
-u32 *smmu_alloc_pdir();
-void smmu_flush_regs();
-void smmu_flush_all();
-void smmu_init();
-void smmu_enable();
-u32 *smmu_init_domain4(u32 dev_base, u32 asid);
-u32 *smmu_get_pte(u32 *pdir, u32 iova);
-void smmu_map(u32 *pdir, u32 addr, u32 page, int cnt, u32 attr);
-u32 *smmu_init_for_tsec();
-void smmu_deinit_for_tsec();
+void *smmu_page_zalloc(u32 num);
+void  smmu_flush_all();
+void  smmu_init();
+void  smmu_enable();
+u32  *smmu_init_domain4(u32 dev_base, u32 asid);
+u32  *smmu_get_pte(u32 *pdir, u32 iova);
+void  smmu_map(u32 *pdir, u32 addr, u32 page, int cnt, u32 attr);
+u32  *smmu_init_domain(u32 asid);
+void  smmu_deinit_domain(u32 asid);
diff --git a/bdk/memory_map.h b/bdk/memory_map.h
index e24d924..c687f2c 100644
--- a/bdk/memory_map.h
+++ b/bdk/memory_map.h
@@ -50,7 +50,9 @@
 /* Stack theoretical max: 33MB */
 #define IPL_STACK_TOP  0x83100000
 #define IPL_HEAP_START 0x84000000
-#define  IPL_HEAP_SZ      SZ_512M
+#define  IPL_HEAP_SZ     (SZ_512M - SZ_64M)
+
+#define SMMU_HEAP_ADDR 0xA0000000
 /* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */
 
 // Virtual disk / Chainloader buffers.
diff --git a/bdk/sec/tsec.c b/bdk/sec/tsec.c
index 820a2d3..52f130e 100644
--- a/bdk/sec/tsec.c
+++ b/bdk/sec/tsec.c
@@ -145,20 +145,20 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
 	if (type == TSEC_FW_TYPE_EMU)
 	{
 		// Init SMMU translation for TSEC.
-		pdir = smmu_init_for_tsec();
+		pdir = smmu_init_domain(MC_SMMU_TSEC_ASID);
 		smmu_init();
 
 		// Enable SMMU.
 		smmu_enable();
 
 		// Clock reset controller.
-		car = page_alloc(1);
+		car = smmu_page_zalloc(1);
 		memcpy(car, (void *)CLOCK_BASE, SZ_PAGE);
 		car[CLK_RST_CONTROLLER_CLK_SOURCE_TSEC / 4] = 2;
 		smmu_map(pdir, CLOCK_BASE, (u32)car, 1, _WRITABLE | _READABLE | _NONSECURE);
 
 		// Fuse driver.
-		fuse = page_alloc(1);
+		fuse = smmu_page_zalloc(1);
 		memcpy((void *)&fuse[0x800/4], (void *)FUSE_BASE, SZ_1K);
 		fuse[0x82C / 4] = 0;
 		fuse[0x9E0 / 4] = (1 << (TSEC_HOS_KB_620 + 2)) - 1;
@@ -166,34 +166,34 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
 		smmu_map(pdir, (FUSE_BASE - 0x800), (u32)fuse, 1, _READABLE | _NONSECURE);
 
 		// Power management controller.
-		pmc = page_alloc(1);
+		pmc = smmu_page_zalloc(1);
 		smmu_map(pdir, RTC_BASE, (u32)pmc, 1, _READABLE | _NONSECURE);
 
 		// Flow control.
-		flowctrl = page_alloc(1);
+		flowctrl = smmu_page_zalloc(1);
 		smmu_map(pdir, FLOW_CTLR_BASE, (u32)flowctrl, 1, _WRITABLE | _NONSECURE);
 
 		// Security engine.
-		se = page_alloc(1);
+		se = smmu_page_zalloc(1);
 		memcpy(se, (void *)SE_BASE, SZ_PAGE);
 		smmu_map(pdir, SE_BASE, (u32)se, 1, _READABLE | _WRITABLE | _NONSECURE);
 
 		// Memory controller.
-		mc = page_alloc(1);
+		mc = smmu_page_zalloc(1);
 		memcpy(mc, (void *)MC_BASE, SZ_PAGE);
 		mc[MC_IRAM_BOM / 4] = 0;
 		mc[MC_IRAM_TOM / 4] = DRAM_START;
 		smmu_map(pdir, MC_BASE, (u32)mc, 1, _READABLE | _NONSECURE);
 
 		// IRAM
-		iram = page_alloc(0x30);
+		iram = smmu_page_zalloc(0x30);
 		memcpy(iram, tsec_ctxt->pkg1, 0x30000);
 		// PKG1.1 magic offset.
 		pkg11_magic_off = (u32 *)(iram + ((tsec_ctxt->pkg11_off + 0x20) / 4));
 		smmu_map(pdir, 0x40010000, (u32)iram, 0x30, _READABLE | _WRITABLE | _NONSECURE);
 
 		// Exception vectors
-		evec = page_alloc(1);
+		evec = smmu_page_zalloc(1);
 		smmu_map(pdir, EXCP_VEC_BASE, (u32)evec, 1, _READABLE | _WRITABLE | _NONSECURE);
 	}
 
@@ -229,7 +229,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
 		if (kidx != 8)
 		{
 			res = -6;
-			smmu_deinit_for_tsec();
+			smmu_deinit_domain(MC_SMMU_TSEC_ASID);
 
 			goto out_free;
 		}
@@ -240,7 +240,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt)
 		memcpy(tsec_keys, &key, 0x20);
 		memcpy(tsec_ctxt->pkg1, iram, 0x30000);
 
-		smmu_deinit_for_tsec();
+		smmu_deinit_domain(MC_SMMU_TSEC_ASID);
 
 		// for (int i = 0; i < kidx; i++)
 		// 	gfx_printf("key %08X\n", key[i]);
diff --git a/bdk/soc/irq.c b/bdk/soc/irq.c
index 380cfe1..5ecfb58 100644
--- a/bdk/soc/irq.c
+++ b/bdk/soc/irq.c
@@ -194,7 +194,7 @@ void irq_wait_event(u32 irq)
 	_irq_enable_source(irq);
 
 	// Halt BPMP and wait for the IRQ. No need to use WAIT_EVENT + LIC_IRQ when BPMP serves the IRQ.
-	FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_COP_STOP_UNTIL_IRQ;
+	FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_MODE_STOP_UNTIL_IRQ;
 
 	_irq_disable_source(irq);
 	_irq_ack_source(irq);