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