xrdc_core.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /*
  2. * Copyright 2020-2024 NXP
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <stdbool.h>
  9. #include <common/debug.h>
  10. #include <lib/mmio.h>
  11. #include <plat/common/platform.h>
  12. #include <platform_def.h>
  13. #include "xrdc_config.h"
  14. #define XRDC_ADDR 0x292f0000
  15. #define MRC_OFFSET 0x2000
  16. #define MRC_STEP 0x200
  17. #define XRDC_MGR_PAC_ID U(0)
  18. #define XRDC_MGR_PAC_SLOT U(47)
  19. enum xrdc_comp_type {
  20. MDA_TYPE = (1 << 16),
  21. MRC_TYPE = (2 << 16),
  22. PAC_TYPE = (3 << 16),
  23. MSC_TYPE = (4 << 16),
  24. };
  25. enum xrdc_pd_type {
  26. XRDC_AD_PD,
  27. XRDC_HIFI_PD,
  28. XRDC_AV_PD,
  29. };
  30. #define XRDC_TYPE_MASK (0x7 << 16)
  31. #define XRDC_ID_MASK 0xFFFF
  32. #define XRDC_ID(id) ((id) & XRDC_ID_MASK)
  33. typedef bool (*xrdc_check_func)(enum xrdc_comp_type type, uint16_t id);
  34. /* Access below XRDC needs enable PS 8
  35. * and HIFI clocks and release HIFI firstly
  36. */
  37. uint32_t hifi_xrdc_list[] = {
  38. (MDA_TYPE | XRDC_ID(9)),
  39. (MRC_TYPE | XRDC_ID(7)),
  40. (MRC_TYPE | XRDC_ID(9)),
  41. (MRC_TYPE | XRDC_ID(11)),
  42. };
  43. /* Access below XRDC needs enable PS 16 firstly */
  44. uint32_t av_periph_xrdc_list[] = {
  45. (MDA_TYPE | XRDC_ID(10)),
  46. (MDA_TYPE | XRDC_ID(11)),
  47. (MDA_TYPE | XRDC_ID(12)),
  48. (MDA_TYPE | XRDC_ID(13)),
  49. (MDA_TYPE | XRDC_ID(14)),
  50. (MDA_TYPE | XRDC_ID(15)),
  51. (MDA_TYPE | XRDC_ID(16)),
  52. (PAC_TYPE | XRDC_ID(2)),
  53. (MRC_TYPE | XRDC_ID(6)),
  54. (MRC_TYPE | XRDC_ID(8)),
  55. (MRC_TYPE | XRDC_ID(10)),
  56. (MSC_TYPE | XRDC_ID(1)),
  57. (MSC_TYPE | XRDC_ID(2)),
  58. };
  59. uint32_t imx8ulp_pac_slots[] = {
  60. 61, 23, 53
  61. };
  62. uint32_t imx8ulp_msc_slots[] = {
  63. 2, 1, 7
  64. };
  65. static int xrdc_config_mrc_w0_w1(uint32_t mrc_con, uint32_t region, uint32_t w0, uint32_t size)
  66. {
  67. uint32_t w0_addr, w1_addr;
  68. w0_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20;
  69. w1_addr = w0_addr + 4;
  70. if ((size % 32) != 0) {
  71. return -EINVAL;
  72. }
  73. mmio_write_32(w0_addr, w0 & ~0x1f);
  74. mmio_write_32(w1_addr, w0 + size - 1);
  75. return 0;
  76. }
  77. static int xrdc_config_mrc_w2(uint32_t mrc_con, uint32_t region, uint32_t dxsel_all)
  78. {
  79. uint32_t w2_addr;
  80. w2_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20 + 0x8;
  81. mmio_write_32(w2_addr, dxsel_all);
  82. return 0;
  83. }
  84. static int xrdc_config_mrc_w3_w4(uint32_t mrc_con, uint32_t region, uint32_t w3, uint32_t w4)
  85. {
  86. uint32_t w3_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20 + 0xC;
  87. uint32_t w4_addr = w3_addr + 4;
  88. mmio_write_32(w3_addr, w3);
  89. mmio_write_32(w4_addr, w4);
  90. return 0;
  91. }
  92. static int xrdc_config_pac(uint32_t pac, uint32_t index, uint32_t dxacp)
  93. {
  94. uint32_t w0_addr;
  95. uint32_t val;
  96. if (pac > 2U) {
  97. return -EINVAL;
  98. }
  99. /* Skip the PAC slot for XRDC MGR, use Sentinel configuration */
  100. if (pac == XRDC_MGR_PAC_ID && index == XRDC_MGR_PAC_SLOT) {
  101. return 0;
  102. }
  103. w0_addr = XRDC_ADDR + 0x1000 + 0x400 * pac + 0x8 * index;
  104. mmio_write_32(w0_addr, dxacp);
  105. val = mmio_read_32(w0_addr + 4);
  106. mmio_write_32(w0_addr + 4, val | BIT_32(31));
  107. return 0;
  108. }
  109. static int xrdc_config_msc(uint32_t msc, uint32_t index, uint32_t dxacp)
  110. {
  111. uint32_t w0_addr;
  112. uint32_t val;
  113. if (msc > 2) {
  114. return -EINVAL;
  115. }
  116. w0_addr = XRDC_ADDR + 0x4000 + 0x400 * msc + 0x8 * index;
  117. mmio_write_32(w0_addr, dxacp);
  118. val = mmio_read_32(w0_addr + 4);
  119. mmio_write_32(w0_addr + 4, val | BIT_32(31));
  120. return 0;
  121. }
  122. static int xrdc_config_mda(uint32_t mda_con, uint32_t dom, enum xrdc_mda_sa sa)
  123. {
  124. uint32_t w0_addr;
  125. uint32_t val;
  126. w0_addr = XRDC_ADDR + 0x800 + mda_con * 0x20;
  127. val = mmio_read_32(w0_addr);
  128. if (val & BIT_32(29)) {
  129. mmio_write_32(w0_addr, (val & (~0xFF)) | dom |
  130. BIT_32(31) | 0x20 | ((sa & 0x3) << 6));
  131. } else {
  132. mmio_write_32(w0_addr, dom | BIT_32(31));
  133. mmio_write_32(w0_addr + 0x4, dom | BIT_32(31));
  134. }
  135. return 0;
  136. }
  137. static bool xrdc_check_pd(enum xrdc_comp_type type,
  138. uint16_t id, enum xrdc_pd_type pd)
  139. {
  140. unsigned int i, size;
  141. uint32_t item = type | XRDC_ID(id);
  142. uint32_t *list;
  143. if (pd == XRDC_HIFI_PD) {
  144. size = ARRAY_SIZE(hifi_xrdc_list);
  145. list = hifi_xrdc_list;
  146. } else if (pd == XRDC_AV_PD) {
  147. size = ARRAY_SIZE(av_periph_xrdc_list);
  148. list = av_periph_xrdc_list;
  149. } else {
  150. return false;
  151. }
  152. for (i = 0U; i < size; i++) {
  153. if (item == list[i]) {
  154. return true;
  155. }
  156. }
  157. return false;
  158. }
  159. static bool xrdc_check_lpav(enum xrdc_comp_type type, uint16_t id)
  160. {
  161. return xrdc_check_pd(type, id, XRDC_AV_PD);
  162. }
  163. static bool xrdc_check_hifi(enum xrdc_comp_type type, uint16_t id)
  164. {
  165. return xrdc_check_pd(type, id, XRDC_HIFI_PD);
  166. }
  167. static bool xrdc_check_ad(enum xrdc_comp_type type, uint16_t id)
  168. {
  169. return (!xrdc_check_pd(type, id, XRDC_HIFI_PD) &&
  170. !xrdc_check_pd(type, id, XRDC_AV_PD));
  171. }
  172. static int xrdc_apply_config(xrdc_check_func check_func)
  173. {
  174. unsigned int i, j;
  175. uint32_t val;
  176. for (i = 0U; i < ARRAY_SIZE(imx8ulp_mda); i++) {
  177. if (check_func(MDA_TYPE, imx8ulp_mda[i].mda_id)) {
  178. xrdc_config_mda(imx8ulp_mda[i].mda_id,
  179. imx8ulp_mda[i].did, imx8ulp_mda[i].sa);
  180. }
  181. }
  182. for (i = 0U; i < ARRAY_SIZE(imx8ulp_mrc); i++) {
  183. if (check_func(MRC_TYPE, imx8ulp_mrc[i].mrc_id)) {
  184. xrdc_config_mrc_w0_w1(imx8ulp_mrc[i].mrc_id,
  185. imx8ulp_mrc[i].region_id,
  186. imx8ulp_mrc[i].region_start,
  187. imx8ulp_mrc[i].region_size);
  188. val = 0;
  189. for (j = 0U; j < DID_MAX; j++) {
  190. val |= imx8ulp_mrc[i].dsel[j] << (3 * j);
  191. }
  192. xrdc_config_mrc_w2(imx8ulp_mrc[i].mrc_id, imx8ulp_mrc[i].region_id, val);
  193. xrdc_config_mrc_w3_w4(imx8ulp_mrc[i].mrc_id, imx8ulp_mrc[i].region_id,
  194. 0, imx8ulp_mrc[i].accset[0] | (imx8ulp_mrc[i].accset[1] << 16) | BIT_32(31));
  195. }
  196. }
  197. for (i = 0U; i < ARRAY_SIZE(imx8ulp_pdac); i++) {
  198. if (check_func(PAC_TYPE, imx8ulp_pdac[i].pac_msc_id)) {
  199. val = 0;
  200. for (j = 0U; j < DID_MAX; j++) {
  201. val |= imx8ulp_pdac[i].dsel[j] << (3 * j);
  202. }
  203. if (imx8ulp_pdac[i].slot_id == PAC_SLOT_ALL) {
  204. /* Apply to all slots*/
  205. for (j = 0U; j < imx8ulp_pac_slots[imx8ulp_pdac[i].pac_msc_id]; j++) {
  206. xrdc_config_pac(imx8ulp_pdac[i].pac_msc_id, j, val);
  207. }
  208. } else {
  209. if (imx8ulp_pdac[i].slot_id >= imx8ulp_pac_slots[imx8ulp_pdac[i].pac_msc_id]) {
  210. return -EINVAL;
  211. }
  212. xrdc_config_pac(imx8ulp_pdac[i].pac_msc_id, imx8ulp_pdac[i].slot_id, val);
  213. }
  214. }
  215. }
  216. for (i = 0U; i < ARRAY_SIZE(imx8ulp_msc); i++) {
  217. if (check_func(MSC_TYPE, imx8ulp_msc[i].pac_msc_id)) {
  218. val = 0;
  219. for (j = 0U; j < DID_MAX; j++) {
  220. val |= imx8ulp_msc[i].dsel[j] << (3 * j);
  221. }
  222. if (imx8ulp_msc[i].slot_id == MSC_SLOT_ALL) {
  223. /* Apply to all slots*/
  224. for (j = 0U; j < imx8ulp_msc_slots[imx8ulp_msc[i].pac_msc_id]; j++) {
  225. xrdc_config_msc(imx8ulp_msc[i].pac_msc_id, j, val);
  226. }
  227. } else {
  228. if (imx8ulp_msc[i].slot_id >= imx8ulp_msc_slots[imx8ulp_msc[i].pac_msc_id]) {
  229. return -EINVAL;
  230. }
  231. xrdc_config_msc(imx8ulp_msc[i].pac_msc_id, imx8ulp_msc[i].slot_id, val);
  232. }
  233. }
  234. }
  235. return 0;
  236. }
  237. int xrdc_apply_lpav_config(void)
  238. {
  239. /* Configure PAC2 to allow to access PCC5 */
  240. xrdc_config_pac(2, 39, 0xe00000);
  241. /* Enable the eDMA2 MP clock for MDA16 access */
  242. mmio_write_32(IMX_PCC5_BASE + 0x0, 0xc0000000);
  243. return xrdc_apply_config(xrdc_check_lpav);
  244. }
  245. int xrdc_apply_hifi_config(void)
  246. {
  247. return xrdc_apply_config(xrdc_check_hifi);
  248. }
  249. int xrdc_apply_apd_config(void)
  250. {
  251. return xrdc_apply_config(xrdc_check_ad);
  252. }
  253. void xrdc_enable(void)
  254. {
  255. mmio_write_32(XRDC_ADDR, BIT(14) | BIT(15) | BIT(0));
  256. }