blob: bc3379a250bdd08b27c5ccc9daa23340c998db03 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Peng Faneae4de22018-01-10 13:20:37 +08002/*
Gaurav Jain81113a02022-03-24 11:50:27 +05303 * Copyright 2017-2019, 2021 NXP
Peng Faneae4de22018-01-10 13:20:37 +08004 *
5 * Peng Fan <peng.fan@nxp.com>
Peng Faneae4de22018-01-10 13:20:37 +08006 */
7
8#include <common.h>
Simon Glass1d91ba72019-11-14 12:57:37 -07009#include <cpu_func.h>
Simon Glassfc557362022-03-04 08:43:05 -070010#include <event.h>
Simon Glass97589732020-05-10 11:40:02 -060011#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Peng Faneae4de22018-01-10 13:20:37 +080013#include <asm/arch/imx-regs.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060014#include <asm/global_data.h>
Peng Faneae4de22018-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 Fana35215d2020-07-09 13:39:26 +080021#include <asm/ptrace.h>
Peng Faneae4de22018-01-10 13:20:37 +080022#include <asm/armv8/mmu.h>
Peng Fanc98e0322019-08-27 06:25:58 +000023#include <dm/uclass.h>
Gaurav Jain81113a02022-03-24 11:50:27 +053024#include <dm/device.h>
Peng Fana35215d2020-07-09 13:39:26 +080025#include <efi_loader.h>
Ye Li0513f362019-07-15 01:16:46 -070026#include <env.h>
27#include <env_internal.h>
Peng Faneae4de22018-01-10 13:20:37 +080028#include <errno.h>
29#include <fdt_support.h>
30#include <fsl_wdog.h>
31#include <imx_sip.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060032#include <linux/bitops.h>
Peng Faneae4de22018-01-10 13:20:37 +080033
34DECLARE_GLOBAL_DATA_PTR;
35
Stefano Babicf8b509b2019-09-20 08:47:53 +020036#if defined(CONFIG_IMX_HAB)
Peng Faneae4de22018-01-10 13:20:37 +080037struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
38 .bank = 1,
39 .word = 3,
40};
41#endif
42
43int timer_init(void)
44{
45#ifdef CONFIG_SPL_BUILD
46 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
47 unsigned long freq = readl(&sctr->cntfid0);
48
49 /* Update with accurate clock frequency */
50 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
51
52 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
53 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
54#endif
55
56 gd->arch.tbl = 0;
57 gd->arch.tbu = 0;
58
59 return 0;
60}
61
62void enable_tzc380(void)
63{
64 struct iomuxc_gpr_base_regs *gpr =
65 (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
66
67 /* Enable TZASC and lock setting */
68 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN);
69 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010070
71 /*
72 * According to TRM, TZASC_ID_SWAP_BYPASS should be set in
73 * order to avoid AXI Bus errors when GPU is in use
74 */
Peng Fandbe5d682022-04-10 12:18:27 +080075 if (is_imx8mq() || is_imx8mm() || is_imx8mn() || is_imx8mp())
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010076 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS);
77
78 /*
79 * imx8mn and imx8mp implements the lock bit for
80 * TZASC_ID_SWAP_BYPASS, enable it to lock settings
81 */
82 if (is_imx8mn() || is_imx8mp())
83 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS_LOCK);
84
Ye Li4c97c462019-08-27 06:25:34 +000085 /*
86 * set Region 0 attribute to allow secure and non-secure
87 * read/write permission. Found some masters like usb dwc3
88 * controllers can't work with secure memory.
89 */
90 writel(0xf0000000, TZASC_BASE_ADDR + 0x108);
Peng Faneae4de22018-01-10 13:20:37 +080091}
92
93void set_wdog_reset(struct wdog_regs *wdog)
94{
95 /*
96 * Output WDOG_B signal to reset external pmic or POR_B decided by
97 * the board design. Without external reset, the peripherals/DDR/
98 * PMIC are not reset, that may cause system working abnormal.
99 * WDZST bit is write-once only bit. Align this bit in kernel,
100 * otherwise kernel code will have no chance to set this bit.
101 */
102 setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK);
103}
104
105static struct mm_region imx8m_mem_map[] = {
106 {
107 /* ROM */
108 .virt = 0x0UL,
109 .phys = 0x0UL,
110 .size = 0x100000UL,
111 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
112 PTE_BLOCK_OUTER_SHARE
113 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100114 /* CAAM */
115 .virt = 0x100000UL,
116 .phys = 0x100000UL,
117 .size = 0x8000UL,
118 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
119 PTE_BLOCK_NON_SHARE |
120 PTE_BLOCK_PXN | PTE_BLOCK_UXN
121 }, {
Marek Vasutb1738e02021-02-25 21:52:26 +0100122 /* OCRAM_S */
123 .virt = 0x180000UL,
124 .phys = 0x180000UL,
125 .size = 0x8000UL,
126 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
127 PTE_BLOCK_OUTER_SHARE
128 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100129 /* TCM */
130 .virt = 0x7C0000UL,
131 .phys = 0x7C0000UL,
132 .size = 0x80000UL,
133 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
134 PTE_BLOCK_NON_SHARE |
135 PTE_BLOCK_PXN | PTE_BLOCK_UXN
136 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800137 /* OCRAM */
138 .virt = 0x900000UL,
139 .phys = 0x900000UL,
140 .size = 0x200000UL,
141 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
142 PTE_BLOCK_OUTER_SHARE
143 }, {
144 /* AIPS */
145 .virt = 0xB00000UL,
146 .phys = 0xB00000UL,
147 .size = 0x3f500000UL,
148 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
149 PTE_BLOCK_NON_SHARE |
150 PTE_BLOCK_PXN | PTE_BLOCK_UXN
151 }, {
152 /* DRAM1 */
153 .virt = 0x40000000UL,
154 .phys = 0x40000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000155 .size = PHYS_SDRAM_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800156 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
157 PTE_BLOCK_OUTER_SHARE
Peng Fanb749b5e2019-08-27 06:25:27 +0000158#ifdef PHYS_SDRAM_2_SIZE
Peng Faneae4de22018-01-10 13:20:37 +0800159 }, {
160 /* DRAM2 */
161 .virt = 0x100000000UL,
162 .phys = 0x100000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000163 .size = PHYS_SDRAM_2_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800164 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
165 PTE_BLOCK_OUTER_SHARE
Peng Fanb749b5e2019-08-27 06:25:27 +0000166#endif
Peng Faneae4de22018-01-10 13:20:37 +0800167 }, {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800168 /* empty entrie to split table entry 5 if needed when TEEs are used */
169 0,
170 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800171 /* List terminator */
172 0,
173 }
174};
175
176struct mm_region *mem_map = imx8m_mem_map;
177
Marek Vasute48aac02021-02-27 14:59:00 +0100178static unsigned int imx8m_find_dram_entry_in_mem_map(void)
179{
180 int i;
181
182 for (i = 0; i < ARRAY_SIZE(imx8m_mem_map); i++)
183 if (imx8m_mem_map[i].phys == CONFIG_SYS_SDRAM_BASE)
184 return i;
185
186 hang(); /* Entry not found, this must never happen. */
187}
188
Peng Fanb749b5e2019-08-27 06:25:27 +0000189void enable_caches(void)
190{
Ye Li453bfcb2022-04-07 15:55:56 +0800191 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
192 * If OPTEE does not run, still update the MMU table according to dram banks structure
193 * to set correct dram size from board_phys_sdram_size
194 */
195 int i = 0;
196 /*
197 * please make sure that entry initial value matches
198 * imx8m_mem_map for DRAM1
199 */
200 int entry = imx8m_find_dram_entry_in_mem_map();
201 u64 attrs = imx8m_mem_map[entry].attrs;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800202
Ye Li453bfcb2022-04-07 15:55:56 +0800203 while (i < CONFIG_NR_DRAM_BANKS &&
204 entry < ARRAY_SIZE(imx8m_mem_map)) {
205 if (gd->bd->bi_dram[i].start == 0)
206 break;
207 imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start;
208 imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start;
209 imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size;
210 imx8m_mem_map[entry].attrs = attrs;
211 debug("Added memory mapping (%d): %llx %llx\n", entry,
212 imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size);
213 i++; entry++;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800214 }
Peng Fanb749b5e2019-08-27 06:25:27 +0000215
216 icache_enable();
217 dcache_enable();
218}
219
Peng Fanfa35c3d2020-07-09 15:26:06 +0800220__weak int board_phys_sdram_size(phys_size_t *size)
221{
222 if (!size)
223 return -EINVAL;
224
225 *size = PHYS_SDRAM_SIZE;
Ye Li453bfcb2022-04-07 15:55:56 +0800226
227#ifdef PHYS_SDRAM_2_SIZE
228 *size += PHYS_SDRAM_2_SIZE;
229#endif
Peng Fanfa35c3d2020-07-09 15:26:06 +0800230 return 0;
231}
232
233int dram_init(void)
234{
235 phys_size_t sdram_size;
236 int ret;
237
238 ret = board_phys_sdram_size(&sdram_size);
239 if (ret)
240 return ret;
241
242 /* rom_pointer[1] contains the size of TEE occupies */
243 if (rom_pointer[1])
244 gd->ram_size = sdram_size - rom_pointer[1];
245 else
246 gd->ram_size = sdram_size;
247
Peng Fanfa35c3d2020-07-09 15:26:06 +0800248 return 0;
249}
250
251int dram_init_banksize(void)
252{
253 int bank = 0;
254 int ret;
255 phys_size_t sdram_size;
Ye Li453bfcb2022-04-07 15:55:56 +0800256 phys_size_t sdram_b1_size, sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800257
258 ret = board_phys_sdram_size(&sdram_size);
259 if (ret)
260 return ret;
261
Ye Li453bfcb2022-04-07 15:55:56 +0800262 /* Bank 1 can't cross over 4GB space */
263 if (sdram_size > 0xc0000000) {
264 sdram_b1_size = 0xc0000000;
265 sdram_b2_size = sdram_size - 0xc0000000;
266 } else {
267 sdram_b1_size = sdram_size;
268 sdram_b2_size = 0;
269 }
270
Peng Fanfa35c3d2020-07-09 15:26:06 +0800271 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
272 if (rom_pointer[1]) {
273 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
274 phys_size_t optee_size = (size_t)rom_pointer[1];
275
276 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
Ye Li453bfcb2022-04-07 15:55:56 +0800277 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800278 if (++bank >= CONFIG_NR_DRAM_BANKS) {
279 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
280 return -1;
281 }
282
283 gd->bd->bi_dram[bank].start = optee_start + optee_size;
284 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
Ye Li453bfcb2022-04-07 15:55:56 +0800285 sdram_b1_size - gd->bd->bi_dram[bank].start;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800286 }
287 } else {
Ye Li453bfcb2022-04-07 15:55:56 +0800288 gd->bd->bi_dram[bank].size = sdram_b1_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800289 }
290
Ye Li453bfcb2022-04-07 15:55:56 +0800291 if (sdram_b2_size) {
292 if (++bank >= CONFIG_NR_DRAM_BANKS) {
293 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
294 return -1;
295 }
296 gd->bd->bi_dram[bank].start = 0x100000000UL;
297 gd->bd->bi_dram[bank].size = sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800298 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800299
300 return 0;
301}
302
303phys_size_t get_effective_memsize(void)
304{
Ye Li453bfcb2022-04-07 15:55:56 +0800305 int ret;
306 phys_size_t sdram_size;
307 phys_size_t sdram_b1_size;
308 ret = board_phys_sdram_size(&sdram_size);
309 if (!ret) {
310 /* Bank 1 can't cross over 4GB space */
311 if (sdram_size > 0xc0000000) {
312 sdram_b1_size = 0xc0000000;
313 } else {
314 sdram_b1_size = sdram_size;
315 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800316
Ye Li453bfcb2022-04-07 15:55:56 +0800317 if (rom_pointer[1]) {
318 /* We will relocate u-boot to Top of dram1. Tee position has two cases:
319 * 1. At the top of dram1, Then return the size removed optee size.
320 * 2. In the middle of dram1, return the size of dram1.
321 */
322 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
323 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
324 }
325
326 return sdram_b1_size;
327 } else {
328 return PHYS_SDRAM_SIZE;
329 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800330}
331
Frieder Schrempf159879e2021-06-07 14:36:44 +0200332ulong board_get_usable_ram_top(ulong total_size)
333{
Marek Vasutdcbbf782022-04-14 15:51:46 +0200334 ulong top_addr;
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800335
Frieder Schrempf159879e2021-06-07 14:36:44 +0200336 /*
337 * Some IPs have their accessible address space restricted by
338 * the interconnect. Let's make sure U-Boot only ever uses the
339 * space below the 4G address boundary (which is 3GiB big),
340 * even when the effective available memory is bigger.
341 */
Marek Vasutdcbbf782022-04-14 15:51:46 +0200342 top_addr = clamp_val((u64)PHYS_SDRAM + gd->ram_size, 0, 0xffffffff);
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800343
344 /*
345 * rom_pointer[0] stores the TEE memory start address.
346 * rom_pointer[1] stores the size TEE uses.
347 * We need to reserve the memory region for TEE.
348 */
349 if (rom_pointer[0] && rom_pointer[1] && top_addr > rom_pointer[0])
350 top_addr = rom_pointer[0];
Frieder Schrempf159879e2021-06-07 14:36:44 +0200351
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800352 return top_addr;
Frieder Schrempf159879e2021-06-07 14:36:44 +0200353}
354
Peng Fan1caffdf2019-08-27 06:25:17 +0000355static u32 get_cpu_variant_type(u32 type)
356{
357 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
358 struct fuse_bank *bank = &ocotp->bank[1];
359 struct fuse_bank1_regs *fuse =
360 (struct fuse_bank1_regs *)bank->fuse_regs;
361
362 u32 value = readl(&fuse->tester4);
363
Peng Fan67815082020-02-05 17:34:54 +0800364 if (type == MXC_CPU_IMX8MQ) {
365 if ((value & 0x3) == 0x2)
366 return MXC_CPU_IMX8MD;
367 else if (value & 0x200000)
368 return MXC_CPU_IMX8MQL;
369
370 } else if (type == MXC_CPU_IMX8MM) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000371 switch (value & 0x3) {
372 case 2:
373 if (value & 0x1c0000)
374 return MXC_CPU_IMX8MMDL;
375 else
376 return MXC_CPU_IMX8MMD;
377 case 3:
378 if (value & 0x1c0000)
379 return MXC_CPU_IMX8MMSL;
380 else
381 return MXC_CPU_IMX8MMS;
382 default:
383 if (value & 0x1c0000)
384 return MXC_CPU_IMX8MML;
385 break;
386 }
Peng Fan1a07d912020-02-05 17:39:27 +0800387 } else if (type == MXC_CPU_IMX8MN) {
388 switch (value & 0x3) {
389 case 2:
Ye Li715180e2021-03-19 15:57:11 +0800390 if (value & 0x1000000) {
391 if (value & 0x10000000) /* MIPI DSI */
392 return MXC_CPU_IMX8MNUD;
393 else
394 return MXC_CPU_IMX8MNDL;
395 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800396 return MXC_CPU_IMX8MND;
Ye Li715180e2021-03-19 15:57:11 +0800397 }
Peng Fan1a07d912020-02-05 17:39:27 +0800398 case 3:
Ye Li715180e2021-03-19 15:57:11 +0800399 if (value & 0x1000000) {
400 if (value & 0x10000000) /* MIPI DSI */
401 return MXC_CPU_IMX8MNUS;
402 else
403 return MXC_CPU_IMX8MNSL;
404 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800405 return MXC_CPU_IMX8MNS;
Ye Li715180e2021-03-19 15:57:11 +0800406 }
Peng Fan1a07d912020-02-05 17:39:27 +0800407 default:
Ye Li715180e2021-03-19 15:57:11 +0800408 if (value & 0x1000000) {
409 if (value & 0x10000000) /* MIPI DSI */
410 return MXC_CPU_IMX8MNUQ;
411 else
412 return MXC_CPU_IMX8MNL;
413 }
Peng Fan1a07d912020-02-05 17:39:27 +0800414 break;
415 }
Ye Lid2d754f2020-04-20 20:12:54 -0700416 } else if (type == MXC_CPU_IMX8MP) {
417 u32 value0 = readl(&fuse->tester3);
418 u32 flag = 0;
419
420 if ((value0 & 0xc0000) == 0x80000)
421 return MXC_CPU_IMX8MPD;
422
423 /* vpu disabled */
424 if ((value0 & 0x43000000) == 0x43000000)
425 flag = 1;
426
427 /* npu disabled*/
428 if ((value & 0x8) == 0x8)
Peng Fan0386e7f2022-04-07 15:55:52 +0800429 flag |= BIT(1);
Ye Lid2d754f2020-04-20 20:12:54 -0700430
431 /* isp disabled */
432 if ((value & 0x3) == 0x3)
Peng Fan0386e7f2022-04-07 15:55:52 +0800433 flag |= BIT(2);
434
435 /* gpu disabled */
436 if ((value & 0xc0) == 0xc0)
437 flag |= BIT(3);
438
439 /* lvds disabled */
440 if ((value & 0x180000) == 0x180000)
441 flag |= BIT(4);
442
443 /* mipi dsi disabled */
444 if ((value & 0x60000) == 0x60000)
445 flag |= BIT(5);
Ye Lid2d754f2020-04-20 20:12:54 -0700446
447 switch (flag) {
Peng Fan0386e7f2022-04-07 15:55:52 +0800448 case 0x3f:
449 return MXC_CPU_IMX8MPUL;
Ye Lid2d754f2020-04-20 20:12:54 -0700450 case 7:
451 return MXC_CPU_IMX8MPL;
Ye Lid2d754f2020-04-20 20:12:54 -0700452 case 2:
453 return MXC_CPU_IMX8MP6;
Ye Lid2d754f2020-04-20 20:12:54 -0700454 default:
455 break;
456 }
457
Peng Fan1caffdf2019-08-27 06:25:17 +0000458 }
459
460 return type;
461}
462
Peng Faneae4de22018-01-10 13:20:37 +0800463u32 get_cpu_rev(void)
464{
465 struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
466 u32 reg = readl(&ana_pll->digprog);
467 u32 type = (reg >> 16) & 0xff;
Peng Fan1caffdf2019-08-27 06:25:17 +0000468 u32 major_low = (reg >> 8) & 0xff;
Peng Faneae4de22018-01-10 13:20:37 +0800469 u32 rom_version;
470
471 reg &= 0xff;
472
Peng Fan69cec072019-12-27 10:14:02 +0800473 /* iMX8MP */
474 if (major_low == 0x43) {
Ye Lid2d754f2020-04-20 20:12:54 -0700475 type = get_cpu_variant_type(MXC_CPU_IMX8MP);
Peng Fan69cec072019-12-27 10:14:02 +0800476 } else if (major_low == 0x42) {
477 /* iMX8MN */
Peng Fan1a07d912020-02-05 17:39:27 +0800478 type = get_cpu_variant_type(MXC_CPU_IMX8MN);
Peng Fan5d2f2062019-06-27 17:23:49 +0800479 } else if (major_low == 0x41) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000480 type = get_cpu_variant_type(MXC_CPU_IMX8MM);
481 } else {
482 if (reg == CHIP_REV_1_0) {
483 /*
Peng Fanc23fbdd2019-10-16 10:24:17 +0000484 * For B0 chip, the DIGPROG is not updated,
485 * it is still TO1.0. we have to check ROM
486 * version or OCOTP_READ_FUSE_DATA.
487 * 0xff0055aa is magic number for B1.
Peng Fan1caffdf2019-08-27 06:25:17 +0000488 */
Peng Fanc23fbdd2019-10-16 10:24:17 +0000489 if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
Ye Lic963ed12021-03-19 15:57:16 +0800490 /*
491 * B2 uses same DIGPROG and OCOTP_READ_FUSE_DATA value with B1,
492 * so have to check ROM to distinguish them
493 */
494 rom_version = readl((void __iomem *)ROM_VERSION_B0);
495 rom_version &= 0xff;
496 if (rom_version == CHIP_REV_2_2)
497 reg = CHIP_REV_2_2;
498 else
499 reg = CHIP_REV_2_1;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000500 } else {
501 rom_version =
502 readl((void __iomem *)ROM_VERSION_A0);
503 if (rom_version != CHIP_REV_1_0) {
504 rom_version = readl((void __iomem *)ROM_VERSION_B0);
Patrick Wildtd4a78b92019-11-19 09:42:06 +0100505 rom_version &= 0xff;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000506 if (rom_version == CHIP_REV_2_0)
507 reg = CHIP_REV_2_0;
508 }
Peng Fan1caffdf2019-08-27 06:25:17 +0000509 }
Peng Faneae4de22018-01-10 13:20:37 +0800510 }
Peng Fan67815082020-02-05 17:34:54 +0800511
512 type = get_cpu_variant_type(type);
Peng Faneae4de22018-01-10 13:20:37 +0800513 }
514
515 return (type << 12) | reg;
516}
517
518static void imx_set_wdog_powerdown(bool enable)
519{
520 struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
521 struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
522 struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
523
524 /* Write to the PDE (Power Down Enable) bit */
525 writew(enable, &wdog1->wmcr);
526 writew(enable, &wdog2->wmcr);
527 writew(enable, &wdog3->wmcr);
528}
529
Simon Glassfc557362022-03-04 08:43:05 -0700530static int imx8m_check_clock(void *ctx, struct event *event)
Peng Fanc98e0322019-08-27 06:25:58 +0000531{
532 struct udevice *dev;
533 int ret;
534
Peng Fan3c073342019-10-16 03:01:51 +0000535 if (CONFIG_IS_ENABLED(CLK)) {
536 ret = uclass_get_device_by_name(UCLASS_CLK,
537 "clock-controller@30380000",
538 &dev);
539 if (ret < 0) {
540 printf("Failed to find clock node. Check device tree\n");
541 return ret;
542 }
Peng Fanc98e0322019-08-27 06:25:58 +0000543 }
544
545 return 0;
546}
Simon Glassfc557362022-03-04 08:43:05 -0700547EVENT_SPY(EVT_DM_POST_INIT, imx8m_check_clock);
Peng Fanc98e0322019-08-27 06:25:58 +0000548
Peng Faneae4de22018-01-10 13:20:37 +0800549int arch_cpu_init(void)
550{
Peng Fanc0b30d72019-04-17 09:41:16 +0000551 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
Marek Vasut3ea500a2022-04-13 00:41:52 +0200552
553#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
554 icache_enable();
555#endif
556
Peng Faneae4de22018-01-10 13:20:37 +0800557 /*
Peng Fand0ca2892019-08-27 06:25:37 +0000558 * ROM might disable clock for SCTR,
559 * enable the clock before timer_init.
560 */
561 if (IS_ENABLED(CONFIG_SPL_BUILD))
562 clock_enable(CCGR_SCTR, 1);
563 /*
Peng Faneae4de22018-01-10 13:20:37 +0800564 * Init timer at very early state, because sscg pll setting
565 * will use it
566 */
567 timer_init();
568
569 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
570 clock_init();
571 imx_set_wdog_powerdown(false);
Peng Fan9cf2aa32020-07-09 13:52:41 +0800572
573 if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
574 is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
Ye Li715180e2021-03-19 15:57:11 +0800575 is_imx8mnsl() || is_imx8mpd() || is_imx8mnud() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800576 /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
577 struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
578 struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
579 struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0);
580 struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR;
581
582 writel(0x1, &pgc_core2->pgcr);
583 writel(0x1, &pgc_core3->pgcr);
Ye Li715180e2021-03-19 15:57:11 +0800584 if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800585 writel(0x1, &pgc_core1->pgcr);
586 writel(0xE, &gpc->cpu_pgc_dn_trg);
587 } else {
588 writel(0xC, &gpc->cpu_pgc_dn_trg);
589 }
590 }
Peng Faneae4de22018-01-10 13:20:37 +0800591 }
592
Peng Fanc0b30d72019-04-17 09:41:16 +0000593 if (is_imx8mq()) {
594 clock_enable(CCGR_OCOTP, 1);
595 if (readl(&ocotp->ctrl) & 0x200)
596 writel(0x200, &ocotp->ctrl_clr);
597 }
598
Peng Faneae4de22018-01-10 13:20:37 +0800599 return 0;
600}
601
Peng Fanc9823b02019-09-16 03:09:36 +0000602#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
603struct rom_api *g_rom_api = (struct rom_api *)0x980;
604
605enum boot_device get_boot_device(void)
606{
607 volatile gd_t *pgd = gd;
608 int ret;
609 u32 boot;
610 u16 boot_type;
611 u8 boot_instance;
612 enum boot_device boot_dev = SD1_BOOT;
613
614 ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
615 ((uintptr_t)&boot) ^ QUERY_BT_DEV);
Marek Behúna8cf1552021-05-20 13:24:10 +0200616 set_gd(pgd);
Peng Fanc9823b02019-09-16 03:09:36 +0000617
618 if (ret != ROM_API_OKAY) {
619 puts("ROMAPI: failure at query_boot_info\n");
620 return -1;
621 }
622
623 boot_type = boot >> 16;
624 boot_instance = (boot >> 8) & 0xff;
625
626 switch (boot_type) {
627 case BT_DEV_TYPE_SD:
628 boot_dev = boot_instance + SD1_BOOT;
629 break;
630 case BT_DEV_TYPE_MMC:
631 boot_dev = boot_instance + MMC1_BOOT;
632 break;
633 case BT_DEV_TYPE_NAND:
634 boot_dev = NAND_BOOT;
635 break;
636 case BT_DEV_TYPE_FLEXSPINOR:
637 boot_dev = QSPI_BOOT;
638 break;
Marek Vasut31b3bc42022-03-25 18:59:28 +0100639 case BT_DEV_TYPE_SPI_NOR:
640 boot_dev = SPI_NOR_BOOT;
641 break;
Peng Fanc9823b02019-09-16 03:09:36 +0000642 case BT_DEV_TYPE_USB:
643 boot_dev = USB_BOOT;
644 break;
645 default:
646 break;
647 }
648
649 return boot_dev;
650}
651#endif
652
Marek Vasut520ded02021-07-03 04:55:33 +0200653#if defined(CONFIG_IMX8M)
654#include <spl.h>
655int spl_mmc_emmc_boot_partition(struct mmc *mmc)
656{
657 u32 *rom_log_addr = (u32 *)0x9e0;
658 u32 *rom_log;
659 u8 event_id;
660 int i, part;
661
662 part = default_spl_mmc_emmc_boot_partition(mmc);
663
664 /* If the ROM event log pointer is not valid. */
665 if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 ||
666 *rom_log_addr & 0x3)
667 return part;
668
669 /* Parse the ROM event ID version 2 log */
670 rom_log = (u32 *)(uintptr_t)(*rom_log_addr);
671 for (i = 0; i < 128; i++) {
672 event_id = rom_log[i] >> 24;
673 switch (event_id) {
674 case 0x00: /* End of list */
675 return part;
676 /* Log entries with 1 parameter, skip 1 */
677 case 0x80: /* Start to perform the device initialization */
678 case 0x81: /* The boot device initialization completes */
679 case 0x8f: /* The boot device initialization fails */
680 case 0x90: /* Start to read data from boot device */
681 case 0x91: /* Reading data from boot device completes */
682 case 0x9f: /* Reading data from boot device fails */
683 i += 1;
684 continue;
685 /* Log entries with 2 parameters, skip 2 */
686 case 0xa0: /* Image authentication result */
687 case 0xc0: /* Jump to the boot image soon */
688 i += 2;
689 continue;
690 /* Boot from the secondary boot image */
691 case 0x51:
692 /*
693 * Swap the eMMC boot partitions in case there was a
694 * fallback event (i.e. primary image was corrupted
695 * and that corruption was recognized by the BootROM),
696 * so the SPL loads the rest of the U-Boot from the
697 * correct eMMC boot partition, since the BootROM
698 * leaves the boot partition set to the corrupted one.
699 */
700 if (part == 1)
701 part = 2;
702 else if (part == 2)
703 part = 1;
704 continue;
705 default:
706 continue;
707 }
708 }
709
710 return part;
711}
712#endif
713
Peng Faneae4de22018-01-10 13:20:37 +0800714bool is_usb_boot(void)
715{
716 return get_boot_device() == USB_BOOT;
717}
718
719#ifdef CONFIG_OF_SYSTEM_SETUP
Peng Fan435dc122020-07-09 14:06:49 +0800720bool check_fdt_new_path(void *blob)
721{
722 const char *soc_path = "/soc@0";
723 int nodeoff;
724
725 nodeoff = fdt_path_offset(blob, soc_path);
726 if (nodeoff < 0)
727 return false;
728
729 return true;
730}
731
732static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
733{
734 int i = 0;
735 int rc;
736 int nodeoff;
737 const char *status = "disabled";
738
739 for (i = 0; i < size_array; i++) {
740 nodeoff = fdt_path_offset(blob, nodes_path[i]);
741 if (nodeoff < 0)
742 continue; /* Not found, skip it */
743
744 printf("Found %s node\n", nodes_path[i]);
745
746add_status:
747 rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
748 if (rc) {
749 if (rc == -FDT_ERR_NOSPACE) {
750 rc = fdt_increase_size(blob, 512);
751 if (!rc)
752 goto add_status;
753 }
754 printf("Unable to update property %s:%s, err=%s\n",
755 nodes_path[i], "status", fdt_strerror(rc));
756 } else {
757 printf("Modify %s:%s disabled\n",
758 nodes_path[i], "status");
759 }
760 }
761
762 return 0;
763}
764
765#ifdef CONFIG_IMX8MQ
766bool check_dcss_fused(void)
767{
768 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
769 struct fuse_bank *bank = &ocotp->bank[1];
770 struct fuse_bank1_regs *fuse =
771 (struct fuse_bank1_regs *)bank->fuse_regs;
772 u32 value = readl(&fuse->tester4);
773
774 if (value & 0x4000000)
775 return true;
776
777 return false;
778}
779
780static int disable_mipi_dsi_nodes(void *blob)
781{
782 static const char * const nodes_path[] = {
783 "/mipi_dsi@30A00000",
784 "/mipi_dsi_bridge@30A00000",
785 "/dsi_phy@30A00300",
786 "/soc@0/bus@30800000/mipi_dsi@30a00000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800787 "/soc@0/bus@30800000/dphy@30a00300",
788 "/soc@0/bus@30800000/mipi-dsi@30a00000",
Peng Fan435dc122020-07-09 14:06:49 +0800789 };
790
791 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
792}
793
794static int disable_dcss_nodes(void *blob)
795{
796 static const char * const nodes_path[] = {
797 "/dcss@0x32e00000",
798 "/dcss@32e00000",
799 "/hdmi@32c00000",
800 "/hdmi_cec@32c33800",
801 "/hdmi_drm@32c00000",
802 "/display-subsystem",
803 "/sound-hdmi",
804 "/sound-hdmi-arc",
805 "/soc@0/bus@32c00000/display-controller@32e00000",
806 "/soc@0/bus@32c00000/hdmi@32c00000",
807 };
808
809 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
810}
811
812static int check_mipi_dsi_nodes(void *blob)
813{
814 static const char * const lcdif_path[] = {
815 "/lcdif@30320000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800816 "/soc@0/bus@30000000/lcdif@30320000",
817 "/soc@0/bus@30000000/lcd-controller@30320000"
Peng Fan435dc122020-07-09 14:06:49 +0800818 };
819 static const char * const mipi_dsi_path[] = {
820 "/mipi_dsi@30A00000",
821 "/soc@0/bus@30800000/mipi_dsi@30a00000"
822 };
823 static const char * const lcdif_ep_path[] = {
824 "/lcdif@30320000/port@0/mipi-dsi-endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800825 "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
826 "/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
Peng Fan435dc122020-07-09 14:06:49 +0800827 };
828 static const char * const mipi_dsi_ep_path[] = {
829 "/mipi_dsi@30A00000/port@1/endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800830 "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
831 "/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
Peng Fan435dc122020-07-09 14:06:49 +0800832 };
833
834 int lookup_node;
835 int nodeoff;
836 bool new_path = check_fdt_new_path(blob);
837 int i = new_path ? 1 : 0;
838
839 nodeoff = fdt_path_offset(blob, lcdif_path[i]);
840 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
841 /*
842 * If can't find lcdif node or lcdif node is disabled,
843 * then disable all mipi dsi, since they only can input
844 * from DCSS
845 */
846 return disable_mipi_dsi_nodes(blob);
847 }
848
849 nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
850 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
851 return 0;
852
853 nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
854 if (nodeoff < 0) {
855 /*
856 * If can't find lcdif endpoint, then disable all mipi dsi,
857 * since they only can input from DCSS
858 */
859 return disable_mipi_dsi_nodes(blob);
860 }
861
862 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
863 nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
864
865 if (nodeoff > 0 && nodeoff == lookup_node)
866 return 0;
867
868 return disable_mipi_dsi_nodes(blob);
869}
870#endif
871
872int disable_vpu_nodes(void *blob)
873{
874 static const char * const nodes_path_8mq[] = {
875 "/vpu@38300000",
876 "/soc@0/vpu@38300000"
877 };
878
879 static const char * const nodes_path_8mm[] = {
880 "/vpu_g1@38300000",
881 "/vpu_g2@38310000",
882 "/vpu_h1@38320000"
883 };
884
885 static const char * const nodes_path_8mp[] = {
886 "/vpu_g1@38300000",
887 "/vpu_g2@38310000",
888 "/vpu_vc8000e@38320000"
889 };
890
891 if (is_imx8mq())
892 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
893 else if (is_imx8mm())
894 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
895 else if (is_imx8mp())
896 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
897 else
898 return -EPERM;
899}
900
Ye Liee337ce2021-03-19 15:57:09 +0800901#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
902static int low_drive_gpu_freq(void *blob)
903{
904 static const char *nodes_path_8mn[] = {
905 "/gpu@38000000",
906 "/soc@0/gpu@38000000"
907 };
908
909 int nodeoff, cnt, i;
910 u32 assignedclks[7];
911
912 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
913 if (nodeoff < 0)
914 return nodeoff;
915
916 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
917 if (cnt < 0)
918 return cnt;
919
920 if (cnt != 7)
921 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
922
923 assignedclks[cnt - 1] = 200000000;
924 assignedclks[cnt - 2] = 200000000;
925
926 for (i = 0; i < cnt; i++) {
927 debug("<%u>, ", assignedclks[i]);
928 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
929 }
930 debug("\n");
931
932 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
933}
934#endif
935
Peng Fanf5f9b8e2022-04-07 15:55:53 +0800936static bool check_remote_endpoint(void *blob, const char *ep1, const char *ep2)
937{
938 int lookup_node;
939 int nodeoff;
940
941 nodeoff = fdt_path_offset(blob, ep1);
942 if (nodeoff) {
943 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
944 nodeoff = fdt_path_offset(blob, ep2);
945
946 if (nodeoff > 0 && nodeoff == lookup_node)
947 return true;
948 }
949
950 return false;
951}
952
953int disable_dsi_lcdif_nodes(void *blob)
954{
955 int ret;
956
957 static const char * const dsi_path_8mp[] = {
958 "/soc@0/bus@32c00000/mipi_dsi@32e60000"
959 };
960
961 static const char * const lcdif_path_8mp[] = {
962 "/soc@0/bus@32c00000/lcd-controller@32e80000"
963 };
964
965 static const char * const lcdif_ep_path_8mp[] = {
966 "/soc@0/bus@32c00000/lcd-controller@32e80000/port@0/endpoint"
967 };
968 static const char * const dsi_ep_path_8mp[] = {
969 "/soc@0/bus@32c00000/mipi_dsi@32e60000/port@0/endpoint"
970 };
971
972 ret = disable_fdt_nodes(blob, dsi_path_8mp, ARRAY_SIZE(dsi_path_8mp));
973 if (ret)
974 return ret;
975
976 if (check_remote_endpoint(blob, dsi_ep_path_8mp[0], lcdif_ep_path_8mp[0])) {
977 /* Disable lcdif node */
978 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
979 }
980
981 return 0;
982}
983
984int disable_lvds_lcdif_nodes(void *blob)
985{
986 int ret, i;
987
988 static const char * const ldb_path_8mp[] = {
989 "/soc@0/bus@32c00000/ldb@32ec005c",
990 "/soc@0/bus@32c00000/phy@32ec0128"
991 };
992
993 static const char * const lcdif_path_8mp[] = {
994 "/soc@0/bus@32c00000/lcd-controller@32e90000"
995 };
996
997 static const char * const lcdif_ep_path_8mp[] = {
998 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@0",
999 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@1"
1000 };
1001 static const char * const ldb_ep_path_8mp[] = {
1002 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@0/port@0/endpoint",
1003 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@1/port@0/endpoint"
1004 };
1005
1006 ret = disable_fdt_nodes(blob, ldb_path_8mp, ARRAY_SIZE(ldb_path_8mp));
1007 if (ret)
1008 return ret;
1009
1010 for (i = 0; i < ARRAY_SIZE(ldb_ep_path_8mp); i++) {
1011 if (check_remote_endpoint(blob, ldb_ep_path_8mp[i], lcdif_ep_path_8mp[i])) {
1012 /* Disable lcdif node */
1013 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1014 }
1015 }
1016
1017 return 0;
1018}
1019
Peng Fan435dc122020-07-09 14:06:49 +08001020int disable_gpu_nodes(void *blob)
1021{
1022 static const char * const nodes_path_8mn[] = {
Peng Fan7d4195c2021-03-19 15:57:13 +08001023 "/gpu@38000000",
1024 "/soc@/gpu@38000000"
Peng Fan435dc122020-07-09 14:06:49 +08001025 };
1026
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001027 static const char * const nodes_path_8mp[] = {
1028 "/gpu3d@38000000",
1029 "/gpu2d@38008000"
1030 };
1031
1032 if (is_imx8mp())
1033 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1034 else
1035 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
Peng Fan435dc122020-07-09 14:06:49 +08001036}
1037
1038int disable_npu_nodes(void *blob)
1039{
1040 static const char * const nodes_path_8mp[] = {
1041 "/vipsi@38500000"
1042 };
1043
1044 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1045}
1046
1047int disable_isp_nodes(void *blob)
1048{
1049 static const char * const nodes_path_8mp[] = {
1050 "/soc@0/bus@32c00000/camera/isp@32e10000",
1051 "/soc@0/bus@32c00000/camera/isp@32e20000"
1052 };
1053
1054 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1055}
1056
1057int disable_dsp_nodes(void *blob)
1058{
1059 static const char * const nodes_path_8mp[] = {
1060 "/dsp@3b6e8000"
1061 };
1062
1063 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1064}
1065
Ye Li26517af2021-03-19 15:57:12 +08001066static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores)
1067{
1068 static const char * const thermal_path[] = {
1069 "/thermal-zones/cpu-thermal/cooling-maps/map0"
1070 };
1071
1072 int nodeoff, cnt, i, ret, j;
1073 u32 cooling_dev[12];
1074
1075 for (i = 0; i < ARRAY_SIZE(thermal_path); i++) {
1076 nodeoff = fdt_path_offset(blob, thermal_path[i]);
1077 if (nodeoff < 0)
1078 continue; /* Not found, skip it */
1079
1080 cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 12);
1081 if (cnt < 0)
1082 continue;
1083
1084 if (cnt != 12)
1085 printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt);
1086
1087 for (j = 0; j < cnt; j++)
1088 cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]);
1089
1090 ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev,
1091 sizeof(u32) * (12 - disabled_cores * 3));
1092 if (ret < 0) {
1093 printf("Warning: %s, cooling-device setprop failed %d\n",
1094 thermal_path[i], ret);
1095 continue;
1096 }
1097
1098 printf("Update node %s, cooling-device prop\n", thermal_path[i]);
1099 }
1100}
1101
1102static void disable_pmu_cpu_nodes(void *blob, u32 disabled_cores)
1103{
1104 static const char * const pmu_path[] = {
1105 "/pmu"
1106 };
1107
1108 int nodeoff, cnt, i, ret, j;
1109 u32 irq_affinity[4];
1110
1111 for (i = 0; i < ARRAY_SIZE(pmu_path); i++) {
1112 nodeoff = fdt_path_offset(blob, pmu_path[i]);
1113 if (nodeoff < 0)
1114 continue; /* Not found, skip it */
1115
1116 cnt = fdtdec_get_int_array_count(blob, nodeoff, "interrupt-affinity",
1117 irq_affinity, 4);
1118 if (cnt < 0)
1119 continue;
1120
1121 if (cnt != 4)
1122 printf("Warning: %s, interrupt-affinity count %d\n", pmu_path[i], cnt);
1123
1124 for (j = 0; j < cnt; j++)
1125 irq_affinity[j] = cpu_to_fdt32(irq_affinity[j]);
1126
1127 ret = fdt_setprop(blob, nodeoff, "interrupt-affinity", &irq_affinity,
1128 sizeof(u32) * (4 - disabled_cores));
1129 if (ret < 0) {
1130 printf("Warning: %s, interrupt-affinity setprop failed %d\n",
1131 pmu_path[i], ret);
1132 continue;
1133 }
1134
1135 printf("Update node %s, interrupt-affinity prop\n", pmu_path[i]);
1136 }
1137}
1138
Peng Fan435dc122020-07-09 14:06:49 +08001139static int disable_cpu_nodes(void *blob, u32 disabled_cores)
1140{
1141 static const char * const nodes_path[] = {
1142 "/cpus/cpu@1",
1143 "/cpus/cpu@2",
1144 "/cpus/cpu@3",
1145 };
1146 u32 i = 0;
1147 int rc;
1148 int nodeoff;
1149
1150 if (disabled_cores > 3)
1151 return -EINVAL;
1152
1153 i = 3 - disabled_cores;
1154
1155 for (; i < 3; i++) {
1156 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1157 if (nodeoff < 0)
1158 continue; /* Not found, skip it */
1159
1160 debug("Found %s node\n", nodes_path[i]);
1161
1162 rc = fdt_del_node(blob, nodeoff);
1163 if (rc < 0) {
1164 printf("Unable to delete node %s, err=%s\n",
1165 nodes_path[i], fdt_strerror(rc));
1166 } else {
1167 printf("Delete node %s\n", nodes_path[i]);
1168 }
1169 }
1170
Ye Li26517af2021-03-19 15:57:12 +08001171 disable_thermal_cpu_nodes(blob, disabled_cores);
1172 disable_pmu_cpu_nodes(blob, disabled_cores);
1173
Peng Fan435dc122020-07-09 14:06:49 +08001174 return 0;
1175}
1176
Peng Fana08bc872022-04-07 15:55:54 +08001177static int cleanup_nodes_for_efi(void *blob)
1178{
Peng Fan1585b202022-04-07 15:55:55 +08001179 static const char * const path[][2] = {
1180 { "/soc@0/bus@32c00000/usb@32e40000", "extcon" },
1181 { "/soc@0/bus@32c00000/usb@32e50000", "extcon" },
1182 { "/soc@0/bus@30800000/ethernet@30be0000", "phy-reset-gpios" },
1183 { "/soc@0/bus@30800000/ethernet@30bf0000", "phy-reset-gpios" }
1184 };
Peng Fana08bc872022-04-07 15:55:54 +08001185 int nodeoff, i, rc;
1186
Peng Fan1585b202022-04-07 15:55:55 +08001187 for (i = 0; i < ARRAY_SIZE(path); i++) {
1188 nodeoff = fdt_path_offset(blob, path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001189 if (nodeoff < 0)
1190 continue; /* Not found, skip it */
Peng Fan1585b202022-04-07 15:55:55 +08001191 debug("Found %s node\n", path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001192
Peng Fan1585b202022-04-07 15:55:55 +08001193 rc = fdt_delprop(blob, nodeoff, path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001194 if (rc == -FDT_ERR_NOTFOUND)
1195 continue;
1196 if (rc) {
1197 printf("Unable to update property %s:%s, err=%s\n",
Peng Fan1585b202022-04-07 15:55:55 +08001198 path[i][0], path[i][1], fdt_strerror(rc));
Peng Fana08bc872022-04-07 15:55:54 +08001199 return rc;
1200 }
1201
Peng Fan1585b202022-04-07 15:55:55 +08001202 printf("Remove %s:%s\n", path[i][0], path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001203 }
1204
1205 return 0;
1206}
Peng Fana08bc872022-04-07 15:55:54 +08001207
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001208int ft_system_setup(void *blob, struct bd_info *bd)
Peng Faneae4de22018-01-10 13:20:37 +08001209{
Peng Fan435dc122020-07-09 14:06:49 +08001210#ifdef CONFIG_IMX8MQ
Peng Faneae4de22018-01-10 13:20:37 +08001211 int i = 0;
1212 int rc;
1213 int nodeoff;
1214
Peng Fan435dc122020-07-09 14:06:49 +08001215 if (get_boot_device() == USB_BOOT) {
1216 disable_dcss_nodes(blob);
1217
1218 bool new_path = check_fdt_new_path(blob);
1219 int v = new_path ? 1 : 0;
1220 static const char * const usb_dwc3_path[] = {
1221 "/usb@38100000/dwc3",
1222 "/soc@0/usb@38100000"
1223 };
1224
1225 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1226 if (nodeoff >= 0) {
1227 const char *speed = "high-speed";
1228
1229 printf("Found %s node\n", usb_dwc3_path[v]);
1230
1231usb_modify_speed:
1232
1233 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1234 if (rc) {
1235 if (rc == -FDT_ERR_NOSPACE) {
1236 rc = fdt_increase_size(blob, 512);
1237 if (!rc)
1238 goto usb_modify_speed;
1239 }
1240 printf("Unable to set property %s:%s, err=%s\n",
1241 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1242 } else {
1243 printf("Modify %s:%s = %s\n",
1244 usb_dwc3_path[v], "maximum-speed", speed);
1245 }
1246 } else {
1247 printf("Can't found %s node\n", usb_dwc3_path[v]);
1248 }
1249 }
1250
Peng Faneae4de22018-01-10 13:20:37 +08001251 /* Disable the CPU idle for A0 chip since the HW does not support it */
1252 if (is_soc_rev(CHIP_REV_1_0)) {
1253 static const char * const nodes_path[] = {
1254 "/cpus/cpu@0",
1255 "/cpus/cpu@1",
1256 "/cpus/cpu@2",
1257 "/cpus/cpu@3",
1258 };
1259
1260 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1261 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1262 if (nodeoff < 0)
1263 continue; /* Not found, skip it */
1264
Marek Vasute2e7a772020-04-24 21:37:33 +02001265 debug("Found %s node\n", nodes_path[i]);
Peng Faneae4de22018-01-10 13:20:37 +08001266
1267 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasute2e7a772020-04-24 21:37:33 +02001268 if (rc == -FDT_ERR_NOTFOUND)
1269 continue;
Peng Faneae4de22018-01-10 13:20:37 +08001270 if (rc) {
1271 printf("Unable to update property %s:%s, err=%s\n",
1272 nodes_path[i], "status", fdt_strerror(rc));
1273 return rc;
1274 }
1275
Marek Vasute2e7a772020-04-24 21:37:33 +02001276 debug("Remove %s:%s\n", nodes_path[i],
Peng Faneae4de22018-01-10 13:20:37 +08001277 "cpu-idle-states");
1278 }
1279 }
1280
Peng Fan435dc122020-07-09 14:06:49 +08001281 if (is_imx8mql()) {
1282 disable_vpu_nodes(blob);
1283 if (check_dcss_fused()) {
1284 printf("DCSS is fused\n");
1285 disable_dcss_nodes(blob);
1286 check_mipi_dsi_nodes(blob);
1287 }
1288 }
1289
1290 if (is_imx8md())
1291 disable_cpu_nodes(blob, 2);
1292
1293#elif defined(CONFIG_IMX8MM)
1294 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1295 disable_vpu_nodes(blob);
1296
1297 if (is_imx8mmd() || is_imx8mmdl())
1298 disable_cpu_nodes(blob, 2);
1299 else if (is_imx8mms() || is_imx8mmsl())
1300 disable_cpu_nodes(blob, 3);
1301
1302#elif defined(CONFIG_IMX8MN)
1303 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1304 disable_gpu_nodes(blob);
Ye Liee337ce2021-03-19 15:57:09 +08001305#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1306 else {
1307 int ldm_gpu = low_drive_gpu_freq(blob);
1308
1309 if (ldm_gpu < 0)
1310 printf("Update GPU node assigned-clock-rates failed\n");
1311 else
1312 printf("Update GPU node assigned-clock-rates ok\n");
1313 }
1314#endif
Peng Fan435dc122020-07-09 14:06:49 +08001315
Ye Li715180e2021-03-19 15:57:11 +08001316 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan435dc122020-07-09 14:06:49 +08001317 disable_cpu_nodes(blob, 2);
Ye Li715180e2021-03-19 15:57:11 +08001318 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan435dc122020-07-09 14:06:49 +08001319 disable_cpu_nodes(blob, 3);
1320
1321#elif defined(CONFIG_IMX8MP)
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001322 if (is_imx8mpul()) {
1323 /* Disable GPU */
1324 disable_gpu_nodes(blob);
1325
1326 /* Disable DSI */
1327 disable_dsi_lcdif_nodes(blob);
1328
1329 /* Disable LVDS */
1330 disable_lvds_lcdif_nodes(blob);
1331 }
1332
1333 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001334 disable_vpu_nodes(blob);
1335
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001336 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001337 disable_npu_nodes(blob);
1338
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001339 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001340 disable_isp_nodes(blob);
1341
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001342 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001343 disable_dsp_nodes(blob);
1344
1345 if (is_imx8mpd())
1346 disable_cpu_nodes(blob, 2);
1347#endif
1348
Peng Fan1585b202022-04-07 15:55:55 +08001349 cleanup_nodes_for_efi(blob);
Peng Faneae4de22018-01-10 13:20:37 +08001350 return 0;
1351}
1352#endif
1353
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001354#ifdef CONFIG_OF_BOARD_FIXUP
1355#ifndef CONFIG_SPL_BUILD
1356int board_fix_fdt(void *fdt)
1357{
1358 if (is_imx8mpul()) {
1359 int i = 0;
1360 int nodeoff, ret;
1361 const char *status = "disabled";
1362 static const char * const dsi_nodes[] = {
1363 "/soc@0/bus@32c00000/mipi_dsi@32e60000",
1364 "/soc@0/bus@32c00000/lcd-controller@32e80000",
1365 "/dsi-host"
1366 };
1367
1368 for (i = 0; i < ARRAY_SIZE(dsi_nodes); i++) {
1369 nodeoff = fdt_path_offset(fdt, dsi_nodes[i]);
1370 if (nodeoff > 0) {
1371set_status:
1372 ret = fdt_setprop(fdt, nodeoff, "status", status,
1373 strlen(status) + 1);
1374 if (ret == -FDT_ERR_NOSPACE) {
1375 ret = fdt_increase_size(fdt, 512);
1376 if (!ret)
1377 goto set_status;
1378 }
1379 }
1380 }
1381 }
1382
1383 return 0;
1384}
1385#endif
1386#endif
1387
Marek Vasut64dc4de2020-04-29 15:04:21 +02001388#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler6f14d5f2020-12-15 16:47:52 +01001389void reset_cpu(void)
Peng Faneae4de22018-01-10 13:20:37 +08001390{
Claudius Heinee73f3942020-04-29 15:04:23 +02001391 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Faneae4de22018-01-10 13:20:37 +08001392
Ye Li54a915a2019-12-09 00:47:18 -08001393 /* Clear WDA to trigger WDOG_B immediately */
1394 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fan24290d92019-08-27 06:25:41 +00001395
Ye Li54a915a2019-12-09 00:47:18 -08001396 while (1) {
1397 /*
Harald Seilerec0c4472020-04-29 15:04:22 +02001398 * spin for .5 seconds before reset
Ye Li54a915a2019-12-09 00:47:18 -08001399 */
1400 }
Peng Faneae4de22018-01-10 13:20:37 +08001401}
Peng Fan24290d92019-08-27 06:25:41 +00001402#endif
Peng Fan5760d8d2020-04-22 10:51:13 +08001403
1404#if defined(CONFIG_ARCH_MISC_INIT)
Peng Fan5760d8d2020-04-22 10:51:13 +08001405int arch_misc_init(void)
1406{
Gaurav Jain81113a02022-03-24 11:50:27 +05301407 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1408 struct udevice *dev;
1409 int ret;
1410
1411 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1412 if (ret)
1413 printf("Failed to initialize %s: %d\n", dev->name, ret);
1414 }
Peng Fan5760d8d2020-04-22 10:51:13 +08001415
1416 return 0;
1417}
1418#endif
Ye Li325cd012020-05-03 22:19:52 +08001419
1420void imx_tmu_arch_init(void *reg_base)
1421{
Ye Lia00f2f02020-05-03 22:19:53 +08001422 if (is_imx8mm() || is_imx8mn()) {
Ye Li325cd012020-05-03 22:19:52 +08001423 /* Load TCALIV and TASR from fuses */
1424 struct ocotp_regs *ocotp =
1425 (struct ocotp_regs *)OCOTP_BASE_ADDR;
1426 struct fuse_bank *bank = &ocotp->bank[3];
1427 struct fuse_bank3_regs *fuse =
1428 (struct fuse_bank3_regs *)bank->fuse_regs;
1429
1430 u32 tca_rt, tca_hr, tca_en;
1431 u32 buf_vref, buf_slope;
1432
1433 tca_rt = fuse->ana0 & 0xFF;
1434 tca_hr = (fuse->ana0 & 0xFF00) >> 8;
1435 tca_en = (fuse->ana0 & 0x2000000) >> 25;
1436
1437 buf_vref = (fuse->ana0 & 0x1F00000) >> 20;
1438 buf_slope = (fuse->ana0 & 0xF0000) >> 16;
1439
1440 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1441 writel((tca_en << 31) | (tca_hr << 16) | tca_rt,
1442 (ulong)reg_base + 0x30);
1443 }
Ye Li41a20252020-05-03 22:19:54 +08001444#ifdef CONFIG_IMX8MP
1445 /* Load TCALIV0/1/m40 and TRIM from fuses */
1446 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
1447 struct fuse_bank *bank = &ocotp->bank[38];
1448 struct fuse_bank38_regs *fuse =
1449 (struct fuse_bank38_regs *)bank->fuse_regs;
1450 struct fuse_bank *bank2 = &ocotp->bank[39];
1451 struct fuse_bank39_regs *fuse2 =
1452 (struct fuse_bank39_regs *)bank2->fuse_regs;
1453 u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr;
1454 u32 reg;
1455 u32 tca40[2], tca25[2], tca105[2];
1456
1457 /* For blank sample */
1458 if (!fuse->ana_trim2 && !fuse->ana_trim3 &&
1459 !fuse->ana_trim4 && !fuse2->ana_trim5) {
1460 /* Use a default 25C binary codes */
1461 tca25[0] = 1596;
Ye Lid756ca02020-05-03 22:19:55 +08001462 tca25[1] = 1596;
Ye Li41a20252020-05-03 22:19:54 +08001463 writel(tca25[0], (ulong)reg_base + 0x30);
Ye Lid756ca02020-05-03 22:19:55 +08001464 writel(tca25[1], (ulong)reg_base + 0x34);
Ye Li41a20252020-05-03 22:19:54 +08001465 return;
1466 }
1467
1468 buf_vref = (fuse->ana_trim2 & 0xc0) >> 6;
1469 buf_slope = (fuse->ana_trim2 & 0xF00) >> 8;
1470 bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12;
1471 bgr = (fuse->ana_trim2 & 0xF0000) >> 16;
1472 vlsb = (fuse->ana_trim2 & 0xF00000) >> 20;
1473 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1474
1475 reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7);
1476 writel(reg, (ulong)reg_base + 0x3c);
1477
1478 tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16;
1479 tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28;
1480 tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4);
1481 tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8;
1482 tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20;
1483 tca25[1] = fuse2->ana_trim5 & 0xFFF;
1484 tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12;
1485
1486 /* use 25c for 1p calibration */
1487 writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30);
1488 writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34);
1489 writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38);
1490#endif
Ye Li325cd012020-05-03 22:19:52 +08001491}
Peng Fana35215d2020-07-09 13:39:26 +08001492
1493#if defined(CONFIG_SPL_BUILD)
1494#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1495bool serror_need_skip = true;
1496
Sean Anderson2d755492022-03-22 17:17:35 -04001497void do_error(struct pt_regs *pt_regs)
Peng Fana35215d2020-07-09 13:39:26 +08001498{
1499 /*
1500 * If stack is still in ROM reserved OCRAM not switch to SPL,
1501 * it is the ROM SError
1502 */
1503 ulong sp;
1504
1505 asm volatile("mov %0, sp" : "=r"(sp) : );
1506
1507 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1508 /* Check for ERR050342, imx8mq HDCP enabled parts */
1509 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1510 serror_need_skip = false;
1511 return; /* Do nothing skip the SError in ROM */
1512 }
1513
1514 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1515 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1516 serror_need_skip = false;
1517 return; /* Do nothing skip the SError in ROM */
1518 }
1519 }
1520
1521 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -04001522 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fana35215d2020-07-09 13:39:26 +08001523 show_regs(pt_regs);
1524 panic("Resetting CPU ...\n");
1525}
1526#endif
1527#endif
Ye Li0513f362019-07-15 01:16:46 -07001528
1529#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
Marek Vasut765b5802022-04-06 02:21:34 +02001530enum env_location arch_env_get_location(enum env_operation op, int prio)
Ye Li0513f362019-07-15 01:16:46 -07001531{
1532 enum boot_device dev = get_boot_device();
Ye Li0513f362019-07-15 01:16:46 -07001533
1534 if (prio)
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001535 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001536
1537 switch (dev) {
Fabio Estevam9be6daf2022-04-21 15:05:23 -03001538 case USB_BOOT:
1539 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1540 return ENVL_SPI_FLASH;
1541 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1542 return ENVL_NAND;
1543 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1544 return ENVL_MMC;
1545 if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
1546 return ENVL_NOWHERE;
1547 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001548 case QSPI_BOOT:
Marek Vasut31b3bc42022-03-25 18:59:28 +01001549 case SPI_NOR_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001550 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1551 return ENVL_SPI_FLASH;
1552 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001553 case NAND_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001554 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1555 return ENVL_NAND;
1556 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001557 case SD1_BOOT:
1558 case SD2_BOOT:
1559 case SD3_BOOT:
1560 case MMC1_BOOT:
1561 case MMC2_BOOT:
1562 case MMC3_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001563 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1564 return ENVL_MMC;
1565 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1566 return ENVL_EXT4;
1567 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1568 return ENVL_FAT;
1569 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001570 default:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001571 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001572 }
Ye Li0513f362019-07-15 01:16:46 -07001573}
1574
Ye Li0513f362019-07-15 01:16:46 -07001575#endif