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