xref: /optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c (revision bf9dfcc22a3c26edaba666d63cfaec0c3d1c5655)
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 "sa2ul.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_BIG_ARM_PRIVID       0x01
30 #define FW_WILDCARD_PRIVID      0xc3
31 #define FW_SECURE_ONLY          GENMASK_32(8, 0)
32 #define FW_NON_SECURE           GENMASK_32(16, 0)
33 
34 register_phys_mem_pgdir(MEM_AREA_IO_SEC, SA2UL_BASE, SA2UL_REG_SIZE);
35 
36 static TEE_Result sa2ul_init(void)
37 {
38 	vaddr_t sa2ul = (vaddr_t)phys_to_virt(SA2UL_BASE, MEM_AREA_IO_SEC,
39 					      RNG_REG_SIZE);
40 	uint16_t fwl_id = SA2UL_TI_SCI_FW_ID;
41 	uint16_t sa2ul_region = SA2UL_TI_SCI_FW_RGN_ID;
42 	uint16_t rng_region = RNG_TI_SCI_FW_RGN_ID;
43 	uint8_t owner_index = OPTEE_HOST_ID;
44 	uint8_t owner_privid = 0;
45 	uint16_t owner_permission_bits = 0;
46 	uint32_t control = 0;
47 	uint32_t permissions[FWL_MAX_PRIVID_SLOTS] = { };
48 	uint64_t start_address = 0;
49 	uint64_t end_address = 0;
50 	uint32_t val = 0;
51 	TEE_Result result = TEE_SUCCESS;
52 	int ret = 0;
53 
54 	/* Power on the SA2UL device */
55 	ret = ti_sci_device_get(SA2UL_TI_SCI_DEV_ID);
56 	if (ret) {
57 		EMSG("Failed to get SA2UL device");
58 		return TEE_ERROR_GENERIC;
59 	}
60 
61 	IMSG("Activated SA2UL device");
62 
63 	/* Try to claim the SA2UL firewall for ourselves */
64 	ret = ti_sci_change_fwl_owner(fwl_id, sa2ul_region, owner_index,
65 				      &owner_privid, &owner_permission_bits);
66 	if (ret) {
67 		/*
68 		 * This is not fatal, it just means we are on an HS device
69 		 * where the DMSC already owns the SA2UL. On GP we need
70 		 * to do additional setup for access permissions below.
71 		 */
72 		DMSG("Could not change SA2UL firewall owner");
73 	} else {
74 		DMSG("Fixing SA2UL firewall owner for GP device");
75 
76 		/* Get current SA2UL firewall configuration */
77 		ret = ti_sci_get_fwl_region(fwl_id, sa2ul_region, 1,
78 					    &control, permissions,
79 					    &start_address, &end_address);
80 		if (ret) {
81 			EMSG("Could not get firewall region information");
82 			return TEE_ERROR_GENERIC;
83 		}
84 
85 		/* Modify SA2UL firewall to allow all others access*/
86 		control = FW_ENABLE_REGION;
87 		permissions[0] = (FW_WILDCARD_PRIVID << 16) | FW_NON_SECURE;
88 		ret = ti_sci_set_fwl_region(fwl_id, sa2ul_region, 1,
89 					    control, permissions,
90 					    start_address, end_address);
91 		if (ret) {
92 			EMSG("Could not set firewall region information");
93 			return TEE_ERROR_GENERIC;
94 		}
95 	}
96 
97 	/* Claim the TRNG firewall for ourselves */
98 	ret = ti_sci_change_fwl_owner(fwl_id, rng_region, owner_index,
99 				      &owner_privid, &owner_permission_bits);
100 	if (ret) {
101 		EMSG("Could not change TRNG firewall owner");
102 		return TEE_ERROR_GENERIC;
103 	}
104 
105 	/* Get current TRNG firewall configuration */
106 	ret = ti_sci_get_fwl_region(fwl_id, rng_region, 1,
107 				    &control, permissions,
108 				    &start_address, &end_address);
109 	if (ret) {
110 		EMSG("Could not get firewall region information");
111 		return TEE_ERROR_GENERIC;
112 	}
113 
114 	/* Modify TRNG firewall to block all others access */
115 	control = FW_ENABLE_REGION;
116 	permissions[0] = (FW_BIG_ARM_PRIVID << 16) | FW_SECURE_ONLY;
117 	ret = ti_sci_set_fwl_region(fwl_id, rng_region, 1,
118 				    control, permissions,
119 				    start_address, end_address);
120 	if (ret) {
121 		EMSG("Could not set firewall region information");
122 		return TEE_ERROR_GENERIC;
123 	}
124 
125 	IMSG("Enabled firewalls for SA2UL TRNG device");
126 
127 	/* Enable RNG engine in SA2UL if not already enabled */
128 	val = io_read32(sa2ul + SA2UL_ES);
129 	if (!(val & SA2UL_ES_TRNG)) {
130 		IMSG("Enabling SA2UL TRNG engine");
131 		io_setbits32(sa2ul + SA2UL_EEC, SA2UL_EEC_TRNG);
132 	}
133 
134 	/* Initialize the RNG Module */
135 	result = sa2ul_rng_init();
136 	if (result != TEE_SUCCESS)
137 		return result;
138 
139 	IMSG("SA2UL Drivers initialized");
140 
141 	return TEE_SUCCESS;
142 }
143 driver_init(sa2ul_init);
144