mt_adsp.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  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. [ADSP_B_IMAGE_ITCM] = IMAGE_UNIT(ADSP_B_ITCM_NAME, ADSP_B_ITCM_BASE, ADSP_B_ITCM_SIZE),
  74. [ADSP_B_IMAGE_DTCM] = IMAGE_UNIT(ADSP_B_DTCM_NAME, ADSP_B_DTCM_BASE, ADSP_B_DTCM_SIZE),
  75. [ADSP_B_IMAGE_DRAM] = IMAGE_UNIT(ADSP_B_DRAM_NAME, 0, ADSP_B_DRAM_SIZE),
  76. };
  77. static char *adsp_audio_mem_name[AUDIO_MEM_TOTAL_NUM] = {
  78. [AUDIO_MEM_VOIP_ID] = "mtk_dsp_voip",
  79. [AUDIO_MEM_PRIMARY_ID] = "mtk_dsp_primary",
  80. [AUDIO_MEM_OFFLOAD_ID] = "mtk_dsp_offload",
  81. [AUDIO_MEM_DEEPBUFFER_ID] = "mtk_dsp_deep",
  82. [AUDIO_MEM_PLAYBACK_ID] = "mtk_dsp_playback",
  83. [AUDIO_MEM_MUSIC_ID] = "mtk_dsp_music",
  84. [AUDIO_MEM_CAPTURE_UL1_ID] = "mtk_dsp_capture1",
  85. [AUDIO_MEM_A2DP_ID] = "mtk_dsp_a2dp",
  86. [AUDIO_MEM_DATAPROVIDER_ID] = "mtk_dsp_dataprovider",
  87. [AUDIO_MEM_CALL_FINAL_ID] = "mtk_dsp_call_final",
  88. [AUDIO_MEM_FAST_ID] = "mtk_dsp_fast",
  89. [AUDIO_MEM_KTV_ID] = "mtk_dsp_ktv",
  90. [AUDIO_MEM_AFE_ID] = "mtk_dsp_mem_afe",
  91. };
  92. static char *adsp_rsv_name[ADSP_RSV_TOTAL_NUM] = {
  93. [ADSP_RSV_IPIDMA_A] = "adsp-rsv-ipidma-a",
  94. [ADSP_RSV_IPIDMA_B] = "adsp-rsv-ipidma-b",
  95. [ADSP_RSV_LOGGER_A] = "adsp-rsv-logger-a",
  96. [ADSP_RSV_LOGGER_B] = "adsp-rsv-logger-b",
  97. [ADSP_RSV_C2C] = "adsp-rsv-c2c",
  98. [ADSP_RSV_DBG_DUMP_A] = "adsp-rsv-dbg-dump-a",
  99. [ADSP_RSV_DBG_DUMP_B] = "adsp-rsv-dbg-dump-b",
  100. [ADSP_RSV_CORE_DUMP_A] = "adsp-rsv-core-dump-a",
  101. [ADSP_RSV_CORE_DUMP_B] = "adsp-rsv-core-dump-b",
  102. [ADSP_RSV_AUDIO] = "adsp-rsv-audio",
  103. };
  104. extern void dsb(void);
  105. extern int mboot_common_load_part(char *part_name, char *img_name, unsigned long addr);
  106. extern int verify_load_adsp_image(char *part_name, void *addr);
  107. static int calc_and_update_audio_rsv(void);
  108. static int update_and_set_adsp_rsv_size(void);
  109. static int get_adsp_sysram_info_from_dt(void);
  110. static uint32_t parse_adsp_memory_from_dt(void);
  111. static void set_adsp_image_base(uint32_t id, void *base);
  112. static void set_adsp_image_size(uint32_t id, uint32_t size);
  113. static void set_adsp_dram_remap(void *base);
  114. static void print_adsp_image_info(void);
  115. static char *adsp_partition_name(void)
  116. {
  117. return adsp_part_name;
  118. }
  119. int load_adsp_image(char *part_name, char *img_name, void *addr)
  120. {
  121. int ret = 0;
  122. #ifdef MTK_SECURITY_SW_SUPPORT
  123. /* we use this API because audio dsp TCM 8 byte access
  124. * limitation */
  125. ret = img_auth_stor(part_name, img_name, 0x1);
  126. if (ret != 0) {
  127. pal_log_err("<ASSERT> %s:line %d\n", __FILE__, __LINE__);
  128. PAL_ASSERT(0);
  129. }
  130. #endif /* MTK_SECURITY_SW_SUPPORT */
  131. ret = mboot_common_load_part(part_name, img_name, (unsigned long)addr);
  132. dprintf(CRITICAL, "[ADSP]mboot_common_load_part ret=%d\n",ret);
  133. if (ret <= 0)
  134. ret = -1;
  135. return ret;
  136. }
  137. int load_adsp(void)
  138. {
  139. int ret;
  140. char *part_name;
  141. #ifdef DEVICE_TREE_SUPPORT
  142. g_dram_size = parse_adsp_memory_from_dt();
  143. if (!g_dram_size)
  144. goto error;
  145. #else
  146. dprintf(CRITICAL, "[ADSP] \"DEVICE_TREE_SUPPORT\" is not defined\n");
  147. #endif
  148. /* memory to store i/dtcm image from partition loader */
  149. g_total_dram_size= ALIGN_TO(g_dram_size + ADSP_TCM_TOTAL_SIZE, RESERVED_MEM_ALIGN);
  150. dram_phys_addr = (void *)(uint32_t)mblock_reserve_ext(&g_boot_arg->mblock_info, g_total_dram_size,
  151. ADSP_DRAM_ADDR_ALIGN, ADSP_DRAM_ADDR_MAX, 0, ADSP_MEM_RESERVED_KEY);
  152. if (!dram_phys_addr) {
  153. dprintf(CRITICAL, "[ADSP] mblock_reserve address fail. phys view=0x%x, adsp view=0x%x\n",
  154. (uint32_t)dram_phys_addr, (uint32_t)image_table[ADSP_A_IMAGE_DRAM].base);
  155. } else {
  156. /* update target(adsp a & b) dram address */
  157. dprintf(INFO, "[ADSP] mblock_reserve success. phys view=0x%x, adsp view=0x%x\n",
  158. (uint32_t)dram_phys_addr, (uint32_t)image_table[ADSP_A_IMAGE_DRAM].base);
  159. set_adsp_dram_remap(dram_phys_addr);
  160. print_adsp_image_info();
  161. }
  162. part_name = adsp_partition_name();
  163. if(!part_name) {
  164. dprintf(CRITICAL, "[ADSP]get partition failed\n");
  165. goto error;
  166. }
  167. /* enable adsp clock & release CPU to access hifi3 */
  168. switch_adsp_power(true, false);
  169. adsp_sw_reset();
  170. /* load adsp image */
  171. ret = verify_load_adsp_image(part_name, dram_phys_addr);
  172. if (ret < 0) {
  173. 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);
  174. goto error;
  175. }
  176. /* disable adsp clock */
  177. #ifndef BRINGUP_WR
  178. switch_adsp_power(false, true);
  179. #endif
  180. /* clean dcache & icache before set up EMI MPU */
  181. arch_sync_cache_range((addr_t)dram_phys_addr, g_total_dram_size);
  182. /* setup EMI MPU
  183. * domain 0: AP
  184. * domain 10: ADSP
  185. */
  186. #if ENABLE_ADSP_EMI_PROTECTION
  187. struct emi_region_info_t region_info;
  188. region_info.start = (unsigned long long)(uint32_t)dram_phys_addr;
  189. region_info.end = (unsigned long long)((uint32_t)dram_phys_addr + g_total_dram_size - 0x1);
  190. region_info.region = MPU_REGION_ID_ADSP_RO_MEM;
  191. SET_ACCESS_PERMISSION(region_info.apc, UNLOCK,
  192. FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
  193. FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN,
  194. FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
  195. FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_R_NSEC_R);
  196. emi_mpu_set_protection(&region_info);
  197. #endif
  198. adsp_load_status = 1;
  199. dprintf(INFO, "%s(): done\n", __func__);
  200. return 0;
  201. error:
  202. /*
  203. * @ret = 0, malloc() error
  204. * @ret < 0, eror code from load_adsp_image()
  205. */
  206. adsp_load_status = 0;
  207. return -1;
  208. }
  209. #ifdef DEVICE_TREE_SUPPORT
  210. static int update_and_set_adsp_rsv_size(void)
  211. {
  212. int nodeoffset, len;
  213. void *fdt = get_kernel_fdt();
  214. const void *data;
  215. uint32_t mem_id, size, total_size = 0;
  216. fdt64_t rsv_size;
  217. if (fdt == NULL)
  218. panic("kernel fdt is NULL!\n");
  219. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, ADSP_COMMON_DTS_COMPATIBLE);
  220. if (nodeoffset < 0) {
  221. dprintf(CRITICAL, "[ADSP] Failed to find %s in dtb\n",
  222. ADSP_COMMON_DTS_COMPATIBLE);
  223. return -1;
  224. }
  225. for (mem_id = 0; mem_id < ADSP_RSV_TOTAL_NUM; mem_id ++) {
  226. data = fdt_getprop(fdt, nodeoffset, adsp_rsv_name[mem_id], &len);
  227. if (data) {
  228. size = fdt32_to_cpu(*(uint32_t *)data);
  229. total_size += size;
  230. } else {
  231. dprintf(CRITICAL, "[ADSP] get \"%s\" fail\n", adsp_rsv_name[mem_id]);
  232. continue;
  233. }
  234. }
  235. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, ADSP_SHARE_DTS_COMPATIBLE);
  236. if (nodeoffset < 0) {
  237. dprintf(CRITICAL, "[ADSP] %s is not found\n", ADSP_SHARE_DTS_COMPATIBLE);
  238. return -1;
  239. }
  240. /* update reserve memory size */
  241. rsv_size = cpu_to_fdt64((uint64_t)ALIGN_TO(total_size, RESERVED_MEM_ALIGN));
  242. fdt_setprop_inplace(fdt, nodeoffset, "size", &rsv_size, sizeof(rsv_size));
  243. return 0;
  244. }
  245. /* return value: size of total dram images */
  246. static uint32_t parse_adsp_memory_from_dt(void)
  247. {
  248. uint32_t adsp_dram_tail, adsp_dram_head;
  249. /* audio feature from dts */
  250. calc_and_update_audio_rsv();
  251. update_and_set_adsp_rsv_size();
  252. /* system from dts */
  253. get_adsp_sysram_info_from_dt();
  254. adsp_dram_head = (uint32_t)image_table[ADSP_A_IMAGE_DRAM].base;
  255. adsp_dram_tail = (uint32_t)image_table[ADSP_B_IMAGE_DRAM].base + image_table[ADSP_B_IMAGE_DRAM].size;
  256. if (!adsp_dram_head || !adsp_dram_tail ) {
  257. dprintf(CRITICAL, "%s error: adsp dram size is NULL!\n", __func__);
  258. return 0;
  259. } else if ((adsp_dram_tail - adsp_dram_head) > ADSP_DRAM_ADDR_ALIGN) {
  260. dprintf(CRITICAL, "%s error: adsp dram size 0x%x exceeds dram remap size!\n",
  261. __func__, (adsp_dram_tail - adsp_dram_head));
  262. return 0;
  263. }
  264. if ((uint32_t)image_table[ADSP_A_IMAGE_DRAM].base + image_table[ADSP_A_IMAGE_DRAM].size
  265. != (uint32_t)image_table[ADSP_B_IMAGE_DRAM].base)
  266. dprintf(CRITICAL, "%s dram image layout is not contiguous\n", __func__);
  267. return (adsp_dram_tail - adsp_dram_head);
  268. }
  269. static int calc_and_update_audio_rsv(void)
  270. {
  271. int nodeoffset, len;
  272. void *fdt = get_kernel_fdt();
  273. const void *data;
  274. uint32_t mem_id, mem_offset;
  275. uint32_t total_mem = 0;
  276. bool afe_enable;
  277. fdt32_t rsv_size;
  278. /* get snd_audio_dsp node,
  279. check audio feature set and calc total memory size
  280. */
  281. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, SND_ADSP_DTS_COMPATIBLE);
  282. if (nodeoffset < 0) {
  283. dprintf(CRITICAL, "[ADSP] %s is not found\n", SND_ADSP_DTS_COMPATIBLE);
  284. return -1;
  285. }
  286. for (mem_id = 0; mem_id < AUDIO_MEM_TOTAL_NUM; mem_id ++) {
  287. if (mem_id < AUDIO_MEM_TASK_NUM)
  288. mem_offset = 4;
  289. else
  290. mem_offset = 1;
  291. data = fdt_getprop(fdt, nodeoffset, adsp_audio_mem_name[mem_id], &len);
  292. if (data) {
  293. mem_attr[mem_id].enable = fdt32_to_cpu(*(uint32_t *)data);
  294. mem_attr[mem_id].size = fdt32_to_cpu(*((uint32_t *)data + mem_offset));
  295. } else {
  296. dprintf(CRITICAL, "[ADSP] get \"%s\" fail\n", adsp_audio_mem_name[mem_id]);
  297. continue;
  298. }
  299. if (mem_id < AUDIO_MEM_TASK_NUM && mem_attr[mem_id].enable != 0) {
  300. total_mem += mem_attr[mem_id].size;
  301. afe_enable = true;
  302. }
  303. }
  304. /* architecture-specific */
  305. if (afe_enable && mem_attr[AUDIO_MEM_AFE_ID].enable)
  306. total_mem += mem_attr[AUDIO_MEM_AFE_ID].size;
  307. if (mem_attr[AUDIO_MEM_CALL_FINAL_ID].enable)
  308. total_mem -= mem_attr[AUDIO_MEM_CALL_FINAL_ID].size;
  309. /* write audio reserved memory back to adsp_common node */
  310. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, ADSP_COMMON_DTS_COMPATIBLE);
  311. if (nodeoffset < 0) {
  312. dprintf(CRITICAL, "[ADSP] %s is not found\n", ADSP_COMMON_DTS_COMPATIBLE);
  313. return -1;
  314. }
  315. rsv_size = cpu_to_fdt32(total_mem);
  316. fdt_setprop_inplace(fdt, nodeoffset, adsp_rsv_name[ADSP_RSV_AUDIO], &rsv_size, sizeof(rsv_size));
  317. dprintf(INFO, "%s update audio feature memory = 0x%x\n", __func__, total_mem);
  318. return 0;
  319. }
  320. static int get_adsp_sysram_info_from_dt(void)
  321. {
  322. int nodeoffset, len;
  323. int n = 0;
  324. char compat_name[32];
  325. void *base = NULL;
  326. void *fdt = get_kernel_fdt();
  327. const void *fdt_data;
  328. uint32_t idx, size = 0, core_id = 0;
  329. uint32_t *data;
  330. for (idx = 0; idx < ADSP_NUM_IMAGE; idx++) {
  331. if (strstr(image_table[idx].name, "sram") == NULL) {
  332. continue;
  333. }
  334. memset(compat_name, 0, sizeof(compat_name));
  335. n = snprintf(compat_name, sizeof(compat_name), "%s_%d",
  336. ADSP_CORE_DTS_COMPATIBLE, core_id);
  337. if (n < 0 || n > (int)sizeof(compat_name))
  338. return -2;
  339. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compat_name);
  340. if (nodeoffset < 0) {
  341. dprintf(CRITICAL, "%s failed to find %s in dtb\n",
  342. __func__, compat_name);
  343. return -1;
  344. }
  345. fdt_data = fdt_getprop(fdt, nodeoffset, "system", &len);
  346. if (!fdt_data) {
  347. return -1;
  348. }
  349. data = (uint32_t *)fdt_data + 1;
  350. base = (void *)fdt32_to_cpu(*data);
  351. data = (uint32_t *)fdt_data + 3;
  352. size = fdt32_to_cpu(*data);
  353. set_adsp_image_base(idx, base);
  354. set_adsp_image_size(idx, size);
  355. core_id ++;
  356. }
  357. return 0;
  358. }
  359. int platform_fdt_adsp(void *fdt)
  360. {
  361. int nodeoffset, ret = 0;
  362. uint32_t idx, coreid = 0;
  363. char compat_name[32];
  364. fdt32_t dram_base, dram_size, load;
  365. int n = 0;
  366. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, ADSP_COMMON_DTS_COMPATIBLE);
  367. if (nodeoffset < 0) {
  368. dprintf(CRITICAL, "[ADSP] Failed to find %s in dtb\n",
  369. ADSP_COMMON_DTS_COMPATIBLE);
  370. return -1;
  371. }
  372. load = cpu_to_fdt32(adsp_load_status);
  373. ret = fdt_setprop(fdt, nodeoffset, "load", &load, sizeof(load));
  374. if (ret < 0)
  375. return ret;
  376. /* dram base/size: image naming rule: hifi3_x_sram */
  377. for (idx = 0; idx < ADSP_NUM_IMAGE; idx++) {
  378. if (strstr(image_table[idx].name, "sram") != NULL) {
  379. memset(compat_name, 0, sizeof(compat_name));
  380. n = snprintf(compat_name, sizeof(compat_name), "%s_%d",
  381. ADSP_CORE_DTS_COMPATIBLE, coreid);
  382. if (n < 0 || n > (int)sizeof(compat_name))
  383. return -2;
  384. nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compat_name);
  385. if (nodeoffset < 0) {
  386. dprintf(CRITICAL, "[ADSP] Failed to find %s in dtb\n", compat_name);
  387. return -1;
  388. }
  389. /* pass parameter to kernel */
  390. dram_base = cpu_to_fdt32((uint32_t)image_table[idx].base);
  391. dram_size = cpu_to_fdt32(image_table[idx].size);
  392. ret = fdt_setprop(fdt, nodeoffset, "sysram",
  393. &dram_base, sizeof(dram_base));
  394. if (ret < 0)
  395. return ret;
  396. ret = fdt_setprop(fdt, nodeoffset, "sysram_size",
  397. &dram_size, sizeof(dram_size));
  398. if (ret < 0)
  399. return ret;
  400. dprintf(INFO, "[ADSP] set core_%d sysram base=0x%x, size=0x%x\n",
  401. coreid, (uint32_t)image_table[idx].base, image_table[idx].size);
  402. coreid ++;
  403. }
  404. }
  405. return ret;
  406. }
  407. #endif
  408. int verify_load_adsp_image(char *part_name, void *addr)
  409. {
  410. uint32_t idx, image_size;
  411. void *image_base;
  412. void *load_tcm_base;
  413. load_tcm_base = dram_phys_addr + g_dram_size;
  414. /* load/verify audio dsp images */
  415. for (idx = 0; idx < ADSP_NUM_IMAGE; idx ++) {
  416. if (strstr(image_table[idx].name, "iram") || strstr(image_table[idx].name, "dram")) {
  417. image_base = load_tcm_base;
  418. } else {
  419. image_base = image_table[idx].base;
  420. }
  421. image_size = load_adsp_image(part_name, image_table[idx].name, image_base);
  422. if (image_size > image_table[idx].size || image_size == 0) {
  423. dprintf(CRITICAL, "[ADSP] load_adsp_image fail %s(addr=0x%x, size=0x%x, expected size=0x%x)\n",
  424. image_table[idx].name, (uint32_t)image_table[idx].base, image_size, image_table[idx].size);
  425. return -1;
  426. } else {
  427. dprintf(INFO, "[ADSP] load image #%d %s success.(addr=0x%x, size=0x%x)\n",
  428. idx, image_table[idx].name, (uint32_t)image_base, image_size);
  429. }
  430. if (strstr(image_table[idx].name, "iram") || strstr(image_table[idx].name, "dram")) {
  431. memcpy(image_table[idx].base, load_tcm_base, image_size);
  432. load_tcm_base += image_size;
  433. }
  434. }
  435. return 0;
  436. }
  437. /* adsp power off (DSP suspend) */
  438. void disable_adsp_hw(void)
  439. {
  440. switch_adsp_power(false, false);
  441. dprintf(CRITICAL, "DISABLE ADSP\n");
  442. }
  443. /* platform driver */
  444. static void set_adsp_image_base(uint32_t id, void *base)
  445. {
  446. if (id >= ADSP_NUM_IMAGE) {
  447. dprintf(CRITICAL, "%s fail. id=%d\n", __func__, id);
  448. return;
  449. }
  450. image_table[id].base = base;
  451. }
  452. static void set_adsp_image_size(uint32_t id, uint32_t size)
  453. {
  454. if (id >= ADSP_NUM_IMAGE) {
  455. dprintf(CRITICAL, "%s fail. id=%d\n", __func__, id);
  456. return;
  457. }
  458. image_table[id].size = size;
  459. }
  460. void set_adsp_dram_remap(void *base)
  461. {
  462. image_table[ADSP_A_IMAGE_DRAM].base = base + ((uint32_t)image_table[ADSP_A_IMAGE_DRAM].base & 0x1FFFFFF);
  463. #ifdef ADSP_B_DRAM_NAME
  464. image_table[ADSP_B_IMAGE_DRAM].base = base + ((uint32_t)image_table[ADSP_B_IMAGE_DRAM].base & 0x1FFFFFF);
  465. #endif
  466. }
  467. void switch_adsp_power(bool on, bool dormant)
  468. {
  469. dprintf(INFO, "%s on=%d dormant=%d\n", module_prefix, on, dormant);
  470. if (on) {
  471. /* 1. power on ADSP MTCMOS by spm */
  472. spm_mtcmos_ctrl_adsp_shut_down(STA_POWER_ON);
  473. /* 2. enable ADSP clock via reg
  474. * adsppll -> adsp sel -> adsp clock cg
  475. */
  476. /* ADSPPLL on */
  477. DRV_SetReg32(ADSPPLL_CON3, (0x1 << 0));
  478. udelay(30); //30us delay
  479. DRV_ClrReg32(ADSPPLL_CON3, (0x1 << 1));
  480. udelay(1); //1us delay
  481. DRV_SetReg32(ADSPPLL_CON0, (0x1 << 0));
  482. /* CLKMUX */
  483. DRV_SetReg32(CLK_CFG_13_CLR, (0x7 << ADSP_SEL_OFFSET));
  484. DRV_SetReg32(CLK_CFG_13_SET, (ADSPPLL_CK << ADSP_SEL_OFFSET));
  485. DRV_SetReg32(CLK_CFG_UPDATE1, (1 << ADSP_CK_UPDATE));
  486. /* ADSP CLK CG */
  487. DRV_ClrReg32(AUDIODSP_CK_CG, (CG_ENABLE << CG_OFFSET));
  488. } else {
  489. /* 1. disable clock via reg
  490. * adsp clock cg -> adsp sel -> adsppll
  491. */
  492. /* ADSP CLK CG */
  493. DRV_SetReg32(AUDIODSP_CK_CG, (CG_ENABLE << CG_OFFSET));
  494. /* ADSP SEL */
  495. DRV_SetReg32(CLK_CFG_13_CLR, (0x7 << ADSP_SEL_OFFSET));
  496. DRV_SetReg32(CLK_CFG_13_SET, (CLK_26M_CK << ADSP_SEL_OFFSET));
  497. DRV_SetReg32(CLK_CFG_UPDATE1, (1 << ADSP_CK_UPDATE));
  498. /* ADSPPLL off */
  499. DRV_ClrReg32(ADSPPLL_CON0, (0x1 << 0));
  500. DRV_SetReg32(ADSPPLL_CON3, (0x1 << 1));
  501. DRV_ClrReg32(ADSPPLL_CON3, (0x1 << 0));
  502. /* 2. power off ADSP MTCMOS by spm */
  503. if (dormant) {
  504. dprintf(INFO, "%s bypass spm_mtcmos_ctrl_adsp_dormant(STA_POWER_DOWN)\n",
  505. module_prefix);
  506. spm_mtcmos_ctrl_adsp_dormant(STA_POWER_DOWN);
  507. } else {
  508. spm_mtcmos_ctrl_adsp_shut_down(STA_POWER_DOWN);
  509. }
  510. }
  511. }
  512. void adsp_sw_reset(void)
  513. {
  514. DRV_SetReg32(ADSP_CFGREG_SW_RSTN, ADSP_SW_RSTN);
  515. udelay(1);
  516. DRV_ClrReg32(ADSP_CFGREG_SW_RSTN, ADSP_SW_RSTN);
  517. }
  518. static void print_adsp_image_info(void)
  519. {
  520. uint32_t id;
  521. for (id = 0; id < ADSP_NUM_IMAGE; id++) {
  522. dprintf(INFO, "%s id=%d, base=0x%x, size=0x%x\n",
  523. __func__, id, (uint32_t)image_table[id].base, image_table[id].size);
  524. }
  525. }