blob: 8810be320b348fce22510731edbd672115d439fc [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>
Dawei Chien67611c82023-08-01 18:52:52 +080010#include <smccc_helpers.h>
11
developer880fb172022-09-05 19:08:59 +080012#include <emi_mpu.h>
13#include <lib/mtk_init/mtk_init.h>
developer76403b72022-12-06 15:22:33 +080014#include <mtk_sip_svc.h>
developer880fb172022-09-05 19:08:59 +080015
16#if ENABLE_EMI_MPU_SW_LOCK
17static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
18#endif
19
20#define EMI_MPU_START_MASK (0x00FFFFFF)
21#define EMI_MPU_END_MASK (0x00FFFFFF)
22#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF)
23#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF)
24
25static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
26 unsigned int apc)
27{
28 unsigned int dgroup;
29 unsigned int region;
30
31 region = (start >> 24) & 0xFF;
32 start &= EMI_MPU_START_MASK;
33 dgroup = (end >> 24) & 0xFF;
34 end &= EMI_MPU_END_MASK;
35
36 if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
37 WARN("invalid region, domain\n");
38 return -1;
39 }
40
41#if ENABLE_EMI_MPU_SW_LOCK
42 if (region_lock_state[region] == 1) {
43 WARN("invalid region\n");
44 return -1;
45 }
46
47 if ((dgroup == 0) && ((apc >> 31) & 0x1)) {
48 region_lock_state[region] = 1;
49 }
50
51 apc &= EMI_MPU_APC_SW_LOCK_MASK;
52#else
53 apc &= EMI_MPU_APC_HW_LOCK_MASK;
54#endif
55
56 if ((start >= DRAM_OFFSET) && (end >= start)) {
57 start -= DRAM_OFFSET;
58 end -= DRAM_OFFSET;
59 } else {
60 WARN("invalid range\n");
61 return -1;
62 }
63
64 mmio_write_32(EMI_MPU_SA(region), start);
65 mmio_write_32(EMI_MPU_EA(region), end);
66 mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
67
68#if defined(SUB_EMI_MPU_BASE)
69 mmio_write_32(SUB_EMI_MPU_SA(region), start);
70 mmio_write_32(SUB_EMI_MPU_EA(region), end);
71 mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
72#endif
73 return 0;
74}
75
76static void dump_emi_mpu_regions(void)
77{
78 int region, i;
79
80 /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
81 for (region = 0; region < 8; ++region) {
82 INFO("region %d:\n", region);
83 INFO("\tsa: 0x%x, ea: 0x%x\n",
84 mmio_read_32(EMI_MPU_SA(region)), mmio_read_32(EMI_MPU_EA(region)));
85
86 for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) {
87 INFO("\tapc%d: 0x%x\n", i, mmio_read_32(EMI_MPU_APC(region, i)));
88 }
89 }
90}
91
92int emi_mpu_set_protection(struct emi_region_info_t *region_info)
93{
94 unsigned int start, end;
95 int i;
96
97 if (region_info->region >= EMI_MPU_REGION_NUM) {
98 WARN("invalid region\n");
99 return -1;
100 }
101
102 start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
103 (region_info->region << 24);
104
105 for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
106 end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24);
107
108 if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) {
109 WARN("Failed to set emi mpu protection(%d, %d, %d)\n",
110 start, end, region_info->apc[i]);
111 }
112 }
113
114 return 0;
115}
116
developer76403b72022-12-06 15:22:33 +0800117u_register_t mtk_emi_mpu_sip_handler(u_register_t x1, u_register_t x2,
118 u_register_t x3, u_register_t x4,
119 void *handle, struct smccc_res *smccc_ret)
120{
Dawei Chien0e1c7f02023-09-01 14:35:25 +0800121 return (u_register_t) emi_mpu_optee_handler(x1, x2, x3);
developer76403b72022-12-06 15:22:33 +0800122}
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);