xref: /rk3399_ARM-atf/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c (revision e1e97947fbbd3e3ad6f260b11444be822db9df63)
11b17e34cSPenny Jan /*
23d4b6f93SAllen-KH Cheng  * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
31b17e34cSPenny Jan  *
41b17e34cSPenny Jan  * SPDX-License-Identifier: BSD-3-Clause
51b17e34cSPenny Jan  */
61b17e34cSPenny Jan 
71b17e34cSPenny Jan #include <string.h>
81b17e34cSPenny Jan #include <common/debug.h>
91b17e34cSPenny Jan #include <lib/mmio.h>
101b17e34cSPenny Jan #include <emi_mpu.h>
111b17e34cSPenny Jan 
121b17e34cSPenny Jan #if ENABLE_EMI_MPU_SW_LOCK
131b17e34cSPenny Jan static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
141b17e34cSPenny Jan #endif
151b17e34cSPenny Jan 
161b17e34cSPenny Jan #define EMI_MPU_START_MASK		(0x00FFFFFF)
171b17e34cSPenny Jan #define EMI_MPU_END_MASK		(0x00FFFFFF)
181b17e34cSPenny Jan #define EMI_MPU_APC_SW_LOCK_MASK	(0x00FFFFFF)
191b17e34cSPenny Jan #define EMI_MPU_APC_HW_LOCK_MASK	(0x80FFFFFF)
201b17e34cSPenny Jan 
_emi_mpu_set_protection(unsigned int start,unsigned int end,unsigned int apc)211b17e34cSPenny Jan static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
221b17e34cSPenny Jan 				   unsigned int apc)
231b17e34cSPenny Jan {
241b17e34cSPenny Jan 	unsigned int dgroup;
251b17e34cSPenny Jan 	unsigned int region;
261b17e34cSPenny Jan 
271b17e34cSPenny Jan 	region = (start >> 24) & 0xFF;
281b17e34cSPenny Jan 	start &= EMI_MPU_START_MASK;
291b17e34cSPenny Jan 	dgroup = (end >> 24) & 0xFF;
301b17e34cSPenny Jan 	end &= EMI_MPU_END_MASK;
311b17e34cSPenny Jan 
321b17e34cSPenny Jan 	if  ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
331b17e34cSPenny Jan 		WARN("invalid region, domain\n");
341b17e34cSPenny Jan 		return -1;
351b17e34cSPenny Jan 	}
361b17e34cSPenny Jan 
371b17e34cSPenny Jan #if ENABLE_EMI_MPU_SW_LOCK
381b17e34cSPenny Jan 	if (region_lock_state[region] == 1) {
391b17e34cSPenny Jan 		WARN("invalid region\n");
401b17e34cSPenny Jan 		return -1;
411b17e34cSPenny Jan 	}
421b17e34cSPenny Jan 
431b17e34cSPenny Jan 	if ((dgroup == 0U) && ((apc >> 31) & 0x1)) {
441b17e34cSPenny Jan 		region_lock_state[region] = 1;
451b17e34cSPenny Jan 	}
461b17e34cSPenny Jan 
471b17e34cSPenny Jan 	apc &= EMI_MPU_APC_SW_LOCK_MASK;
481b17e34cSPenny Jan #else
491b17e34cSPenny Jan 	apc &= EMI_MPU_APC_HW_LOCK_MASK;
501b17e34cSPenny Jan #endif
511b17e34cSPenny Jan 
521b17e34cSPenny Jan 	if ((start >= DRAM_OFFSET) && (end >= start)) {
531b17e34cSPenny Jan 		start -= DRAM_OFFSET;
541b17e34cSPenny Jan 		end -= DRAM_OFFSET;
551b17e34cSPenny Jan 	} else {
561b17e34cSPenny Jan 		WARN("invalid range\n");
571b17e34cSPenny Jan 		return -1;
581b17e34cSPenny Jan 	}
591b17e34cSPenny Jan 
601b17e34cSPenny Jan 	mmio_write_32(EMI_MPU_SA(region), start);
611b17e34cSPenny Jan 	mmio_write_32(EMI_MPU_EA(region), end);
621b17e34cSPenny Jan 	mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
631b17e34cSPenny Jan 
641b17e34cSPenny Jan #if defined(SUB_EMI_MPU_BASE)
651b17e34cSPenny Jan 	mmio_write_32(SUB_EMI_MPU_SA(region), start);
661b17e34cSPenny Jan 	mmio_write_32(SUB_EMI_MPU_EA(region), end);
671b17e34cSPenny Jan 	mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
681b17e34cSPenny Jan #endif
691b17e34cSPenny Jan 	return 0;
701b17e34cSPenny Jan }
711b17e34cSPenny Jan 
emi_mpu_set_protection(struct emi_region_info_t * region_info)721b17e34cSPenny Jan int emi_mpu_set_protection(struct emi_region_info_t *region_info)
731b17e34cSPenny Jan {
741b17e34cSPenny Jan 	unsigned int start, end;
751b17e34cSPenny Jan 	int i;
761b17e34cSPenny Jan 
771b17e34cSPenny Jan 	if (region_info->region >= EMI_MPU_REGION_NUM) {
781b17e34cSPenny Jan 		WARN("invalid region\n");
791b17e34cSPenny Jan 		return -1;
801b17e34cSPenny Jan 	}
811b17e34cSPenny Jan 
821b17e34cSPenny Jan 	start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
831b17e34cSPenny Jan 		(region_info->region << 24);
841b17e34cSPenny Jan 
851b17e34cSPenny Jan 	for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
861b17e34cSPenny Jan 		end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24);
871b17e34cSPenny Jan 
881b17e34cSPenny Jan 		if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) {
891b17e34cSPenny Jan 			WARN("failed to set emi mpu protection(%d, %d, %d)\n",
901b17e34cSPenny Jan 			     start, end, region_info->apc[i]);
911b17e34cSPenny Jan 		}
921b17e34cSPenny Jan 	}
931b17e34cSPenny Jan 
941b17e34cSPenny Jan 	return 0;
951b17e34cSPenny Jan }
961b17e34cSPenny Jan 
emi_mpu_init(void)971b17e34cSPenny Jan void emi_mpu_init(void)
981b17e34cSPenny Jan {
993d4b6f93SAllen-KH Cheng 	struct emi_region_info_t region_info;
1003d4b6f93SAllen-KH Cheng 
1013d4b6f93SAllen-KH Cheng 	/* SCP DRAM */
1023d4b6f93SAllen-KH Cheng 	region_info.start = 0x50000000ULL;
1033d4b6f93SAllen-KH Cheng 	region_info.end = 0x5109FFFFULL;
1043d4b6f93SAllen-KH Cheng 	region_info.region = 2;
1053d4b6f93SAllen-KH Cheng 	SET_ACCESS_PERMISSION(region_info.apc, 1,
1063d4b6f93SAllen-KH Cheng 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
1073d4b6f93SAllen-KH Cheng 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
1088a998b5aSYidi Lin 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION,
1098a998b5aSYidi Lin 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
1103d4b6f93SAllen-KH Cheng 	emi_mpu_set_protection(&region_info);
1113d4b6f93SAllen-KH Cheng 
1123d4b6f93SAllen-KH Cheng 	/* DSP protect address */
1133d4b6f93SAllen-KH Cheng 	region_info.start = 0x60000000ULL;	/* dram base addr */
1143d4b6f93SAllen-KH Cheng 	region_info.end = 0x610FFFFFULL;
1153d4b6f93SAllen-KH Cheng 	region_info.region = 3;
1163d4b6f93SAllen-KH Cheng 	SET_ACCESS_PERMISSION(region_info.apc, 1,
1173d4b6f93SAllen-KH Cheng 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
1183d4b6f93SAllen-KH Cheng 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
119*28a8b738STinghan Shen 			      FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN,
1203d4b6f93SAllen-KH Cheng 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
1213d4b6f93SAllen-KH Cheng 	emi_mpu_set_protection(&region_info);
1223d4b6f93SAllen-KH Cheng 
1233d4b6f93SAllen-KH Cheng 	/* Forbidden All */
1243d4b6f93SAllen-KH Cheng 	region_info.start = 0x40000000ULL;	/* dram base addr */
1253d4b6f93SAllen-KH Cheng 	region_info.end = 0x1FFFF0000ULL;
1263d4b6f93SAllen-KH Cheng 	region_info.region = 4;
1273d4b6f93SAllen-KH Cheng 	SET_ACCESS_PERMISSION(region_info.apc, 1,
1283d4b6f93SAllen-KH Cheng 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
1293d4b6f93SAllen-KH Cheng 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
1303d4b6f93SAllen-KH Cheng 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
1313d4b6f93SAllen-KH Cheng 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
1323d4b6f93SAllen-KH Cheng 	emi_mpu_set_protection(&region_info);
1331b17e34cSPenny Jan }
134