cpu.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2018 NXP
  4. */
  5. #include <common.h>
  6. #include <clk.h>
  7. #include <cpu.h>
  8. #include <cpu_func.h>
  9. #include <dm.h>
  10. #include <init.h>
  11. #include <log.h>
  12. #include <asm/cache.h>
  13. #include <asm/global_data.h>
  14. #include <dm/device-internal.h>
  15. #include <dm/lists.h>
  16. #include <dm/uclass.h>
  17. #include <errno.h>
  18. #include <spl.h>
  19. #include <thermal.h>
  20. #include <asm/arch/sci/sci.h>
  21. #include <asm/arch/sys_proto.h>
  22. #include <asm/arch-imx/cpu.h>
  23. #include <asm/armv8/cpu.h>
  24. #include <asm/armv8/mmu.h>
  25. #include <asm/setup.h>
  26. #include <asm/mach-imx/boot_mode.h>
  27. #include <spl.h>
  28. DECLARE_GLOBAL_DATA_PTR;
  29. #define BT_PASSOVER_TAG 0x504F
  30. struct pass_over_info_t *get_pass_over_info(void)
  31. {
  32. struct pass_over_info_t *p =
  33. (struct pass_over_info_t *)PASS_OVER_INFO_ADDR;
  34. if (p->barker != BT_PASSOVER_TAG ||
  35. p->len != sizeof(struct pass_over_info_t))
  36. return NULL;
  37. return p;
  38. }
  39. int arch_cpu_init(void)
  40. {
  41. #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RECOVER_DATA_SECTION)
  42. spl_save_restore_data();
  43. #endif
  44. #ifdef CONFIG_SPL_BUILD
  45. struct pass_over_info_t *pass_over;
  46. if (is_soc_rev(CHIP_REV_A)) {
  47. pass_over = get_pass_over_info();
  48. if (pass_over && pass_over->g_ap_mu == 0) {
  49. /*
  50. * When ap_mu is 0, means the U-Boot booted
  51. * from first container
  52. */
  53. sc_misc_boot_status(-1, SC_MISC_BOOT_STATUS_SUCCESS);
  54. }
  55. }
  56. #endif
  57. return 0;
  58. }
  59. int arch_cpu_init_dm(void)
  60. {
  61. struct udevice *devp;
  62. int node, ret;
  63. node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8-mu");
  64. ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp);
  65. if (ret) {
  66. printf("could not get scu %d\n", ret);
  67. return ret;
  68. }
  69. if (is_imx8qm()) {
  70. ret = sc_pm_set_resource_power_mode(-1, SC_R_SMMU,
  71. SC_PM_PW_MODE_ON);
  72. if (ret)
  73. return ret;
  74. }
  75. return 0;
  76. }
  77. int print_bootinfo(void)
  78. {
  79. enum boot_device bt_dev = get_boot_device();
  80. puts("Boot: ");
  81. switch (bt_dev) {
  82. case SD1_BOOT:
  83. puts("SD0\n");
  84. break;
  85. case SD2_BOOT:
  86. puts("SD1\n");
  87. break;
  88. case SD3_BOOT:
  89. puts("SD2\n");
  90. break;
  91. case MMC1_BOOT:
  92. puts("MMC0\n");
  93. break;
  94. case MMC2_BOOT:
  95. puts("MMC1\n");
  96. break;
  97. case MMC3_BOOT:
  98. puts("MMC2\n");
  99. break;
  100. case FLEXSPI_BOOT:
  101. puts("FLEXSPI\n");
  102. break;
  103. case SATA_BOOT:
  104. puts("SATA\n");
  105. break;
  106. case NAND_BOOT:
  107. puts("NAND\n");
  108. break;
  109. case USB_BOOT:
  110. puts("USB\n");
  111. break;
  112. default:
  113. printf("Unknown device %u\n", bt_dev);
  114. break;
  115. }
  116. return 0;
  117. }
  118. enum boot_device get_boot_device(void)
  119. {
  120. enum boot_device boot_dev = SD1_BOOT;
  121. sc_rsrc_t dev_rsrc;
  122. sc_misc_get_boot_dev(-1, &dev_rsrc);
  123. switch (dev_rsrc) {
  124. case SC_R_SDHC_0:
  125. boot_dev = MMC1_BOOT;
  126. break;
  127. case SC_R_SDHC_1:
  128. boot_dev = SD2_BOOT;
  129. break;
  130. case SC_R_SDHC_2:
  131. boot_dev = SD3_BOOT;
  132. break;
  133. case SC_R_NAND:
  134. boot_dev = NAND_BOOT;
  135. break;
  136. case SC_R_FSPI_0:
  137. boot_dev = FLEXSPI_BOOT;
  138. break;
  139. case SC_R_SATA_0:
  140. boot_dev = SATA_BOOT;
  141. break;
  142. case SC_R_USB_0:
  143. case SC_R_USB_1:
  144. case SC_R_USB_2:
  145. boot_dev = USB_BOOT;
  146. break;
  147. default:
  148. break;
  149. }
  150. return boot_dev;
  151. }
  152. #ifdef CONFIG_SERIAL_TAG
  153. #define FUSE_UNIQUE_ID_WORD0 16
  154. #define FUSE_UNIQUE_ID_WORD1 17
  155. void get_board_serial(struct tag_serialnr *serialnr)
  156. {
  157. sc_err_t err;
  158. u32 val1 = 0, val2 = 0;
  159. u32 word1, word2;
  160. if (!serialnr)
  161. return;
  162. word1 = FUSE_UNIQUE_ID_WORD0;
  163. word2 = FUSE_UNIQUE_ID_WORD1;
  164. err = sc_misc_otp_fuse_read(-1, word1, &val1);
  165. if (err != SC_ERR_NONE) {
  166. printf("%s fuse %d read error: %d\n", __func__, word1, err);
  167. return;
  168. }
  169. err = sc_misc_otp_fuse_read(-1, word2, &val2);
  170. if (err != SC_ERR_NONE) {
  171. printf("%s fuse %d read error: %d\n", __func__, word2, err);
  172. return;
  173. }
  174. serialnr->low = val1;
  175. serialnr->high = val2;
  176. }
  177. #endif /*CONFIG_SERIAL_TAG*/
  178. #ifdef CONFIG_ENV_IS_IN_MMC
  179. __weak int board_mmc_get_env_dev(int devno)
  180. {
  181. return CONFIG_SYS_MMC_ENV_DEV;
  182. }
  183. int mmc_get_env_dev(void)
  184. {
  185. sc_rsrc_t dev_rsrc;
  186. int devno;
  187. sc_misc_get_boot_dev(-1, &dev_rsrc);
  188. switch (dev_rsrc) {
  189. case SC_R_SDHC_0:
  190. devno = 0;
  191. break;
  192. case SC_R_SDHC_1:
  193. devno = 1;
  194. break;
  195. case SC_R_SDHC_2:
  196. devno = 2;
  197. break;
  198. default:
  199. /* If not boot from sd/mmc, use default value */
  200. return CONFIG_SYS_MMC_ENV_DEV;
  201. }
  202. return board_mmc_get_env_dev(devno);
  203. }
  204. #endif
  205. #define MEMSTART_ALIGNMENT SZ_2M /* Align the memory start with 2MB */
  206. static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start,
  207. sc_faddr_t *addr_end)
  208. {
  209. sc_faddr_t start, end;
  210. int ret;
  211. bool owned;
  212. owned = sc_rm_is_memreg_owned(-1, mr);
  213. if (owned) {
  214. ret = sc_rm_get_memreg_info(-1, mr, &start, &end);
  215. if (ret) {
  216. printf("Memreg get info failed, %d\n", ret);
  217. return -EINVAL;
  218. }
  219. debug("0x%llx -- 0x%llx\n", start, end);
  220. *addr_start = start;
  221. *addr_end = end;
  222. return 0;
  223. }
  224. return -EINVAL;
  225. }
  226. __weak void board_mem_get_layout(u64 *phys_sdram_1_start,
  227. u64 *phys_sdram_1_size,
  228. u64 *phys_sdram_2_start,
  229. u64 *phys_sdram_2_size)
  230. {
  231. *phys_sdram_1_start = PHYS_SDRAM_1;
  232. *phys_sdram_1_size = PHYS_SDRAM_1_SIZE;
  233. *phys_sdram_2_start = PHYS_SDRAM_2;
  234. *phys_sdram_2_size = PHYS_SDRAM_2_SIZE;
  235. }
  236. phys_size_t get_effective_memsize(void)
  237. {
  238. sc_rm_mr_t mr;
  239. sc_faddr_t start, end, end1, start_aligned;
  240. u64 phys_sdram_1_start, phys_sdram_1_size;
  241. u64 phys_sdram_2_start, phys_sdram_2_size;
  242. int err;
  243. board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
  244. &phys_sdram_2_start, &phys_sdram_2_size);
  245. end1 = (sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size;
  246. for (mr = 0; mr < 64; mr++) {
  247. err = get_owned_memreg(mr, &start, &end);
  248. if (!err) {
  249. start_aligned = roundup(start, MEMSTART_ALIGNMENT);
  250. /* Too small memory region, not use it */
  251. if (start_aligned > end)
  252. continue;
  253. /* Find the memory region runs the U-Boot */
  254. if (start >= phys_sdram_1_start && start <= end1 &&
  255. (start <= CONFIG_SYS_TEXT_BASE &&
  256. end >= CONFIG_SYS_TEXT_BASE)) {
  257. if ((end + 1) <=
  258. ((sc_faddr_t)phys_sdram_1_start +
  259. phys_sdram_1_size))
  260. return (end - phys_sdram_1_start + 1);
  261. else
  262. return phys_sdram_1_size;
  263. }
  264. }
  265. }
  266. return phys_sdram_1_size;
  267. }
  268. int dram_init(void)
  269. {
  270. sc_rm_mr_t mr;
  271. sc_faddr_t start, end, end1, end2;
  272. u64 phys_sdram_1_start, phys_sdram_1_size;
  273. u64 phys_sdram_2_start, phys_sdram_2_size;
  274. int err;
  275. board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
  276. &phys_sdram_2_start, &phys_sdram_2_size);
  277. end1 = (sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size;
  278. end2 = (sc_faddr_t)phys_sdram_2_start + phys_sdram_2_size;
  279. for (mr = 0; mr < 64; mr++) {
  280. err = get_owned_memreg(mr, &start, &end);
  281. if (!err) {
  282. start = roundup(start, MEMSTART_ALIGNMENT);
  283. /* Too small memory region, not use it */
  284. if (start > end)
  285. continue;
  286. if (start >= phys_sdram_1_start && start <= end1) {
  287. if ((end + 1) <= end1)
  288. gd->ram_size += end - start + 1;
  289. else
  290. gd->ram_size += end1 - start;
  291. } else if (start >= phys_sdram_2_start &&
  292. start <= end2) {
  293. if ((end + 1) <= end2)
  294. gd->ram_size += end - start + 1;
  295. else
  296. gd->ram_size += end2 - start;
  297. }
  298. }
  299. }
  300. /* If error, set to the default value */
  301. if (!gd->ram_size) {
  302. gd->ram_size = phys_sdram_1_size;
  303. gd->ram_size += phys_sdram_2_size;
  304. }
  305. return 0;
  306. }
  307. static void dram_bank_sort(int current_bank)
  308. {
  309. phys_addr_t start;
  310. phys_size_t size;
  311. while (current_bank > 0) {
  312. if (gd->bd->bi_dram[current_bank - 1].start >
  313. gd->bd->bi_dram[current_bank].start) {
  314. start = gd->bd->bi_dram[current_bank - 1].start;
  315. size = gd->bd->bi_dram[current_bank - 1].size;
  316. gd->bd->bi_dram[current_bank - 1].start =
  317. gd->bd->bi_dram[current_bank].start;
  318. gd->bd->bi_dram[current_bank - 1].size =
  319. gd->bd->bi_dram[current_bank].size;
  320. gd->bd->bi_dram[current_bank].start = start;
  321. gd->bd->bi_dram[current_bank].size = size;
  322. }
  323. current_bank--;
  324. }
  325. }
  326. int dram_init_banksize(void)
  327. {
  328. sc_rm_mr_t mr;
  329. sc_faddr_t start, end, end1, end2;
  330. int i = 0;
  331. u64 phys_sdram_1_start, phys_sdram_1_size;
  332. u64 phys_sdram_2_start, phys_sdram_2_size;
  333. int err;
  334. board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
  335. &phys_sdram_2_start, &phys_sdram_2_size);
  336. end1 = (sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size;
  337. end2 = (sc_faddr_t)phys_sdram_2_start + phys_sdram_2_size;
  338. for (mr = 0; mr < 64 && i < CONFIG_NR_DRAM_BANKS; mr++) {
  339. err = get_owned_memreg(mr, &start, &end);
  340. if (!err) {
  341. start = roundup(start, MEMSTART_ALIGNMENT);
  342. if (start > end) /* Small memory region, no use it */
  343. continue;
  344. if (start >= phys_sdram_1_start && start <= end1) {
  345. gd->bd->bi_dram[i].start = start;
  346. if ((end + 1) <= end1)
  347. gd->bd->bi_dram[i].size =
  348. end - start + 1;
  349. else
  350. gd->bd->bi_dram[i].size = end1 - start;
  351. dram_bank_sort(i);
  352. i++;
  353. } else if (start >= phys_sdram_2_start && start <= end2) {
  354. gd->bd->bi_dram[i].start = start;
  355. if ((end + 1) <= end2)
  356. gd->bd->bi_dram[i].size =
  357. end - start + 1;
  358. else
  359. gd->bd->bi_dram[i].size = end2 - start;
  360. dram_bank_sort(i);
  361. i++;
  362. }
  363. }
  364. }
  365. /* If error, set to the default value */
  366. if (!i) {
  367. gd->bd->bi_dram[0].start = phys_sdram_1_start;
  368. gd->bd->bi_dram[0].size = phys_sdram_1_size;
  369. gd->bd->bi_dram[1].start = phys_sdram_2_start;
  370. gd->bd->bi_dram[1].size = phys_sdram_2_size;
  371. }
  372. return 0;
  373. }
  374. static u64 get_block_attrs(sc_faddr_t addr_start)
  375. {
  376. u64 attr = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE |
  377. PTE_BLOCK_PXN | PTE_BLOCK_UXN;
  378. u64 phys_sdram_1_start, phys_sdram_1_size;
  379. u64 phys_sdram_2_start, phys_sdram_2_size;
  380. board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
  381. &phys_sdram_2_start, &phys_sdram_2_size);
  382. if ((addr_start >= phys_sdram_1_start &&
  383. addr_start <= ((sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size)) ||
  384. (addr_start >= phys_sdram_2_start &&
  385. addr_start <= ((sc_faddr_t)phys_sdram_2_start + phys_sdram_2_size)))
  386. return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE);
  387. return attr;
  388. }
  389. static u64 get_block_size(sc_faddr_t addr_start, sc_faddr_t addr_end)
  390. {
  391. sc_faddr_t end1, end2;
  392. u64 phys_sdram_1_start, phys_sdram_1_size;
  393. u64 phys_sdram_2_start, phys_sdram_2_size;
  394. board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
  395. &phys_sdram_2_start, &phys_sdram_2_size);
  396. end1 = (sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size;
  397. end2 = (sc_faddr_t)phys_sdram_2_start + phys_sdram_2_size;
  398. if (addr_start >= phys_sdram_1_start && addr_start <= end1) {
  399. if ((addr_end + 1) > end1)
  400. return end1 - addr_start;
  401. } else if (addr_start >= phys_sdram_2_start && addr_start <= end2) {
  402. if ((addr_end + 1) > end2)
  403. return end2 - addr_start;
  404. }
  405. return (addr_end - addr_start + 1);
  406. }
  407. #define MAX_PTE_ENTRIES 512
  408. #define MAX_MEM_MAP_REGIONS 16
  409. static struct mm_region imx8_mem_map[MAX_MEM_MAP_REGIONS];
  410. struct mm_region *mem_map = imx8_mem_map;
  411. void enable_caches(void)
  412. {
  413. sc_rm_mr_t mr;
  414. sc_faddr_t start, end;
  415. int err, i;
  416. /* Create map for registers access from 0x1c000000 to 0x80000000*/
  417. imx8_mem_map[0].virt = 0x1c000000UL;
  418. imx8_mem_map[0].phys = 0x1c000000UL;
  419. imx8_mem_map[0].size = 0x64000000UL;
  420. imx8_mem_map[0].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
  421. PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN;
  422. i = 1;
  423. for (mr = 0; mr < 64 && i < MAX_MEM_MAP_REGIONS; mr++) {
  424. err = get_owned_memreg(mr, &start, &end);
  425. if (!err) {
  426. imx8_mem_map[i].virt = start;
  427. imx8_mem_map[i].phys = start;
  428. imx8_mem_map[i].size = get_block_size(start, end);
  429. imx8_mem_map[i].attrs = get_block_attrs(start);
  430. i++;
  431. }
  432. }
  433. if (i < MAX_MEM_MAP_REGIONS) {
  434. imx8_mem_map[i].size = 0;
  435. imx8_mem_map[i].attrs = 0;
  436. } else {
  437. puts("Error, need more MEM MAP REGIONS reserved\n");
  438. icache_enable();
  439. return;
  440. }
  441. for (i = 0; i < MAX_MEM_MAP_REGIONS; i++) {
  442. debug("[%d] vir = 0x%llx phys = 0x%llx size = 0x%llx attrs = 0x%llx\n",
  443. i, imx8_mem_map[i].virt, imx8_mem_map[i].phys,
  444. imx8_mem_map[i].size, imx8_mem_map[i].attrs);
  445. }
  446. icache_enable();
  447. dcache_enable();
  448. }
  449. #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
  450. u64 get_page_table_size(void)
  451. {
  452. u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
  453. u64 size = 0;
  454. /*
  455. * For each memory region, the max table size:
  456. * 2 level 3 tables + 2 level 2 tables + 1 level 1 table
  457. */
  458. size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt;
  459. /*
  460. * We need to duplicate our page table once to have an emergency pt to
  461. * resort to when splitting page tables later on
  462. */
  463. size *= 2;
  464. /*
  465. * We may need to split page tables later on if dcache settings change,
  466. * so reserve up to 4 (random pick) page tables for that.
  467. */
  468. size += one_pt * 4;
  469. return size;
  470. }
  471. #endif
  472. #if defined(CONFIG_IMX8QM)
  473. #define FUSE_MAC0_WORD0 452
  474. #define FUSE_MAC0_WORD1 453
  475. #define FUSE_MAC1_WORD0 454
  476. #define FUSE_MAC1_WORD1 455
  477. #elif defined(CONFIG_IMX8QXP)
  478. #define FUSE_MAC0_WORD0 708
  479. #define FUSE_MAC0_WORD1 709
  480. #define FUSE_MAC1_WORD0 710
  481. #define FUSE_MAC1_WORD1 711
  482. #endif
  483. void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
  484. {
  485. u32 word[2], val[2] = {};
  486. int i, ret;
  487. if (dev_id == 0) {
  488. word[0] = FUSE_MAC0_WORD0;
  489. word[1] = FUSE_MAC0_WORD1;
  490. } else {
  491. word[0] = FUSE_MAC1_WORD0;
  492. word[1] = FUSE_MAC1_WORD1;
  493. }
  494. for (i = 0; i < 2; i++) {
  495. ret = sc_misc_otp_fuse_read(-1, word[i], &val[i]);
  496. if (ret < 0)
  497. goto err;
  498. }
  499. mac[0] = val[0];
  500. mac[1] = val[0] >> 8;
  501. mac[2] = val[0] >> 16;
  502. mac[3] = val[0] >> 24;
  503. mac[4] = val[1];
  504. mac[5] = val[1] >> 8;
  505. debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n",
  506. __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  507. return;
  508. err:
  509. printf("%s: fuse %d, err: %d\n", __func__, word[i], ret);
  510. }
  511. u32 get_cpu_rev(void)
  512. {
  513. u32 id = 0, rev = 0;
  514. int ret;
  515. ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id);
  516. if (ret)
  517. return 0;
  518. rev = (id >> 5) & 0xf;
  519. id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */
  520. return (id << 12) | rev;
  521. }
  522. void board_boot_order(u32 *spl_boot_list)
  523. {
  524. spl_boot_list[0] = spl_boot_device();
  525. if (spl_boot_list[0] == BOOT_DEVICE_SPI) {
  526. /* Check whether we own the flexspi0, if not, use NOR boot */
  527. if (!sc_rm_is_resource_owned(-1, SC_R_FSPI_0))
  528. spl_boot_list[0] = BOOT_DEVICE_NOR;
  529. }
  530. }
  531. bool m4_parts_booted(void)
  532. {
  533. sc_rm_pt_t m4_parts[2];
  534. int err;
  535. err = sc_rm_get_resource_owner(-1, SC_R_M4_0_PID0, &m4_parts[0]);
  536. if (err) {
  537. printf("%s get resource [%d] owner error: %d\n", __func__,
  538. SC_R_M4_0_PID0, err);
  539. return false;
  540. }
  541. if (sc_pm_is_partition_started(-1, m4_parts[0]))
  542. return true;
  543. if (is_imx8qm()) {
  544. err = sc_rm_get_resource_owner(-1, SC_R_M4_1_PID0, &m4_parts[1]);
  545. if (err) {
  546. printf("%s get resource [%d] owner error: %d\n",
  547. __func__, SC_R_M4_1_PID0, err);
  548. return false;
  549. }
  550. if (sc_pm_is_partition_started(-1, m4_parts[1]))
  551. return true;
  552. }
  553. return false;
  554. }