zynqmp_common.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*
  2. * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
  3. * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. */
  7. #include <stdbool.h>
  8. #include <string.h>
  9. #include <common/debug.h>
  10. #include <drivers/generic_delay_timer.h>
  11. #include <lib/mmio.h>
  12. #include <lib/smccc.h>
  13. #include <lib/xlat_tables/xlat_tables_v2.h>
  14. #include <plat/common/platform.h>
  15. #include <plat_arm.h>
  16. #include <services/arm_arch_svc.h>
  17. #include <plat_ipi.h>
  18. #include <plat_private.h>
  19. #include <plat_startup.h>
  20. #include "zynqmp_pm_api_sys.h"
  21. /*
  22. * Table of regions to map using the MMU.
  23. * This doesn't include TZRAM as the 'mem_layout' argument passed to
  24. * configure_mmu_elx() will give the available subset of that,
  25. */
  26. const mmap_region_t plat_zynqmp_mmap[] = {
  27. MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
  28. MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
  29. MAP_REGION_FLAT(CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
  30. {0}
  31. };
  32. const mmap_region_t *plat_get_mmap(void)
  33. {
  34. return plat_zynqmp_mmap;
  35. }
  36. static uint32_t zynqmp_get_silicon_ver(void)
  37. {
  38. static unsigned int ver;
  39. if (!ver) {
  40. ver = mmio_read_32(ZYNQMP_CSU_BASEADDR +
  41. ZYNQMP_CSU_VERSION_OFFSET);
  42. ver &= ZYNQMP_SILICON_VER_MASK;
  43. ver >>= ZYNQMP_SILICON_VER_SHIFT;
  44. }
  45. return ver;
  46. }
  47. uint32_t get_uart_clk(void)
  48. {
  49. unsigned int ver = zynqmp_get_silicon_ver();
  50. if (ver == ZYNQMP_CSU_VERSION_QEMU) {
  51. return 133000000;
  52. } else {
  53. return 100000000;
  54. }
  55. }
  56. #if LOG_LEVEL >= LOG_LEVEL_NOTICE
  57. static const struct {
  58. uint8_t id;
  59. bool evexists;
  60. uint16_t ver;
  61. char *name;
  62. } __packed zynqmp_devices[] = {
  63. {
  64. .id = 0x10,
  65. .name = "XCZU3EG",
  66. },
  67. {
  68. .id = 0x10,
  69. .ver = 0x2c,
  70. .name = "XCZU3CG",
  71. },
  72. {
  73. .id = 0x11,
  74. .name = "XCZU2EG",
  75. },
  76. {
  77. .id = 0x11,
  78. .ver = 0x2c,
  79. .name = "XCZU2CG",
  80. },
  81. {
  82. .id = 0x20,
  83. .name = "XCZU5EV",
  84. .evexists = true,
  85. },
  86. {
  87. .id = 0x20,
  88. .ver = 0x100,
  89. .name = "XCZU5EG",
  90. .evexists = true,
  91. },
  92. {
  93. .id = 0x20,
  94. .ver = 0x12c,
  95. .name = "XCZU5CG",
  96. },
  97. {
  98. .id = 0x21,
  99. .name = "XCZU4EV",
  100. .evexists = true,
  101. },
  102. {
  103. .id = 0x21,
  104. .ver = 0x100,
  105. .name = "XCZU4EG",
  106. .evexists = true,
  107. },
  108. {
  109. .id = 0x21,
  110. .ver = 0x12c,
  111. .name = "XCZU4CG",
  112. },
  113. {
  114. .id = 0x30,
  115. .name = "XCZU7EV",
  116. .evexists = true,
  117. },
  118. {
  119. .id = 0x30,
  120. .ver = 0x100,
  121. .name = "XCZU7EG",
  122. .evexists = true,
  123. },
  124. {
  125. .id = 0x30,
  126. .ver = 0x12c,
  127. .name = "XCZU7CG",
  128. },
  129. {
  130. .id = 0x38,
  131. .name = "XCZU9EG",
  132. },
  133. {
  134. .id = 0x38,
  135. .ver = 0x2c,
  136. .name = "XCZU9CG",
  137. },
  138. {
  139. .id = 0x39,
  140. .name = "XCZU6EG",
  141. },
  142. {
  143. .id = 0x39,
  144. .ver = 0x2c,
  145. .name = "XCZU6CG",
  146. },
  147. {
  148. .id = 0x40,
  149. .name = "XCZU11EG",
  150. },
  151. {
  152. .id = 0x50,
  153. .name = "XCZU15EG",
  154. },
  155. {
  156. .id = 0x58,
  157. .name = "XCZU19EG",
  158. },
  159. {
  160. .id = 0x59,
  161. .name = "XCZU17EG",
  162. },
  163. {
  164. .id = 0x60,
  165. .name = "XCZU28DR",
  166. },
  167. {
  168. .id = 0x61,
  169. .name = "XCZU21DR",
  170. },
  171. {
  172. .id = 0x62,
  173. .name = "XCZU29DR",
  174. },
  175. {
  176. .id = 0x63,
  177. .name = "XCZU23DR",
  178. },
  179. {
  180. .id = 0x64,
  181. .name = "XCZU27DR",
  182. },
  183. {
  184. .id = 0x65,
  185. .name = "XCZU25DR",
  186. },
  187. {
  188. .id = 0x66,
  189. .name = "XCZU39DR",
  190. },
  191. {
  192. .id = 0x7d,
  193. .name = "XCZU43DR",
  194. },
  195. {
  196. .id = 0x78,
  197. .name = "XCZU46DR",
  198. },
  199. {
  200. .id = 0x7f,
  201. .name = "XCZU47DR",
  202. },
  203. {
  204. .id = 0x7b,
  205. .name = "XCZU48DR",
  206. },
  207. {
  208. .id = 0x7e,
  209. .name = "XCZU49DR",
  210. },
  211. };
  212. #define ZYNQMP_PL_STATUS_BIT 9
  213. #define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT)
  214. #define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK)
  215. #define SILICON_ID_XCK24 0x4712093U
  216. #define SILICON_ID_XCK26 0x4724093U
  217. static char *zynqmp_get_silicon_idcode_name(void)
  218. {
  219. uint32_t id, ver, chipid[2];
  220. size_t i, j, len;
  221. const char *name = "EG/EV";
  222. if (pm_get_chipid(chipid) != PM_RET_SUCCESS) {
  223. return "XCZUUNKN";
  224. }
  225. id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
  226. ZYNQMP_CSU_IDCODE_SVD_MASK);
  227. id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
  228. ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT;
  229. for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
  230. if ((zynqmp_devices[i].id == id) &&
  231. (zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK))) {
  232. break;
  233. }
  234. }
  235. if (i >= ARRAY_SIZE(zynqmp_devices)) {
  236. switch (chipid[0]) {
  237. case SILICON_ID_XCK24:
  238. return "XCK24";
  239. case SILICON_ID_XCK26:
  240. return "XCK26";
  241. default:
  242. return "XCZUUNKN";
  243. }
  244. }
  245. if (!zynqmp_devices[i].evexists) {
  246. return zynqmp_devices[i].name;
  247. }
  248. if ((ver & ZYNQMP_PL_STATUS_MASK) != 0U) {
  249. return zynqmp_devices[i].name;
  250. }
  251. len = strlen(zynqmp_devices[i].name) - 2;
  252. for (j = 0; j < strlen(name); j++) {
  253. zynqmp_devices[i].name[len] = name[j];
  254. len++;
  255. }
  256. zynqmp_devices[i].name[len] = '\0';
  257. return zynqmp_devices[i].name;
  258. }
  259. static unsigned int zynqmp_get_rtl_ver(void)
  260. {
  261. uint32_t ver;
  262. ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
  263. ver &= ZYNQMP_RTL_VER_MASK;
  264. ver >>= ZYNQMP_RTL_VER_SHIFT;
  265. return ver;
  266. }
  267. static char *zynqmp_print_silicon_idcode(void)
  268. {
  269. uint32_t id, maskid, tmp;
  270. id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
  271. tmp = id;
  272. tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
  273. ZYNQMP_CSU_IDCODE_FAMILY_MASK;
  274. maskid = (ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT) |
  275. (ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT);
  276. if (tmp != maskid) {
  277. ERROR("Incorrect IDCODE 0x%x, maskid 0x%x\n", id, maskid);
  278. return "UNKN";
  279. }
  280. VERBOSE("IDCODE 0x%x\n", id);
  281. return zynqmp_get_silicon_idcode_name();
  282. }
  283. int32_t plat_is_smccc_feature_available(u_register_t fid)
  284. {
  285. switch (fid) {
  286. case SMCCC_ARCH_SOC_ID:
  287. return SMC_ARCH_CALL_SUCCESS;
  288. default:
  289. return SMC_ARCH_CALL_NOT_SUPPORTED;
  290. }
  291. return SMC_ARCH_CALL_NOT_SUPPORTED;
  292. }
  293. int32_t plat_get_soc_version(void)
  294. {
  295. uint32_t chip_id = zynqmp_get_silicon_ver();
  296. uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_XILINX_BKID, JEDEC_XILINX_MFID);
  297. return (int32_t)(manfid | (chip_id & 0xFFFF));
  298. }
  299. int32_t plat_get_soc_revision(void)
  300. {
  301. return mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
  302. }
  303. static uint32_t zynqmp_get_ps_ver(void)
  304. {
  305. uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
  306. ver &= ZYNQMP_PS_VER_MASK;
  307. ver >>= ZYNQMP_PS_VER_SHIFT;
  308. return ver + 1U;
  309. }
  310. static void zynqmp_print_platform_name(void)
  311. {
  312. uint32_t ver = zynqmp_get_silicon_ver();
  313. uint32_t rtl = zynqmp_get_rtl_ver();
  314. const char *label = "Unknown";
  315. switch (ver) {
  316. case ZYNQMP_CSU_VERSION_QEMU:
  317. label = "QEMU";
  318. break;
  319. case ZYNQMP_CSU_VERSION_SILICON:
  320. label = "silicon";
  321. break;
  322. default:
  323. /* Do nothing in default case */
  324. break;
  325. }
  326. VERBOSE("TF-A running on %s/%s at 0x%x\n",
  327. zynqmp_print_silicon_idcode(), label, BL31_BASE);
  328. VERBOSE("TF-A running on v%d/RTL%d.%d\n",
  329. zynqmp_get_ps_ver(), (rtl & 0xf0) >> 4, rtl & 0xf);
  330. }
  331. #else
  332. static inline void zynqmp_print_platform_name(void) { }
  333. #endif
  334. uint32_t zynqmp_get_bootmode(void)
  335. {
  336. uint32_t r;
  337. unsigned int ret;
  338. ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
  339. if (ret != PM_RET_SUCCESS) {
  340. r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
  341. }
  342. return r & CRL_APB_BOOT_MODE_MASK;
  343. }
  344. void zynqmp_config_setup(void)
  345. {
  346. uint64_t counter_freq;
  347. /* Configure IPI data for ZynqMP */
  348. zynqmp_ipi_config_table_init();
  349. zynqmp_print_platform_name();
  350. /* Configure counter frequency */
  351. counter_freq = read_cntfrq_el0();
  352. if (counter_freq == ZYNQMP_DEFAULT_COUNTER_FREQ) {
  353. write_cntfrq_el0(plat_get_syscnt_freq2());
  354. }
  355. generic_delay_timer_init();
  356. }
  357. uint32_t plat_get_syscnt_freq2(void)
  358. {
  359. uint32_t ver = zynqmp_get_silicon_ver();
  360. if (ver == ZYNQMP_CSU_VERSION_QEMU) {
  361. return 65000000;
  362. } else {
  363. return mmio_read_32(IOU_SCNTRS_BASEFREQ);
  364. }
  365. }