mt_adsp.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2018. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <stdint.h>
  32. #include <string.h>
  33. #include <debug.h>
  34. #include <platform.h>
  35. #include <platform/mt_gpt.h>
  36. #include <platform/boot_mode.h>
  37. #include <part_interface.h>
  38. #include <pal_typedefs.h>
  39. #include <pal_assert.h>
  40. #include <pal_log.h>
  41. #include <platform/verified_boot.h>
  42. #include <env.h>
  43. #ifdef DEVICE_TREE_SUPPORT
  44. #include <libfdt.h>
  45. #include <fdt_op.h>
  46. #endif
  47. #include <assert.h>
  48. #include <platform/mt_adsp.h>
  49. #if ENABLE_ADSP_EMI_PROTECTION
  50. #include <platform/mt_emi_mpu.h>
  51. #endif
  52. #include <platform/errno.h>
  53. #include <spm.h> //mtcmos
  54. #include <arch/ops.h> //for arch_sync_cache_range()
  55. #define ALIGN_TO(x, n) \
  56. (((x) + ((n) - 1)) & ~((n) - 1))
  57. static char module_prefix[] = "[ADSP]";
  58. extern BOOT_ARGUMENT *g_boot_arg;
  59. static uint32_t g_dram_size = ADSP_DRAM_SIZE;
  60. static uint32_t g_total_dram_size = 0;
  61. static unsigned int adsp_load_status = 0;
  62. static void *dram_phys_addr;
  63. static char *adsp_part_name = "audio_dsp"; /* name registered in partition */
  64. struct adsp_mem_attr {
  65. uint32_t enable; /* default setting */
  66. uint32_t size;
  67. };
  68. static struct adsp_mem_attr mem_attr[AUDIO_MEM_TOTAL_NUM];
  69. struct image_node image_table[ADSP_NUM_IMAGE] = {
  70. [ADSP_A_IMAGE_ITCM] = IMAGE_UNIT(ADSP_A_ITCM_NAME, ADSP_A_ITCM_BASE, ADSP_A_ITCM_SIZE),
  71. [ADSP_A_IMAGE_DTCM] = IMAGE_UNIT(ADSP_A_DTCM_NAME, ADSP_A_DTCM_BASE, ADSP_A_DTCM_SIZE),
  72. [ADSP_A_IMAGE_DRAM] = IMAGE_UNIT(ADSP_A_DRAM_NAME, 0, ADSP_A_DRAM_SIZE),
  73. };
  74. static char *adsp_audio_mem_name[AUDIO_MEM_TOTAL_NUM] = {
  75. [AUDIO_MEM_VOIP_ID] = "mtk_dsp_voip",
  76. [AUDIO_MEM_PRIMARY_ID] = "mtk_dsp_primary",
  77. [AUDIO_MEM_OFFLOAD_ID] = "mtk_dsp_offload",
  78. [AUDIO_MEM_DEEPBUFFER_ID] = "mtk_dsp_deep",
  79. [AUDIO_MEM_PLAYBACK_ID] = "mtk_dsp_playback",
  80. [AUDIO_MEM_MUSIC_ID] = "mtk_dsp_music",
  81. [AUDIO_MEM_CAPTURE_UL1_ID] = "mtk_dsp_capture1",
  82. [AUDIO_MEM_A2DP_ID] = "mtk_dsp_a2dp",
  83. [AUDIO_MEM_DATAPROVIDER_ID] = "mtk_dsp_dataprovider",
  84. [AUDIO_MEM_CALL_FINAL_ID] = "mtk_dsp_call_final",
  85. [AUDIO_MEM_FAST_ID] = "mtk_dsp_fast",
  86. [AUDIO_MEM_KTV_ID] = "mtk_dsp_ktv",
  87. [AUDIO_MEM_AFE_ID] = "mtk_dsp_mem_afe",
  88. };
  89. static char *adsp_rsv_name[ADSP_RSV_TOTAL_NUM] = {
  90. [ADSP_RSV_IPIDMA_A] = "adsp-rsv-ipidma-a",
  91. [ADSP_RSV_LOGGER_A] = "adsp-rsv-logger-a",
  92. [ADSP_RSV_DBG_DUMP_A] = "adsp-rsv-dbg-dump-a",
  93. [ADSP_RSV_CORE_DUMP_A] = "adsp-rsv-core-dump-a",
  94. [ADSP_RSV_AUDIO] = "adsp-rsv-audio",
  95. };
  96. extern void dsb(void);
  97. extern int mboot_common_load_part(char *part_name, char *img_name, unsigned long addr);
  98. extern int verify_load_adsp_image(char *part_name, void *addr);
  99. static int calc_and_update_audio_rsv(void);
  100. static int update_and_set_adsp_rsv_size(void);
  101. static int get_adsp_sysram_info_from_dt(void);
  102. static uint32_t parse_adsp_memory_from_dt(void);
  103. static void set_adsp_image_base(uint32_t id, void *base);
  104. static void set_adsp_image_size(uint32_t id, uint32_t size);
  105. static void set_adsp_dram_remap(void *base);
  106. static void print_adsp_image_info(void);
  107. static char *adsp_partition_name(void)
  108. {
  109. return adsp_part_name;
  110. }
  111. int load_adsp_image(char *part_name, char *img_name, void *addr)
  112. {
  113. int ret = 0;
  114. #ifdef MTK_SECURITY_SW_SUPPORT
  115. /* we use this API because audio dsp TCM 8 byte access
  116. * limitation */
  117. ret = img_auth_stor(part_name, img_name, 0x1);
  118. if (ret != 0) {
  119. pal_log_err("<ASSERT> %s:line %d\n", __FILE__, __LINE__);
  120. PAL_ASSERT(0);
  121. }
  122. #endif /* MTK_SECURITY_SW_SUPPORT */
  123. ret = mboot_common_load_part(part_name, img_name, (unsigned long)addr);
  124. dprintf(CRITICAL, "[ADSP]mboot_common_load_part ret=%d\n",ret);
  125. if (ret <= 0)
  126. ret = -1;
  127. return ret;
  128. }
  129. int load_adsp(void)
  130. {
  131. int ret;
  132. char *part_name;
  133. #ifdef DEVICE_TREE_SUPPORT
  134. g_dram_size = parse_adsp_memory_from_dt();
  135. if (!g_dram_size)
  136. goto error;
  137. #else
  138. dprintf(CRITICAL, "[ADSP] \"DEVICE_TREE_SUPPORT\" is not defined\n");
  139. #endif
  140. /* memory to store i/dtcm image from partition loader */
  141. g_total_dram_size= ALIGN_TO(g_dram_size + ADSP_TCM_TOTAL_SIZE, RESERVED_MEM_ALIGN);
  142. dram_phys_addr = (void *)(uint32_t)mblock_reserve_ext(&g_boot_arg->mblock_info, g_total_dram_size,
  143. ADSP_DRAM_ADDR_ALIGN, ADSP_DRAM_ADDR_MAX, 0, ADSP_MEM_RESERVED_KEY);
  144. if (!dram_phys_addr) {
  145. dprintf(CRITICAL, "[ADSP] mblock_reserve address fail. phys view=0x%x, adsp view=0x%x\n",
  146. (uint32_t)dram_phys_addr, (uint32_t)image_table[ADSP_A_IMAGE_DRAM].base);
  147. } else {
  148. /* update target(adsp a & b) dram address */
  149. dprintf(INFO, "[ADSP] mblock_reserve success. phys view=0x%x, adsp view=0x%x\n",
  150. (uint32_t)dram_phys_addr, (uint32_t)image_table[ADSP_A_IMAGE_DRAM].base);
  151. set_adsp_dram_remap(dram_phys_addr);
  152. print_adsp_image_info();
  153. }
  154. part_name = adsp_partition_name();
  155. if(!part_name) {
  156. dprintf(CRITICAL, "[ADSP]get partition failed\n");
  157. goto error;
  158. }
  159. /* enable adsp clock & release CPU to access hifi3 */
  160. switch_adsp_power(true, false);
  161. adsp_sw_reset();
  162. /* load adsp image */
  163. ret = verify_load_adsp_image(part_name, dram_phys_addr);
  164. if (ret < 0) {
  165. dprintf(CRITICAL, "[ADSP]verify %s failed, ret=%d(-1: load image fail, -5:sram size<0, -6:sram size not 32*N)\n", part_name, ret);
  166. goto error;
  167. }
  168. /* disable adsp clock */
  169. #ifndef BRINGUP_WR
  170. switch_adsp_power(false, true);
  171. #endif
  172. /* clean dcache & icache before set up EMI MPU */
  173. arch_sync_cache_range((addr_t)dram_phys_addr, g_total_dram_size);
  174. /* setup EMI MPU
  175. * domain 0: AP
  176. * domain 10: ADSP
  177. */
  178. #if ENABLE_ADSP_EMI_PROTECTION
  179. struct emi_region_info_t region_info;
  180. region_info.start = (unsigned long long)(uint32_t)dram_phys_addr;
  181. region_info.end = (unsigned long long)((uint32_t)dram_phys_addr + g_total_dram_size - 0x1);
  182. region_info.region = MPU_REGION_ID_ADSP_RO_MEM;
  183. SET_ACCESS_PERMISSION(region_info.apc, UNLOCK,
  184. FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
  185. FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN,
  186. FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
  187. FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_R_NSEC_R);
  188. emi_mpu_set_protection(&region_info);
  189. #endif
  190. adsp_load_status = 1;
  191. dprintf(INFO, "%s(): done\n", __func__);
  192. return 0;
  193. error:
  194. /*
  195. * @ret = 0, malloc() error
  196. * @ret < 0, eror code from load_adsp_image()
  197. */
  198. adsp_load_status = 0;
  199. return -1;
  200. }
  201. #ifdef DEVICE_TREE_SUPPORT
  202. static int update_and_set_adsp_rsv_size(void)
  203. {
  204. int nodeoffset, len;
  205. void *fdt = get_kernel_fdt();
  206. const void *data;
  207. uint32_t mem_id, size, total_size = 0;
  208. fdt64_t rsv_size;
  209. if (fdt == NULL)
  210. panic("kernel fdt is NULL!\n");
  211. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, ADSP_COMMON_DTS_COMPATIBLE);
  212. if (nodeoffset < 0) {
  213. dprintf(CRITICAL, "[ADSP] Failed to find %s in dtb\n",
  214. ADSP_COMMON_DTS_COMPATIBLE);
  215. return -1;
  216. }
  217. for (mem_id = 0; mem_id < ADSP_RSV_TOTAL_NUM; mem_id ++) {
  218. data = fdt_getprop(fdt, nodeoffset, adsp_rsv_name[mem_id], &len);
  219. if (data) {
  220. size = fdt32_to_cpu(*(uint32_t *)data);
  221. total_size += size;
  222. } else {
  223. dprintf(CRITICAL, "[ADSP] get \"%s\" fail\n", adsp_rsv_name[mem_id]);
  224. continue;
  225. }
  226. }
  227. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, ADSP_SHARE_DTS_COMPATIBLE);
  228. if (nodeoffset < 0) {
  229. dprintf(CRITICAL, "[ADSP] %s is not found\n", ADSP_SHARE_DTS_COMPATIBLE);
  230. return -1;
  231. }
  232. /* update reserve memory size */
  233. rsv_size = cpu_to_fdt64((uint64_t)ALIGN_TO(total_size, RESERVED_MEM_ALIGN));
  234. fdt_setprop_inplace(fdt, nodeoffset, "size", &rsv_size, sizeof(rsv_size));
  235. return 0;
  236. }
  237. /* return value: size of total dram images */
  238. static uint32_t parse_adsp_memory_from_dt(void)
  239. {
  240. uint32_t adsp_dram_tail, adsp_dram_head;
  241. /* audio feature from dts */
  242. calc_and_update_audio_rsv();
  243. update_and_set_adsp_rsv_size();
  244. /* system from dts */
  245. get_adsp_sysram_info_from_dt();
  246. adsp_dram_head = (uint32_t)image_table[ADSP_A_IMAGE_DRAM].base;
  247. adsp_dram_tail = (uint32_t)image_table[ADSP_A_IMAGE_DRAM].base + image_table[ADSP_A_IMAGE_DRAM].size;
  248. if (!adsp_dram_head || !adsp_dram_tail ) {
  249. dprintf(CRITICAL, "%s error: adsp dram size is NULL!\n", __func__);
  250. return 0;
  251. } else if ((adsp_dram_tail - adsp_dram_head) > ADSP_DRAM_ADDR_ALIGN) {
  252. dprintf(CRITICAL, "%s error: adsp dram size 0x%x exceeds dram remap size!\n",
  253. __func__, (adsp_dram_tail - adsp_dram_head));
  254. return 0;
  255. }
  256. return (uint32_t)image_table[ADSP_A_IMAGE_DRAM].size;
  257. }
  258. static int calc_and_update_audio_rsv(void)
  259. {
  260. int nodeoffset, len;
  261. void *fdt = get_kernel_fdt();
  262. const void *data;
  263. uint32_t mem_id, mem_offset;
  264. uint32_t total_mem = 0;
  265. bool afe_enable;
  266. fdt32_t rsv_size;
  267. /* get snd_audio_dsp node,
  268. check audio feature set and calc total memory size
  269. */
  270. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, SND_ADSP_DTS_COMPATIBLE);
  271. if (nodeoffset < 0) {
  272. dprintf(CRITICAL, "[ADSP] %s is not found\n", SND_ADSP_DTS_COMPATIBLE);
  273. return -1;
  274. }
  275. for (mem_id = 0; mem_id < AUDIO_MEM_TOTAL_NUM; mem_id ++) {
  276. if (mem_id < AUDIO_MEM_TASK_NUM)
  277. mem_offset = 4;
  278. else
  279. mem_offset = 1;
  280. data = fdt_getprop(fdt, nodeoffset, adsp_audio_mem_name[mem_id], &len);
  281. if (data) {
  282. mem_attr[mem_id].enable = fdt32_to_cpu(*(uint32_t *)data);
  283. mem_attr[mem_id].size = fdt32_to_cpu(*((uint32_t *)data + mem_offset));
  284. } else {
  285. dprintf(CRITICAL, "[ADSP] get \"%s\" fail\n", adsp_audio_mem_name[mem_id]);
  286. continue;
  287. }
  288. if (mem_id < AUDIO_MEM_TASK_NUM && mem_attr[mem_id].enable != 0) {
  289. total_mem += mem_attr[mem_id].size;
  290. afe_enable = true;
  291. }
  292. }
  293. /* architecture-specific */
  294. if (afe_enable && mem_attr[AUDIO_MEM_AFE_ID].enable)
  295. total_mem += mem_attr[AUDIO_MEM_AFE_ID].size;
  296. if (mem_attr[AUDIO_MEM_CALL_FINAL_ID].enable)
  297. total_mem -= mem_attr[AUDIO_MEM_CALL_FINAL_ID].size;
  298. /* write audio reserved memory back to adsp_common node */
  299. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, ADSP_COMMON_DTS_COMPATIBLE);
  300. if (nodeoffset < 0) {
  301. dprintf(CRITICAL, "[ADSP] %s is not found\n", ADSP_COMMON_DTS_COMPATIBLE);
  302. return -1;
  303. }
  304. rsv_size = cpu_to_fdt32(total_mem);
  305. fdt_setprop_inplace(fdt, nodeoffset, adsp_rsv_name[ADSP_RSV_AUDIO], &rsv_size, sizeof(rsv_size));
  306. dprintf(INFO, "%s update audio feature memory = 0x%x\n", __func__, total_mem);
  307. return 0;
  308. }
  309. static int get_adsp_sysram_info_from_dt(void)
  310. {
  311. int nodeoffset, len;
  312. int n = 0;
  313. char compat_name[32];
  314. void *base = NULL;
  315. void *fdt = get_kernel_fdt();
  316. const void *fdt_data;
  317. uint32_t idx, size = 0, core_id = 0;
  318. uint32_t *data;
  319. for (idx = 0; idx < ADSP_NUM_IMAGE; idx++) {
  320. if (strstr(image_table[idx].name, "sram") == NULL) {
  321. continue;
  322. }
  323. memset(compat_name, 0, sizeof(compat_name));
  324. n = snprintf(compat_name, sizeof(compat_name), "%s_%d",
  325. ADSP_CORE_DTS_COMPATIBLE, core_id);
  326. if (n < 0 || n > (int)sizeof(compat_name))
  327. return -2;
  328. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compat_name);
  329. if (nodeoffset < 0) {
  330. dprintf(CRITICAL, "%s failed to find %s in dtb\n",
  331. __func__, compat_name);
  332. return -1;
  333. }
  334. fdt_data = fdt_getprop(fdt, nodeoffset, "system", &len);
  335. if (!fdt_data) {
  336. return -1;
  337. }
  338. data = (uint32_t *)fdt_data + 1;
  339. base = (void *)fdt32_to_cpu(*data);
  340. data = (uint32_t *)fdt_data + 3;
  341. size = fdt32_to_cpu(*data);
  342. set_adsp_image_base(idx, base);
  343. set_adsp_image_size(idx, size);
  344. core_id ++;
  345. }
  346. return 0;
  347. }
  348. int platform_fdt_adsp(void *fdt)
  349. {
  350. int nodeoffset, ret = 0;
  351. uint32_t idx, coreid = 0;
  352. char compat_name[32];
  353. fdt32_t dram_base, dram_size, load;
  354. int n = 0;
  355. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, ADSP_COMMON_DTS_COMPATIBLE);
  356. if (nodeoffset < 0) {
  357. dprintf(CRITICAL, "[ADSP] Failed to find %s in dtb\n",
  358. ADSP_COMMON_DTS_COMPATIBLE);
  359. return -1;
  360. }
  361. load = cpu_to_fdt32(adsp_load_status);
  362. ret = fdt_setprop(fdt, nodeoffset, "load", &load, sizeof(load));
  363. if (ret < 0)
  364. return ret;
  365. /* dram base/size: image naming rule: hifi3_x_sram */
  366. for (idx = 0; idx < ADSP_NUM_IMAGE; idx++) {
  367. if (strstr(image_table[idx].name, "sram") != NULL) {
  368. memset(compat_name, 0, sizeof(compat_name));
  369. n = snprintf(compat_name, sizeof(compat_name), "%s_%d",
  370. ADSP_CORE_DTS_COMPATIBLE, coreid);
  371. if (n < 0 || n > (int)sizeof(compat_name))
  372. return -2;
  373. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compat_name);
  374. if (nodeoffset < 0) {
  375. dprintf(CRITICAL, "[ADSP] Failed to find %s in dtb\n", compat_name);
  376. return -1;
  377. }
  378. /* pass parameter to kernel */
  379. dram_base = cpu_to_fdt32((uint32_t)image_table[idx].base);
  380. dram_size = cpu_to_fdt32(image_table[idx].size);
  381. ret = fdt_setprop(fdt, nodeoffset, "sysram",
  382. &dram_base, sizeof(dram_base));
  383. if (ret < 0)
  384. return ret;
  385. ret = fdt_setprop(fdt, nodeoffset, "sysram_size",
  386. &dram_size, sizeof(dram_size));
  387. if (ret < 0)
  388. return ret;
  389. dprintf(INFO, "[ADSP] set core_%d sysram base=0x%x, size=0x%x\n",
  390. coreid, (uint32_t)image_table[idx].base, image_table[idx].size);
  391. coreid ++;
  392. }
  393. }
  394. return ret;
  395. }
  396. #endif
  397. int verify_load_adsp_image(char *part_name, void *addr)
  398. {
  399. uint32_t idx, image_size;
  400. void *image_base;
  401. void *load_tcm_base;
  402. load_tcm_base = dram_phys_addr + g_dram_size;
  403. /* load/verify audio dsp images */
  404. for (idx = 0; idx < ADSP_NUM_IMAGE; idx ++) {
  405. if (strstr(image_table[idx].name, "iram") || strstr(image_table[idx].name, "dram")) {
  406. image_base = load_tcm_base;
  407. } else {
  408. image_base = image_table[idx].base;
  409. }
  410. image_size = load_adsp_image(part_name, image_table[idx].name, image_base);
  411. if (image_size > image_table[idx].size || image_size == 0) {
  412. dprintf(CRITICAL, "[ADSP] load_adsp_image fail %s(addr=0x%x, size=0x%x, expected size=0x%x)\n",
  413. image_table[idx].name, (uint32_t)image_table[idx].base, image_size, image_table[idx].size);
  414. return -1;
  415. } else {
  416. dprintf(INFO, "[ADSP] load image #%d %s success.(addr=0x%x, size=0x%x)\n",
  417. idx, image_table[idx].name, (uint32_t)image_base, image_size);
  418. }
  419. if (strstr(image_table[idx].name, "iram") || strstr(image_table[idx].name, "dram")) {
  420. memcpy(image_table[idx].base, load_tcm_base, image_size);
  421. load_tcm_base += image_size;
  422. }
  423. }
  424. return 0;
  425. }
  426. /* adsp power off (DSP suspend) */
  427. void disable_adsp_hw(void)
  428. {
  429. switch_adsp_power(false, false);
  430. dprintf(CRITICAL, "DISABLE ADSP\n");
  431. }
  432. /* platform driver */
  433. static void set_adsp_image_base(uint32_t id, void *base)
  434. {
  435. if (id >= ADSP_NUM_IMAGE) {
  436. dprintf(CRITICAL, "%s fail. id=%d\n", __func__, id);
  437. return;
  438. }
  439. image_table[id].base = base;
  440. }
  441. static void set_adsp_image_size(uint32_t id, uint32_t size)
  442. {
  443. if (id >= ADSP_NUM_IMAGE) {
  444. dprintf(CRITICAL, "%s fail. id=%d\n", __func__, id);
  445. return;
  446. }
  447. image_table[id].size = size;
  448. }
  449. void set_adsp_dram_remap(void *base)
  450. {
  451. image_table[ADSP_A_IMAGE_DRAM].base = base + ((uint32_t)image_table[ADSP_A_IMAGE_DRAM].base & 0x1FFFFFF);
  452. }
  453. void switch_adsp_power(bool on, bool dormant)
  454. {
  455. dprintf(INFO, "%s on=%d dormant=%d\n", module_prefix, on, dormant);
  456. if (on) {
  457. /* 1. power on ADSP MTCMOS by spm */
  458. spm_mtcmos_ctrl_adsp_shut_down(STA_POWER_ON);
  459. /* 2. enable ADSP clock via reg
  460. * adsppll -> adsp sel -> adsp clock cg
  461. */
  462. /* ADSPPLL on */
  463. DRV_SetReg32(ADSPPLL_CON3, (0x1 << 0));
  464. udelay(30); //30us delay
  465. DRV_ClrReg32(ADSPPLL_CON3, (0x1 << 1));
  466. udelay(1); //1us delay
  467. DRV_SetReg32(ADSPPLL_CON0, (0x1 << 0));
  468. /* CLKMUX */
  469. DRV_SetReg32(CLK_CFG_13_CLR, (0x7 << ADSP_SEL_OFFSET));
  470. DRV_SetReg32(CLK_CFG_13_SET, (ADSPPLL_CK << ADSP_SEL_OFFSET));
  471. DRV_SetReg32(CLK_CFG_UPDATE1, (1 << ADSP_CK_UPDATE));
  472. /* ADSP CLK CG */
  473. DRV_ClrReg32(AUDIODSP_CK_CG, (CG_ENABLE << CG_OFFSET));
  474. } else {
  475. /* 1. disable clock via reg
  476. * adsp clock cg -> adsp sel -> adsppll
  477. */
  478. /* ADSP CLK CG */
  479. DRV_SetReg32(AUDIODSP_CK_CG, (CG_ENABLE << CG_OFFSET));
  480. /* ADSP SEL */
  481. DRV_SetReg32(CLK_CFG_13_CLR, (0x7 << ADSP_SEL_OFFSET));
  482. DRV_SetReg32(CLK_CFG_13_SET, (CLK_26M_CK << ADSP_SEL_OFFSET));
  483. DRV_SetReg32(CLK_CFG_UPDATE1, (1 << ADSP_CK_UPDATE));
  484. /* ADSPPLL off */
  485. DRV_ClrReg32(ADSPPLL_CON0, (0x1 << 0));
  486. DRV_SetReg32(ADSPPLL_CON3, (0x1 << 1));
  487. DRV_ClrReg32(ADSPPLL_CON3, (0x1 << 0));
  488. /* 2. power off ADSP MTCMOS by spm */
  489. if (dormant) {
  490. dprintf(INFO, "%s bypass spm_mtcmos_ctrl_adsp_dormant(STA_POWER_DOWN)\n",
  491. module_prefix);
  492. spm_mtcmos_ctrl_adsp_dormant(STA_POWER_DOWN);
  493. } else {
  494. spm_mtcmos_ctrl_adsp_shut_down(STA_POWER_DOWN);
  495. }
  496. }
  497. }
  498. void adsp_sw_reset(void)
  499. {
  500. DRV_SetReg32(ADSP_CFGREG_SW_RSTN, ADSP_SW_RSTN);
  501. udelay(1);
  502. DRV_ClrReg32(ADSP_CFGREG_SW_RSTN, ADSP_SW_RSTN);
  503. }
  504. static void print_adsp_image_info(void)
  505. {
  506. uint32_t id;
  507. for (id = 0; id < ADSP_NUM_IMAGE; id++) {
  508. dprintf(INFO, "%s id=%d, base=0x%x, size=0x%x\n",
  509. __func__, id, (uint32_t)image_table[id].base, image_table[id].size);
  510. }
  511. }