mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-25 01:58:13 +01:00 
			
		
		
		
	Add initial support for STM32MP2 SoCs family. SoCs information are available here : https://www.st.com/content/st_com/en/campaigns/microprocessor-stm32mp2.html Migrate all MP1 related code into stm32mp1/ directory Create stm32mp2 directory dedicated for STM32MP2 SoCs. Common code to MP1, MP13 and MP25 is kept into arch/arm/mach-stm32/mach-stm32mp directory : - boot_params.c - bsec - cmd_stm32key - cmd_stm32prog - dram_init.c - syscon.c - ecdsa_romapi.c For STM32MP2, it also : - adds memory region description needed for ARMv8 MMU. - enables early data cache before relocation. During the transition before/after relocation, the MMU, initially setup at the beginning of DDR, must be setup again at a correct address after relocation. This is done in enables_caches() by disabling cache, force arch.tlb_fillptr to NULL which will force the MMU to be setup again but with a new value for gd->arch.tlb_addr. gd->arch.tlb_addr has been updated after relocation in arm_reserve_mmu(). Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com> Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
		
			
				
	
	
		
			137 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0+
 | |
| /*
 | |
|  * Simple API for configuring TrustZone memory restrictions for TZC400
 | |
|  */
 | |
| 
 | |
| #define LOG_CATEGORY LOGC_ARCH
 | |
| 
 | |
| #include <linux/iopoll.h>
 | |
| #include <mach/tzc.h>
 | |
| 
 | |
| #define TZC_TIMEOUT_US		100
 | |
| 
 | |
| #define TZC_BUILD_CONFIG	0x00
 | |
| #define TZC_ACTION		0x04
 | |
| #define TZC_ACTION_NONE		0
 | |
| #define TZC_ACTION_ERR		1
 | |
| #define TZC_ACTION_INT		2
 | |
| #define TZC_ACTION_INT_ERR	3
 | |
| #define TZC_GATE_KEEPER		0x08
 | |
| 
 | |
| #define TZC_REGION0_OFFSET	0x100
 | |
| #define TZC_REGION_CFG_SIZE	0x20
 | |
| #define TZC_REGION1_OFFSET	0x120
 | |
| #define TZC_REGION_BASE		0x00
 | |
| #define TZC_REGION_TOP		0x08
 | |
| #define TZC_REGION_ATTRIBUTE	0x10
 | |
| #define TZC_REGION_ACCESS	0x14
 | |
| 
 | |
| static uint32_t tzc_read(uintptr_t tzc, size_t reg)
 | |
| {
 | |
| 	return readl(tzc + reg);
 | |
| }
 | |
| 
 | |
| static void tzc_write(uintptr_t tzc, size_t reg, uint32_t val)
 | |
| {
 | |
| 	writel(val, tzc + reg);
 | |
| }
 | |
| 
 | |
| static uint16_t tzc_config_get_active_filters(const struct tzc_region *cfg)
 | |
| {
 | |
| 	uint16_t active_filters = 0;
 | |
| 
 | |
| 	for ( ; cfg->top != 0; cfg++)
 | |
| 		active_filters |= cfg->filters_mask;
 | |
| 
 | |
| 	return active_filters;
 | |
| }
 | |
| 
 | |
| int tzc_configure(uintptr_t tzc, const struct tzc_region *cfg)
 | |
| {
 | |
| 	uintptr_t region = tzc + TZC_REGION1_OFFSET;
 | |
| 	uint32_t nsid, attr_reg, active_filters;
 | |
| 	int ret;
 | |
| 
 | |
| 	active_filters = tzc_config_get_active_filters(cfg);
 | |
| 	if (active_filters == 0)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	ret = tzc_disable_filters(tzc, active_filters);
 | |
| 	if (ret < 0)
 | |
| 		return ret;
 | |
| 
 | |
| 	for ( ; cfg->top != 0; cfg++, region += TZC_REGION_CFG_SIZE) {
 | |
| 		attr_reg = (cfg->sec_mode & 0x03) << 30;
 | |
| 		attr_reg |= (cfg->filters_mask & 0x03) << 0;
 | |
| 		nsid = cfg->nsec_id & 0xffff;
 | |
| 		nsid |= nsid << 16;
 | |
| 
 | |
| 		tzc_write(region, TZC_REGION_BASE, cfg->base);
 | |
| 		tzc_write(region, TZC_REGION_TOP, cfg->top);
 | |
| 		tzc_write(region, TZC_REGION_ACCESS, nsid);
 | |
| 		tzc_write(region, TZC_REGION_ATTRIBUTE, attr_reg);
 | |
| 	}
 | |
| 
 | |
| 	tzc_write(tzc, TZC_ACTION, TZC_ACTION_ERR);
 | |
| 	return tzc_enable_filters(tzc, active_filters);
 | |
| }
 | |
| 
 | |
| int tzc_disable_filters(uintptr_t tzc, uint16_t filters_mask)
 | |
| {
 | |
| 	uint32_t gate = tzc_read(tzc, TZC_GATE_KEEPER);
 | |
| 	uint32_t filter_status = filters_mask << 16;
 | |
| 
 | |
| 	gate &= ~filters_mask;
 | |
| 	tzc_write(tzc, TZC_GATE_KEEPER, gate);
 | |
| 
 | |
| 	return readl_poll_timeout(tzc + TZC_GATE_KEEPER, gate,
 | |
| 				 (gate & filter_status) == 0, TZC_TIMEOUT_US);
 | |
| }
 | |
| 
 | |
| int tzc_enable_filters(uintptr_t tzc, uint16_t filters_mask)
 | |
| {
 | |
| 	uint32_t gate = tzc_read(tzc, TZC_GATE_KEEPER);
 | |
| 	uint32_t filter_status = filters_mask << 16;
 | |
| 
 | |
| 	gate |= filters_mask;
 | |
| 	tzc_write(tzc, TZC_GATE_KEEPER, gate);
 | |
| 
 | |
| 	return readl_poll_timeout(tzc + TZC_GATE_KEEPER, gate,
 | |
| 				 (gate & filter_status) == filter_status,
 | |
| 				 TZC_TIMEOUT_US);
 | |
| }
 | |
| 
 | |
| static const char *sec_access_str_from_attr(uint32_t attr)
 | |
| {
 | |
| 	const char *const sec_mode[] = { "none", "RO  ", "WO  ", "RW  " };
 | |
| 
 | |
| 	return sec_mode[(attr >> 30) & 0x03];
 | |
| }
 | |
| 
 | |
| void tzc_dump_config(uintptr_t tzc)
 | |
| {
 | |
| 	uint32_t build_config, base, top, attr, nsaid;
 | |
| 	int num_regions, i;
 | |
| 	uintptr_t region;
 | |
| 
 | |
| 	build_config = tzc_read(tzc, TZC_BUILD_CONFIG);
 | |
| 	num_regions = ((build_config >> 0) & 0x1f) + 1;
 | |
| 
 | |
| 	for (i = 0; i < num_regions; i++) {
 | |
| 		region = tzc + TZC_REGION0_OFFSET + i * TZC_REGION_CFG_SIZE;
 | |
| 
 | |
| 		base = tzc_read(region, TZC_REGION_BASE);
 | |
| 		top = tzc_read(region, TZC_REGION_TOP);
 | |
| 		attr = tzc_read(region, TZC_REGION_ATTRIBUTE);
 | |
| 		nsaid = tzc_read(region, TZC_REGION_ACCESS);
 | |
| 
 | |
| 		if (attr == 0 && nsaid == 0)
 | |
| 			continue;
 | |
| 
 | |
| 		log_info("TZC region %u: %08x->%08x - filters 0x%x\n",
 | |
| 			 i, base, top, (attr >> 0) & 0xf);
 | |
| 		log_info("\t Secure access %s NSAID %08x\n",
 | |
| 			 sec_access_str_from_attr(attr), nsaid);
 | |
| 	}
 | |
| }
 |