emi_mpu_common.c 4.2 KB

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