blob: 89670b1c4c2d6fa69468459fe149dac76c70c2f7 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Peng Fanfcdbde72018-01-10 13:20:37 +08002/*
Gaurav Jain2cddfcb2022-03-24 11:50:27 +05303 * Copyright 2017-2019, 2021 NXP
Peng Fanfcdbde72018-01-10 13:20:37 +08004 *
5 * Peng Fan <peng.fan@nxp.com>
Peng Fanfcdbde72018-01-10 13:20:37 +08006 */
7
8#include <common.h>
Simon Glass9edefc22019-11-14 12:57:37 -07009#include <cpu_func.h>
Simon Glass7fe32b32022-03-04 08:43:05 -070010#include <event.h>
Simon Glass691d7192020-05-10 11:40:02 -060011#include <init.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060012#include <log.h>
Peng Fanfcdbde72018-01-10 13:20:37 +080013#include <asm/arch/imx-regs.h>
Simon Glass401d1c42020-10-30 21:38:53 -060014#include <asm/global_data.h>
Peng Fanfcdbde72018-01-10 13:20:37 +080015#include <asm/io.h>
16#include <asm/arch/clock.h>
17#include <asm/arch/sys_proto.h>
18#include <asm/mach-imx/hab.h>
19#include <asm/mach-imx/boot_mode.h>
20#include <asm/mach-imx/syscounter.h>
Peng Fan2f3c9202020-07-09 13:39:26 +080021#include <asm/ptrace.h>
Peng Fanfcdbde72018-01-10 13:20:37 +080022#include <asm/armv8/mmu.h>
Peng Fane663c702019-08-27 06:25:58 +000023#include <dm/uclass.h>
Gaurav Jain2cddfcb2022-03-24 11:50:27 +053024#include <dm/device.h>
Peng Fan2f3c9202020-07-09 13:39:26 +080025#include <efi_loader.h>
Ye Li2707faf2019-07-15 01:16:46 -070026#include <env.h>
27#include <env_internal.h>
Peng Fanfcdbde72018-01-10 13:20:37 +080028#include <errno.h>
29#include <fdt_support.h>
30#include <fsl_wdog.h>
31#include <imx_sip.h>
Peng Fana2f143e2020-05-11 15:14:04 +080032#include <linux/arm-smccc.h>
Simon Glasscd93d622020-05-10 11:40:13 -060033#include <linux/bitops.h>
Peng Fanfcdbde72018-01-10 13:20:37 +080034
35DECLARE_GLOBAL_DATA_PTR;
36
Stefano Babicd714a752019-09-20 08:47:53 +020037#if defined(CONFIG_IMX_HAB)
Peng Fanfcdbde72018-01-10 13:20:37 +080038struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
39 .bank = 1,
40 .word = 3,
41};
42#endif
43
44int timer_init(void)
45{
46#ifdef CONFIG_SPL_BUILD
47 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
48 unsigned long freq = readl(&sctr->cntfid0);
49
50 /* Update with accurate clock frequency */
51 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
52
53 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
54 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
55#endif
56
57 gd->arch.tbl = 0;
58 gd->arch.tbu = 0;
59
60 return 0;
61}
62
63void enable_tzc380(void)
64{
65 struct iomuxc_gpr_base_regs *gpr =
66 (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
67
68 /* Enable TZASC and lock setting */
69 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN);
70 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK);
Andrey Zhizhikin1289ff72022-01-24 21:48:09 +010071
72 /*
73 * According to TRM, TZASC_ID_SWAP_BYPASS should be set in
74 * order to avoid AXI Bus errors when GPU is in use
75 */
Peng Fana07c7182019-12-27 10:19:42 +080076 if (is_imx8mm() || is_imx8mn() || is_imx8mp())
Andrey Zhizhikin1289ff72022-01-24 21:48:09 +010077 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS);
78
79 /*
80 * imx8mn and imx8mp implements the lock bit for
81 * TZASC_ID_SWAP_BYPASS, enable it to lock settings
82 */
83 if (is_imx8mn() || is_imx8mp())
84 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS_LOCK);
85
Ye Lib3cf0a82019-08-27 06:25:34 +000086 /*
87 * set Region 0 attribute to allow secure and non-secure
88 * read/write permission. Found some masters like usb dwc3
89 * controllers can't work with secure memory.
90 */
91 writel(0xf0000000, TZASC_BASE_ADDR + 0x108);
Peng Fanfcdbde72018-01-10 13:20:37 +080092}
93
94void set_wdog_reset(struct wdog_regs *wdog)
95{
96 /*
97 * Output WDOG_B signal to reset external pmic or POR_B decided by
98 * the board design. Without external reset, the peripherals/DDR/
99 * PMIC are not reset, that may cause system working abnormal.
100 * WDZST bit is write-once only bit. Align this bit in kernel,
101 * otherwise kernel code will have no chance to set this bit.
102 */
103 setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK);
104}
105
106static struct mm_region imx8m_mem_map[] = {
107 {
108 /* ROM */
109 .virt = 0x0UL,
110 .phys = 0x0UL,
111 .size = 0x100000UL,
112 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
113 PTE_BLOCK_OUTER_SHARE
114 }, {
Gary Bissoncb158852018-11-14 17:55:28 +0100115 /* CAAM */
116 .virt = 0x100000UL,
117 .phys = 0x100000UL,
118 .size = 0x8000UL,
119 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
120 PTE_BLOCK_NON_SHARE |
121 PTE_BLOCK_PXN | PTE_BLOCK_UXN
122 }, {
Marek Vasut09d86ea2021-02-25 21:52:26 +0100123 /* OCRAM_S */
124 .virt = 0x180000UL,
125 .phys = 0x180000UL,
126 .size = 0x8000UL,
127 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
128 PTE_BLOCK_OUTER_SHARE
129 }, {
Gary Bissoncb158852018-11-14 17:55:28 +0100130 /* TCM */
131 .virt = 0x7C0000UL,
132 .phys = 0x7C0000UL,
133 .size = 0x80000UL,
134 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
135 PTE_BLOCK_NON_SHARE |
136 PTE_BLOCK_PXN | PTE_BLOCK_UXN
137 }, {
Peng Fanfcdbde72018-01-10 13:20:37 +0800138 /* OCRAM */
139 .virt = 0x900000UL,
140 .phys = 0x900000UL,
141 .size = 0x200000UL,
142 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
143 PTE_BLOCK_OUTER_SHARE
144 }, {
145 /* AIPS */
146 .virt = 0xB00000UL,
147 .phys = 0xB00000UL,
148 .size = 0x3f500000UL,
149 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
150 PTE_BLOCK_NON_SHARE |
151 PTE_BLOCK_PXN | PTE_BLOCK_UXN
152 }, {
153 /* DRAM1 */
154 .virt = 0x40000000UL,
155 .phys = 0x40000000UL,
Peng Fan59efa6b2019-08-27 06:25:27 +0000156 .size = PHYS_SDRAM_SIZE,
Peng Fanfcdbde72018-01-10 13:20:37 +0800157 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
158 PTE_BLOCK_OUTER_SHARE
Peng Fan59efa6b2019-08-27 06:25:27 +0000159#ifdef PHYS_SDRAM_2_SIZE
Peng Fanfcdbde72018-01-10 13:20:37 +0800160 }, {
161 /* DRAM2 */
162 .virt = 0x100000000UL,
163 .phys = 0x100000000UL,
Peng Fan59efa6b2019-08-27 06:25:27 +0000164 .size = PHYS_SDRAM_2_SIZE,
Peng Fanfcdbde72018-01-10 13:20:37 +0800165 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
166 PTE_BLOCK_OUTER_SHARE
Peng Fan59efa6b2019-08-27 06:25:27 +0000167#endif
Peng Fanfcdbde72018-01-10 13:20:37 +0800168 }, {
Peng Fan3c417282020-07-09 15:26:06 +0800169 /* empty entrie to split table entry 5 if needed when TEEs are used */
170 0,
171 }, {
Peng Fanfcdbde72018-01-10 13:20:37 +0800172 /* List terminator */
173 0,
174 }
175};
176
177struct mm_region *mem_map = imx8m_mem_map;
178
Marek Vasut076dc922021-02-27 14:59:00 +0100179static unsigned int imx8m_find_dram_entry_in_mem_map(void)
180{
181 int i;
182
183 for (i = 0; i < ARRAY_SIZE(imx8m_mem_map); i++)
184 if (imx8m_mem_map[i].phys == CONFIG_SYS_SDRAM_BASE)
185 return i;
186
187 hang(); /* Entry not found, this must never happen. */
188}
189
Peng Fan59efa6b2019-08-27 06:25:27 +0000190void enable_caches(void)
191{
Ye Li1c9bc0f2022-04-07 15:55:56 +0800192 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
193 * If OPTEE does not run, still update the MMU table according to dram banks structure
194 * to set correct dram size from board_phys_sdram_size
195 */
196 int i = 0;
197 /*
198 * please make sure that entry initial value matches
199 * imx8m_mem_map for DRAM1
200 */
201 int entry = imx8m_find_dram_entry_in_mem_map();
202 u64 attrs = imx8m_mem_map[entry].attrs;
Peng Fan3c417282020-07-09 15:26:06 +0800203
Ye Li1c9bc0f2022-04-07 15:55:56 +0800204 while (i < CONFIG_NR_DRAM_BANKS &&
205 entry < ARRAY_SIZE(imx8m_mem_map)) {
206 if (gd->bd->bi_dram[i].start == 0)
207 break;
208 imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start;
209 imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start;
210 imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size;
211 imx8m_mem_map[entry].attrs = attrs;
212 debug("Added memory mapping (%d): %llx %llx\n", entry,
213 imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size);
214 i++; entry++;
Peng Fan3c417282020-07-09 15:26:06 +0800215 }
Peng Fan59efa6b2019-08-27 06:25:27 +0000216
217 icache_enable();
218 dcache_enable();
219}
220
Peng Fan3c417282020-07-09 15:26:06 +0800221__weak int board_phys_sdram_size(phys_size_t *size)
222{
223 if (!size)
224 return -EINVAL;
225
226 *size = PHYS_SDRAM_SIZE;
Ye Li1c9bc0f2022-04-07 15:55:56 +0800227
228#ifdef PHYS_SDRAM_2_SIZE
229 *size += PHYS_SDRAM_2_SIZE;
230#endif
Peng Fan3c417282020-07-09 15:26:06 +0800231 return 0;
232}
233
234int dram_init(void)
235{
236 phys_size_t sdram_size;
237 int ret;
238
239 ret = board_phys_sdram_size(&sdram_size);
240 if (ret)
241 return ret;
242
243 /* rom_pointer[1] contains the size of TEE occupies */
244 if (rom_pointer[1])
245 gd->ram_size = sdram_size - rom_pointer[1];
246 else
247 gd->ram_size = sdram_size;
248
Peng Fan3c417282020-07-09 15:26:06 +0800249 return 0;
250}
251
252int dram_init_banksize(void)
253{
254 int bank = 0;
255 int ret;
256 phys_size_t sdram_size;
Ye Li1c9bc0f2022-04-07 15:55:56 +0800257 phys_size_t sdram_b1_size, sdram_b2_size;
Peng Fan3c417282020-07-09 15:26:06 +0800258
259 ret = board_phys_sdram_size(&sdram_size);
260 if (ret)
261 return ret;
262
Ye Li1c9bc0f2022-04-07 15:55:56 +0800263 /* Bank 1 can't cross over 4GB space */
264 if (sdram_size > 0xc0000000) {
265 sdram_b1_size = 0xc0000000;
266 sdram_b2_size = sdram_size - 0xc0000000;
267 } else {
268 sdram_b1_size = sdram_size;
269 sdram_b2_size = 0;
270 }
271
Peng Fan3c417282020-07-09 15:26:06 +0800272 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
273 if (rom_pointer[1]) {
274 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
275 phys_size_t optee_size = (size_t)rom_pointer[1];
276
277 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
Ye Li1c9bc0f2022-04-07 15:55:56 +0800278 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
Peng Fan3c417282020-07-09 15:26:06 +0800279 if (++bank >= CONFIG_NR_DRAM_BANKS) {
280 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
281 return -1;
282 }
283
284 gd->bd->bi_dram[bank].start = optee_start + optee_size;
285 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
Ye Li1c9bc0f2022-04-07 15:55:56 +0800286 sdram_b1_size - gd->bd->bi_dram[bank].start;
Peng Fan3c417282020-07-09 15:26:06 +0800287 }
288 } else {
Ye Li1c9bc0f2022-04-07 15:55:56 +0800289 gd->bd->bi_dram[bank].size = sdram_b1_size;
Peng Fan3c417282020-07-09 15:26:06 +0800290 }
291
Ye Li1c9bc0f2022-04-07 15:55:56 +0800292 if (sdram_b2_size) {
293 if (++bank >= CONFIG_NR_DRAM_BANKS) {
294 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
295 return -1;
296 }
297 gd->bd->bi_dram[bank].start = 0x100000000UL;
298 gd->bd->bi_dram[bank].size = sdram_b2_size;
Peng Fan3c417282020-07-09 15:26:06 +0800299 }
Peng Fan3c417282020-07-09 15:26:06 +0800300
301 return 0;
302}
303
304phys_size_t get_effective_memsize(void)
305{
Ye Li1c9bc0f2022-04-07 15:55:56 +0800306 int ret;
307 phys_size_t sdram_size;
308 phys_size_t sdram_b1_size;
309 ret = board_phys_sdram_size(&sdram_size);
310 if (!ret) {
311 /* Bank 1 can't cross over 4GB space */
312 if (sdram_size > 0xc0000000) {
313 sdram_b1_size = 0xc0000000;
314 } else {
315 sdram_b1_size = sdram_size;
316 }
Peng Fan3c417282020-07-09 15:26:06 +0800317
Ye Li1c9bc0f2022-04-07 15:55:56 +0800318 if (rom_pointer[1]) {
319 /* We will relocate u-boot to Top of dram1. Tee position has two cases:
320 * 1. At the top of dram1, Then return the size removed optee size.
321 * 2. In the middle of dram1, return the size of dram1.
322 */
323 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
324 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
325 }
326
327 return sdram_b1_size;
328 } else {
329 return PHYS_SDRAM_SIZE;
330 }
Peng Fan3c417282020-07-09 15:26:06 +0800331}
332
Frieder Schrempfe27bddf2021-06-07 14:36:44 +0200333ulong board_get_usable_ram_top(ulong total_size)
334{
Ying-Chun Liu (PaulLiu)5a6af8c2021-08-23 10:43:06 +0800335 ulong top_addr = PHYS_SDRAM + gd->ram_size;
336
Frieder Schrempfe27bddf2021-06-07 14:36:44 +0200337 /*
338 * Some IPs have their accessible address space restricted by
339 * the interconnect. Let's make sure U-Boot only ever uses the
340 * space below the 4G address boundary (which is 3GiB big),
341 * even when the effective available memory is bigger.
342 */
Ying-Chun Liu (PaulLiu)5a6af8c2021-08-23 10:43:06 +0800343 if (top_addr > 0x80000000)
344 top_addr = 0x80000000;
Frieder Schrempfe27bddf2021-06-07 14:36:44 +0200345
Ying-Chun Liu (PaulLiu)5a6af8c2021-08-23 10:43:06 +0800346 /*
347 * rom_pointer[0] stores the TEE memory start address.
348 * rom_pointer[1] stores the size TEE uses.
349 * We need to reserve the memory region for TEE.
350 */
351 if (rom_pointer[0] && rom_pointer[1] && top_addr > rom_pointer[0])
352 top_addr = rom_pointer[0];
353
354 return top_addr;
Frieder Schrempfe27bddf2021-06-07 14:36:44 +0200355}
356
Peng Fan78db9a52019-08-27 06:25:17 +0000357static u32 get_cpu_variant_type(u32 type)
358{
359 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
360 struct fuse_bank *bank = &ocotp->bank[1];
361 struct fuse_bank1_regs *fuse =
362 (struct fuse_bank1_regs *)bank->fuse_regs;
363
364 u32 value = readl(&fuse->tester4);
365
Peng Fancb1a1de2020-02-05 17:34:54 +0800366 if (type == MXC_CPU_IMX8MQ) {
367 if ((value & 0x3) == 0x2)
368 return MXC_CPU_IMX8MD;
369 else if (value & 0x200000)
370 return MXC_CPU_IMX8MQL;
371
372 } else if (type == MXC_CPU_IMX8MM) {
Peng Fan78db9a52019-08-27 06:25:17 +0000373 switch (value & 0x3) {
374 case 2:
375 if (value & 0x1c0000)
376 return MXC_CPU_IMX8MMDL;
377 else
378 return MXC_CPU_IMX8MMD;
379 case 3:
380 if (value & 0x1c0000)
381 return MXC_CPU_IMX8MMSL;
382 else
383 return MXC_CPU_IMX8MMS;
384 default:
385 if (value & 0x1c0000)
386 return MXC_CPU_IMX8MML;
387 break;
388 }
Peng Fanc9154032020-02-05 17:39:27 +0800389 } else if (type == MXC_CPU_IMX8MN) {
390 switch (value & 0x3) {
391 case 2:
Ye Lic4f78cb2021-03-19 15:57:11 +0800392 if (value & 0x1000000) {
393 if (value & 0x10000000) /* MIPI DSI */
394 return MXC_CPU_IMX8MNUD;
395 else
396 return MXC_CPU_IMX8MNDL;
397 } else {
Peng Fanc9154032020-02-05 17:39:27 +0800398 return MXC_CPU_IMX8MND;
Ye Lic4f78cb2021-03-19 15:57:11 +0800399 }
Peng Fanc9154032020-02-05 17:39:27 +0800400 case 3:
Ye Lic4f78cb2021-03-19 15:57:11 +0800401 if (value & 0x1000000) {
402 if (value & 0x10000000) /* MIPI DSI */
403 return MXC_CPU_IMX8MNUS;
404 else
405 return MXC_CPU_IMX8MNSL;
406 } else {
Peng Fanc9154032020-02-05 17:39:27 +0800407 return MXC_CPU_IMX8MNS;
Ye Lic4f78cb2021-03-19 15:57:11 +0800408 }
Peng Fanc9154032020-02-05 17:39:27 +0800409 default:
Ye Lic4f78cb2021-03-19 15:57:11 +0800410 if (value & 0x1000000) {
411 if (value & 0x10000000) /* MIPI DSI */
412 return MXC_CPU_IMX8MNUQ;
413 else
414 return MXC_CPU_IMX8MNL;
415 }
Peng Fanc9154032020-02-05 17:39:27 +0800416 break;
417 }
Ye Lid1eee7e2020-04-20 20:12:54 -0700418 } else if (type == MXC_CPU_IMX8MP) {
419 u32 value0 = readl(&fuse->tester3);
420 u32 flag = 0;
421
422 if ((value0 & 0xc0000) == 0x80000)
423 return MXC_CPU_IMX8MPD;
424
425 /* vpu disabled */
426 if ((value0 & 0x43000000) == 0x43000000)
427 flag = 1;
428
429 /* npu disabled*/
430 if ((value & 0x8) == 0x8)
Peng Fan36bfd712022-04-07 15:55:52 +0800431 flag |= BIT(1);
Ye Lid1eee7e2020-04-20 20:12:54 -0700432
433 /* isp disabled */
434 if ((value & 0x3) == 0x3)
Peng Fan36bfd712022-04-07 15:55:52 +0800435 flag |= BIT(2);
436
437 /* gpu disabled */
438 if ((value & 0xc0) == 0xc0)
439 flag |= BIT(3);
440
441 /* lvds disabled */
442 if ((value & 0x180000) == 0x180000)
443 flag |= BIT(4);
444
445 /* mipi dsi disabled */
446 if ((value & 0x60000) == 0x60000)
447 flag |= BIT(5);
Ye Lid1eee7e2020-04-20 20:12:54 -0700448
449 switch (flag) {
Peng Fan36bfd712022-04-07 15:55:52 +0800450 case 0x3f:
451 return MXC_CPU_IMX8MPUL;
Ye Lid1eee7e2020-04-20 20:12:54 -0700452 case 7:
453 return MXC_CPU_IMX8MPL;
Ye Lid1eee7e2020-04-20 20:12:54 -0700454 case 2:
455 return MXC_CPU_IMX8MP6;
Ye Lid1eee7e2020-04-20 20:12:54 -0700456 default:
457 break;
458 }
459
Peng Fan78db9a52019-08-27 06:25:17 +0000460 }
461
462 return type;
463}
464
Peng Fanfcdbde72018-01-10 13:20:37 +0800465u32 get_cpu_rev(void)
466{
467 struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
468 u32 reg = readl(&ana_pll->digprog);
469 u32 type = (reg >> 16) & 0xff;
Peng Fan78db9a52019-08-27 06:25:17 +0000470 u32 major_low = (reg >> 8) & 0xff;
Peng Fanfcdbde72018-01-10 13:20:37 +0800471 u32 rom_version;
472
473 reg &= 0xff;
474
Peng Fan625b03d2019-12-27 10:14:02 +0800475 /* iMX8MP */
476 if (major_low == 0x43) {
Ye Lid1eee7e2020-04-20 20:12:54 -0700477 type = get_cpu_variant_type(MXC_CPU_IMX8MP);
Peng Fan625b03d2019-12-27 10:14:02 +0800478 } else if (major_low == 0x42) {
479 /* iMX8MN */
Peng Fanc9154032020-02-05 17:39:27 +0800480 type = get_cpu_variant_type(MXC_CPU_IMX8MN);
Peng Fan24341312019-06-27 17:23:49 +0800481 } else if (major_low == 0x41) {
Peng Fan78db9a52019-08-27 06:25:17 +0000482 type = get_cpu_variant_type(MXC_CPU_IMX8MM);
483 } else {
484 if (reg == CHIP_REV_1_0) {
485 /*
Peng Fan9e094452019-10-16 10:24:17 +0000486 * For B0 chip, the DIGPROG is not updated,
487 * it is still TO1.0. we have to check ROM
488 * version or OCOTP_READ_FUSE_DATA.
489 * 0xff0055aa is magic number for B1.
Peng Fan78db9a52019-08-27 06:25:17 +0000490 */
Peng Fan9e094452019-10-16 10:24:17 +0000491 if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
Ye Liea2b26fb2021-03-19 15:57:16 +0800492 /*
493 * B2 uses same DIGPROG and OCOTP_READ_FUSE_DATA value with B1,
494 * so have to check ROM to distinguish them
495 */
496 rom_version = readl((void __iomem *)ROM_VERSION_B0);
497 rom_version &= 0xff;
498 if (rom_version == CHIP_REV_2_2)
499 reg = CHIP_REV_2_2;
500 else
501 reg = CHIP_REV_2_1;
Peng Fan9e094452019-10-16 10:24:17 +0000502 } else {
503 rom_version =
504 readl((void __iomem *)ROM_VERSION_A0);
505 if (rom_version != CHIP_REV_1_0) {
506 rom_version = readl((void __iomem *)ROM_VERSION_B0);
Patrick Wildt6a4b07e2019-11-19 09:42:06 +0100507 rom_version &= 0xff;
Peng Fan9e094452019-10-16 10:24:17 +0000508 if (rom_version == CHIP_REV_2_0)
509 reg = CHIP_REV_2_0;
510 }
Peng Fan78db9a52019-08-27 06:25:17 +0000511 }
Peng Fanfcdbde72018-01-10 13:20:37 +0800512 }
Peng Fancb1a1de2020-02-05 17:34:54 +0800513
514 type = get_cpu_variant_type(type);
Peng Fanfcdbde72018-01-10 13:20:37 +0800515 }
516
517 return (type << 12) | reg;
518}
519
520static void imx_set_wdog_powerdown(bool enable)
521{
522 struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
523 struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
524 struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
525
526 /* Write to the PDE (Power Down Enable) bit */
527 writew(enable, &wdog1->wmcr);
528 writew(enable, &wdog2->wmcr);
529 writew(enable, &wdog3->wmcr);
530}
531
Simon Glass7fe32b32022-03-04 08:43:05 -0700532static int imx8m_check_clock(void *ctx, struct event *event)
Peng Fane663c702019-08-27 06:25:58 +0000533{
534 struct udevice *dev;
535 int ret;
536
Peng Fancd7c8062019-10-16 03:01:51 +0000537 if (CONFIG_IS_ENABLED(CLK)) {
538 ret = uclass_get_device_by_name(UCLASS_CLK,
539 "clock-controller@30380000",
540 &dev);
541 if (ret < 0) {
542 printf("Failed to find clock node. Check device tree\n");
543 return ret;
544 }
Peng Fane663c702019-08-27 06:25:58 +0000545 }
546
547 return 0;
548}
Simon Glass7fe32b32022-03-04 08:43:05 -0700549EVENT_SPY(EVT_DM_POST_INIT, imx8m_check_clock);
Peng Fane663c702019-08-27 06:25:58 +0000550
Peng Fanfcdbde72018-01-10 13:20:37 +0800551int arch_cpu_init(void)
552{
Peng Fan702339b2019-04-17 09:41:16 +0000553 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
Peng Fanfcdbde72018-01-10 13:20:37 +0800554 /*
Peng Fan0528ba02019-08-27 06:25:37 +0000555 * ROM might disable clock for SCTR,
556 * enable the clock before timer_init.
557 */
558 if (IS_ENABLED(CONFIG_SPL_BUILD))
559 clock_enable(CCGR_SCTR, 1);
560 /*
Peng Fanfcdbde72018-01-10 13:20:37 +0800561 * Init timer at very early state, because sscg pll setting
562 * will use it
563 */
564 timer_init();
565
566 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
567 clock_init();
568 imx_set_wdog_powerdown(false);
Peng Fan7a42bf02020-07-09 13:52:41 +0800569
570 if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
571 is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
Ye Lic4f78cb2021-03-19 15:57:11 +0800572 is_imx8mnsl() || is_imx8mpd() || is_imx8mnud() || is_imx8mnus()) {
Peng Fan7a42bf02020-07-09 13:52:41 +0800573 /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
574 struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
575 struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
576 struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0);
577 struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR;
578
579 writel(0x1, &pgc_core2->pgcr);
580 writel(0x1, &pgc_core3->pgcr);
Ye Lic4f78cb2021-03-19 15:57:11 +0800581 if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) {
Peng Fan7a42bf02020-07-09 13:52:41 +0800582 writel(0x1, &pgc_core1->pgcr);
583 writel(0xE, &gpc->cpu_pgc_dn_trg);
584 } else {
585 writel(0xC, &gpc->cpu_pgc_dn_trg);
586 }
587 }
Peng Fanfcdbde72018-01-10 13:20:37 +0800588 }
589
Peng Fan702339b2019-04-17 09:41:16 +0000590 if (is_imx8mq()) {
591 clock_enable(CCGR_OCOTP, 1);
592 if (readl(&ocotp->ctrl) & 0x200)
593 writel(0x200, &ocotp->ctrl_clr);
594 }
595
Peng Fanfcdbde72018-01-10 13:20:37 +0800596 return 0;
597}
598
Peng Fanb1821372019-09-16 03:09:36 +0000599#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
600struct rom_api *g_rom_api = (struct rom_api *)0x980;
601
602enum boot_device get_boot_device(void)
603{
604 volatile gd_t *pgd = gd;
605 int ret;
606 u32 boot;
607 u16 boot_type;
608 u8 boot_instance;
609 enum boot_device boot_dev = SD1_BOOT;
610
611 ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
612 ((uintptr_t)&boot) ^ QUERY_BT_DEV);
Marek Behún86c5e212021-05-20 13:24:10 +0200613 set_gd(pgd);
Peng Fanb1821372019-09-16 03:09:36 +0000614
615 if (ret != ROM_API_OKAY) {
616 puts("ROMAPI: failure at query_boot_info\n");
617 return -1;
618 }
619
620 boot_type = boot >> 16;
621 boot_instance = (boot >> 8) & 0xff;
622
623 switch (boot_type) {
624 case BT_DEV_TYPE_SD:
625 boot_dev = boot_instance + SD1_BOOT;
626 break;
627 case BT_DEV_TYPE_MMC:
628 boot_dev = boot_instance + MMC1_BOOT;
629 break;
630 case BT_DEV_TYPE_NAND:
631 boot_dev = NAND_BOOT;
632 break;
633 case BT_DEV_TYPE_FLEXSPINOR:
634 boot_dev = QSPI_BOOT;
635 break;
Marek Vasute26d0152022-03-25 18:59:28 +0100636 case BT_DEV_TYPE_SPI_NOR:
637 boot_dev = SPI_NOR_BOOT;
638 break;
Peng Fanb1821372019-09-16 03:09:36 +0000639 case BT_DEV_TYPE_USB:
640 boot_dev = USB_BOOT;
641 break;
642 default:
643 break;
644 }
645
646 return boot_dev;
647}
648#endif
649
Marek Vasuta5ee05c2021-07-03 04:55:33 +0200650#if defined(CONFIG_IMX8M)
651#include <spl.h>
652int spl_mmc_emmc_boot_partition(struct mmc *mmc)
653{
654 u32 *rom_log_addr = (u32 *)0x9e0;
655 u32 *rom_log;
656 u8 event_id;
657 int i, part;
658
659 part = default_spl_mmc_emmc_boot_partition(mmc);
660
661 /* If the ROM event log pointer is not valid. */
662 if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 ||
663 *rom_log_addr & 0x3)
664 return part;
665
666 /* Parse the ROM event ID version 2 log */
667 rom_log = (u32 *)(uintptr_t)(*rom_log_addr);
668 for (i = 0; i < 128; i++) {
669 event_id = rom_log[i] >> 24;
670 switch (event_id) {
671 case 0x00: /* End of list */
672 return part;
673 /* Log entries with 1 parameter, skip 1 */
674 case 0x80: /* Start to perform the device initialization */
675 case 0x81: /* The boot device initialization completes */
676 case 0x8f: /* The boot device initialization fails */
677 case 0x90: /* Start to read data from boot device */
678 case 0x91: /* Reading data from boot device completes */
679 case 0x9f: /* Reading data from boot device fails */
680 i += 1;
681 continue;
682 /* Log entries with 2 parameters, skip 2 */
683 case 0xa0: /* Image authentication result */
684 case 0xc0: /* Jump to the boot image soon */
685 i += 2;
686 continue;
687 /* Boot from the secondary boot image */
688 case 0x51:
689 /*
690 * Swap the eMMC boot partitions in case there was a
691 * fallback event (i.e. primary image was corrupted
692 * and that corruption was recognized by the BootROM),
693 * so the SPL loads the rest of the U-Boot from the
694 * correct eMMC boot partition, since the BootROM
695 * leaves the boot partition set to the corrupted one.
696 */
697 if (part == 1)
698 part = 2;
699 else if (part == 2)
700 part = 1;
701 continue;
702 default:
703 continue;
704 }
705 }
706
707 return part;
708}
709#endif
710
Peng Fanfcdbde72018-01-10 13:20:37 +0800711bool is_usb_boot(void)
712{
713 return get_boot_device() == USB_BOOT;
714}
715
716#ifdef CONFIG_OF_SYSTEM_SETUP
Peng Fan6036dba2020-07-09 14:06:49 +0800717bool check_fdt_new_path(void *blob)
718{
719 const char *soc_path = "/soc@0";
720 int nodeoff;
721
722 nodeoff = fdt_path_offset(blob, soc_path);
723 if (nodeoff < 0)
724 return false;
725
726 return true;
727}
728
729static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
Peng Fanfcdbde72018-01-10 13:20:37 +0800730{
731 int i = 0;
732 int rc;
733 int nodeoff;
Peng Fan6036dba2020-07-09 14:06:49 +0800734 const char *status = "disabled";
735
736 for (i = 0; i < size_array; i++) {
737 nodeoff = fdt_path_offset(blob, nodes_path[i]);
738 if (nodeoff < 0)
739 continue; /* Not found, skip it */
740
741 printf("Found %s node\n", nodes_path[i]);
742
743add_status:
744 rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
745 if (rc) {
746 if (rc == -FDT_ERR_NOSPACE) {
747 rc = fdt_increase_size(blob, 512);
748 if (!rc)
749 goto add_status;
750 }
751 printf("Unable to update property %s:%s, err=%s\n",
752 nodes_path[i], "status", fdt_strerror(rc));
753 } else {
754 printf("Modify %s:%s disabled\n",
755 nodes_path[i], "status");
756 }
757 }
758
759 return 0;
760}
761
762#ifdef CONFIG_IMX8MQ
763bool check_dcss_fused(void)
764{
765 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
766 struct fuse_bank *bank = &ocotp->bank[1];
767 struct fuse_bank1_regs *fuse =
768 (struct fuse_bank1_regs *)bank->fuse_regs;
769 u32 value = readl(&fuse->tester4);
770
771 if (value & 0x4000000)
772 return true;
773
774 return false;
775}
776
777static int disable_mipi_dsi_nodes(void *blob)
778{
779 static const char * const nodes_path[] = {
780 "/mipi_dsi@30A00000",
781 "/mipi_dsi_bridge@30A00000",
782 "/dsi_phy@30A00300",
783 "/soc@0/bus@30800000/mipi_dsi@30a00000",
Peng Fanc0e2f762021-03-19 15:57:13 +0800784 "/soc@0/bus@30800000/dphy@30a00300",
785 "/soc@0/bus@30800000/mipi-dsi@30a00000",
Peng Fan6036dba2020-07-09 14:06:49 +0800786 };
787
788 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
789}
790
791static int disable_dcss_nodes(void *blob)
792{
793 static const char * const nodes_path[] = {
794 "/dcss@0x32e00000",
795 "/dcss@32e00000",
796 "/hdmi@32c00000",
797 "/hdmi_cec@32c33800",
798 "/hdmi_drm@32c00000",
799 "/display-subsystem",
800 "/sound-hdmi",
801 "/sound-hdmi-arc",
802 "/soc@0/bus@32c00000/display-controller@32e00000",
803 "/soc@0/bus@32c00000/hdmi@32c00000",
804 };
805
806 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
807}
808
809static int check_mipi_dsi_nodes(void *blob)
810{
811 static const char * const lcdif_path[] = {
812 "/lcdif@30320000",
Peng Fanc0e2f762021-03-19 15:57:13 +0800813 "/soc@0/bus@30000000/lcdif@30320000",
814 "/soc@0/bus@30000000/lcd-controller@30320000"
Peng Fan6036dba2020-07-09 14:06:49 +0800815 };
816 static const char * const mipi_dsi_path[] = {
817 "/mipi_dsi@30A00000",
818 "/soc@0/bus@30800000/mipi_dsi@30a00000"
819 };
820 static const char * const lcdif_ep_path[] = {
821 "/lcdif@30320000/port@0/mipi-dsi-endpoint",
Peng Fanc0e2f762021-03-19 15:57:13 +0800822 "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
823 "/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
Peng Fan6036dba2020-07-09 14:06:49 +0800824 };
825 static const char * const mipi_dsi_ep_path[] = {
826 "/mipi_dsi@30A00000/port@1/endpoint",
Peng Fanc0e2f762021-03-19 15:57:13 +0800827 "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
828 "/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
Peng Fan6036dba2020-07-09 14:06:49 +0800829 };
830
831 int lookup_node;
832 int nodeoff;
833 bool new_path = check_fdt_new_path(blob);
834 int i = new_path ? 1 : 0;
835
836 nodeoff = fdt_path_offset(blob, lcdif_path[i]);
837 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
838 /*
839 * If can't find lcdif node or lcdif node is disabled,
840 * then disable all mipi dsi, since they only can input
841 * from DCSS
842 */
843 return disable_mipi_dsi_nodes(blob);
844 }
845
846 nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
847 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
848 return 0;
849
850 nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
851 if (nodeoff < 0) {
852 /*
853 * If can't find lcdif endpoint, then disable all mipi dsi,
854 * since they only can input from DCSS
855 */
856 return disable_mipi_dsi_nodes(blob);
857 }
858
859 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
860 nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
861
862 if (nodeoff > 0 && nodeoff == lookup_node)
863 return 0;
864
865 return disable_mipi_dsi_nodes(blob);
866}
867#endif
868
869int disable_vpu_nodes(void *blob)
870{
871 static const char * const nodes_path_8mq[] = {
872 "/vpu@38300000",
873 "/soc@0/vpu@38300000"
874 };
875
876 static const char * const nodes_path_8mm[] = {
877 "/vpu_g1@38300000",
878 "/vpu_g2@38310000",
879 "/vpu_h1@38320000"
880 };
881
882 static const char * const nodes_path_8mp[] = {
883 "/vpu_g1@38300000",
884 "/vpu_g2@38310000",
885 "/vpu_vc8000e@38320000"
886 };
887
888 if (is_imx8mq())
889 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
890 else if (is_imx8mm())
891 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
892 else if (is_imx8mp())
893 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
894 else
895 return -EPERM;
896}
897
Ye Li98bcdf12021-03-19 15:57:09 +0800898#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
899static int low_drive_gpu_freq(void *blob)
900{
901 static const char *nodes_path_8mn[] = {
902 "/gpu@38000000",
903 "/soc@0/gpu@38000000"
904 };
905
906 int nodeoff, cnt, i;
907 u32 assignedclks[7];
908
909 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
910 if (nodeoff < 0)
911 return nodeoff;
912
913 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
914 if (cnt < 0)
915 return cnt;
916
917 if (cnt != 7)
918 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
919
920 assignedclks[cnt - 1] = 200000000;
921 assignedclks[cnt - 2] = 200000000;
922
923 for (i = 0; i < cnt; i++) {
924 debug("<%u>, ", assignedclks[i]);
925 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
926 }
927 debug("\n");
928
929 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
930}
931#endif
932
Peng Fan35bb6072022-04-07 15:55:53 +0800933static bool check_remote_endpoint(void *blob, const char *ep1, const char *ep2)
934{
935 int lookup_node;
936 int nodeoff;
937
938 nodeoff = fdt_path_offset(blob, ep1);
939 if (nodeoff) {
940 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
941 nodeoff = fdt_path_offset(blob, ep2);
942
943 if (nodeoff > 0 && nodeoff == lookup_node)
944 return true;
945 }
946
947 return false;
948}
949
950int disable_dsi_lcdif_nodes(void *blob)
951{
952 int ret;
953
954 static const char * const dsi_path_8mp[] = {
955 "/soc@0/bus@32c00000/mipi_dsi@32e60000"
956 };
957
958 static const char * const lcdif_path_8mp[] = {
959 "/soc@0/bus@32c00000/lcd-controller@32e80000"
960 };
961
962 static const char * const lcdif_ep_path_8mp[] = {
963 "/soc@0/bus@32c00000/lcd-controller@32e80000/port@0/endpoint"
964 };
965 static const char * const dsi_ep_path_8mp[] = {
966 "/soc@0/bus@32c00000/mipi_dsi@32e60000/port@0/endpoint"
967 };
968
969 ret = disable_fdt_nodes(blob, dsi_path_8mp, ARRAY_SIZE(dsi_path_8mp));
970 if (ret)
971 return ret;
972
973 if (check_remote_endpoint(blob, dsi_ep_path_8mp[0], lcdif_ep_path_8mp[0])) {
974 /* Disable lcdif node */
975 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
976 }
977
978 return 0;
979}
980
981int disable_lvds_lcdif_nodes(void *blob)
982{
983 int ret, i;
984
985 static const char * const ldb_path_8mp[] = {
986 "/soc@0/bus@32c00000/ldb@32ec005c",
987 "/soc@0/bus@32c00000/phy@32ec0128"
988 };
989
990 static const char * const lcdif_path_8mp[] = {
991 "/soc@0/bus@32c00000/lcd-controller@32e90000"
992 };
993
994 static const char * const lcdif_ep_path_8mp[] = {
995 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@0",
996 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@1"
997 };
998 static const char * const ldb_ep_path_8mp[] = {
999 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@0/port@0/endpoint",
1000 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@1/port@0/endpoint"
1001 };
1002
1003 ret = disable_fdt_nodes(blob, ldb_path_8mp, ARRAY_SIZE(ldb_path_8mp));
1004 if (ret)
1005 return ret;
1006
1007 for (i = 0; i < ARRAY_SIZE(ldb_ep_path_8mp); i++) {
1008 if (check_remote_endpoint(blob, ldb_ep_path_8mp[i], lcdif_ep_path_8mp[i])) {
1009 /* Disable lcdif node */
1010 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1011 }
1012 }
1013
1014 return 0;
1015}
1016
Peng Fan6036dba2020-07-09 14:06:49 +08001017int disable_gpu_nodes(void *blob)
1018{
1019 static const char * const nodes_path_8mn[] = {
Peng Fanc0e2f762021-03-19 15:57:13 +08001020 "/gpu@38000000",
1021 "/soc@/gpu@38000000"
Peng Fan6036dba2020-07-09 14:06:49 +08001022 };
1023
Peng Fan35bb6072022-04-07 15:55:53 +08001024 static const char * const nodes_path_8mp[] = {
1025 "/gpu3d@38000000",
1026 "/gpu2d@38008000"
1027 };
1028
1029 if (is_imx8mp())
1030 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1031 else
1032 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
Peng Fan6036dba2020-07-09 14:06:49 +08001033}
1034
1035int disable_npu_nodes(void *blob)
1036{
1037 static const char * const nodes_path_8mp[] = {
1038 "/vipsi@38500000"
1039 };
1040
1041 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1042}
1043
1044int disable_isp_nodes(void *blob)
1045{
1046 static const char * const nodes_path_8mp[] = {
1047 "/soc@0/bus@32c00000/camera/isp@32e10000",
1048 "/soc@0/bus@32c00000/camera/isp@32e20000"
1049 };
1050
1051 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1052}
1053
1054int disable_dsp_nodes(void *blob)
1055{
1056 static const char * const nodes_path_8mp[] = {
1057 "/dsp@3b6e8000"
1058 };
1059
1060 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1061}
1062
Ye Li4e83c052021-03-19 15:57:12 +08001063static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores)
1064{
1065 static const char * const thermal_path[] = {
1066 "/thermal-zones/cpu-thermal/cooling-maps/map0"
1067 };
1068
1069 int nodeoff, cnt, i, ret, j;
1070 u32 cooling_dev[12];
1071
1072 for (i = 0; i < ARRAY_SIZE(thermal_path); i++) {
1073 nodeoff = fdt_path_offset(blob, thermal_path[i]);
1074 if (nodeoff < 0)
1075 continue; /* Not found, skip it */
1076
1077 cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 12);
1078 if (cnt < 0)
1079 continue;
1080
1081 if (cnt != 12)
1082 printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt);
1083
1084 for (j = 0; j < cnt; j++)
1085 cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]);
1086
1087 ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev,
1088 sizeof(u32) * (12 - disabled_cores * 3));
1089 if (ret < 0) {
1090 printf("Warning: %s, cooling-device setprop failed %d\n",
1091 thermal_path[i], ret);
1092 continue;
1093 }
1094
1095 printf("Update node %s, cooling-device prop\n", thermal_path[i]);
1096 }
1097}
1098
1099static void disable_pmu_cpu_nodes(void *blob, u32 disabled_cores)
1100{
1101 static const char * const pmu_path[] = {
1102 "/pmu"
1103 };
1104
1105 int nodeoff, cnt, i, ret, j;
1106 u32 irq_affinity[4];
1107
1108 for (i = 0; i < ARRAY_SIZE(pmu_path); i++) {
1109 nodeoff = fdt_path_offset(blob, pmu_path[i]);
1110 if (nodeoff < 0)
1111 continue; /* Not found, skip it */
1112
1113 cnt = fdtdec_get_int_array_count(blob, nodeoff, "interrupt-affinity",
1114 irq_affinity, 4);
1115 if (cnt < 0)
1116 continue;
1117
1118 if (cnt != 4)
1119 printf("Warning: %s, interrupt-affinity count %d\n", pmu_path[i], cnt);
1120
1121 for (j = 0; j < cnt; j++)
1122 irq_affinity[j] = cpu_to_fdt32(irq_affinity[j]);
1123
1124 ret = fdt_setprop(blob, nodeoff, "interrupt-affinity", &irq_affinity,
1125 sizeof(u32) * (4 - disabled_cores));
1126 if (ret < 0) {
1127 printf("Warning: %s, interrupt-affinity setprop failed %d\n",
1128 pmu_path[i], ret);
1129 continue;
1130 }
1131
1132 printf("Update node %s, interrupt-affinity prop\n", pmu_path[i]);
1133 }
1134}
1135
Peng Fan6036dba2020-07-09 14:06:49 +08001136static int disable_cpu_nodes(void *blob, u32 disabled_cores)
1137{
1138 static const char * const nodes_path[] = {
1139 "/cpus/cpu@1",
1140 "/cpus/cpu@2",
1141 "/cpus/cpu@3",
1142 };
1143 u32 i = 0;
1144 int rc;
1145 int nodeoff;
1146
1147 if (disabled_cores > 3)
1148 return -EINVAL;
1149
1150 i = 3 - disabled_cores;
1151
1152 for (; i < 3; i++) {
1153 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1154 if (nodeoff < 0)
1155 continue; /* Not found, skip it */
1156
1157 debug("Found %s node\n", nodes_path[i]);
1158
1159 rc = fdt_del_node(blob, nodeoff);
1160 if (rc < 0) {
1161 printf("Unable to delete node %s, err=%s\n",
1162 nodes_path[i], fdt_strerror(rc));
1163 } else {
1164 printf("Delete node %s\n", nodes_path[i]);
1165 }
1166 }
1167
Ye Li4e83c052021-03-19 15:57:12 +08001168 disable_thermal_cpu_nodes(blob, disabled_cores);
1169 disable_pmu_cpu_nodes(blob, disabled_cores);
1170
Peng Fan6036dba2020-07-09 14:06:49 +08001171 return 0;
1172}
1173
Peng Fan8325ef32022-04-07 15:55:54 +08001174static int cleanup_nodes_for_efi(void *blob)
1175{
Peng Fan1166bd42022-04-07 15:55:55 +08001176 static const char * const path[][2] = {
1177 { "/soc@0/bus@32c00000/usb@32e40000", "extcon" },
1178 { "/soc@0/bus@32c00000/usb@32e50000", "extcon" },
1179 { "/soc@0/bus@30800000/ethernet@30be0000", "phy-reset-gpios" },
1180 { "/soc@0/bus@30800000/ethernet@30bf0000", "phy-reset-gpios" }
1181 };
Peng Fan8325ef32022-04-07 15:55:54 +08001182 int nodeoff, i, rc;
1183
Peng Fan1166bd42022-04-07 15:55:55 +08001184 for (i = 0; i < ARRAY_SIZE(path); i++) {
1185 nodeoff = fdt_path_offset(blob, path[i][0]);
Peng Fan8325ef32022-04-07 15:55:54 +08001186 if (nodeoff < 0)
1187 continue; /* Not found, skip it */
Peng Fan1166bd42022-04-07 15:55:55 +08001188 debug("Found %s node\n", path[i][0]);
Peng Fan8325ef32022-04-07 15:55:54 +08001189
Peng Fan1166bd42022-04-07 15:55:55 +08001190 rc = fdt_delprop(blob, nodeoff, path[i][1]);
Peng Fan8325ef32022-04-07 15:55:54 +08001191 if (rc == -FDT_ERR_NOTFOUND)
1192 continue;
1193 if (rc) {
1194 printf("Unable to update property %s:%s, err=%s\n",
Peng Fan1166bd42022-04-07 15:55:55 +08001195 path[i][0], path[i][1], fdt_strerror(rc));
Peng Fan8325ef32022-04-07 15:55:54 +08001196 return rc;
1197 }
1198
Peng Fan1166bd42022-04-07 15:55:55 +08001199 printf("Remove %s:%s\n", path[i][0], path[i][1]);
Peng Fan8325ef32022-04-07 15:55:54 +08001200 }
1201
1202 return 0;
1203}
Peng Fan8325ef32022-04-07 15:55:54 +08001204
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +09001205int ft_system_setup(void *blob, struct bd_info *bd)
Peng Fan6036dba2020-07-09 14:06:49 +08001206{
1207#ifdef CONFIG_IMX8MQ
1208 int i = 0;
1209 int rc;
1210 int nodeoff;
1211
1212 if (get_boot_device() == USB_BOOT) {
1213 disable_dcss_nodes(blob);
1214
1215 bool new_path = check_fdt_new_path(blob);
1216 int v = new_path ? 1 : 0;
1217 static const char * const usb_dwc3_path[] = {
1218 "/usb@38100000/dwc3",
1219 "/soc@0/usb@38100000"
1220 };
1221
1222 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1223 if (nodeoff >= 0) {
1224 const char *speed = "high-speed";
1225
1226 printf("Found %s node\n", usb_dwc3_path[v]);
1227
1228usb_modify_speed:
1229
1230 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1231 if (rc) {
1232 if (rc == -FDT_ERR_NOSPACE) {
1233 rc = fdt_increase_size(blob, 512);
1234 if (!rc)
1235 goto usb_modify_speed;
1236 }
1237 printf("Unable to set property %s:%s, err=%s\n",
1238 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1239 } else {
1240 printf("Modify %s:%s = %s\n",
1241 usb_dwc3_path[v], "maximum-speed", speed);
1242 }
1243 } else {
1244 printf("Can't found %s node\n", usb_dwc3_path[v]);
1245 }
1246 }
Peng Fanfcdbde72018-01-10 13:20:37 +08001247
1248 /* Disable the CPU idle for A0 chip since the HW does not support it */
1249 if (is_soc_rev(CHIP_REV_1_0)) {
1250 static const char * const nodes_path[] = {
1251 "/cpus/cpu@0",
1252 "/cpus/cpu@1",
1253 "/cpus/cpu@2",
1254 "/cpus/cpu@3",
1255 };
1256
1257 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1258 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1259 if (nodeoff < 0)
1260 continue; /* Not found, skip it */
1261
Marek Vasutdabaabd2020-04-24 21:37:33 +02001262 debug("Found %s node\n", nodes_path[i]);
Peng Fanfcdbde72018-01-10 13:20:37 +08001263
1264 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasutdabaabd2020-04-24 21:37:33 +02001265 if (rc == -FDT_ERR_NOTFOUND)
1266 continue;
Peng Fanfcdbde72018-01-10 13:20:37 +08001267 if (rc) {
1268 printf("Unable to update property %s:%s, err=%s\n",
1269 nodes_path[i], "status", fdt_strerror(rc));
1270 return rc;
1271 }
1272
Marek Vasutdabaabd2020-04-24 21:37:33 +02001273 debug("Remove %s:%s\n", nodes_path[i],
Peng Fanfcdbde72018-01-10 13:20:37 +08001274 "cpu-idle-states");
1275 }
1276 }
1277
Peng Fan6036dba2020-07-09 14:06:49 +08001278 if (is_imx8mql()) {
1279 disable_vpu_nodes(blob);
1280 if (check_dcss_fused()) {
1281 printf("DCSS is fused\n");
1282 disable_dcss_nodes(blob);
1283 check_mipi_dsi_nodes(blob);
1284 }
1285 }
1286
1287 if (is_imx8md())
1288 disable_cpu_nodes(blob, 2);
1289
1290#elif defined(CONFIG_IMX8MM)
1291 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1292 disable_vpu_nodes(blob);
1293
1294 if (is_imx8mmd() || is_imx8mmdl())
1295 disable_cpu_nodes(blob, 2);
1296 else if (is_imx8mms() || is_imx8mmsl())
1297 disable_cpu_nodes(blob, 3);
1298
1299#elif defined(CONFIG_IMX8MN)
1300 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1301 disable_gpu_nodes(blob);
Ye Li98bcdf12021-03-19 15:57:09 +08001302#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1303 else {
1304 int ldm_gpu = low_drive_gpu_freq(blob);
1305
1306 if (ldm_gpu < 0)
1307 printf("Update GPU node assigned-clock-rates failed\n");
1308 else
1309 printf("Update GPU node assigned-clock-rates ok\n");
1310 }
1311#endif
Peng Fan6036dba2020-07-09 14:06:49 +08001312
Ye Lic4f78cb2021-03-19 15:57:11 +08001313 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan6036dba2020-07-09 14:06:49 +08001314 disable_cpu_nodes(blob, 2);
Ye Lic4f78cb2021-03-19 15:57:11 +08001315 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan6036dba2020-07-09 14:06:49 +08001316 disable_cpu_nodes(blob, 3);
1317
1318#elif defined(CONFIG_IMX8MP)
Peng Fan35bb6072022-04-07 15:55:53 +08001319 if (is_imx8mpul()) {
1320 /* Disable GPU */
1321 disable_gpu_nodes(blob);
1322
1323 /* Disable DSI */
1324 disable_dsi_lcdif_nodes(blob);
1325
1326 /* Disable LVDS */
1327 disable_lvds_lcdif_nodes(blob);
1328 }
1329
1330 if (is_imx8mpul() || is_imx8mpl())
Peng Fan6036dba2020-07-09 14:06:49 +08001331 disable_vpu_nodes(blob);
1332
Peng Fan35bb6072022-04-07 15:55:53 +08001333 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan6036dba2020-07-09 14:06:49 +08001334 disable_npu_nodes(blob);
1335
Peng Fan35bb6072022-04-07 15:55:53 +08001336 if (is_imx8mpul() || is_imx8mpl())
Peng Fan6036dba2020-07-09 14:06:49 +08001337 disable_isp_nodes(blob);
1338
Peng Fan35bb6072022-04-07 15:55:53 +08001339 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan6036dba2020-07-09 14:06:49 +08001340 disable_dsp_nodes(blob);
1341
1342 if (is_imx8mpd())
1343 disable_cpu_nodes(blob, 2);
1344#endif
1345
Peng Fan1166bd42022-04-07 15:55:55 +08001346 cleanup_nodes_for_efi(blob);
Peng Fanfcdbde72018-01-10 13:20:37 +08001347 return 0;
1348}
1349#endif
1350
Peng Fan35bb6072022-04-07 15:55:53 +08001351#ifdef CONFIG_OF_BOARD_FIXUP
1352#ifndef CONFIG_SPL_BUILD
1353int board_fix_fdt(void *fdt)
1354{
1355 if (is_imx8mpul()) {
1356 int i = 0;
1357 int nodeoff, ret;
1358 const char *status = "disabled";
1359 static const char * const dsi_nodes[] = {
1360 "/soc@0/bus@32c00000/mipi_dsi@32e60000",
1361 "/soc@0/bus@32c00000/lcd-controller@32e80000",
1362 "/dsi-host"
1363 };
1364
1365 for (i = 0; i < ARRAY_SIZE(dsi_nodes); i++) {
1366 nodeoff = fdt_path_offset(fdt, dsi_nodes[i]);
1367 if (nodeoff > 0) {
1368set_status:
1369 ret = fdt_setprop(fdt, nodeoff, "status", status,
1370 strlen(status) + 1);
1371 if (ret == -FDT_ERR_NOSPACE) {
1372 ret = fdt_increase_size(fdt, 512);
1373 if (!ret)
1374 goto set_status;
1375 }
1376 }
1377 }
1378 }
1379
1380 return 0;
1381}
1382#endif
1383#endif
1384
Marek Vasutefa1a622020-04-29 15:04:21 +02001385#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler35b65dd2020-12-15 16:47:52 +01001386void reset_cpu(void)
Peng Fanfcdbde72018-01-10 13:20:37 +08001387{
Claudius Heinec5635a02020-04-29 15:04:23 +02001388 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Fanfcdbde72018-01-10 13:20:37 +08001389
Ye Li72479742019-12-09 00:47:18 -08001390 /* Clear WDA to trigger WDOG_B immediately */
1391 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fand2041722019-08-27 06:25:41 +00001392
Ye Li72479742019-12-09 00:47:18 -08001393 while (1) {
1394 /*
Harald Seiler568af922020-04-29 15:04:22 +02001395 * spin for .5 seconds before reset
Ye Li72479742019-12-09 00:47:18 -08001396 */
1397 }
Peng Fanfcdbde72018-01-10 13:20:37 +08001398}
Peng Fand2041722019-08-27 06:25:41 +00001399#endif
Peng Fana07bcec2020-04-22 10:51:13 +08001400
1401#if defined(CONFIG_ARCH_MISC_INIT)
1402static void acquire_buildinfo(void)
1403{
1404 u64 atf_commit = 0;
Peng Fana2f143e2020-05-11 15:14:04 +08001405 struct arm_smccc_res res;
Peng Fana07bcec2020-04-22 10:51:13 +08001406
1407 /* Get ARM Trusted Firmware commit id */
Peng Fana2f143e2020-05-11 15:14:04 +08001408 arm_smccc_smc(IMX_SIP_BUILDINFO, IMX_SIP_BUILDINFO_GET_COMMITHASH,
Fabio Estevam68a699e2020-07-17 16:36:54 -03001409 0, 0, 0, 0, 0, 0, &res);
Peng Fana2f143e2020-05-11 15:14:04 +08001410 atf_commit = res.a0;
Peng Fana07bcec2020-04-22 10:51:13 +08001411 if (atf_commit == 0xffffffff) {
1412 debug("ATF does not support build info\n");
1413 atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */
1414 }
1415
1416 printf("\n BuildInfo:\n - ATF %s\n\n", (char *)&atf_commit);
1417}
1418
1419int arch_misc_init(void)
1420{
Gaurav Jain2cddfcb2022-03-24 11:50:27 +05301421 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1422 struct udevice *dev;
1423 int ret;
1424
1425 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1426 if (ret)
1427 printf("Failed to initialize %s: %d\n", dev->name, ret);
1428 }
Peng Fana07bcec2020-04-22 10:51:13 +08001429 acquire_buildinfo();
1430
1431 return 0;
1432}
1433#endif
Ye Li70487ff2020-05-03 22:19:52 +08001434
1435void imx_tmu_arch_init(void *reg_base)
1436{
Ye Li94c693d2020-05-03 22:19:53 +08001437 if (is_imx8mm() || is_imx8mn()) {
Ye Li70487ff2020-05-03 22:19:52 +08001438 /* Load TCALIV and TASR from fuses */
1439 struct ocotp_regs *ocotp =
1440 (struct ocotp_regs *)OCOTP_BASE_ADDR;
1441 struct fuse_bank *bank = &ocotp->bank[3];
1442 struct fuse_bank3_regs *fuse =
1443 (struct fuse_bank3_regs *)bank->fuse_regs;
1444
1445 u32 tca_rt, tca_hr, tca_en;
1446 u32 buf_vref, buf_slope;
1447
1448 tca_rt = fuse->ana0 & 0xFF;
1449 tca_hr = (fuse->ana0 & 0xFF00) >> 8;
1450 tca_en = (fuse->ana0 & 0x2000000) >> 25;
1451
1452 buf_vref = (fuse->ana0 & 0x1F00000) >> 20;
1453 buf_slope = (fuse->ana0 & 0xF0000) >> 16;
1454
1455 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1456 writel((tca_en << 31) | (tca_hr << 16) | tca_rt,
1457 (ulong)reg_base + 0x30);
1458 }
Ye Liebb9aab2020-05-03 22:19:54 +08001459#ifdef CONFIG_IMX8MP
1460 /* Load TCALIV0/1/m40 and TRIM from fuses */
1461 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
1462 struct fuse_bank *bank = &ocotp->bank[38];
1463 struct fuse_bank38_regs *fuse =
1464 (struct fuse_bank38_regs *)bank->fuse_regs;
1465 struct fuse_bank *bank2 = &ocotp->bank[39];
1466 struct fuse_bank39_regs *fuse2 =
1467 (struct fuse_bank39_regs *)bank2->fuse_regs;
1468 u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr;
1469 u32 reg;
1470 u32 tca40[2], tca25[2], tca105[2];
1471
1472 /* For blank sample */
1473 if (!fuse->ana_trim2 && !fuse->ana_trim3 &&
1474 !fuse->ana_trim4 && !fuse2->ana_trim5) {
1475 /* Use a default 25C binary codes */
1476 tca25[0] = 1596;
Ye Li3462b552020-05-03 22:19:55 +08001477 tca25[1] = 1596;
Ye Liebb9aab2020-05-03 22:19:54 +08001478 writel(tca25[0], (ulong)reg_base + 0x30);
Ye Li3462b552020-05-03 22:19:55 +08001479 writel(tca25[1], (ulong)reg_base + 0x34);
Ye Liebb9aab2020-05-03 22:19:54 +08001480 return;
1481 }
1482
1483 buf_vref = (fuse->ana_trim2 & 0xc0) >> 6;
1484 buf_slope = (fuse->ana_trim2 & 0xF00) >> 8;
1485 bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12;
1486 bgr = (fuse->ana_trim2 & 0xF0000) >> 16;
1487 vlsb = (fuse->ana_trim2 & 0xF00000) >> 20;
1488 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1489
1490 reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7);
1491 writel(reg, (ulong)reg_base + 0x3c);
1492
1493 tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16;
1494 tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28;
1495 tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4);
1496 tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8;
1497 tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20;
1498 tca25[1] = fuse2->ana_trim5 & 0xFFF;
1499 tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12;
1500
1501 /* use 25c for 1p calibration */
1502 writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30);
1503 writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34);
1504 writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38);
1505#endif
Ye Li70487ff2020-05-03 22:19:52 +08001506}
Peng Fan2f3c9202020-07-09 13:39:26 +08001507
1508#if defined(CONFIG_SPL_BUILD)
1509#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1510bool serror_need_skip = true;
1511
Sean Andersone97ac472022-03-22 17:17:35 -04001512void do_error(struct pt_regs *pt_regs)
Peng Fan2f3c9202020-07-09 13:39:26 +08001513{
1514 /*
1515 * If stack is still in ROM reserved OCRAM not switch to SPL,
1516 * it is the ROM SError
1517 */
1518 ulong sp;
1519
1520 asm volatile("mov %0, sp" : "=r"(sp) : );
1521
1522 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1523 /* Check for ERR050342, imx8mq HDCP enabled parts */
1524 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1525 serror_need_skip = false;
1526 return; /* Do nothing skip the SError in ROM */
1527 }
1528
1529 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1530 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1531 serror_need_skip = false;
1532 return; /* Do nothing skip the SError in ROM */
1533 }
1534 }
1535
1536 efi_restore_gd();
Sean Andersone97ac472022-03-22 17:17:35 -04001537 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fan2f3c9202020-07-09 13:39:26 +08001538 show_regs(pt_regs);
1539 panic("Resetting CPU ...\n");
1540}
1541#endif
1542#endif
Ye Li2707faf2019-07-15 01:16:46 -07001543
1544#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
1545enum env_location env_get_location(enum env_operation op, int prio)
1546{
1547 enum boot_device dev = get_boot_device();
Ye Li2707faf2019-07-15 01:16:46 -07001548
1549 if (prio)
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001550 return ENVL_UNKNOWN;
Ye Li2707faf2019-07-15 01:16:46 -07001551
1552 switch (dev) {
Ye Li2707faf2019-07-15 01:16:46 -07001553 case QSPI_BOOT:
Marek Vasute26d0152022-03-25 18:59:28 +01001554 case SPI_NOR_BOOT:
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001555 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1556 return ENVL_SPI_FLASH;
1557 return ENVL_NOWHERE;
Ye Li2707faf2019-07-15 01:16:46 -07001558 case NAND_BOOT:
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001559 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1560 return ENVL_NAND;
1561 return ENVL_NOWHERE;
Ye Li2707faf2019-07-15 01:16:46 -07001562 case SD1_BOOT:
1563 case SD2_BOOT:
1564 case SD3_BOOT:
1565 case MMC1_BOOT:
1566 case MMC2_BOOT:
1567 case MMC3_BOOT:
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001568 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1569 return ENVL_MMC;
1570 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1571 return ENVL_EXT4;
1572 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1573 return ENVL_FAT;
1574 return ENVL_NOWHERE;
Ye Li2707faf2019-07-15 01:16:46 -07001575 default:
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001576 return ENVL_NOWHERE;
Ye Li2707faf2019-07-15 01:16:46 -07001577 }
Ye Li2707faf2019-07-15 01:16:46 -07001578}
1579
Ye Li2707faf2019-07-15 01:16:46 -07001580#endif