1 /*
2  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3  * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <assert.h>
9 #include <errno.h>
10 #include <stdbool.h>
11 #include <stdint.h>
12 
13 #include <common/debug.h>
14 #include <lib/mmio.h>
15 #include <lib/smccc.h>
16 #include <lib/xlat_tables/xlat_tables_v2.h>
17 #include <services/arm_arch_svc.h>
18 
19 #include <platform_def.h>
20 #include <qti_plat.h>
21 #include <qtiseclib_interface.h>
22 
23 /*
24  * Table of regions for various BL stages to map using the MMU.
25  * This doesn't include TZRAM as the 'mem_layout' argument passed to
26  * qti_configure_mmu_elx() will give the available subset of that,
27  */
28 
29 const mmap_region_t plat_qti_mmap[] = {
30 	MAP_REGION_FLAT(QTI_DEVICE_BASE, QTI_DEVICE_SIZE,
31 			MT_DEVICE | MT_RW | MT_SECURE),
32 	MAP_REGION_FLAT(QTI_AOP_CMD_DB_BASE, QTI_AOP_CMD_DB_SIZE,
33 			MT_NS | MT_RO | MT_EXECUTE_NEVER),
34 	{0}
35 };
36 
37 CASSERT(ARRAY_SIZE(plat_qti_mmap) <= MAX_MMAP_REGIONS, assert_max_mmap_regions);
38 
39 
qti_is_overlap_atf_rg(unsigned long long addr,size_t size)40 bool qti_is_overlap_atf_rg(unsigned long long addr, size_t size)
41 {
42 	if (addr > addr + size
43 			|| (BL31_BASE < addr + size && BL31_LIMIT > addr)) {
44 		return true;
45 	}
46 	return false;
47 }
48 
49 /*
50  *  unsigned int plat_qti_my_cluster_pos(void)
51  *  definition to get the cluster index of the calling CPU.
52  *  - In ARM v8   (MPIDR_EL1[24]=0)
53  *    ClusterId = MPIDR_EL1[15:8]
54  *  - In ARM v8.1 & Later version (MPIDR_EL1[24]=1)
55  *    ClusterId = MPIDR_EL1[23:15]
56  */
plat_qti_my_cluster_pos(void)57 unsigned int plat_qti_my_cluster_pos(void)
58 {
59 	unsigned int mpidr, cluster_id;
60 
61 	mpidr = read_mpidr_el1();
62 	if ((mpidr & MPIDR_MT_MASK) == 0) {	/* MT not supported */
63 		cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
64 	} else {		/* MT supported */
65 		cluster_id = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK;
66 	}
67 	assert(cluster_id < PLAT_CLUSTER_COUNT);
68 	return cluster_id;
69 }
70 
71 /*
72  * Set up the page tables for the generic and platform-specific memory regions.
73  * The extents of the generic memory regions are specified by the function
74  * arguments and consist of:
75  * - Trusted SRAM seen by the BL image;
76  * - Code section;
77  * - Read-only data section;
78  * - Coherent memory region, if applicable.
79  */
qti_setup_page_tables(uintptr_t total_base,size_t total_size,uintptr_t code_start,uintptr_t code_limit,uintptr_t rodata_start,uintptr_t rodata_limit,uintptr_t coh_start,uintptr_t coh_limit)80 void qti_setup_page_tables(uintptr_t total_base,
81 			   size_t total_size,
82 			   uintptr_t code_start,
83 			   uintptr_t code_limit,
84 			   uintptr_t rodata_start,
85 			   uintptr_t rodata_limit,
86 			   uintptr_t coh_start, uintptr_t coh_limit)
87 {
88 	/*
89 	 * Map the Trusted SRAM with appropriate memory attributes.
90 	 * Subsequent mappings will adjust the attributes for specific regions.
91 	 */
92 	VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n",
93 		(void *)total_base, (void *)(total_base + total_size));
94 	mmap_add_region(total_base, total_base,
95 			total_size, MT_MEMORY | MT_RW | MT_SECURE);
96 
97 	/* Re-map the code section */
98 	VERBOSE("Code region: %p - %p\n",
99 		(void *)code_start, (void *)code_limit);
100 	mmap_add_region(code_start, code_start,
101 			code_limit - code_start, MT_CODE | MT_SECURE);
102 
103 	/* Re-map the read-only data section */
104 	VERBOSE("Read-only data region: %p - %p\n",
105 		(void *)rodata_start, (void *)rodata_limit);
106 	mmap_add_region(rodata_start, rodata_start,
107 			rodata_limit - rodata_start, MT_RO_DATA | MT_SECURE);
108 
109 	/* Re-map the coherent memory region */
110 	VERBOSE("Coherent region: %p - %p\n",
111 		(void *)coh_start, (void *)coh_limit);
112 	mmap_add_region(coh_start, coh_start,
113 			coh_limit - coh_start, MT_DEVICE | MT_RW | MT_SECURE);
114 
115 	/* Now (re-)map the platform-specific memory regions */
116 	mmap_add(plat_qti_mmap);
117 
118 	/* Create the page tables to reflect the above mappings */
119 	init_xlat_tables();
120 }
121 
qti_align_mem_region(uintptr_t addr,size_t size,uintptr_t * aligned_addr,size_t * aligned_size)122 static inline void qti_align_mem_region(uintptr_t addr, size_t size,
123 					uintptr_t *aligned_addr,
124 					size_t *aligned_size)
125 {
126 	*aligned_addr = round_down(addr, PAGE_SIZE);
127 	*aligned_size = round_up(addr - *aligned_addr + size, PAGE_SIZE);
128 }
129 
qti_mmap_add_dynamic_region(uintptr_t base_pa,size_t size,unsigned int attr)130 int qti_mmap_add_dynamic_region(uintptr_t base_pa, size_t size,
131 				unsigned int attr)
132 {
133 	uintptr_t aligned_pa;
134 	size_t aligned_size;
135 
136 	qti_align_mem_region(base_pa, size, &aligned_pa, &aligned_size);
137 
138 	if (qti_is_overlap_atf_rg(base_pa, size)) {
139 		/* Memory shouldn't overlap with TF-A range. */
140 		return -EPERM;
141 	}
142 
143 	return mmap_add_dynamic_region(aligned_pa, aligned_pa, aligned_size,
144 				       attr);
145 }
146 
qti_mmap_remove_dynamic_region(uintptr_t base_va,size_t size)147 int qti_mmap_remove_dynamic_region(uintptr_t base_va, size_t size)
148 {
149 	qti_align_mem_region(base_va, size, &base_va, &size);
150 	return mmap_remove_dynamic_region(base_va, size);
151 }
152 
153 /*
154  * This function returns soc version which mainly consist of below fields
155  *
156  * soc_version[30:24] = JEP-106 continuation code for the SiP
157  * soc_version[23:16] = JEP-106 identification code with parity bit for the SiP
158  * soc_version[0:15]  = Implementation defined SoC ID
159  */
plat_get_soc_version(void)160 int32_t plat_get_soc_version(void)
161 {
162 	uint32_t soc_version = (QTI_SOC_VERSION & QTI_SOC_VERSION_MASK);
163 	uint32_t jep106az_code = (JEDEC_QTI_BKID << QTI_SOC_CONTINUATION_SHIFT)
164 			 | (JEDEC_QTI_MFID << QTI_SOC_IDENTIFICATION_SHIFT);
165 	return (int32_t)(jep106az_code | (soc_version));
166 }
167 
168 /*
169  * This function returns soc revision in below format
170  *
171  *   soc_revision[0:30] = SOC revision of specific SOC
172  */
plat_get_soc_revision(void)173 int32_t plat_get_soc_revision(void)
174 {
175 	return mmio_read_32(QTI_SOC_REVISION_REG) & QTI_SOC_REVISION_MASK;
176 }
177 
178 /*****************************************************************************
179  * plat_is_smccc_feature_available() - This function checks whether SMCCC feature
180  *                                  is availabile for the platform or not.
181  * @fid: SMCCC function id
182  *
183  * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
184  * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
185  *****************************************************************************/
plat_is_smccc_feature_available(u_register_t fid)186 int32_t plat_is_smccc_feature_available(u_register_t fid)
187 {
188 	switch (fid) {
189 	case SMCCC_ARCH_SOC_ID:
190 		return SMC_ARCH_CALL_SUCCESS;
191 	default:
192 		return SMC_ARCH_CALL_NOT_SUPPORTED;
193 	}
194 }
195