apusys_ammu.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * Copyright (c) 2024, MediaTek Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <errno.h>
  7. #include <common/debug.h>
  8. #include <lib/mmio.h>
  9. #include <lib/utils_def.h>
  10. #include "apusys_ammu.h"
  11. #include <apusys_security_ctrl_perm.h>
  12. #include <mtk_mmap_pool.h>
  13. static void apummu_set_segment_offset0(uint32_t vsid_idx, uint8_t seg_idx, uint32_t input_adr,
  14. uint8_t res_bits, uint8_t page_sel, uint8_t page_len)
  15. {
  16. mmio_write_32(APUMMU_VSID_SEGMENT_BASE(vsid_idx, seg_idx, APUMMU_SEG_OFFSET_0),
  17. APUMMU_BUILD_SEGMENT_OFFSET0(input_adr, res_bits, page_sel, page_len));
  18. }
  19. static void apummu_set_segment_offset1(uint32_t vsid_idx, uint8_t seg_idx, uint32_t output_adr,
  20. uint8_t res0, uint8_t iommu_en, uint8_t res1)
  21. {
  22. mmio_write_32(APUMMU_VSID_SEGMENT_BASE(vsid_idx, seg_idx, APUMMU_SEG_OFFSET_1),
  23. APUMMU_BUILD_SEGMENT_OFFSET1(output_adr, res0, iommu_en, res1));
  24. }
  25. static void apummu_set_segment_offset2(uint32_t vsid_idx, uint8_t seg_idx, uint8_t resv,
  26. uint8_t domain, uint8_t acp_en, uint8_t aw_clr,
  27. uint8_t aw_invalid, uint8_t ar_exclu, uint8_t ar_sepcu,
  28. uint8_t aw_cache_allocate, uint8_t aw_slc_en,
  29. uint8_t aw_slb_en, uint8_t ar_cache_allocate,
  30. uint8_t ar_slc_en, uint8_t ar_slb_en, uint8_t ro,
  31. uint8_t ns)
  32. {
  33. mmio_write_32(APUMMU_VSID_SEGMENT_BASE(vsid_idx, seg_idx, APUMMU_SEG_OFFSET_2),
  34. APUMMU_BUILD_SEGMENT_OFFSET2(resv, domain, acp_en, aw_clr, aw_invalid,
  35. ar_exclu, ar_sepcu, aw_cache_allocate,
  36. aw_slc_en, aw_slb_en, ar_cache_allocate,
  37. ar_slc_en, ar_slb_en, ro, ns));
  38. }
  39. static void apummu_vsid_segment_enable_init(uint8_t vsid_idx)
  40. {
  41. mmio_write_32(APUMMU_VSID_SEGMENT_ENABLE(vsid_idx), 0);
  42. }
  43. static void apummu_set_single_segment(uint8_t vsid_idx, uint8_t seg_idx)
  44. {
  45. mmio_setbits_32(APUMMU_VSID_SEGMENT_ENABLE(vsid_idx), BIT(seg_idx));
  46. }
  47. static int apummu_enable_vsid(uint32_t vsid_idx)
  48. {
  49. if (vsid_idx > (APUMMU_VSID_ACTIVE - 1) &&
  50. vsid_idx < (APUMMU_RSV_VSID_IDX_END - APUMMU_VSID_RSV + 1)) {
  51. ERROR("invalid vsid index %d\n", vsid_idx);
  52. return -1;
  53. }
  54. mmio_write_32(APUMMU_VSID_ENABLE_BASE(vsid_idx), BIT(vsid_idx & APUMMU_VSID_EN_MASK));
  55. mmio_write_32(APUMMU_VSID_VALID_BASE(vsid_idx), BIT(vsid_idx & APUMMU_VSID_EN_MASK));
  56. return 0;
  57. }
  58. static void apummu_enable(void)
  59. {
  60. mmio_setbits_32(APUMMU_CMU_TOP_BASE, 0x1);
  61. }
  62. static void apummu_vsid_sram_config(void)
  63. {
  64. uint32_t idx;
  65. uint32_t base = (APUMMU_VSID_SRAM_TOTAL - APUMMU_VSID_RSV);
  66. for (idx = 0; idx < APUMMU_VSID_RSV; idx++) {
  67. mmio_write_32(APUMMU_VSID(APUMMU_RSV_VSID_IDX_START + idx),
  68. APUMMU_VSID_DESC(base + idx));
  69. apummu_vsid_segment_enable_init(base + idx);
  70. }
  71. }
  72. static void apummu_bind_vsid(uint32_t tcu_base, uint32_t vsid_idx, uint8_t cor_id,
  73. uint8_t hw_thread, uint8_t cor_valid, uint8_t vsid_valid)
  74. {
  75. mmio_write_32((tcu_base + hw_thread * VSID_THREAD_SZ),
  76. (((cor_id & VSID_CORID_MASK) << VSID_CORID_OFF) |
  77. ((vsid_idx & VSID_IDX_MASK) << VSID_IDX_OFF) |
  78. ((cor_valid & VSID_VALID_MASK) << VSID_COR_VALID_OFF) |
  79. ((vsid_valid & VSID_VALID_MASK) << VSID_VALID_OFF)));
  80. }
  81. static int apummu_rv_bind_vsid(uint8_t hw_thread)
  82. {
  83. uint8_t cor_id = 0, cor_valid = 0, vsid_valid = 1;
  84. if (hw_thread > APUMMU_HW_THREAD_MAX) {
  85. ERROR("%s: the hw thread id (%d) is not valid for rv/logger\n", __func__,
  86. hw_thread);
  87. return -EINVAL;
  88. }
  89. apummu_bind_vsid(APUMMU_RCX_UPRV_TCU_BASE, APUMMU_UPRV_RSV_VSID, cor_id, hw_thread,
  90. cor_valid, vsid_valid);
  91. return 0;
  92. }
  93. static int apummu_apmcu_bind_vsid(uint8_t hw_thread)
  94. {
  95. uint8_t cor_id = 0, cor_valid = 0, vsid_valid = 1;
  96. if (hw_thread > APUMMU_HW_THREAD_MAX) {
  97. ERROR("%s: the hw thread id (%d) is not valid for apmcu\n", __func__, hw_thread);
  98. return -EINVAL;
  99. }
  100. apummu_bind_vsid(APUMMU_RCX_EXTM_TCU_BASE, APUMMU_APMCU_RSV_VSID, cor_id, hw_thread,
  101. cor_valid, vsid_valid);
  102. return 0;
  103. }
  104. static int apummu_add_map(uint32_t vsid_idx, uint8_t seg_idx, uint64_t input_adr,
  105. uint64_t output_adr, uint8_t page_sel, uint8_t page_len,
  106. uint8_t domain, uint8_t ns)
  107. {
  108. uint8_t smmu_sid;
  109. bool smmu_sec_id;
  110. if (seg_idx > APUMMU_SEG_MAX) {
  111. ERROR("seg_idx is illegal (0x%x)\n", seg_idx);
  112. return -EINVAL;
  113. }
  114. smmu_sec_id = false;
  115. if (ns == 0)
  116. smmu_sid = SMMU_NORMAL_1_4G_SID;
  117. else
  118. smmu_sid = (output_adr > 0xFFFFFFFF) ? SMMU_NORMAL_4_16G_SID
  119. : SMMU_NORMAL_1_4G_SID;
  120. /* fill segment */
  121. apummu_set_segment_offset0(vsid_idx, seg_idx, (input_adr >> APUMMU_ADDR_SHIFT), 0,
  122. page_sel, page_len);
  123. apummu_set_segment_offset1(vsid_idx, seg_idx, (output_adr >> APUMMU_ADDR_SHIFT),
  124. smmu_sid, 0, smmu_sec_id);
  125. apummu_set_segment_offset2(vsid_idx, seg_idx, 0, domain,
  126. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ns);
  127. apummu_set_single_segment(vsid_idx, seg_idx);
  128. return 0;
  129. }
  130. static int apummu_get_dns(enum apusys_dev_type engine_type, enum apusys_sec_level sec_level,
  131. uint8_t *domain, uint8_t *ns)
  132. {
  133. int ret = 0;
  134. if (engine_type != APUSYS_DEVICE_NUM) {
  135. ret = sec_get_dns(engine_type, sec_level, domain, ns);
  136. if (ret)
  137. ERROR("engine:%d, sec: %d\n", engine_type, sec_level);
  138. } else {
  139. *domain = 7;
  140. *ns = 1;
  141. }
  142. return ret;
  143. }
  144. static void apummu_init(void)
  145. {
  146. apummu_vsid_sram_config();
  147. mmio_write_32((APU_VCORE_CONFIG_BASE + APUMMU_SSID_SID_WIDTH_CTRL),
  148. CSR_SMMU_AXMMUSID_WIDTH);
  149. apummu_enable();
  150. }
  151. static void virtual_engine_thread(void)
  152. {
  153. mmio_write_32((APUMMU_RCX_EXTM_TCU_BASE + APUMMU_INT_D2T_TBL0_OFS), APUMMU_THD_ID_TEE);
  154. }
  155. static int apummu_add_apmcu_map(uint32_t seg0_input, uint32_t seg0_output,
  156. enum apummu_page_size page_size)
  157. {
  158. int i, ret;
  159. uint8_t domain, ns, seg;
  160. ret = apummu_get_dns(APUSYS_DEVICE_NUM, SEC_LEVEL_SECURE, &domain, &ns);
  161. if (ret) {
  162. return ret;
  163. }
  164. seg = 0;
  165. ret = apummu_add_map(APUMMU_APMCU_RSV_DESC_IDX, seg, seg0_input, seg0_output, 0,
  166. page_size, domain, ns);
  167. seg += 1;
  168. if (ret)
  169. return ret;
  170. for (i = 0; i < 4; i++) {
  171. ret = apummu_add_map(APUMMU_APMCU_RSV_DESC_IDX, seg,
  172. APUSYS_TCM + (i * APUMMU_1M_SIZE),
  173. APUSYS_TCM + (i * APUMMU_1M_SIZE),
  174. 0, APUMMU_PAGE_LEN_1MB, domain, ns);
  175. seg += 1;
  176. if (ret)
  177. return ret;
  178. }
  179. ret = apummu_enable_vsid(APUMMU_APMCU_RSV_VSID);
  180. return ret;
  181. }
  182. static int apummu_add_rv_boot_map(uint32_t seg0_output, uint32_t seg1_output, uint32_t seg2_output)
  183. {
  184. int ret;
  185. uint8_t domain, ns;
  186. ret = apummu_get_dns(APUSYS_DEVICE_UP, SEC_LEVEL_SECURE, &domain, &ns);
  187. if (ret) {
  188. ERROR("sec get dns fail %d\n", ret);
  189. return ret;
  190. }
  191. /* must be in order */
  192. ret |= apummu_add_map(APUMMU_RSV_VSID_DESC_IDX_END, 0, 0, seg0_output, 0,
  193. APUMMU_PAGE_LEN_1MB, domain, ns);
  194. ret |= apummu_add_map(APUMMU_RSV_VSID_DESC_IDX_END, 1, 0, seg1_output, 0,
  195. APUMMU_PAGE_LEN_512MB, domain, ns);
  196. ret |= apummu_get_dns(APUSYS_DEVICE_UP, SEC_LEVEL_NORMAL, &domain, &ns);
  197. if (ret) {
  198. return ret;
  199. }
  200. ret |= apummu_add_map(APUMMU_RSV_VSID_DESC_IDX_END, 2,
  201. 0, seg2_output, 0, APUMMU_PAGE_LEN_4GB,
  202. domain, ns);
  203. if (ret) {
  204. ERROR("sec add map fail %d\n", ret);
  205. return ret;
  206. }
  207. ret = apummu_enable_vsid(APUMMU_UPRV_RSV_VSID);
  208. return ret;
  209. }
  210. int rv_boot(uint32_t uP_seg_output, uint8_t uP_hw_thread,
  211. enum apummu_page_size logger_page_size,
  212. uint32_t XPU_seg_output, enum apummu_page_size XPU_page_size)
  213. {
  214. int ret = 0;
  215. apummu_init();
  216. ret = apummu_add_rv_boot_map(uP_seg_output, 0, 0);
  217. if (ret) {
  218. return ret;
  219. }
  220. ret = apummu_rv_bind_vsid(uP_hw_thread);
  221. if (ret)
  222. return ret;
  223. ret = apummu_rv_bind_vsid(uP_hw_thread + 1);
  224. if (ret)
  225. return ret;
  226. virtual_engine_thread();
  227. ret = apummu_add_apmcu_map(XPU_seg_output, XPU_seg_output,
  228. XPU_page_size);
  229. if (ret)
  230. return ret;
  231. ret = apummu_apmcu_bind_vsid(APUMMU_THD_ID_TEE);
  232. return ret;
  233. }