blob: 7bfba4febcf7b51b6134d986cb77a48e77ede61e [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 Fanda7a16c2022-04-29 16:18:49 +080075 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010076
77 /*
78 * imx8mn and imx8mp implements the lock bit for
79 * TZASC_ID_SWAP_BYPASS, enable it to lock settings
80 */
Peng Fanda7a16c2022-04-29 16:18:49 +080081 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS_LOCK);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010082
Ye Li4c97c462019-08-27 06:25:34 +000083 /*
84 * set Region 0 attribute to allow secure and non-secure
85 * read/write permission. Found some masters like usb dwc3
86 * controllers can't work with secure memory.
87 */
88 writel(0xf0000000, TZASC_BASE_ADDR + 0x108);
Peng Faneae4de22018-01-10 13:20:37 +080089}
90
91void set_wdog_reset(struct wdog_regs *wdog)
92{
93 /*
94 * Output WDOG_B signal to reset external pmic or POR_B decided by
95 * the board design. Without external reset, the peripherals/DDR/
96 * PMIC are not reset, that may cause system working abnormal.
97 * WDZST bit is write-once only bit. Align this bit in kernel,
98 * otherwise kernel code will have no chance to set this bit.
99 */
100 setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK);
101}
102
Marek Vasut003969b2022-12-22 01:46:40 +0100103#ifdef CONFIG_ARMV8_PSCI
104#define PTE_MAP_NS PTE_BLOCK_NS
105#else
106#define PTE_MAP_NS 0
107#endif
108
Peng Faneae4de22018-01-10 13:20:37 +0800109static struct mm_region imx8m_mem_map[] = {
110 {
111 /* ROM */
112 .virt = 0x0UL,
113 .phys = 0x0UL,
114 .size = 0x100000UL,
115 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
116 PTE_BLOCK_OUTER_SHARE
117 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100118 /* CAAM */
119 .virt = 0x100000UL,
120 .phys = 0x100000UL,
121 .size = 0x8000UL,
122 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
123 PTE_BLOCK_NON_SHARE |
124 PTE_BLOCK_PXN | PTE_BLOCK_UXN
125 }, {
Marek Vasutb1738e02021-02-25 21:52:26 +0100126 /* OCRAM_S */
127 .virt = 0x180000UL,
128 .phys = 0x180000UL,
129 .size = 0x8000UL,
130 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100131 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Marek Vasutb1738e02021-02-25 21:52:26 +0100132 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100133 /* TCM */
134 .virt = 0x7C0000UL,
135 .phys = 0x7C0000UL,
136 .size = 0x80000UL,
137 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
138 PTE_BLOCK_NON_SHARE |
Marek Vasut003969b2022-12-22 01:46:40 +0100139 PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_MAP_NS
Gary Bisson5c72a452018-11-14 17:55:28 +0100140 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800141 /* OCRAM */
142 .virt = 0x900000UL,
143 .phys = 0x900000UL,
144 .size = 0x200000UL,
145 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100146 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Faneae4de22018-01-10 13:20:37 +0800147 }, {
148 /* AIPS */
149 .virt = 0xB00000UL,
150 .phys = 0xB00000UL,
151 .size = 0x3f500000UL,
152 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
153 PTE_BLOCK_NON_SHARE |
154 PTE_BLOCK_PXN | PTE_BLOCK_UXN
155 }, {
156 /* DRAM1 */
157 .virt = 0x40000000UL,
158 .phys = 0x40000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000159 .size = PHYS_SDRAM_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800160 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100161 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fanb749b5e2019-08-27 06:25:27 +0000162#ifdef PHYS_SDRAM_2_SIZE
Peng Faneae4de22018-01-10 13:20:37 +0800163 }, {
164 /* DRAM2 */
165 .virt = 0x100000000UL,
166 .phys = 0x100000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000167 .size = PHYS_SDRAM_2_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800168 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100169 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fanb749b5e2019-08-27 06:25:27 +0000170#endif
Peng Faneae4de22018-01-10 13:20:37 +0800171 }, {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800172 /* empty entrie to split table entry 5 if needed when TEEs are used */
173 0,
174 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800175 /* List terminator */
176 0,
177 }
178};
179
180struct mm_region *mem_map = imx8m_mem_map;
181
Marek Vasute48aac02021-02-27 14:59:00 +0100182static unsigned int imx8m_find_dram_entry_in_mem_map(void)
183{
184 int i;
185
186 for (i = 0; i < ARRAY_SIZE(imx8m_mem_map); i++)
Tom Rinibb4dd962022-11-16 13:10:37 -0500187 if (imx8m_mem_map[i].phys == CFG_SYS_SDRAM_BASE)
Marek Vasute48aac02021-02-27 14:59:00 +0100188 return i;
189
190 hang(); /* Entry not found, this must never happen. */
191}
192
Peng Fanb749b5e2019-08-27 06:25:27 +0000193void enable_caches(void)
194{
Ye Li453bfcb2022-04-07 15:55:56 +0800195 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
196 * If OPTEE does not run, still update the MMU table according to dram banks structure
197 * to set correct dram size from board_phys_sdram_size
198 */
199 int i = 0;
200 /*
201 * please make sure that entry initial value matches
202 * imx8m_mem_map for DRAM1
203 */
204 int entry = imx8m_find_dram_entry_in_mem_map();
205 u64 attrs = imx8m_mem_map[entry].attrs;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800206
Ye Li453bfcb2022-04-07 15:55:56 +0800207 while (i < CONFIG_NR_DRAM_BANKS &&
208 entry < ARRAY_SIZE(imx8m_mem_map)) {
209 if (gd->bd->bi_dram[i].start == 0)
210 break;
211 imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start;
212 imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start;
213 imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size;
214 imx8m_mem_map[entry].attrs = attrs;
215 debug("Added memory mapping (%d): %llx %llx\n", entry,
216 imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size);
217 i++; entry++;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800218 }
Peng Fanb749b5e2019-08-27 06:25:27 +0000219
220 icache_enable();
221 dcache_enable();
222}
223
Peng Fanfa35c3d2020-07-09 15:26:06 +0800224__weak int board_phys_sdram_size(phys_size_t *size)
225{
226 if (!size)
227 return -EINVAL;
228
229 *size = PHYS_SDRAM_SIZE;
Ye Li453bfcb2022-04-07 15:55:56 +0800230
231#ifdef PHYS_SDRAM_2_SIZE
232 *size += PHYS_SDRAM_2_SIZE;
233#endif
Peng Fanfa35c3d2020-07-09 15:26:06 +0800234 return 0;
235}
236
237int dram_init(void)
238{
239 phys_size_t sdram_size;
240 int ret;
241
242 ret = board_phys_sdram_size(&sdram_size);
243 if (ret)
244 return ret;
245
246 /* rom_pointer[1] contains the size of TEE occupies */
Elena Popa65c9edb2023-08-08 14:58:26 +0300247 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_SPL_BUILD) && rom_pointer[1])
Peng Fanfa35c3d2020-07-09 15:26:06 +0800248 gd->ram_size = sdram_size - rom_pointer[1];
249 else
250 gd->ram_size = sdram_size;
251
Peng Fanfa35c3d2020-07-09 15:26:06 +0800252 return 0;
253}
254
255int dram_init_banksize(void)
256{
257 int bank = 0;
258 int ret;
259 phys_size_t sdram_size;
Ye Li453bfcb2022-04-07 15:55:56 +0800260 phys_size_t sdram_b1_size, sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800261
262 ret = board_phys_sdram_size(&sdram_size);
263 if (ret)
264 return ret;
265
Ye Li453bfcb2022-04-07 15:55:56 +0800266 /* Bank 1 can't cross over 4GB space */
267 if (sdram_size > 0xc0000000) {
268 sdram_b1_size = 0xc0000000;
269 sdram_b2_size = sdram_size - 0xc0000000;
270 } else {
271 sdram_b1_size = sdram_size;
272 sdram_b2_size = 0;
273 }
274
Peng Fanfa35c3d2020-07-09 15:26:06 +0800275 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
Elena Popa65c9edb2023-08-08 14:58:26 +0300276 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_SPL_BUILD) && rom_pointer[1]) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800277 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
278 phys_size_t optee_size = (size_t)rom_pointer[1];
279
280 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
Ye Li453bfcb2022-04-07 15:55:56 +0800281 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800282 if (++bank >= CONFIG_NR_DRAM_BANKS) {
283 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
284 return -1;
285 }
286
287 gd->bd->bi_dram[bank].start = optee_start + optee_size;
288 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
Ye Li453bfcb2022-04-07 15:55:56 +0800289 sdram_b1_size - gd->bd->bi_dram[bank].start;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800290 }
291 } else {
Ye Li453bfcb2022-04-07 15:55:56 +0800292 gd->bd->bi_dram[bank].size = sdram_b1_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800293 }
294
Ye Li453bfcb2022-04-07 15:55:56 +0800295 if (sdram_b2_size) {
296 if (++bank >= CONFIG_NR_DRAM_BANKS) {
297 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
298 return -1;
299 }
300 gd->bd->bi_dram[bank].start = 0x100000000UL;
301 gd->bd->bi_dram[bank].size = sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800302 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800303
304 return 0;
305}
306
307phys_size_t get_effective_memsize(void)
308{
Ye Li453bfcb2022-04-07 15:55:56 +0800309 int ret;
310 phys_size_t sdram_size;
311 phys_size_t sdram_b1_size;
312 ret = board_phys_sdram_size(&sdram_size);
313 if (!ret) {
314 /* Bank 1 can't cross over 4GB space */
315 if (sdram_size > 0xc0000000) {
316 sdram_b1_size = 0xc0000000;
317 } else {
318 sdram_b1_size = sdram_size;
319 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800320
Elena Popa65c9edb2023-08-08 14:58:26 +0300321 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_SPL_BUILD) &&
322 rom_pointer[1]) {
Ye Li453bfcb2022-04-07 15:55:56 +0800323 /* We will relocate u-boot to Top of dram1. Tee position has two cases:
324 * 1. At the top of dram1, Then return the size removed optee size.
325 * 2. In the middle of dram1, return the size of dram1.
326 */
327 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
328 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
329 }
330
331 return sdram_b1_size;
332 } else {
333 return PHYS_SDRAM_SIZE;
334 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800335}
336
Heinrich Schuchardt51a9aac2023-08-12 20:16:58 +0200337phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Frieder Schrempf159879e2021-06-07 14:36:44 +0200338{
Marek Vasutdcbbf782022-04-14 15:51:46 +0200339 ulong top_addr;
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800340
Frieder Schrempf159879e2021-06-07 14:36:44 +0200341 /*
342 * Some IPs have their accessible address space restricted by
343 * the interconnect. Let's make sure U-Boot only ever uses the
344 * space below the 4G address boundary (which is 3GiB big),
345 * even when the effective available memory is bigger.
346 */
Marek Vasutdcbbf782022-04-14 15:51:46 +0200347 top_addr = clamp_val((u64)PHYS_SDRAM + gd->ram_size, 0, 0xffffffff);
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800348
349 /*
350 * rom_pointer[0] stores the TEE memory start address.
351 * rom_pointer[1] stores the size TEE uses.
352 * We need to reserve the memory region for TEE.
353 */
Marek Vasut9ca966e2022-12-22 01:46:38 +0100354 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && rom_pointer[0] &&
355 rom_pointer[1] && top_addr > rom_pointer[0])
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800356 top_addr = rom_pointer[0];
Frieder Schrempf159879e2021-06-07 14:36:44 +0200357
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800358 return top_addr;
Frieder Schrempf159879e2021-06-07 14:36:44 +0200359}
360
Peng Fan1caffdf2019-08-27 06:25:17 +0000361static u32 get_cpu_variant_type(u32 type)
362{
363 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
364 struct fuse_bank *bank = &ocotp->bank[1];
365 struct fuse_bank1_regs *fuse =
366 (struct fuse_bank1_regs *)bank->fuse_regs;
367
368 u32 value = readl(&fuse->tester4);
369
Peng Fan67815082020-02-05 17:34:54 +0800370 if (type == MXC_CPU_IMX8MQ) {
371 if ((value & 0x3) == 0x2)
372 return MXC_CPU_IMX8MD;
373 else if (value & 0x200000)
374 return MXC_CPU_IMX8MQL;
375
376 } else if (type == MXC_CPU_IMX8MM) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000377 switch (value & 0x3) {
378 case 2:
379 if (value & 0x1c0000)
380 return MXC_CPU_IMX8MMDL;
381 else
382 return MXC_CPU_IMX8MMD;
383 case 3:
384 if (value & 0x1c0000)
385 return MXC_CPU_IMX8MMSL;
386 else
387 return MXC_CPU_IMX8MMS;
388 default:
389 if (value & 0x1c0000)
390 return MXC_CPU_IMX8MML;
391 break;
392 }
Peng Fan1a07d912020-02-05 17:39:27 +0800393 } else if (type == MXC_CPU_IMX8MN) {
394 switch (value & 0x3) {
395 case 2:
Ye Li715180e2021-03-19 15:57:11 +0800396 if (value & 0x1000000) {
397 if (value & 0x10000000) /* MIPI DSI */
398 return MXC_CPU_IMX8MNUD;
399 else
400 return MXC_CPU_IMX8MNDL;
401 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800402 return MXC_CPU_IMX8MND;
Ye Li715180e2021-03-19 15:57:11 +0800403 }
Peng Fan1a07d912020-02-05 17:39:27 +0800404 case 3:
Ye Li715180e2021-03-19 15:57:11 +0800405 if (value & 0x1000000) {
406 if (value & 0x10000000) /* MIPI DSI */
407 return MXC_CPU_IMX8MNUS;
408 else
409 return MXC_CPU_IMX8MNSL;
410 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800411 return MXC_CPU_IMX8MNS;
Ye Li715180e2021-03-19 15:57:11 +0800412 }
Peng Fan1a07d912020-02-05 17:39:27 +0800413 default:
Ye Li715180e2021-03-19 15:57:11 +0800414 if (value & 0x1000000) {
415 if (value & 0x10000000) /* MIPI DSI */
416 return MXC_CPU_IMX8MNUQ;
417 else
418 return MXC_CPU_IMX8MNL;
419 }
Peng Fan1a07d912020-02-05 17:39:27 +0800420 break;
421 }
Ye Lid2d754f2020-04-20 20:12:54 -0700422 } else if (type == MXC_CPU_IMX8MP) {
423 u32 value0 = readl(&fuse->tester3);
424 u32 flag = 0;
425
426 if ((value0 & 0xc0000) == 0x80000)
427 return MXC_CPU_IMX8MPD;
428
429 /* vpu disabled */
430 if ((value0 & 0x43000000) == 0x43000000)
431 flag = 1;
432
433 /* npu disabled*/
434 if ((value & 0x8) == 0x8)
Peng Fan0386e7f2022-04-07 15:55:52 +0800435 flag |= BIT(1);
Ye Lid2d754f2020-04-20 20:12:54 -0700436
437 /* isp disabled */
438 if ((value & 0x3) == 0x3)
Peng Fan0386e7f2022-04-07 15:55:52 +0800439 flag |= BIT(2);
440
441 /* gpu disabled */
442 if ((value & 0xc0) == 0xc0)
443 flag |= BIT(3);
444
445 /* lvds disabled */
446 if ((value & 0x180000) == 0x180000)
447 flag |= BIT(4);
448
449 /* mipi dsi disabled */
450 if ((value & 0x60000) == 0x60000)
451 flag |= BIT(5);
Ye Lid2d754f2020-04-20 20:12:54 -0700452
453 switch (flag) {
Peng Fan0386e7f2022-04-07 15:55:52 +0800454 case 0x3f:
455 return MXC_CPU_IMX8MPUL;
Ye Lid2d754f2020-04-20 20:12:54 -0700456 case 7:
457 return MXC_CPU_IMX8MPL;
Ye Lid2d754f2020-04-20 20:12:54 -0700458 case 2:
459 return MXC_CPU_IMX8MP6;
Ye Lid2d754f2020-04-20 20:12:54 -0700460 default:
461 break;
462 }
463
Peng Fan1caffdf2019-08-27 06:25:17 +0000464 }
465
466 return type;
467}
468
Peng Faneae4de22018-01-10 13:20:37 +0800469u32 get_cpu_rev(void)
470{
471 struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
472 u32 reg = readl(&ana_pll->digprog);
473 u32 type = (reg >> 16) & 0xff;
Peng Fan1caffdf2019-08-27 06:25:17 +0000474 u32 major_low = (reg >> 8) & 0xff;
Peng Faneae4de22018-01-10 13:20:37 +0800475 u32 rom_version;
476
477 reg &= 0xff;
478
Peng Fan69cec072019-12-27 10:14:02 +0800479 /* iMX8MP */
480 if (major_low == 0x43) {
Ye Lid2d754f2020-04-20 20:12:54 -0700481 type = get_cpu_variant_type(MXC_CPU_IMX8MP);
Peng Fan69cec072019-12-27 10:14:02 +0800482 } else if (major_low == 0x42) {
483 /* iMX8MN */
Peng Fan1a07d912020-02-05 17:39:27 +0800484 type = get_cpu_variant_type(MXC_CPU_IMX8MN);
Peng Fan5d2f2062019-06-27 17:23:49 +0800485 } else if (major_low == 0x41) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000486 type = get_cpu_variant_type(MXC_CPU_IMX8MM);
487 } else {
488 if (reg == CHIP_REV_1_0) {
489 /*
Peng Fanc23fbdd2019-10-16 10:24:17 +0000490 * For B0 chip, the DIGPROG is not updated,
491 * it is still TO1.0. we have to check ROM
492 * version or OCOTP_READ_FUSE_DATA.
493 * 0xff0055aa is magic number for B1.
Peng Fan1caffdf2019-08-27 06:25:17 +0000494 */
Peng Fanc23fbdd2019-10-16 10:24:17 +0000495 if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
Ye Lic963ed12021-03-19 15:57:16 +0800496 /*
497 * B2 uses same DIGPROG and OCOTP_READ_FUSE_DATA value with B1,
498 * so have to check ROM to distinguish them
499 */
500 rom_version = readl((void __iomem *)ROM_VERSION_B0);
501 rom_version &= 0xff;
502 if (rom_version == CHIP_REV_2_2)
503 reg = CHIP_REV_2_2;
504 else
505 reg = CHIP_REV_2_1;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000506 } else {
507 rom_version =
508 readl((void __iomem *)ROM_VERSION_A0);
509 if (rom_version != CHIP_REV_1_0) {
510 rom_version = readl((void __iomem *)ROM_VERSION_B0);
Patrick Wildtd4a78b92019-11-19 09:42:06 +0100511 rom_version &= 0xff;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000512 if (rom_version == CHIP_REV_2_0)
513 reg = CHIP_REV_2_0;
514 }
Peng Fan1caffdf2019-08-27 06:25:17 +0000515 }
Peng Faneae4de22018-01-10 13:20:37 +0800516 }
Peng Fan67815082020-02-05 17:34:54 +0800517
518 type = get_cpu_variant_type(type);
Peng Faneae4de22018-01-10 13:20:37 +0800519 }
520
521 return (type << 12) | reg;
522}
523
524static void imx_set_wdog_powerdown(bool enable)
525{
526 struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
527 struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
528 struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
529
530 /* Write to the PDE (Power Down Enable) bit */
531 writew(enable, &wdog1->wmcr);
532 writew(enable, &wdog2->wmcr);
533 writew(enable, &wdog3->wmcr);
534}
535
Simon Glassb8357c12023-08-21 21:16:56 -0600536static int imx8m_check_clock(void)
Peng Fanc98e0322019-08-27 06:25:58 +0000537{
538 struct udevice *dev;
539 int ret;
540
Peng Fan3c073342019-10-16 03:01:51 +0000541 if (CONFIG_IS_ENABLED(CLK)) {
542 ret = uclass_get_device_by_name(UCLASS_CLK,
543 "clock-controller@30380000",
544 &dev);
545 if (ret < 0) {
546 printf("Failed to find clock node. Check device tree\n");
547 return ret;
548 }
Peng Fanc98e0322019-08-27 06:25:58 +0000549 }
550
551 return 0;
552}
Simon Glassb8357c12023-08-21 21:16:56 -0600553EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, imx8m_check_clock);
Peng Fanc98e0322019-08-27 06:25:58 +0000554
Marek Vasutf7b184e2022-09-19 21:37:07 +0200555static void imx8m_setup_snvs(void)
556{
557 /* Enable SNVS clock */
558 clock_enable(CCGR_SNVS, 1);
559 /* Initialize glitch detect */
560 writel(SNVS_LPPGDR_INIT, SNVS_BASE_ADDR + SNVS_LPLVDR);
561 /* Clear interrupt status */
562 writel(0xffffffff, SNVS_BASE_ADDR + SNVS_LPSR);
563}
564
Marek Vasut829858a2022-12-22 01:46:42 +0100565static void imx8m_setup_csu_tzasc(void)
566{
567 const uintptr_t tzasc_base[4] = {
568 0x301f0000, 0x301f0000, 0x301f0000, 0x301f0000
569 };
570 int i, j;
571
572 if (!IS_ENABLED(CONFIG_ARMV8_PSCI))
573 return;
574
575 /* CSU */
576 for (i = 0; i < 64; i++)
577 writel(0x00ff00ff, (void *)CSU_BASE_ADDR + (4 * i));
578
579 /* TZASC */
580 for (j = 0; j < 4; j++) {
581 writel(0x77777777, (void *)(tzasc_base[j]));
582 writel(0x77777777, (void *)(tzasc_base[j]) + 0x4);
583 for (i = 0; i <= 0x10; i += 4)
584 writel(0, (void *)(tzasc_base[j]) + 0x40 + i);
585 }
586}
587
Peng Faneae4de22018-01-10 13:20:37 +0800588int arch_cpu_init(void)
589{
Peng Fanc0b30d72019-04-17 09:41:16 +0000590 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
Marek Vasut3ea500a2022-04-13 00:41:52 +0200591
592#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
593 icache_enable();
594#endif
595
Peng Faneae4de22018-01-10 13:20:37 +0800596 /*
Peng Fand0ca2892019-08-27 06:25:37 +0000597 * ROM might disable clock for SCTR,
598 * enable the clock before timer_init.
599 */
600 if (IS_ENABLED(CONFIG_SPL_BUILD))
601 clock_enable(CCGR_SCTR, 1);
602 /*
Peng Faneae4de22018-01-10 13:20:37 +0800603 * Init timer at very early state, because sscg pll setting
604 * will use it
605 */
606 timer_init();
607
608 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
609 clock_init();
610 imx_set_wdog_powerdown(false);
Peng Fan9cf2aa32020-07-09 13:52:41 +0800611
612 if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
613 is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
Ye Li715180e2021-03-19 15:57:11 +0800614 is_imx8mnsl() || is_imx8mpd() || is_imx8mnud() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800615 /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
616 struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
617 struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
618 struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0);
619 struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR;
620
621 writel(0x1, &pgc_core2->pgcr);
622 writel(0x1, &pgc_core3->pgcr);
Ye Li715180e2021-03-19 15:57:11 +0800623 if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800624 writel(0x1, &pgc_core1->pgcr);
625 writel(0xE, &gpc->cpu_pgc_dn_trg);
626 } else {
627 writel(0xC, &gpc->cpu_pgc_dn_trg);
628 }
629 }
Peng Faneae4de22018-01-10 13:20:37 +0800630 }
631
Peng Fanc0b30d72019-04-17 09:41:16 +0000632 if (is_imx8mq()) {
633 clock_enable(CCGR_OCOTP, 1);
634 if (readl(&ocotp->ctrl) & 0x200)
635 writel(0x200, &ocotp->ctrl_clr);
636 }
637
Marek Vasutf7b184e2022-09-19 21:37:07 +0200638 imx8m_setup_snvs();
639
Marek Vasut829858a2022-12-22 01:46:42 +0100640 imx8m_setup_csu_tzasc();
641
Peng Faneae4de22018-01-10 13:20:37 +0800642 return 0;
643}
644
Peng Fanc9823b02019-09-16 03:09:36 +0000645#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
646struct rom_api *g_rom_api = (struct rom_api *)0x980;
Peng Fanc9823b02019-09-16 03:09:36 +0000647#endif
648
Marek Vasut520ded02021-07-03 04:55:33 +0200649#if defined(CONFIG_IMX8M)
650#include <spl.h>
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200651int imx8m_detect_secondary_image_boot(void)
Marek Vasut520ded02021-07-03 04:55:33 +0200652{
653 u32 *rom_log_addr = (u32 *)0x9e0;
654 u32 *rom_log;
655 u8 event_id;
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200656 int i, boot_secondary = 0;
Marek Vasut520ded02021-07-03 04:55:33 +0200657
658 /* If the ROM event log pointer is not valid. */
659 if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 ||
660 *rom_log_addr & 0x3)
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200661 return -EINVAL;
Marek Vasut520ded02021-07-03 04:55:33 +0200662
663 /* Parse the ROM event ID version 2 log */
664 rom_log = (u32 *)(uintptr_t)(*rom_log_addr);
665 for (i = 0; i < 128; i++) {
666 event_id = rom_log[i] >> 24;
667 switch (event_id) {
668 case 0x00: /* End of list */
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200669 return boot_secondary;
Marek Vasut520ded02021-07-03 04:55:33 +0200670 /* Log entries with 1 parameter, skip 1 */
671 case 0x80: /* Start to perform the device initialization */
672 case 0x81: /* The boot device initialization completes */
Fedor Ross7e02ff62022-04-14 18:36:23 +0200673 case 0x82: /* Starts to execute boot device driver pre-config */
Marek Vasut520ded02021-07-03 04:55:33 +0200674 case 0x8f: /* The boot device initialization fails */
675 case 0x90: /* Start to read data from boot device */
676 case 0x91: /* Reading data from boot device completes */
677 case 0x9f: /* Reading data from boot device fails */
678 i += 1;
679 continue;
680 /* Log entries with 2 parameters, skip 2 */
681 case 0xa0: /* Image authentication result */
682 case 0xc0: /* Jump to the boot image soon */
683 i += 2;
684 continue;
685 /* Boot from the secondary boot image */
686 case 0x51:
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200687 boot_secondary = 1;
Marek Vasut520ded02021-07-03 04:55:33 +0200688 continue;
689 default:
690 continue;
691 }
692 }
693
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200694 return boot_secondary;
695}
696
697int spl_mmc_emmc_boot_partition(struct mmc *mmc)
698{
699 int part, ret;
700
701 part = default_spl_mmc_emmc_boot_partition(mmc);
702 if (part == 0)
703 return part;
704
705 ret = imx8m_detect_secondary_image_boot();
706 if (ret < 0) {
707 printf("Could not get boot partition! Using %d\n", part);
708 return part;
709 }
710
711 if (ret == 1) {
712 /*
713 * Swap the eMMC boot partitions in case there was a
714 * fallback event (i.e. primary image was corrupted
715 * and that corruption was recognized by the BootROM),
716 * so the SPL loads the rest of the U-Boot from the
717 * correct eMMC boot partition, since the BootROM
718 * leaves the boot partition set to the corrupted one.
719 */
720 if (part == 1)
721 part = 2;
722 else if (part == 2)
723 part = 1;
724 }
725
Marek Vasut520ded02021-07-03 04:55:33 +0200726 return part;
727}
728#endif
729
Peng Faneae4de22018-01-10 13:20:37 +0800730bool is_usb_boot(void)
731{
732 return get_boot_device() == USB_BOOT;
733}
734
735#ifdef CONFIG_OF_SYSTEM_SETUP
Peng Fan435dc122020-07-09 14:06:49 +0800736bool check_fdt_new_path(void *blob)
737{
738 const char *soc_path = "/soc@0";
739 int nodeoff;
740
741 nodeoff = fdt_path_offset(blob, soc_path);
742 if (nodeoff < 0)
743 return false;
744
745 return true;
746}
747
748static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
749{
750 int i = 0;
751 int rc;
752 int nodeoff;
753 const char *status = "disabled";
754
755 for (i = 0; i < size_array; i++) {
756 nodeoff = fdt_path_offset(blob, nodes_path[i]);
757 if (nodeoff < 0)
758 continue; /* Not found, skip it */
759
Rasmus Villemoes8ab149a2023-05-22 11:27:28 +0200760 debug("Found %s node\n", nodes_path[i]);
Peng Fan435dc122020-07-09 14:06:49 +0800761
762add_status:
763 rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
764 if (rc) {
765 if (rc == -FDT_ERR_NOSPACE) {
766 rc = fdt_increase_size(blob, 512);
767 if (!rc)
768 goto add_status;
769 }
770 printf("Unable to update property %s:%s, err=%s\n",
771 nodes_path[i], "status", fdt_strerror(rc));
772 } else {
773 printf("Modify %s:%s disabled\n",
774 nodes_path[i], "status");
775 }
776 }
777
778 return 0;
779}
780
781#ifdef CONFIG_IMX8MQ
782bool check_dcss_fused(void)
783{
784 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
785 struct fuse_bank *bank = &ocotp->bank[1];
786 struct fuse_bank1_regs *fuse =
787 (struct fuse_bank1_regs *)bank->fuse_regs;
788 u32 value = readl(&fuse->tester4);
789
790 if (value & 0x4000000)
791 return true;
792
793 return false;
794}
795
796static int disable_mipi_dsi_nodes(void *blob)
797{
798 static const char * const nodes_path[] = {
799 "/mipi_dsi@30A00000",
800 "/mipi_dsi_bridge@30A00000",
801 "/dsi_phy@30A00300",
802 "/soc@0/bus@30800000/mipi_dsi@30a00000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800803 "/soc@0/bus@30800000/dphy@30a00300",
804 "/soc@0/bus@30800000/mipi-dsi@30a00000",
Peng Fan435dc122020-07-09 14:06:49 +0800805 };
806
807 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
808}
809
810static int disable_dcss_nodes(void *blob)
811{
812 static const char * const nodes_path[] = {
813 "/dcss@0x32e00000",
814 "/dcss@32e00000",
815 "/hdmi@32c00000",
816 "/hdmi_cec@32c33800",
817 "/hdmi_drm@32c00000",
818 "/display-subsystem",
819 "/sound-hdmi",
820 "/sound-hdmi-arc",
821 "/soc@0/bus@32c00000/display-controller@32e00000",
822 "/soc@0/bus@32c00000/hdmi@32c00000",
823 };
824
825 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
826}
827
828static int check_mipi_dsi_nodes(void *blob)
829{
830 static const char * const lcdif_path[] = {
831 "/lcdif@30320000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800832 "/soc@0/bus@30000000/lcdif@30320000",
833 "/soc@0/bus@30000000/lcd-controller@30320000"
Peng Fan435dc122020-07-09 14:06:49 +0800834 };
835 static const char * const mipi_dsi_path[] = {
836 "/mipi_dsi@30A00000",
837 "/soc@0/bus@30800000/mipi_dsi@30a00000"
838 };
839 static const char * const lcdif_ep_path[] = {
840 "/lcdif@30320000/port@0/mipi-dsi-endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800841 "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
842 "/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
Peng Fan435dc122020-07-09 14:06:49 +0800843 };
844 static const char * const mipi_dsi_ep_path[] = {
845 "/mipi_dsi@30A00000/port@1/endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800846 "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
847 "/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
Peng Fan435dc122020-07-09 14:06:49 +0800848 };
849
850 int lookup_node;
851 int nodeoff;
852 bool new_path = check_fdt_new_path(blob);
853 int i = new_path ? 1 : 0;
854
855 nodeoff = fdt_path_offset(blob, lcdif_path[i]);
856 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
857 /*
858 * If can't find lcdif node or lcdif node is disabled,
859 * then disable all mipi dsi, since they only can input
860 * from DCSS
861 */
862 return disable_mipi_dsi_nodes(blob);
863 }
864
865 nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
866 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
867 return 0;
868
869 nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
870 if (nodeoff < 0) {
871 /*
872 * If can't find lcdif endpoint, then disable all mipi dsi,
873 * since they only can input from DCSS
874 */
875 return disable_mipi_dsi_nodes(blob);
876 }
877
878 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
879 nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
880
881 if (nodeoff > 0 && nodeoff == lookup_node)
882 return 0;
883
884 return disable_mipi_dsi_nodes(blob);
885}
886#endif
887
888int disable_vpu_nodes(void *blob)
889{
890 static const char * const nodes_path_8mq[] = {
891 "/vpu@38300000",
892 "/soc@0/vpu@38300000"
893 };
894
895 static const char * const nodes_path_8mm[] = {
896 "/vpu_g1@38300000",
897 "/vpu_g2@38310000",
898 "/vpu_h1@38320000"
899 };
900
901 static const char * const nodes_path_8mp[] = {
902 "/vpu_g1@38300000",
903 "/vpu_g2@38310000",
904 "/vpu_vc8000e@38320000"
905 };
906
907 if (is_imx8mq())
908 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
909 else if (is_imx8mm())
910 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
911 else if (is_imx8mp())
912 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
913 else
914 return -EPERM;
915}
916
Ye Liee337ce2021-03-19 15:57:09 +0800917#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
918static int low_drive_gpu_freq(void *blob)
919{
920 static const char *nodes_path_8mn[] = {
921 "/gpu@38000000",
922 "/soc@0/gpu@38000000"
923 };
924
925 int nodeoff, cnt, i;
926 u32 assignedclks[7];
927
928 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
929 if (nodeoff < 0)
930 return nodeoff;
931
932 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
933 if (cnt < 0)
934 return cnt;
935
936 if (cnt != 7)
937 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
Heinrich Schuchardt72c891f2023-04-18 01:37:21 +0200938 if (cnt < 2)
939 return -1;
Ye Liee337ce2021-03-19 15:57:09 +0800940
941 assignedclks[cnt - 1] = 200000000;
942 assignedclks[cnt - 2] = 200000000;
943
944 for (i = 0; i < cnt; i++) {
945 debug("<%u>, ", assignedclks[i]);
946 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
947 }
948 debug("\n");
949
950 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
951}
952#endif
953
Peng Fanf5f9b8e2022-04-07 15:55:53 +0800954static bool check_remote_endpoint(void *blob, const char *ep1, const char *ep2)
955{
956 int lookup_node;
957 int nodeoff;
958
959 nodeoff = fdt_path_offset(blob, ep1);
960 if (nodeoff) {
961 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
962 nodeoff = fdt_path_offset(blob, ep2);
963
964 if (nodeoff > 0 && nodeoff == lookup_node)
965 return true;
966 }
967
968 return false;
969}
970
971int disable_dsi_lcdif_nodes(void *blob)
972{
973 int ret;
974
975 static const char * const dsi_path_8mp[] = {
976 "/soc@0/bus@32c00000/mipi_dsi@32e60000"
977 };
978
979 static const char * const lcdif_path_8mp[] = {
980 "/soc@0/bus@32c00000/lcd-controller@32e80000"
981 };
982
983 static const char * const lcdif_ep_path_8mp[] = {
984 "/soc@0/bus@32c00000/lcd-controller@32e80000/port@0/endpoint"
985 };
986 static const char * const dsi_ep_path_8mp[] = {
987 "/soc@0/bus@32c00000/mipi_dsi@32e60000/port@0/endpoint"
988 };
989
990 ret = disable_fdt_nodes(blob, dsi_path_8mp, ARRAY_SIZE(dsi_path_8mp));
991 if (ret)
992 return ret;
993
994 if (check_remote_endpoint(blob, dsi_ep_path_8mp[0], lcdif_ep_path_8mp[0])) {
995 /* Disable lcdif node */
996 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
997 }
998
999 return 0;
1000}
1001
1002int disable_lvds_lcdif_nodes(void *blob)
1003{
1004 int ret, i;
1005
1006 static const char * const ldb_path_8mp[] = {
1007 "/soc@0/bus@32c00000/ldb@32ec005c",
1008 "/soc@0/bus@32c00000/phy@32ec0128"
1009 };
1010
1011 static const char * const lcdif_path_8mp[] = {
1012 "/soc@0/bus@32c00000/lcd-controller@32e90000"
1013 };
1014
1015 static const char * const lcdif_ep_path_8mp[] = {
1016 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@0",
1017 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@1"
1018 };
1019 static const char * const ldb_ep_path_8mp[] = {
1020 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@0/port@0/endpoint",
1021 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@1/port@0/endpoint"
1022 };
1023
1024 ret = disable_fdt_nodes(blob, ldb_path_8mp, ARRAY_SIZE(ldb_path_8mp));
1025 if (ret)
1026 return ret;
1027
1028 for (i = 0; i < ARRAY_SIZE(ldb_ep_path_8mp); i++) {
1029 if (check_remote_endpoint(blob, ldb_ep_path_8mp[i], lcdif_ep_path_8mp[i])) {
1030 /* Disable lcdif node */
1031 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1032 }
1033 }
1034
1035 return 0;
1036}
1037
Peng Fan435dc122020-07-09 14:06:49 +08001038int disable_gpu_nodes(void *blob)
1039{
1040 static const char * const nodes_path_8mn[] = {
Peng Fan7d4195c2021-03-19 15:57:13 +08001041 "/gpu@38000000",
1042 "/soc@/gpu@38000000"
Peng Fan435dc122020-07-09 14:06:49 +08001043 };
1044
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001045 static const char * const nodes_path_8mp[] = {
1046 "/gpu3d@38000000",
1047 "/gpu2d@38008000"
1048 };
1049
1050 if (is_imx8mp())
1051 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1052 else
1053 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
Peng Fan435dc122020-07-09 14:06:49 +08001054}
1055
1056int disable_npu_nodes(void *blob)
1057{
1058 static const char * const nodes_path_8mp[] = {
1059 "/vipsi@38500000"
1060 };
1061
1062 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1063}
1064
1065int disable_isp_nodes(void *blob)
1066{
1067 static const char * const nodes_path_8mp[] = {
1068 "/soc@0/bus@32c00000/camera/isp@32e10000",
1069 "/soc@0/bus@32c00000/camera/isp@32e20000"
1070 };
1071
1072 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1073}
1074
1075int disable_dsp_nodes(void *blob)
1076{
1077 static const char * const nodes_path_8mp[] = {
1078 "/dsp@3b6e8000"
1079 };
1080
1081 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1082}
1083
Ye Li26517af2021-03-19 15:57:12 +08001084static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores)
1085{
1086 static const char * const thermal_path[] = {
1087 "/thermal-zones/cpu-thermal/cooling-maps/map0"
1088 };
1089
1090 int nodeoff, cnt, i, ret, j;
1091 u32 cooling_dev[12];
1092
1093 for (i = 0; i < ARRAY_SIZE(thermal_path); i++) {
1094 nodeoff = fdt_path_offset(blob, thermal_path[i]);
1095 if (nodeoff < 0)
1096 continue; /* Not found, skip it */
1097
1098 cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 12);
1099 if (cnt < 0)
1100 continue;
1101
1102 if (cnt != 12)
1103 printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt);
1104
1105 for (j = 0; j < cnt; j++)
1106 cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]);
1107
1108 ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev,
1109 sizeof(u32) * (12 - disabled_cores * 3));
1110 if (ret < 0) {
1111 printf("Warning: %s, cooling-device setprop failed %d\n",
1112 thermal_path[i], ret);
1113 continue;
1114 }
1115
1116 printf("Update node %s, cooling-device prop\n", thermal_path[i]);
1117 }
1118}
1119
1120static void disable_pmu_cpu_nodes(void *blob, u32 disabled_cores)
1121{
1122 static const char * const pmu_path[] = {
1123 "/pmu"
1124 };
1125
1126 int nodeoff, cnt, i, ret, j;
1127 u32 irq_affinity[4];
1128
1129 for (i = 0; i < ARRAY_SIZE(pmu_path); i++) {
1130 nodeoff = fdt_path_offset(blob, pmu_path[i]);
1131 if (nodeoff < 0)
1132 continue; /* Not found, skip it */
1133
1134 cnt = fdtdec_get_int_array_count(blob, nodeoff, "interrupt-affinity",
1135 irq_affinity, 4);
1136 if (cnt < 0)
1137 continue;
1138
1139 if (cnt != 4)
1140 printf("Warning: %s, interrupt-affinity count %d\n", pmu_path[i], cnt);
1141
1142 for (j = 0; j < cnt; j++)
1143 irq_affinity[j] = cpu_to_fdt32(irq_affinity[j]);
1144
1145 ret = fdt_setprop(blob, nodeoff, "interrupt-affinity", &irq_affinity,
1146 sizeof(u32) * (4 - disabled_cores));
1147 if (ret < 0) {
1148 printf("Warning: %s, interrupt-affinity setprop failed %d\n",
1149 pmu_path[i], ret);
1150 continue;
1151 }
1152
1153 printf("Update node %s, interrupt-affinity prop\n", pmu_path[i]);
1154 }
1155}
1156
Peng Fan435dc122020-07-09 14:06:49 +08001157static int disable_cpu_nodes(void *blob, u32 disabled_cores)
1158{
1159 static const char * const nodes_path[] = {
1160 "/cpus/cpu@1",
1161 "/cpus/cpu@2",
1162 "/cpus/cpu@3",
1163 };
1164 u32 i = 0;
1165 int rc;
1166 int nodeoff;
1167
1168 if (disabled_cores > 3)
1169 return -EINVAL;
1170
1171 i = 3 - disabled_cores;
1172
1173 for (; i < 3; i++) {
1174 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1175 if (nodeoff < 0)
1176 continue; /* Not found, skip it */
1177
1178 debug("Found %s node\n", nodes_path[i]);
1179
1180 rc = fdt_del_node(blob, nodeoff);
1181 if (rc < 0) {
1182 printf("Unable to delete node %s, err=%s\n",
1183 nodes_path[i], fdt_strerror(rc));
1184 } else {
1185 printf("Delete node %s\n", nodes_path[i]);
1186 }
1187 }
1188
Ye Li26517af2021-03-19 15:57:12 +08001189 disable_thermal_cpu_nodes(blob, disabled_cores);
1190 disable_pmu_cpu_nodes(blob, disabled_cores);
1191
Peng Fan435dc122020-07-09 14:06:49 +08001192 return 0;
1193}
1194
Peng Fana08bc872022-04-07 15:55:54 +08001195static int cleanup_nodes_for_efi(void *blob)
1196{
Peng Fan1585b202022-04-07 15:55:55 +08001197 static const char * const path[][2] = {
1198 { "/soc@0/bus@32c00000/usb@32e40000", "extcon" },
1199 { "/soc@0/bus@32c00000/usb@32e50000", "extcon" },
1200 { "/soc@0/bus@30800000/ethernet@30be0000", "phy-reset-gpios" },
1201 { "/soc@0/bus@30800000/ethernet@30bf0000", "phy-reset-gpios" }
1202 };
Peng Fana08bc872022-04-07 15:55:54 +08001203 int nodeoff, i, rc;
1204
Peng Fan1585b202022-04-07 15:55:55 +08001205 for (i = 0; i < ARRAY_SIZE(path); i++) {
1206 nodeoff = fdt_path_offset(blob, path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001207 if (nodeoff < 0)
1208 continue; /* Not found, skip it */
Peng Fan1585b202022-04-07 15:55:55 +08001209 debug("Found %s node\n", path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001210
Peng Fan1585b202022-04-07 15:55:55 +08001211 rc = fdt_delprop(blob, nodeoff, path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001212 if (rc == -FDT_ERR_NOTFOUND)
1213 continue;
1214 if (rc) {
1215 printf("Unable to update property %s:%s, err=%s\n",
Peng Fan1585b202022-04-07 15:55:55 +08001216 path[i][0], path[i][1], fdt_strerror(rc));
Peng Fana08bc872022-04-07 15:55:54 +08001217 return rc;
1218 }
1219
Peng Fan1585b202022-04-07 15:55:55 +08001220 printf("Remove %s:%s\n", path[i][0], path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001221 }
1222
1223 return 0;
1224}
Peng Fana08bc872022-04-07 15:55:54 +08001225
Andrejs Cainikovs2f3491c2022-05-27 15:20:42 +02001226static int fixup_thermal_trips(void *blob, const char *name)
1227{
1228 int minc, maxc;
1229 int node, trip;
1230
1231 node = fdt_path_offset(blob, "/thermal-zones");
1232 if (node < 0)
1233 return node;
1234
1235 node = fdt_subnode_offset(blob, node, name);
1236 if (node < 0)
1237 return node;
1238
1239 node = fdt_subnode_offset(blob, node, "trips");
1240 if (node < 0)
1241 return node;
1242
1243 get_cpu_temp_grade(&minc, &maxc);
1244
1245 fdt_for_each_subnode(trip, blob, node) {
1246 const char *type;
1247 int temp, ret;
1248
1249 type = fdt_getprop(blob, trip, "type", NULL);
1250 if (!type)
1251 continue;
1252
1253 temp = 0;
1254 if (!strcmp(type, "critical"))
1255 temp = 1000 * maxc;
1256 else if (!strcmp(type, "passive"))
1257 temp = 1000 * (maxc - 10);
1258 if (temp) {
1259 ret = fdt_setprop_u32(blob, trip, "temperature", temp);
1260 if (ret)
1261 return ret;
1262 }
1263 }
1264
1265 return 0;
1266}
1267
Tim Harvey709ace82023-08-24 12:05:17 -07001268#define OPTEE_SHM_SIZE 0x00400000
1269static int ft_add_optee_node(void *fdt, struct bd_info *bd)
1270{
1271 struct fdt_memory carveout;
1272 const char *path, *subpath;
1273 phys_addr_t optee_start;
1274 size_t optee_size;
1275 int offs;
1276 int ret;
1277
1278 /*
1279 * No TEE space allocated indicating no TEE running, so no
1280 * need to add optee node in dts
1281 */
1282 if (!rom_pointer[1])
1283 return 0;
1284
1285 optee_start = (phys_addr_t)rom_pointer[0];
1286 optee_size = rom_pointer[1] - OPTEE_SHM_SIZE;
1287
1288 offs = fdt_increase_size(fdt, 512);
1289 if (offs) {
1290 printf("No Space for dtb\n");
1291 return 1;
1292 }
1293
1294 path = "/firmware";
1295 offs = fdt_path_offset(fdt, path);
1296 if (offs < 0) {
1297 path = "/";
1298 offs = fdt_path_offset(fdt, path);
1299
1300 if (offs < 0) {
1301 printf("Could not find root node.\n");
1302 return offs;
1303 }
1304
1305 subpath = "firmware";
1306 offs = fdt_add_subnode(fdt, offs, subpath);
1307 if (offs < 0) {
1308 printf("Could not create %s node.\n", subpath);
1309 return offs;
1310 }
1311 }
1312
1313 subpath = "optee";
1314 offs = fdt_add_subnode(fdt, offs, subpath);
1315 if (offs < 0) {
1316 printf("Could not create %s node.\n", subpath);
1317 return offs;
1318 }
1319
1320 fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz");
1321 fdt_setprop_string(fdt, offs, "method", "smc");
1322
1323 carveout.start = optee_start,
1324 carveout.end = optee_start + optee_size - 1,
1325 ret = fdtdec_add_reserved_memory(fdt, "optee_core", &carveout, NULL, 0,
1326 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1327 if (ret < 0) {
1328 printf("Could not create optee_core node.\n");
1329 return ret;
1330 }
1331
1332 carveout.start = optee_start + optee_size;
1333 carveout.end = optee_start + optee_size + OPTEE_SHM_SIZE - 1;
1334 ret = fdtdec_add_reserved_memory(fdt, "optee_shm", &carveout, NULL, 0,
1335 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1336 if (ret < 0) {
1337 printf("Could not create optee_shm node.\n");
1338 return ret;
1339 }
1340
1341 return 0;
1342}
1343
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001344int ft_system_setup(void *blob, struct bd_info *bd)
Peng Faneae4de22018-01-10 13:20:37 +08001345{
Peng Fan435dc122020-07-09 14:06:49 +08001346#ifdef CONFIG_IMX8MQ
Peng Faneae4de22018-01-10 13:20:37 +08001347 int i = 0;
1348 int rc;
1349 int nodeoff;
1350
Peng Fan435dc122020-07-09 14:06:49 +08001351 if (get_boot_device() == USB_BOOT) {
1352 disable_dcss_nodes(blob);
1353
1354 bool new_path = check_fdt_new_path(blob);
1355 int v = new_path ? 1 : 0;
1356 static const char * const usb_dwc3_path[] = {
1357 "/usb@38100000/dwc3",
1358 "/soc@0/usb@38100000"
1359 };
1360
1361 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1362 if (nodeoff >= 0) {
1363 const char *speed = "high-speed";
1364
Rasmus Villemoes8ab149a2023-05-22 11:27:28 +02001365 debug("Found %s node\n", usb_dwc3_path[v]);
Peng Fan435dc122020-07-09 14:06:49 +08001366
1367usb_modify_speed:
1368
1369 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1370 if (rc) {
1371 if (rc == -FDT_ERR_NOSPACE) {
1372 rc = fdt_increase_size(blob, 512);
1373 if (!rc)
1374 goto usb_modify_speed;
1375 }
1376 printf("Unable to set property %s:%s, err=%s\n",
1377 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1378 } else {
1379 printf("Modify %s:%s = %s\n",
1380 usb_dwc3_path[v], "maximum-speed", speed);
1381 }
1382 } else {
1383 printf("Can't found %s node\n", usb_dwc3_path[v]);
1384 }
1385 }
1386
Peng Faneae4de22018-01-10 13:20:37 +08001387 /* Disable the CPU idle for A0 chip since the HW does not support it */
1388 if (is_soc_rev(CHIP_REV_1_0)) {
1389 static const char * const nodes_path[] = {
1390 "/cpus/cpu@0",
1391 "/cpus/cpu@1",
1392 "/cpus/cpu@2",
1393 "/cpus/cpu@3",
1394 };
1395
1396 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1397 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1398 if (nodeoff < 0)
1399 continue; /* Not found, skip it */
1400
Marek Vasute2e7a772020-04-24 21:37:33 +02001401 debug("Found %s node\n", nodes_path[i]);
Peng Faneae4de22018-01-10 13:20:37 +08001402
1403 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasute2e7a772020-04-24 21:37:33 +02001404 if (rc == -FDT_ERR_NOTFOUND)
1405 continue;
Peng Faneae4de22018-01-10 13:20:37 +08001406 if (rc) {
1407 printf("Unable to update property %s:%s, err=%s\n",
1408 nodes_path[i], "status", fdt_strerror(rc));
1409 return rc;
1410 }
1411
Marek Vasute2e7a772020-04-24 21:37:33 +02001412 debug("Remove %s:%s\n", nodes_path[i],
Peng Faneae4de22018-01-10 13:20:37 +08001413 "cpu-idle-states");
1414 }
1415 }
1416
Peng Fan435dc122020-07-09 14:06:49 +08001417 if (is_imx8mql()) {
1418 disable_vpu_nodes(blob);
1419 if (check_dcss_fused()) {
1420 printf("DCSS is fused\n");
1421 disable_dcss_nodes(blob);
1422 check_mipi_dsi_nodes(blob);
1423 }
1424 }
1425
1426 if (is_imx8md())
1427 disable_cpu_nodes(blob, 2);
1428
1429#elif defined(CONFIG_IMX8MM)
1430 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1431 disable_vpu_nodes(blob);
1432
1433 if (is_imx8mmd() || is_imx8mmdl())
1434 disable_cpu_nodes(blob, 2);
1435 else if (is_imx8mms() || is_imx8mmsl())
1436 disable_cpu_nodes(blob, 3);
1437
1438#elif defined(CONFIG_IMX8MN)
1439 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1440 disable_gpu_nodes(blob);
Ye Liee337ce2021-03-19 15:57:09 +08001441#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1442 else {
1443 int ldm_gpu = low_drive_gpu_freq(blob);
1444
1445 if (ldm_gpu < 0)
1446 printf("Update GPU node assigned-clock-rates failed\n");
1447 else
1448 printf("Update GPU node assigned-clock-rates ok\n");
1449 }
1450#endif
Peng Fan435dc122020-07-09 14:06:49 +08001451
Ye Li715180e2021-03-19 15:57:11 +08001452 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan435dc122020-07-09 14:06:49 +08001453 disable_cpu_nodes(blob, 2);
Ye Li715180e2021-03-19 15:57:11 +08001454 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan435dc122020-07-09 14:06:49 +08001455 disable_cpu_nodes(blob, 3);
1456
1457#elif defined(CONFIG_IMX8MP)
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001458 if (is_imx8mpul()) {
1459 /* Disable GPU */
1460 disable_gpu_nodes(blob);
1461
1462 /* Disable DSI */
1463 disable_dsi_lcdif_nodes(blob);
1464
1465 /* Disable LVDS */
1466 disable_lvds_lcdif_nodes(blob);
1467 }
1468
1469 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001470 disable_vpu_nodes(blob);
1471
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001472 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001473 disable_npu_nodes(blob);
1474
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001475 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001476 disable_isp_nodes(blob);
1477
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001478 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001479 disable_dsp_nodes(blob);
1480
1481 if (is_imx8mpd())
1482 disable_cpu_nodes(blob, 2);
1483#endif
1484
Peng Fan1585b202022-04-07 15:55:55 +08001485 cleanup_nodes_for_efi(blob);
Andrejs Cainikovs2f3491c2022-05-27 15:20:42 +02001486
1487 if (fixup_thermal_trips(blob, "cpu-thermal"))
1488 printf("Failed to update cpu-thermal trip(s)");
1489 if (IS_ENABLED(CONFIG_IMX8MP) &&
1490 fixup_thermal_trips(blob, "soc-thermal"))
1491 printf("Failed to update soc-thermal trip(s)");
1492
Tim Harvey709ace82023-08-24 12:05:17 -07001493 return ft_add_optee_node(blob, bd);
Peng Faneae4de22018-01-10 13:20:37 +08001494}
1495#endif
1496
Marek Vasut64dc4de2020-04-29 15:04:21 +02001497#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler6f14d5f2020-12-15 16:47:52 +01001498void reset_cpu(void)
Peng Faneae4de22018-01-10 13:20:37 +08001499{
Claudius Heinee73f3942020-04-29 15:04:23 +02001500 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Faneae4de22018-01-10 13:20:37 +08001501
Ye Li54a915a2019-12-09 00:47:18 -08001502 /* Clear WDA to trigger WDOG_B immediately */
1503 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fan24290d92019-08-27 06:25:41 +00001504
Ye Li54a915a2019-12-09 00:47:18 -08001505 while (1) {
1506 /*
Harald Seilerec0c4472020-04-29 15:04:22 +02001507 * spin for .5 seconds before reset
Ye Li54a915a2019-12-09 00:47:18 -08001508 */
1509 }
Peng Faneae4de22018-01-10 13:20:37 +08001510}
Peng Fan24290d92019-08-27 06:25:41 +00001511#endif
Peng Fan5760d8d2020-04-22 10:51:13 +08001512
1513#if defined(CONFIG_ARCH_MISC_INIT)
Peng Fan5760d8d2020-04-22 10:51:13 +08001514int arch_misc_init(void)
1515{
Gaurav Jain81113a02022-03-24 11:50:27 +05301516 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1517 struct udevice *dev;
1518 int ret;
1519
1520 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1521 if (ret)
Ye Liec346892022-05-11 13:56:20 +05301522 printf("Failed to initialize caam_jr: %d\n", ret);
Gaurav Jain81113a02022-03-24 11:50:27 +05301523 }
Peng Fan5760d8d2020-04-22 10:51:13 +08001524
1525 return 0;
1526}
1527#endif
Ye Li325cd012020-05-03 22:19:52 +08001528
Peng Fana35215d2020-07-09 13:39:26 +08001529#if defined(CONFIG_SPL_BUILD)
1530#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1531bool serror_need_skip = true;
1532
Sean Anderson2d755492022-03-22 17:17:35 -04001533void do_error(struct pt_regs *pt_regs)
Peng Fana35215d2020-07-09 13:39:26 +08001534{
1535 /*
1536 * If stack is still in ROM reserved OCRAM not switch to SPL,
1537 * it is the ROM SError
1538 */
1539 ulong sp;
1540
1541 asm volatile("mov %0, sp" : "=r"(sp) : );
1542
1543 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1544 /* Check for ERR050342, imx8mq HDCP enabled parts */
1545 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1546 serror_need_skip = false;
1547 return; /* Do nothing skip the SError in ROM */
1548 }
1549
1550 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1551 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1552 serror_need_skip = false;
1553 return; /* Do nothing skip the SError in ROM */
1554 }
1555 }
1556
1557 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -04001558 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fana35215d2020-07-09 13:39:26 +08001559 show_regs(pt_regs);
1560 panic("Resetting CPU ...\n");
1561}
1562#endif
1563#endif
Ye Li0513f362019-07-15 01:16:46 -07001564
1565#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
Marek Vasut765b5802022-04-06 02:21:34 +02001566enum env_location arch_env_get_location(enum env_operation op, int prio)
Ye Li0513f362019-07-15 01:16:46 -07001567{
1568 enum boot_device dev = get_boot_device();
Ye Li0513f362019-07-15 01:16:46 -07001569
1570 if (prio)
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001571 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001572
1573 switch (dev) {
Fabio Estevam9be6daf2022-04-21 15:05:23 -03001574 case USB_BOOT:
1575 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1576 return ENVL_SPI_FLASH;
1577 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1578 return ENVL_NAND;
1579 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1580 return ENVL_MMC;
1581 if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
1582 return ENVL_NOWHERE;
1583 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001584 case QSPI_BOOT:
Marek Vasut31b3bc42022-03-25 18:59:28 +01001585 case SPI_NOR_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001586 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1587 return ENVL_SPI_FLASH;
1588 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001589 case NAND_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001590 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1591 return ENVL_NAND;
1592 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001593 case SD1_BOOT:
1594 case SD2_BOOT:
1595 case SD3_BOOT:
1596 case MMC1_BOOT:
1597 case MMC2_BOOT:
1598 case MMC3_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001599 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1600 return ENVL_MMC;
1601 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1602 return ENVL_EXT4;
1603 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1604 return ENVL_FAT;
1605 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001606 default:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001607 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001608 }
Ye Li0513f362019-07-15 01:16:46 -07001609}
1610
Ye Li0513f362019-07-15 01:16:46 -07001611#endif
Peng Fanf19e0e52022-04-29 16:03:14 +08001612
1613#ifdef CONFIG_IMX_BOOTAUX
1614const struct rproc_att hostmap[] = {
1615 /* aux core , host core, size */
1616 { 0x00000000, 0x007e0000, 0x00020000 },
1617 /* OCRAM_S */
1618 { 0x00180000, 0x00180000, 0x00008000 },
1619 /* OCRAM */
1620 { 0x00900000, 0x00900000, 0x00020000 },
1621 /* OCRAM */
1622 { 0x00920000, 0x00920000, 0x00020000 },
1623 /* QSPI Code - alias */
1624 { 0x08000000, 0x08000000, 0x08000000 },
1625 /* DDR (Code) - alias */
1626 { 0x10000000, 0x80000000, 0x0FFE0000 },
1627 /* TCML */
1628 { 0x1FFE0000, 0x007E0000, 0x00040000 },
1629 /* OCRAM_S */
1630 { 0x20180000, 0x00180000, 0x00008000 },
1631 /* OCRAM */
1632 { 0x20200000, 0x00900000, 0x00040000 },
1633 /* DDR (Data) */
1634 { 0x40000000, 0x40000000, 0x80000000 },
1635 { /* sentinel */ }
1636};
Marek Vasutddc59352022-12-13 05:46:07 +01001637
1638const struct rproc_att *imx_bootaux_get_hostmap(void)
1639{
1640 return hostmap;
1641}
Peng Fanf19e0e52022-04-29 16:03:14 +08001642#endif