blob: bf777912de0ba75a2a22c66b61b466164c1a91ab [file] [log] [blame]
developer880fb172022-09-05 19:08:59 +08001/*
developer76403b72022-12-06 15:22:33 +08002 * Copyright (c) 2022-2023, ARM Limited and Contributors. All rights reserved.
developer880fb172022-09-05 19:08:59 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <string.h>
8#include <common/debug.h>
9#include <lib/mmio.h>
10#include <emi_mpu.h>
11#include <lib/mtk_init/mtk_init.h>
developer76403b72022-12-06 15:22:33 +080012#include <mtk_sip_svc.h>
developer880fb172022-09-05 19:08:59 +080013
14#if ENABLE_EMI_MPU_SW_LOCK
15static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
16#endif
17
18#define EMI_MPU_START_MASK (0x00FFFFFF)
19#define EMI_MPU_END_MASK (0x00FFFFFF)
20#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF)
21#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF)
22
23static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
24 unsigned int apc)
25{
26 unsigned int dgroup;
27 unsigned int region;
28
29 region = (start >> 24) & 0xFF;
30 start &= EMI_MPU_START_MASK;
31 dgroup = (end >> 24) & 0xFF;
32 end &= EMI_MPU_END_MASK;
33
34 if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
35 WARN("invalid region, domain\n");
36 return -1;
37 }
38
39#if ENABLE_EMI_MPU_SW_LOCK
40 if (region_lock_state[region] == 1) {
41 WARN("invalid region\n");
42 return -1;
43 }
44
45 if ((dgroup == 0) && ((apc >> 31) & 0x1)) {
46 region_lock_state[region] = 1;
47 }
48
49 apc &= EMI_MPU_APC_SW_LOCK_MASK;
50#else
51 apc &= EMI_MPU_APC_HW_LOCK_MASK;
52#endif
53
54 if ((start >= DRAM_OFFSET) && (end >= start)) {
55 start -= DRAM_OFFSET;
56 end -= DRAM_OFFSET;
57 } else {
58 WARN("invalid range\n");
59 return -1;
60 }
61
62 mmio_write_32(EMI_MPU_SA(region), start);
63 mmio_write_32(EMI_MPU_EA(region), end);
64 mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
65
66#if defined(SUB_EMI_MPU_BASE)
67 mmio_write_32(SUB_EMI_MPU_SA(region), start);
68 mmio_write_32(SUB_EMI_MPU_EA(region), end);
69 mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
70#endif
71 return 0;
72}
73
74static void dump_emi_mpu_regions(void)
75{
76 int region, i;
77
78 /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
79 for (region = 0; region < 8; ++region) {
80 INFO("region %d:\n", region);
81 INFO("\tsa: 0x%x, ea: 0x%x\n",
82 mmio_read_32(EMI_MPU_SA(region)), mmio_read_32(EMI_MPU_EA(region)));
83
84 for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) {
85 INFO("\tapc%d: 0x%x\n", i, mmio_read_32(EMI_MPU_APC(region, i)));
86 }
87 }
88}
89
90int emi_mpu_set_protection(struct emi_region_info_t *region_info)
91{
92 unsigned int start, end;
93 int i;
94
95 if (region_info->region >= EMI_MPU_REGION_NUM) {
96 WARN("invalid region\n");
97 return -1;
98 }
99
100 start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
101 (region_info->region << 24);
102
103 for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
104 end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24);
105
106 if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) {
107 WARN("Failed to set emi mpu protection(%d, %d, %d)\n",
108 start, end, region_info->apc[i]);
109 }
110 }
111
112 return 0;
113}
114
developer76403b72022-12-06 15:22:33 +0800115u_register_t mtk_emi_mpu_sip_handler(u_register_t x1, u_register_t x2,
116 u_register_t x3, u_register_t x4,
117 void *handle, struct smccc_res *smccc_ret)
118{
119 /* TODO: implement emi mpu handler */
120
121 return 0;
122}
123DECLARE_SMC_HANDLER(MTK_SIP_TEE_MPU_PERM_SET, mtk_emi_mpu_sip_handler);
124
developer880fb172022-09-05 19:08:59 +0800125int emi_mpu_init(void)
126{
127 INFO("[%s] emi mpu initialization\n", __func__);
128
129 set_emi_mpu_regions();
130 dump_emi_mpu_regions();
131
132 return 0;
133}
134MTK_PLAT_SETUP_0_INIT(emi_mpu_init);