xref: /optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c (revision 5b6c7df764e5e20f9c3dc2dcb97588e562893115)
1bf9dfcc2SAndrew Davis // SPDX-License-Identifier: BSD-2-Clause
2bf9dfcc2SAndrew Davis /*
3bf9dfcc2SAndrew Davis  * Texas Instruments K3 SA2UL Driver
4bf9dfcc2SAndrew Davis  *
5bf9dfcc2SAndrew Davis  * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
6bf9dfcc2SAndrew Davis  *	Andrew Davis <afd@ti.com>
7bf9dfcc2SAndrew Davis  */
8bf9dfcc2SAndrew Davis 
9bf9dfcc2SAndrew Davis #include <drivers/ti_sci.h>
10bf9dfcc2SAndrew Davis #include <initcall.h>
11bf9dfcc2SAndrew Davis #include <io.h>
12bf9dfcc2SAndrew Davis #include <keep.h>
13bf9dfcc2SAndrew Davis #include <kernel/interrupt.h>
14bf9dfcc2SAndrew Davis #include <kernel/misc.h>
15bf9dfcc2SAndrew Davis #include <kernel/spinlock.h>
16bf9dfcc2SAndrew Davis #include <mm/core_memprot.h>
17bf9dfcc2SAndrew Davis #include <mm/core_mmu.h>
18bf9dfcc2SAndrew Davis #include <platform_config.h>
19bf9dfcc2SAndrew Davis #include <rng_support.h>
20bf9dfcc2SAndrew Davis 
21*5b6c7df7ST Pratham #include "eip76d_trng.h"
22bf9dfcc2SAndrew Davis 
23bf9dfcc2SAndrew Davis #define	SA2UL_ES                0x0008
24bf9dfcc2SAndrew Davis #define SA2UL_ES_TRNG           BIT(3)
25bf9dfcc2SAndrew Davis #define	SA2UL_EEC               0x1000
26bf9dfcc2SAndrew Davis #define SA2UL_EEC_TRNG          BIT(3)
27bf9dfcc2SAndrew Davis 
28bf9dfcc2SAndrew Davis #define FW_ENABLE_REGION        0x0a
2915a746d2SAndrew Davis #define FW_BACKGROUND_REGION    BIT(8)
30bf9dfcc2SAndrew Davis #define FW_BIG_ARM_PRIVID       0x01
31e313f476SKamlesh Gurudasani #define FW_TIFS_PRIVID          0xca
32bf9dfcc2SAndrew Davis #define FW_WILDCARD_PRIVID      0xc3
334621ea8bSKamlesh Gurudasani #define FW_SECURE_ONLY          GENMASK_32(7, 0)
344621ea8bSKamlesh Gurudasani #define FW_NON_SECURE           GENMASK_32(15, 0)
35bf9dfcc2SAndrew Davis 
36bf9dfcc2SAndrew Davis register_phys_mem_pgdir(MEM_AREA_IO_SEC, SA2UL_BASE, SA2UL_REG_SIZE);
37bf9dfcc2SAndrew Davis 
sa2ul_init(void)38bf9dfcc2SAndrew Davis static TEE_Result sa2ul_init(void)
39bf9dfcc2SAndrew Davis {
40bf9dfcc2SAndrew Davis 	vaddr_t sa2ul = (vaddr_t)phys_to_virt(SA2UL_BASE, MEM_AREA_IO_SEC,
41bf9dfcc2SAndrew Davis 					      RNG_REG_SIZE);
42bf9dfcc2SAndrew Davis 	uint16_t fwl_id = SA2UL_TI_SCI_FW_ID;
43bf9dfcc2SAndrew Davis 	uint16_t sa2ul_region = SA2UL_TI_SCI_FW_RGN_ID;
44bf9dfcc2SAndrew Davis 	uint16_t rng_region = RNG_TI_SCI_FW_RGN_ID;
45bf9dfcc2SAndrew Davis 	uint8_t owner_index = OPTEE_HOST_ID;
46bf9dfcc2SAndrew Davis 	uint8_t owner_privid = 0;
47bf9dfcc2SAndrew Davis 	uint16_t owner_permission_bits = 0;
48bf9dfcc2SAndrew Davis 	uint32_t control = 0;
49bf9dfcc2SAndrew Davis 	uint32_t permissions[FWL_MAX_PRIVID_SLOTS] = { };
50e313f476SKamlesh Gurudasani 	uint32_t num_perm = 0;
51bf9dfcc2SAndrew Davis 	uint64_t start_address = 0;
52bf9dfcc2SAndrew Davis 	uint64_t end_address = 0;
53bf9dfcc2SAndrew Davis 	uint32_t val = 0;
54bf9dfcc2SAndrew Davis 	TEE_Result result = TEE_SUCCESS;
55bf9dfcc2SAndrew Davis 	int ret = 0;
56bf9dfcc2SAndrew Davis 
57e48bcda2SJayesh Choudhary 	if (SA2UL_TI_SCI_DEV_ID != -1) {
58bf9dfcc2SAndrew Davis 		/* Power on the SA2UL device */
59bf9dfcc2SAndrew Davis 		ret = ti_sci_device_get(SA2UL_TI_SCI_DEV_ID);
60bf9dfcc2SAndrew Davis 		if (ret) {
61bf9dfcc2SAndrew Davis 			EMSG("Failed to get SA2UL device");
62bf9dfcc2SAndrew Davis 			return TEE_ERROR_GENERIC;
63bf9dfcc2SAndrew Davis 		}
64e48bcda2SJayesh Choudhary 	}
65bf9dfcc2SAndrew Davis 
66bf9dfcc2SAndrew Davis 	IMSG("Activated SA2UL device");
67bf9dfcc2SAndrew Davis 
68bf9dfcc2SAndrew Davis 	/* Try to claim the SA2UL firewall for ourselves */
69bf9dfcc2SAndrew Davis 	ret = ti_sci_change_fwl_owner(fwl_id, sa2ul_region, owner_index,
70bf9dfcc2SAndrew Davis 				      &owner_privid, &owner_permission_bits);
71bf9dfcc2SAndrew Davis 	if (ret) {
72bf9dfcc2SAndrew Davis 		/*
73bf9dfcc2SAndrew Davis 		 * This is not fatal, it just means we are on an HS device
74bf9dfcc2SAndrew Davis 		 * where the DMSC already owns the SA2UL. On GP we need
75bf9dfcc2SAndrew Davis 		 * to do additional setup for access permissions below.
76bf9dfcc2SAndrew Davis 		 */
77bf9dfcc2SAndrew Davis 		DMSG("Could not change SA2UL firewall owner");
78bf9dfcc2SAndrew Davis 	} else {
79115198b4SAndrew Davis 		IMSG("Fixing SA2UL firewall owner for GP device");
80bf9dfcc2SAndrew Davis 
81bf9dfcc2SAndrew Davis 		/* Get current SA2UL firewall configuration */
82bf9dfcc2SAndrew Davis 		ret = ti_sci_get_fwl_region(fwl_id, sa2ul_region, 1,
83bf9dfcc2SAndrew Davis 					    &control, permissions,
84bf9dfcc2SAndrew Davis 					    &start_address, &end_address);
85bf9dfcc2SAndrew Davis 		if (ret) {
86bf9dfcc2SAndrew Davis 			EMSG("Could not get firewall region information");
87bf9dfcc2SAndrew Davis 			return TEE_ERROR_GENERIC;
88bf9dfcc2SAndrew Davis 		}
89bf9dfcc2SAndrew Davis 
90bf9dfcc2SAndrew Davis 		/* Modify SA2UL firewall to allow all others access*/
9115a746d2SAndrew Davis 		control = FW_BACKGROUND_REGION | FW_ENABLE_REGION;
92bf9dfcc2SAndrew Davis 		permissions[0] = (FW_WILDCARD_PRIVID << 16) | FW_NON_SECURE;
93bf9dfcc2SAndrew Davis 		ret = ti_sci_set_fwl_region(fwl_id, sa2ul_region, 1,
94bf9dfcc2SAndrew Davis 					    control, permissions,
9515a746d2SAndrew Davis 					    0x0, UINT32_MAX);
96bf9dfcc2SAndrew Davis 		if (ret) {
97bf9dfcc2SAndrew Davis 			EMSG("Could not set firewall region information");
98bf9dfcc2SAndrew Davis 			return TEE_ERROR_GENERIC;
99bf9dfcc2SAndrew Davis 		}
100bf9dfcc2SAndrew Davis 	}
101bf9dfcc2SAndrew Davis 
102bf9dfcc2SAndrew Davis 	/* Claim the TRNG firewall for ourselves */
103bf9dfcc2SAndrew Davis 	ret = ti_sci_change_fwl_owner(fwl_id, rng_region, owner_index,
104bf9dfcc2SAndrew Davis 				      &owner_privid, &owner_permission_bits);
105bf9dfcc2SAndrew Davis 	if (ret) {
106bf9dfcc2SAndrew Davis 		EMSG("Could not change TRNG firewall owner");
107bf9dfcc2SAndrew Davis 		return TEE_ERROR_GENERIC;
108bf9dfcc2SAndrew Davis 	}
109bf9dfcc2SAndrew Davis 
110bf9dfcc2SAndrew Davis 	/* Get current TRNG firewall configuration */
111bf9dfcc2SAndrew Davis 	ret = ti_sci_get_fwl_region(fwl_id, rng_region, 1,
112bf9dfcc2SAndrew Davis 				    &control, permissions,
113bf9dfcc2SAndrew Davis 				    &start_address, &end_address);
114bf9dfcc2SAndrew Davis 	if (ret) {
115bf9dfcc2SAndrew Davis 		EMSG("Could not get firewall region information");
116bf9dfcc2SAndrew Davis 		return TEE_ERROR_GENERIC;
117bf9dfcc2SAndrew Davis 	}
118bf9dfcc2SAndrew Davis 
119bf9dfcc2SAndrew Davis 	/* Modify TRNG firewall to block all others access */
120bf9dfcc2SAndrew Davis 	control = FW_ENABLE_REGION;
1215bf9286dSAndrew Davis 	start_address = RNG_BASE;
1225bf9286dSAndrew Davis 	end_address = RNG_BASE + RNG_REG_SIZE - 1;
123e313f476SKamlesh Gurudasani 	permissions[num_perm++] = (FW_BIG_ARM_PRIVID << 16) | FW_SECURE_ONLY;
12458ad77ffSBryan Brattlof #if defined(PLATFORM_FLAVOR_am62x) || \
12558ad77ffSBryan Brattlof 	defined(PLATFORM_FLAVOR_am62ax) || \
12658ad77ffSBryan Brattlof 	defined(PLATFORM_FLAVOR_am62px)
12758ad77ffSBryan Brattlof 
128e313f476SKamlesh Gurudasani 	permissions[num_perm++] = (FW_TIFS_PRIVID << 16) | FW_NON_SECURE;
129e313f476SKamlesh Gurudasani #endif
130e313f476SKamlesh Gurudasani 	ret = ti_sci_set_fwl_region(fwl_id, rng_region, num_perm,
131bf9dfcc2SAndrew Davis 				    control, permissions,
132bf9dfcc2SAndrew Davis 				    start_address, end_address);
133bf9dfcc2SAndrew Davis 	if (ret) {
134bf9dfcc2SAndrew Davis 		EMSG("Could not set firewall region information");
135bf9dfcc2SAndrew Davis 		return TEE_ERROR_GENERIC;
136bf9dfcc2SAndrew Davis 	}
137bf9dfcc2SAndrew Davis 
138bf9dfcc2SAndrew Davis 	IMSG("Enabled firewalls for SA2UL TRNG device");
139bf9dfcc2SAndrew Davis 
140bf9dfcc2SAndrew Davis 	/* Enable RNG engine in SA2UL if not already enabled */
141bf9dfcc2SAndrew Davis 	val = io_read32(sa2ul + SA2UL_ES);
142bf9dfcc2SAndrew Davis 	if (!(val & SA2UL_ES_TRNG)) {
143bf9dfcc2SAndrew Davis 		IMSG("Enabling SA2UL TRNG engine");
144bf9dfcc2SAndrew Davis 		io_setbits32(sa2ul + SA2UL_EEC, SA2UL_EEC_TRNG);
145bf9dfcc2SAndrew Davis 	}
146bf9dfcc2SAndrew Davis 
147bf9dfcc2SAndrew Davis 	/* Initialize the RNG Module */
148*5b6c7df7ST Pratham 	result = eip76d_rng_init();
149bf9dfcc2SAndrew Davis 	if (result != TEE_SUCCESS)
150bf9dfcc2SAndrew Davis 		return result;
151bf9dfcc2SAndrew Davis 
152bf9dfcc2SAndrew Davis 	IMSG("SA2UL Drivers initialized");
153bf9dfcc2SAndrew Davis 
154bf9dfcc2SAndrew Davis 	return TEE_SUCCESS;
155bf9dfcc2SAndrew Davis }
156b1eb945eSManorit Chawdhry service_init_crypto(sa2ul_init);
157