mss_scp_bootloader.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. * Copyright (C) 2018 Marvell International Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. * https://spdx.org/licenses
  6. */
  7. #include <assert.h>
  8. #include <platform_def.h>
  9. #include <arch_helpers.h>
  10. #include <common/debug.h>
  11. #include <drivers/delay_timer.h>
  12. #include <mg_conf_cm3/mg_conf_cm3.h>
  13. #include <lib/mmio.h>
  14. #include <plat_pm_trace.h>
  15. #include <mss_scp_bootloader.h>
  16. #include <mss_ipc_drv.h>
  17. #include <mss_mem.h>
  18. #include <mss_defs.h>
  19. #include <mss_scp_bl2_format.h>
  20. #define MSS_DMA_TIMEOUT 1000
  21. #define MSS_EXTERNAL_SPACE 0x50000000
  22. #define MSS_EXTERNAL_ADDR_MASK 0xfffffff
  23. #define MSS_INTERNAL_SPACE 0x40000000
  24. #define MSS_INTERNAL_ADDR_MASK 0x00ffffff
  25. #define DMA_SIZE 128
  26. #define MSS_HANDSHAKE_TIMEOUT 50
  27. static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
  28. {
  29. int timeout = MSS_HANDSHAKE_TIMEOUT;
  30. /* Wait for SCP to signal it's ready */
  31. while ((mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT) &&
  32. (timeout-- > 0))
  33. mdelay(1);
  34. if (mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT)
  35. return -1;
  36. mss_pm_crtl->handshake = HOST_ACKNOWLEDGMENT;
  37. return 0;
  38. }
  39. static int mss_iram_dma_load(uint32_t src_addr, uint32_t size,
  40. uintptr_t mss_regs)
  41. {
  42. uint32_t i, loop_num, timeout;
  43. /* load image to MSS RAM using DMA */
  44. loop_num = (size / DMA_SIZE) + !!(size % DMA_SIZE);
  45. for (i = 0; i < loop_num; i++) {
  46. /* write source address */
  47. mmio_write_32(MSS_DMA_SRCBR(mss_regs),
  48. src_addr + (i * DMA_SIZE));
  49. /* write destination address */
  50. mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
  51. /* make sure DMA data is ready before triggering it */
  52. dsb();
  53. /* set the DMA control register */
  54. mmio_write_32(MSS_DMA_CTRLR(mss_regs),
  55. ((MSS_DMA_CTRLR_REQ_SET <<
  56. MSS_DMA_CTRLR_REQ_OFFSET) |
  57. (DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET)));
  58. /* Poll DMA_ACK at MSS_DMACTLR until it is ready */
  59. timeout = MSS_DMA_TIMEOUT;
  60. while (timeout > 0U) {
  61. if (((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >>
  62. MSS_DMA_CTRLR_ACK_OFFSET) &
  63. MSS_DMA_CTRLR_ACK_MASK)
  64. == MSS_DMA_CTRLR_ACK_READY) {
  65. break;
  66. }
  67. udelay(50);
  68. timeout--;
  69. }
  70. if (timeout == 0) {
  71. ERROR("\nMSS DMA failed (timeout)\n");
  72. return 1;
  73. }
  74. }
  75. return 0;
  76. }
  77. static int mss_image_load(uint32_t src_addr, uint32_t size,
  78. uintptr_t mss_regs, uintptr_t sram)
  79. {
  80. uint32_t chunks = 1; /* !sram case */
  81. uint32_t chunk_num;
  82. int ret;
  83. /* Check if the img size is not bigger than ID-RAM size of MSS CM3 */
  84. if (size > MSS_IDRAM_SIZE) {
  85. ERROR("image is too big to fit into MSS CM3 memory\n");
  86. return 1;
  87. }
  88. /* The CPx MSS DMA cannot access DRAM directly in secure boot mode
  89. * Copy the MSS FW image to MSS SRAM by the CPU first, then run
  90. * MSS DMA for SRAM to IRAM copy
  91. */
  92. if (sram != 0) {
  93. chunks = size / MSS_SRAM_SIZE + !!(size % MSS_SRAM_SIZE);
  94. }
  95. NOTICE("%s Loading MSS FW from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
  96. sram == 0 ? "" : "SECURELY", src_addr, size, mss_regs);
  97. for (chunk_num = 0; chunk_num < chunks; chunk_num++) {
  98. size_t chunk_size = size;
  99. uint32_t img_src = MSS_EXTERNAL_SPACE | /* no SRAM */
  100. (src_addr & MSS_EXTERNAL_ADDR_MASK);
  101. if (sram != 0) {
  102. uintptr_t chunk_source =
  103. src_addr + MSS_SRAM_SIZE * chunk_num;
  104. if (chunk_num != (size / MSS_SRAM_SIZE)) {
  105. chunk_size = MSS_SRAM_SIZE;
  106. } else {
  107. chunk_size = size % MSS_SRAM_SIZE;
  108. }
  109. if (chunk_size == 0) {
  110. break;
  111. }
  112. VERBOSE("Chunk %d -> SRAM 0x%lx from 0x%lx SZ 0x%lx\n",
  113. chunk_num, sram, chunk_source, chunk_size);
  114. memcpy((void *)sram, (void *)chunk_source, chunk_size);
  115. dsb();
  116. img_src = MSS_INTERNAL_SPACE |
  117. (sram & MSS_INTERNAL_ADDR_MASK);
  118. }
  119. ret = mss_iram_dma_load(img_src, chunk_size, mss_regs);
  120. if (ret != 0) {
  121. ERROR("MSS FW chunk %d load failed\n", chunk_num);
  122. return ret;
  123. }
  124. }
  125. bl2_plat_configure_mss_windows(mss_regs);
  126. if (sram != 0) {
  127. /* Wipe the MSS SRAM after using it as copy buffer */
  128. memset((void *)sram, 0, MSS_SRAM_SIZE);
  129. NOTICE("CP MSS startup is postponed\n");
  130. /* FW loaded, but CPU startup postponed until final CP setup */
  131. mmio_write_32(sram, MSS_FW_READY_MAGIC);
  132. dsb();
  133. } else {
  134. /* Release M3 from reset */
  135. mmio_write_32(MSS_M3_RSTCR(mss_regs),
  136. (MSS_M3_RSTCR_RST_OFF <<
  137. MSS_M3_RSTCR_RST_OFFSET));
  138. }
  139. NOTICE("Done\n");
  140. return 0;
  141. }
  142. /* Load image to MSS AP and do PM related initialization
  143. * Note that this routine is different than other CM3 loading routines, because
  144. * firmware for AP is dedicated for PM and therefore some additional PM
  145. * initialization is required
  146. */
  147. static int mss_ap_load_image(uintptr_t single_img,
  148. uint32_t image_size, uint32_t ap_idx)
  149. {
  150. volatile struct mss_pm_ctrl_block *mss_pm_crtl;
  151. int ret;
  152. /* TODO: add PM Control Info from platform */
  153. mss_pm_crtl = (struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE;
  154. mss_pm_crtl->ipc_version = MV_PM_FW_IPC_VERSION;
  155. mss_pm_crtl->num_of_clusters = PLAT_MARVELL_CLUSTER_COUNT;
  156. mss_pm_crtl->num_of_cores_per_cluster =
  157. PLAT_MARVELL_CLUSTER_CORE_COUNT;
  158. mss_pm_crtl->num_of_cores = PLAT_MARVELL_CLUSTER_COUNT *
  159. PLAT_MARVELL_CLUSTER_CORE_COUNT;
  160. mss_pm_crtl->pm_trace_ctrl_base_address = AP_MSS_ATF_CORE_CTRL_BASE;
  161. mss_pm_crtl->pm_trace_info_base_address = AP_MSS_ATF_CORE_INFO_BASE;
  162. mss_pm_crtl->pm_trace_info_core_size = AP_MSS_ATF_CORE_INFO_SIZE;
  163. VERBOSE("MSS Control Block = 0x%x\n", MSS_SRAM_PM_CONTROL_BASE);
  164. VERBOSE("mss_pm_crtl->ipc_version = 0x%x\n",
  165. mss_pm_crtl->ipc_version);
  166. VERBOSE("mss_pm_crtl->num_of_cores = 0x%x\n",
  167. mss_pm_crtl->num_of_cores);
  168. VERBOSE("mss_pm_crtl->num_of_clusters = 0x%x\n",
  169. mss_pm_crtl->num_of_clusters);
  170. VERBOSE("mss_pm_crtl->num_of_cores_per_cluster = 0x%x\n",
  171. mss_pm_crtl->num_of_cores_per_cluster);
  172. VERBOSE("mss_pm_crtl->pm_trace_ctrl_base_address = 0x%x\n",
  173. mss_pm_crtl->pm_trace_ctrl_base_address);
  174. VERBOSE("mss_pm_crtl->pm_trace_info_base_address = 0x%x\n",
  175. mss_pm_crtl->pm_trace_info_base_address);
  176. VERBOSE("mss_pm_crtl->pm_trace_info_core_size = 0x%x\n",
  177. mss_pm_crtl->pm_trace_info_core_size);
  178. /* TODO: add checksum to image */
  179. VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n");
  180. ret = mss_image_load(single_img, image_size,
  181. bl2_plat_get_ap_mss_regs(ap_idx), 0);
  182. if (ret != 0) {
  183. ERROR("SCP Image load failed\n");
  184. return -1;
  185. }
  186. /* check that the image was loaded successfully */
  187. ret = mss_check_image_ready(mss_pm_crtl);
  188. if (ret != 0)
  189. NOTICE("SCP Image doesn't contain PM firmware\n");
  190. return 0;
  191. }
  192. /* Load CM3 image (single_img) to CM3 pointed by cm3_type */
  193. static int load_img_to_cm3(enum cm3_t cm3_type,
  194. uintptr_t single_img, uint32_t image_size)
  195. {
  196. int ret, ap_idx, cp_index;
  197. uint32_t ap_count = bl2_plat_get_ap_count();
  198. switch (cm3_type) {
  199. case MSS_AP:
  200. for (ap_idx = 0; ap_idx < ap_count; ap_idx++) {
  201. NOTICE("Load image to AP%d MSS\n", ap_idx);
  202. ret = mss_ap_load_image(single_img, image_size, ap_idx);
  203. if (ret != 0)
  204. return ret;
  205. }
  206. break;
  207. case MSS_CP0:
  208. case MSS_CP1:
  209. case MSS_CP2:
  210. case MSS_CP3:
  211. /* MSS_AP = 0
  212. * MSS_CP1 = 1
  213. * .
  214. * .
  215. * MSS_CP3 = 4
  216. * Actual CP index is MSS_CPX - 1
  217. */
  218. cp_index = cm3_type - 1;
  219. for (ap_idx = 0; ap_idx < ap_count; ap_idx++) {
  220. /* Check if we should load this image
  221. * according to number of CPs
  222. */
  223. if (bl2_plat_get_cp_count(ap_idx) <= cp_index) {
  224. NOTICE("Skipping MSS CP%d related image\n",
  225. cp_index);
  226. break;
  227. }
  228. NOTICE("Load image to CP%d MSS AP%d\n",
  229. cp_index, ap_idx);
  230. ret = mss_image_load(single_img, image_size,
  231. bl2_plat_get_cp_mss_regs(
  232. ap_idx, cp_index),
  233. bl2_plat_get_cp_mss_sram(
  234. ap_idx, cp_index));
  235. if (ret != 0) {
  236. ERROR("SCP Image load failed\n");
  237. return -1;
  238. }
  239. }
  240. break;
  241. case MG_CP0:
  242. case MG_CP1:
  243. case MG_CP2:
  244. cp_index = cm3_type - MG_CP0;
  245. if (bl2_plat_get_cp_count(0) <= cp_index) {
  246. NOTICE("Skipping MG CP%d related image\n",
  247. cp_index);
  248. break;
  249. }
  250. NOTICE("Load image to CP%d MG\n", cp_index);
  251. ret = mg_image_load(single_img, image_size, cp_index);
  252. if (ret != 0) {
  253. ERROR("SCP Image load failed\n");
  254. return -1;
  255. }
  256. break;
  257. default:
  258. ERROR("SCP_BL2 wrong img format (cm3_type=%d)\n", cm3_type);
  259. break;
  260. }
  261. return 0;
  262. }
  263. /* The Armada 8K has 5 service CPUs and Armada 7K has 3. Therefore it was
  264. * required to provide a method for loading firmware to all of the service CPUs.
  265. * To achieve that, the scp_bl2 image in fact is file containing up to 5
  266. * concatenated firmwares and this routine splits concatenated image into single
  267. * images dedicated for appropriate service CPU and then load them.
  268. */
  269. static int split_and_load_bl2_image(void *image)
  270. {
  271. file_header_t *file_hdr;
  272. img_header_t *img_hdr;
  273. uintptr_t single_img;
  274. int i;
  275. file_hdr = (file_header_t *)image;
  276. if (file_hdr->magic != FILE_MAGIC) {
  277. ERROR("SCP_BL2 wrong img format\n");
  278. return -1;
  279. }
  280. if (file_hdr->nr_of_imgs > MAX_NR_OF_FILES) {
  281. ERROR("SCP_BL2 concatenated image contains too many images\n");
  282. return -1;
  283. }
  284. img_hdr = (img_header_t *)((uintptr_t)image + sizeof(file_header_t));
  285. single_img = (uintptr_t)image + sizeof(file_header_t) +
  286. sizeof(img_header_t) * file_hdr->nr_of_imgs;
  287. NOTICE("SCP_BL2 contains %d concatenated images\n",
  288. file_hdr->nr_of_imgs);
  289. for (i = 0; i < file_hdr->nr_of_imgs; i++) {
  290. /* Before loading make sanity check on header */
  291. if (img_hdr->version != HEADER_VERSION) {
  292. ERROR("Wrong header, img corrupted exiting\n");
  293. return -1;
  294. }
  295. load_img_to_cm3(img_hdr->type, single_img, img_hdr->length);
  296. /* Prepare offsets for next run */
  297. single_img += img_hdr->length;
  298. img_hdr++;
  299. }
  300. return 0;
  301. }
  302. int scp_bootloader_transfer(void *image, unsigned int image_size)
  303. {
  304. #ifdef SCP_BL2_BASE
  305. assert((uintptr_t) image == SCP_BL2_BASE);
  306. #endif
  307. VERBOSE("Concatenated img size %d\n", image_size);
  308. if (image_size == 0) {
  309. ERROR("SCP_BL2 image size can't be 0 (current size = 0x%x)\n",
  310. image_size);
  311. return -1;
  312. }
  313. if (split_and_load_bl2_image(image))
  314. return -1;
  315. return 0;
  316. }