blob: b0ab00fbd9824e1104c54a71cd34bb63a15c1432 [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
Tom Rinidec7ea02024-05-20 13:35:03 -06008#include <config.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>
Fedor Rossed2f94a2023-10-16 18:16:14 +020031#include <fuse.h>
Peng Faneae4de22018-01-10 13:20:37 +080032#include <imx_sip.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060033#include <linux/bitops.h>
Fedor Rossed2f94a2023-10-16 18:16:14 +020034#include <linux/bitfield.h>
Marek Vasut9ce353d2024-09-05 17:35:00 +020035#include <linux/sizes.h>
Peng Faneae4de22018-01-10 13:20:37 +080036
37DECLARE_GLOBAL_DATA_PTR;
38
Stefano Babicf8b509b2019-09-20 08:47:53 +020039#if defined(CONFIG_IMX_HAB)
Peng Faneae4de22018-01-10 13:20:37 +080040struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
41 .bank = 1,
42 .word = 3,
43};
44#endif
45
46int timer_init(void)
47{
Simon Glass85ed77d2024-09-29 19:49:46 -060048#ifdef CONFIG_XPL_BUILD
Peng Faneae4de22018-01-10 13:20:37 +080049 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
50 unsigned long freq = readl(&sctr->cntfid0);
51
52 /* Update with accurate clock frequency */
53 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
54
55 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
56 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
57#endif
58
59 gd->arch.tbl = 0;
60 gd->arch.tbu = 0;
61
62 return 0;
63}
64
65void enable_tzc380(void)
66{
67 struct iomuxc_gpr_base_regs *gpr =
68 (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
69
70 /* Enable TZASC and lock setting */
71 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN);
72 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010073
74 /*
75 * According to TRM, TZASC_ID_SWAP_BYPASS should be set in
76 * order to avoid AXI Bus errors when GPU is in use
77 */
Peng Fanda7a16c2022-04-29 16:18:49 +080078 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010079
80 /*
81 * imx8mn and imx8mp implements the lock bit for
82 * TZASC_ID_SWAP_BYPASS, enable it to lock settings
83 */
Peng Fanda7a16c2022-04-29 16:18:49 +080084 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS_LOCK);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010085
Ye Li4c97c462019-08-27 06:25:34 +000086 /*
87 * set Region 0 attribute to allow secure and non-secure
88 * read/write permission. Found some masters like usb dwc3
89 * controllers can't work with secure memory.
90 */
91 writel(0xf0000000, TZASC_BASE_ADDR + 0x108);
Peng Faneae4de22018-01-10 13:20:37 +080092}
93
94void set_wdog_reset(struct wdog_regs *wdog)
95{
96 /*
97 * Output WDOG_B signal to reset external pmic or POR_B decided by
98 * the board design. Without external reset, the peripherals/DDR/
99 * PMIC are not reset, that may cause system working abnormal.
100 * WDZST bit is write-once only bit. Align this bit in kernel,
101 * otherwise kernel code will have no chance to set this bit.
102 */
103 setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK);
104}
105
Marek Vasut003969b2022-12-22 01:46:40 +0100106#ifdef CONFIG_ARMV8_PSCI
107#define PTE_MAP_NS PTE_BLOCK_NS
108#else
109#define PTE_MAP_NS 0
110#endif
111
Peng Faneae4de22018-01-10 13:20:37 +0800112static struct mm_region imx8m_mem_map[] = {
113 {
114 /* ROM */
115 .virt = 0x0UL,
116 .phys = 0x0UL,
117 .size = 0x100000UL,
118 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
119 PTE_BLOCK_OUTER_SHARE
120 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100121 /* CAAM */
122 .virt = 0x100000UL,
123 .phys = 0x100000UL,
124 .size = 0x8000UL,
125 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
126 PTE_BLOCK_NON_SHARE |
127 PTE_BLOCK_PXN | PTE_BLOCK_UXN
128 }, {
Marek Vasutb1738e02021-02-25 21:52:26 +0100129 /* OCRAM_S */
130 .virt = 0x180000UL,
131 .phys = 0x180000UL,
132 .size = 0x8000UL,
133 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100134 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Marek Vasutb1738e02021-02-25 21:52:26 +0100135 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100136 /* TCM */
137 .virt = 0x7C0000UL,
138 .phys = 0x7C0000UL,
139 .size = 0x80000UL,
140 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
141 PTE_BLOCK_NON_SHARE |
Marek Vasut003969b2022-12-22 01:46:40 +0100142 PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_MAP_NS
Gary Bisson5c72a452018-11-14 17:55:28 +0100143 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800144 /* OCRAM */
145 .virt = 0x900000UL,
146 .phys = 0x900000UL,
147 .size = 0x200000UL,
148 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100149 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Faneae4de22018-01-10 13:20:37 +0800150 }, {
151 /* AIPS */
152 .virt = 0xB00000UL,
153 .phys = 0xB00000UL,
154 .size = 0x3f500000UL,
155 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
156 PTE_BLOCK_NON_SHARE |
157 PTE_BLOCK_PXN | PTE_BLOCK_UXN
158 }, {
159 /* DRAM1 */
160 .virt = 0x40000000UL,
161 .phys = 0x40000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000162 .size = PHYS_SDRAM_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800163 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100164 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fanb749b5e2019-08-27 06:25:27 +0000165#ifdef PHYS_SDRAM_2_SIZE
Peng Faneae4de22018-01-10 13:20:37 +0800166 }, {
167 /* DRAM2 */
168 .virt = 0x100000000UL,
169 .phys = 0x100000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000170 .size = PHYS_SDRAM_2_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800171 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100172 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fanb749b5e2019-08-27 06:25:27 +0000173#endif
Peng Faneae4de22018-01-10 13:20:37 +0800174 }, {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800175 /* empty entrie to split table entry 5 if needed when TEEs are used */
176 0,
177 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800178 /* List terminator */
179 0,
180 }
181};
182
183struct mm_region *mem_map = imx8m_mem_map;
184
Marek Vasute48aac02021-02-27 14:59:00 +0100185static unsigned int imx8m_find_dram_entry_in_mem_map(void)
186{
187 int i;
188
189 for (i = 0; i < ARRAY_SIZE(imx8m_mem_map); i++)
Tom Rinibb4dd962022-11-16 13:10:37 -0500190 if (imx8m_mem_map[i].phys == CFG_SYS_SDRAM_BASE)
Marek Vasute48aac02021-02-27 14:59:00 +0100191 return i;
192
193 hang(); /* Entry not found, this must never happen. */
194}
195
Peng Fanb749b5e2019-08-27 06:25:27 +0000196void enable_caches(void)
197{
Ye Li453bfcb2022-04-07 15:55:56 +0800198 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
199 * If OPTEE does not run, still update the MMU table according to dram banks structure
200 * to set correct dram size from board_phys_sdram_size
201 */
202 int i = 0;
203 /*
204 * please make sure that entry initial value matches
205 * imx8m_mem_map for DRAM1
206 */
207 int entry = imx8m_find_dram_entry_in_mem_map();
208 u64 attrs = imx8m_mem_map[entry].attrs;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800209
Marek Vasut9ce353d2024-09-05 17:35:00 +0200210 /* Deactivate the data cache, possibly enabled in arch_cpu_init() */
211 dcache_disable();
212 /*
213 * Force the call of setup_all_pgtables() in mmu_setup() by clearing tlb_fillptr
214 * to update the TLB location udpated in board_f.c::reserve_mmu
215 */
216 gd->arch.tlb_fillptr = 0;
217
Ye Li453bfcb2022-04-07 15:55:56 +0800218 while (i < CONFIG_NR_DRAM_BANKS &&
219 entry < ARRAY_SIZE(imx8m_mem_map)) {
220 if (gd->bd->bi_dram[i].start == 0)
221 break;
222 imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start;
223 imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start;
224 imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size;
225 imx8m_mem_map[entry].attrs = attrs;
226 debug("Added memory mapping (%d): %llx %llx\n", entry,
227 imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size);
228 i++; entry++;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800229 }
Peng Fanb749b5e2019-08-27 06:25:27 +0000230
231 icache_enable();
232 dcache_enable();
233}
234
Peng Fanfa35c3d2020-07-09 15:26:06 +0800235__weak int board_phys_sdram_size(phys_size_t *size)
236{
237 if (!size)
238 return -EINVAL;
239
240 *size = PHYS_SDRAM_SIZE;
Ye Li453bfcb2022-04-07 15:55:56 +0800241
242#ifdef PHYS_SDRAM_2_SIZE
243 *size += PHYS_SDRAM_2_SIZE;
244#endif
Peng Fanfa35c3d2020-07-09 15:26:06 +0800245 return 0;
246}
247
248int dram_init(void)
249{
250 phys_size_t sdram_size;
251 int ret;
252
253 ret = board_phys_sdram_size(&sdram_size);
254 if (ret)
255 return ret;
256
257 /* rom_pointer[1] contains the size of TEE occupies */
Simon Glass85ed77d2024-09-29 19:49:46 -0600258 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_XPL_BUILD) && rom_pointer[1])
Peng Fanfa35c3d2020-07-09 15:26:06 +0800259 gd->ram_size = sdram_size - rom_pointer[1];
260 else
261 gd->ram_size = sdram_size;
262
Peng Fanfa35c3d2020-07-09 15:26:06 +0800263 return 0;
264}
265
266int dram_init_banksize(void)
267{
268 int bank = 0;
269 int ret;
270 phys_size_t sdram_size;
Ye Li453bfcb2022-04-07 15:55:56 +0800271 phys_size_t sdram_b1_size, sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800272
273 ret = board_phys_sdram_size(&sdram_size);
274 if (ret)
275 return ret;
276
Ye Li453bfcb2022-04-07 15:55:56 +0800277 /* Bank 1 can't cross over 4GB space */
278 if (sdram_size > 0xc0000000) {
279 sdram_b1_size = 0xc0000000;
280 sdram_b2_size = sdram_size - 0xc0000000;
281 } else {
282 sdram_b1_size = sdram_size;
283 sdram_b2_size = 0;
284 }
285
Peng Fanfa35c3d2020-07-09 15:26:06 +0800286 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
Simon Glass85ed77d2024-09-29 19:49:46 -0600287 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_XPL_BUILD) && rom_pointer[1]) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800288 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
289 phys_size_t optee_size = (size_t)rom_pointer[1];
290
291 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
Ye Li453bfcb2022-04-07 15:55:56 +0800292 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800293 if (++bank >= CONFIG_NR_DRAM_BANKS) {
294 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
295 return -1;
296 }
297
298 gd->bd->bi_dram[bank].start = optee_start + optee_size;
299 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
Ye Li453bfcb2022-04-07 15:55:56 +0800300 sdram_b1_size - gd->bd->bi_dram[bank].start;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800301 }
302 } else {
Ye Li453bfcb2022-04-07 15:55:56 +0800303 gd->bd->bi_dram[bank].size = sdram_b1_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800304 }
305
Ye Li453bfcb2022-04-07 15:55:56 +0800306 if (sdram_b2_size) {
307 if (++bank >= CONFIG_NR_DRAM_BANKS) {
308 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
309 return -1;
310 }
311 gd->bd->bi_dram[bank].start = 0x100000000UL;
312 gd->bd->bi_dram[bank].size = sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800313 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800314
315 return 0;
316}
317
318phys_size_t get_effective_memsize(void)
319{
Ye Li453bfcb2022-04-07 15:55:56 +0800320 int ret;
321 phys_size_t sdram_size;
322 phys_size_t sdram_b1_size;
323 ret = board_phys_sdram_size(&sdram_size);
324 if (!ret) {
325 /* Bank 1 can't cross over 4GB space */
326 if (sdram_size > 0xc0000000) {
327 sdram_b1_size = 0xc0000000;
328 } else {
329 sdram_b1_size = sdram_size;
330 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800331
Simon Glass85ed77d2024-09-29 19:49:46 -0600332 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_XPL_BUILD) &&
Elena Popa65c9edb2023-08-08 14:58:26 +0300333 rom_pointer[1]) {
Ye Li453bfcb2022-04-07 15:55:56 +0800334 /* We will relocate u-boot to Top of dram1. Tee position has two cases:
335 * 1. At the top of dram1, Then return the size removed optee size.
336 * 2. In the middle of dram1, return the size of dram1.
337 */
338 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
339 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
340 }
341
342 return sdram_b1_size;
343 } else {
344 return PHYS_SDRAM_SIZE;
345 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800346}
347
Heinrich Schuchardt51a9aac2023-08-12 20:16:58 +0200348phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Frieder Schrempf159879e2021-06-07 14:36:44 +0200349{
Marek Vasutdcbbf782022-04-14 15:51:46 +0200350 ulong top_addr;
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800351
Frieder Schrempf159879e2021-06-07 14:36:44 +0200352 /*
353 * Some IPs have their accessible address space restricted by
354 * the interconnect. Let's make sure U-Boot only ever uses the
355 * space below the 4G address boundary (which is 3GiB big),
356 * even when the effective available memory is bigger.
357 */
Marek Vasutdcbbf782022-04-14 15:51:46 +0200358 top_addr = clamp_val((u64)PHYS_SDRAM + gd->ram_size, 0, 0xffffffff);
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800359
360 /*
361 * rom_pointer[0] stores the TEE memory start address.
362 * rom_pointer[1] stores the size TEE uses.
363 * We need to reserve the memory region for TEE.
364 */
Marek Vasut9ca966e2022-12-22 01:46:38 +0100365 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && rom_pointer[0] &&
366 rom_pointer[1] && top_addr > rom_pointer[0])
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800367 top_addr = rom_pointer[0];
Frieder Schrempf159879e2021-06-07 14:36:44 +0200368
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800369 return top_addr;
Frieder Schrempf159879e2021-06-07 14:36:44 +0200370}
371
Peng Fan1caffdf2019-08-27 06:25:17 +0000372static u32 get_cpu_variant_type(u32 type)
373{
374 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
375 struct fuse_bank *bank = &ocotp->bank[1];
376 struct fuse_bank1_regs *fuse =
377 (struct fuse_bank1_regs *)bank->fuse_regs;
378
379 u32 value = readl(&fuse->tester4);
380
Peng Fan67815082020-02-05 17:34:54 +0800381 if (type == MXC_CPU_IMX8MQ) {
382 if ((value & 0x3) == 0x2)
383 return MXC_CPU_IMX8MD;
384 else if (value & 0x200000)
385 return MXC_CPU_IMX8MQL;
386
387 } else if (type == MXC_CPU_IMX8MM) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000388 switch (value & 0x3) {
389 case 2:
390 if (value & 0x1c0000)
391 return MXC_CPU_IMX8MMDL;
392 else
393 return MXC_CPU_IMX8MMD;
394 case 3:
395 if (value & 0x1c0000)
396 return MXC_CPU_IMX8MMSL;
397 else
398 return MXC_CPU_IMX8MMS;
399 default:
400 if (value & 0x1c0000)
401 return MXC_CPU_IMX8MML;
402 break;
403 }
Peng Fan1a07d912020-02-05 17:39:27 +0800404 } else if (type == MXC_CPU_IMX8MN) {
405 switch (value & 0x3) {
406 case 2:
Ye Li715180e2021-03-19 15:57:11 +0800407 if (value & 0x1000000) {
408 if (value & 0x10000000) /* MIPI DSI */
409 return MXC_CPU_IMX8MNUD;
410 else
411 return MXC_CPU_IMX8MNDL;
412 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800413 return MXC_CPU_IMX8MND;
Ye Li715180e2021-03-19 15:57:11 +0800414 }
Peng Fan1a07d912020-02-05 17:39:27 +0800415 case 3:
Ye Li715180e2021-03-19 15:57:11 +0800416 if (value & 0x1000000) {
417 if (value & 0x10000000) /* MIPI DSI */
418 return MXC_CPU_IMX8MNUS;
419 else
420 return MXC_CPU_IMX8MNSL;
421 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800422 return MXC_CPU_IMX8MNS;
Ye Li715180e2021-03-19 15:57:11 +0800423 }
Peng Fan1a07d912020-02-05 17:39:27 +0800424 default:
Ye Li715180e2021-03-19 15:57:11 +0800425 if (value & 0x1000000) {
426 if (value & 0x10000000) /* MIPI DSI */
427 return MXC_CPU_IMX8MNUQ;
428 else
429 return MXC_CPU_IMX8MNL;
430 }
Peng Fan1a07d912020-02-05 17:39:27 +0800431 break;
432 }
Ye Lid2d754f2020-04-20 20:12:54 -0700433 } else if (type == MXC_CPU_IMX8MP) {
434 u32 value0 = readl(&fuse->tester3);
435 u32 flag = 0;
436
437 if ((value0 & 0xc0000) == 0x80000)
438 return MXC_CPU_IMX8MPD;
439
440 /* vpu disabled */
441 if ((value0 & 0x43000000) == 0x43000000)
442 flag = 1;
443
444 /* npu disabled*/
445 if ((value & 0x8) == 0x8)
Peng Fan0386e7f2022-04-07 15:55:52 +0800446 flag |= BIT(1);
Ye Lid2d754f2020-04-20 20:12:54 -0700447
448 /* isp disabled */
449 if ((value & 0x3) == 0x3)
Peng Fan0386e7f2022-04-07 15:55:52 +0800450 flag |= BIT(2);
451
452 /* gpu disabled */
453 if ((value & 0xc0) == 0xc0)
454 flag |= BIT(3);
455
456 /* lvds disabled */
457 if ((value & 0x180000) == 0x180000)
458 flag |= BIT(4);
459
460 /* mipi dsi disabled */
461 if ((value & 0x60000) == 0x60000)
462 flag |= BIT(5);
Ye Lid2d754f2020-04-20 20:12:54 -0700463
464 switch (flag) {
Peng Fan0386e7f2022-04-07 15:55:52 +0800465 case 0x3f:
466 return MXC_CPU_IMX8MPUL;
Ye Lid2d754f2020-04-20 20:12:54 -0700467 case 7:
468 return MXC_CPU_IMX8MPL;
Ye Lid2d754f2020-04-20 20:12:54 -0700469 case 2:
470 return MXC_CPU_IMX8MP6;
Ye Lid2d754f2020-04-20 20:12:54 -0700471 default:
472 break;
473 }
474
Peng Fan1caffdf2019-08-27 06:25:17 +0000475 }
476
477 return type;
478}
479
Peng Faneae4de22018-01-10 13:20:37 +0800480u32 get_cpu_rev(void)
481{
482 struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
483 u32 reg = readl(&ana_pll->digprog);
484 u32 type = (reg >> 16) & 0xff;
Peng Fan1caffdf2019-08-27 06:25:17 +0000485 u32 major_low = (reg >> 8) & 0xff;
Peng Faneae4de22018-01-10 13:20:37 +0800486 u32 rom_version;
487
488 reg &= 0xff;
489
Peng Fan69cec072019-12-27 10:14:02 +0800490 /* iMX8MP */
491 if (major_low == 0x43) {
Ye Lid2d754f2020-04-20 20:12:54 -0700492 type = get_cpu_variant_type(MXC_CPU_IMX8MP);
Peng Fan69cec072019-12-27 10:14:02 +0800493 } else if (major_low == 0x42) {
494 /* iMX8MN */
Peng Fan1a07d912020-02-05 17:39:27 +0800495 type = get_cpu_variant_type(MXC_CPU_IMX8MN);
Peng Fan5d2f2062019-06-27 17:23:49 +0800496 } else if (major_low == 0x41) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000497 type = get_cpu_variant_type(MXC_CPU_IMX8MM);
498 } else {
499 if (reg == CHIP_REV_1_0) {
500 /*
Peng Fanc23fbdd2019-10-16 10:24:17 +0000501 * For B0 chip, the DIGPROG is not updated,
502 * it is still TO1.0. we have to check ROM
503 * version or OCOTP_READ_FUSE_DATA.
504 * 0xff0055aa is magic number for B1.
Peng Fan1caffdf2019-08-27 06:25:17 +0000505 */
Peng Fanc23fbdd2019-10-16 10:24:17 +0000506 if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
Ye Lic963ed12021-03-19 15:57:16 +0800507 /*
508 * B2 uses same DIGPROG and OCOTP_READ_FUSE_DATA value with B1,
509 * so have to check ROM to distinguish them
510 */
511 rom_version = readl((void __iomem *)ROM_VERSION_B0);
512 rom_version &= 0xff;
513 if (rom_version == CHIP_REV_2_2)
514 reg = CHIP_REV_2_2;
515 else
516 reg = CHIP_REV_2_1;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000517 } else {
518 rom_version =
519 readl((void __iomem *)ROM_VERSION_A0);
520 if (rom_version != CHIP_REV_1_0) {
521 rom_version = readl((void __iomem *)ROM_VERSION_B0);
Patrick Wildtd4a78b92019-11-19 09:42:06 +0100522 rom_version &= 0xff;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000523 if (rom_version == CHIP_REV_2_0)
524 reg = CHIP_REV_2_0;
525 }
Peng Fan1caffdf2019-08-27 06:25:17 +0000526 }
Peng Faneae4de22018-01-10 13:20:37 +0800527 }
Peng Fan67815082020-02-05 17:34:54 +0800528
529 type = get_cpu_variant_type(type);
Peng Faneae4de22018-01-10 13:20:37 +0800530 }
531
532 return (type << 12) | reg;
533}
534
535static void imx_set_wdog_powerdown(bool enable)
536{
537 struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
538 struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
539 struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
540
541 /* Write to the PDE (Power Down Enable) bit */
542 writew(enable, &wdog1->wmcr);
543 writew(enable, &wdog2->wmcr);
544 writew(enable, &wdog3->wmcr);
545}
546
Simon Glassb8357c12023-08-21 21:16:56 -0600547static int imx8m_check_clock(void)
Peng Fanc98e0322019-08-27 06:25:58 +0000548{
549 struct udevice *dev;
550 int ret;
551
Peng Fan3c073342019-10-16 03:01:51 +0000552 if (CONFIG_IS_ENABLED(CLK)) {
553 ret = uclass_get_device_by_name(UCLASS_CLK,
554 "clock-controller@30380000",
555 &dev);
556 if (ret < 0) {
557 printf("Failed to find clock node. Check device tree\n");
558 return ret;
559 }
Peng Fanc98e0322019-08-27 06:25:58 +0000560 }
561
562 return 0;
563}
Simon Glassb8357c12023-08-21 21:16:56 -0600564EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, imx8m_check_clock);
Peng Fanc98e0322019-08-27 06:25:58 +0000565
Marek Vasutf7b184e2022-09-19 21:37:07 +0200566static void imx8m_setup_snvs(void)
567{
568 /* Enable SNVS clock */
569 clock_enable(CCGR_SNVS, 1);
570 /* Initialize glitch detect */
571 writel(SNVS_LPPGDR_INIT, SNVS_BASE_ADDR + SNVS_LPLVDR);
572 /* Clear interrupt status */
573 writel(0xffffffff, SNVS_BASE_ADDR + SNVS_LPSR);
574}
575
Marek Vasut829858a2022-12-22 01:46:42 +0100576static void imx8m_setup_csu_tzasc(void)
577{
578 const uintptr_t tzasc_base[4] = {
579 0x301f0000, 0x301f0000, 0x301f0000, 0x301f0000
580 };
581 int i, j;
582
583 if (!IS_ENABLED(CONFIG_ARMV8_PSCI))
584 return;
585
586 /* CSU */
587 for (i = 0; i < 64; i++)
588 writel(0x00ff00ff, (void *)CSU_BASE_ADDR + (4 * i));
589
590 /* TZASC */
591 for (j = 0; j < 4; j++) {
592 writel(0x77777777, (void *)(tzasc_base[j]));
593 writel(0x77777777, (void *)(tzasc_base[j]) + 0x4);
594 for (i = 0; i <= 0x10; i += 4)
595 writel(0, (void *)(tzasc_base[j]) + 0x40 + i);
596 }
597}
598
Marek Vasut9ce353d2024-09-05 17:35:00 +0200599/*
600 * Place early TLB into the .data section so that it will not
601 * get cleared, use 16 kiB alignment.
602 */
603#define EARLY_TLB_SIZE SZ_64K
604u8 early_tlb[EARLY_TLB_SIZE] __section(".data") __aligned(0x4000);
605
606/*
607 * Initialize the MMU and activate cache in U-Boot pre-reloc stage
608 * MMU/TLB is updated in enable_caches() for U-Boot after relocation
609 */
610static void early_enable_caches(void)
611{
612 phys_size_t sdram_size;
613 int entry, ret;
614
Simon Glass85ed77d2024-09-29 19:49:46 -0600615 if (IS_ENABLED(CONFIG_XPL_BUILD))
Marek Vasut9ce353d2024-09-05 17:35:00 +0200616 return;
617
618 if (CONFIG_IS_ENABLED(SYS_ICACHE_OFF) || CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
619 return;
620
621 /* Use maximum available DRAM size in first bank. */
622 ret = board_phys_sdram_size(&sdram_size);
623 if (ret)
624 return;
625
626 entry = imx8m_find_dram_entry_in_mem_map();
627 imx8m_mem_map[entry].size = max(sdram_size, (phys_size_t)0xc0000000);
628
629 gd->arch.tlb_size = EARLY_TLB_SIZE;
630 gd->arch.tlb_addr = (unsigned long)&early_tlb;
631
632 /* Enable MMU (default configuration) */
633 dcache_enable();
634}
635
Peng Faneae4de22018-01-10 13:20:37 +0800636int arch_cpu_init(void)
637{
Peng Fanc0b30d72019-04-17 09:41:16 +0000638 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
Marek Vasut3ea500a2022-04-13 00:41:52 +0200639
640#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
641 icache_enable();
Marek Vasut9ce353d2024-09-05 17:35:00 +0200642 early_enable_caches();
Marek Vasut3ea500a2022-04-13 00:41:52 +0200643#endif
644
Peng Faneae4de22018-01-10 13:20:37 +0800645 /*
Peng Fand0ca2892019-08-27 06:25:37 +0000646 * ROM might disable clock for SCTR,
647 * enable the clock before timer_init.
648 */
Simon Glass85ed77d2024-09-29 19:49:46 -0600649 if (IS_ENABLED(CONFIG_XPL_BUILD))
Peng Fand0ca2892019-08-27 06:25:37 +0000650 clock_enable(CCGR_SCTR, 1);
651 /*
Peng Faneae4de22018-01-10 13:20:37 +0800652 * Init timer at very early state, because sscg pll setting
653 * will use it
654 */
655 timer_init();
656
Simon Glass85ed77d2024-09-29 19:49:46 -0600657 if (IS_ENABLED(CONFIG_XPL_BUILD)) {
Peng Faneae4de22018-01-10 13:20:37 +0800658 clock_init();
659 imx_set_wdog_powerdown(false);
Peng Fan9cf2aa32020-07-09 13:52:41 +0800660
661 if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
662 is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
Ye Li715180e2021-03-19 15:57:11 +0800663 is_imx8mnsl() || is_imx8mpd() || is_imx8mnud() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800664 /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
665 struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
666 struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
667 struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0);
668 struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR;
669
670 writel(0x1, &pgc_core2->pgcr);
671 writel(0x1, &pgc_core3->pgcr);
Ye Li715180e2021-03-19 15:57:11 +0800672 if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800673 writel(0x1, &pgc_core1->pgcr);
674 writel(0xE, &gpc->cpu_pgc_dn_trg);
675 } else {
676 writel(0xC, &gpc->cpu_pgc_dn_trg);
677 }
678 }
Peng Faneae4de22018-01-10 13:20:37 +0800679 }
680
Peng Fanc0b30d72019-04-17 09:41:16 +0000681 if (is_imx8mq()) {
682 clock_enable(CCGR_OCOTP, 1);
683 if (readl(&ocotp->ctrl) & 0x200)
684 writel(0x200, &ocotp->ctrl_clr);
685 }
686
Marek Vasutf7b184e2022-09-19 21:37:07 +0200687 imx8m_setup_snvs();
688
Marek Vasut829858a2022-12-22 01:46:42 +0100689 imx8m_setup_csu_tzasc();
690
Peng Faneae4de22018-01-10 13:20:37 +0800691 return 0;
692}
693
Peng Fanc9823b02019-09-16 03:09:36 +0000694#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
695struct rom_api *g_rom_api = (struct rom_api *)0x980;
Peng Fanc9823b02019-09-16 03:09:36 +0000696#endif
697
Marek Vasut520ded02021-07-03 04:55:33 +0200698#if defined(CONFIG_IMX8M)
699#include <spl.h>
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200700int imx8m_detect_secondary_image_boot(void)
Marek Vasut520ded02021-07-03 04:55:33 +0200701{
702 u32 *rom_log_addr = (u32 *)0x9e0;
703 u32 *rom_log;
704 u8 event_id;
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200705 int i, boot_secondary = 0;
Marek Vasut520ded02021-07-03 04:55:33 +0200706
707 /* If the ROM event log pointer is not valid. */
708 if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 ||
709 *rom_log_addr & 0x3)
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200710 return -EINVAL;
Marek Vasut520ded02021-07-03 04:55:33 +0200711
712 /* Parse the ROM event ID version 2 log */
713 rom_log = (u32 *)(uintptr_t)(*rom_log_addr);
714 for (i = 0; i < 128; i++) {
715 event_id = rom_log[i] >> 24;
716 switch (event_id) {
717 case 0x00: /* End of list */
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200718 return boot_secondary;
Marek Vasut520ded02021-07-03 04:55:33 +0200719 /* Log entries with 1 parameter, skip 1 */
720 case 0x80: /* Start to perform the device initialization */
721 case 0x81: /* The boot device initialization completes */
Fedor Ross7e02ff62022-04-14 18:36:23 +0200722 case 0x82: /* Starts to execute boot device driver pre-config */
Marek Vasut520ded02021-07-03 04:55:33 +0200723 case 0x8f: /* The boot device initialization fails */
724 case 0x90: /* Start to read data from boot device */
725 case 0x91: /* Reading data from boot device completes */
726 case 0x9f: /* Reading data from boot device fails */
727 i += 1;
728 continue;
729 /* Log entries with 2 parameters, skip 2 */
730 case 0xa0: /* Image authentication result */
731 case 0xc0: /* Jump to the boot image soon */
732 i += 2;
733 continue;
734 /* Boot from the secondary boot image */
735 case 0x51:
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200736 boot_secondary = 1;
Marek Vasut520ded02021-07-03 04:55:33 +0200737 continue;
738 default:
739 continue;
740 }
741 }
742
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200743 return boot_secondary;
744}
745
746int spl_mmc_emmc_boot_partition(struct mmc *mmc)
747{
748 int part, ret;
749
750 part = default_spl_mmc_emmc_boot_partition(mmc);
751 if (part == 0)
752 return part;
753
754 ret = imx8m_detect_secondary_image_boot();
755 if (ret < 0) {
756 printf("Could not get boot partition! Using %d\n", part);
757 return part;
758 }
759
760 if (ret == 1) {
761 /*
762 * Swap the eMMC boot partitions in case there was a
763 * fallback event (i.e. primary image was corrupted
764 * and that corruption was recognized by the BootROM),
765 * so the SPL loads the rest of the U-Boot from the
766 * correct eMMC boot partition, since the BootROM
767 * leaves the boot partition set to the corrupted one.
768 */
769 if (part == 1)
770 part = 2;
771 else if (part == 2)
772 part = 1;
773 }
774
Marek Vasut520ded02021-07-03 04:55:33 +0200775 return part;
776}
Fedor Rossc0b94842023-10-16 18:16:15 +0200777
778int boot_mode_getprisec(void)
779{
780 return !!imx8m_detect_secondary_image_boot();
781}
Marek Vasut520ded02021-07-03 04:55:33 +0200782#endif
783
Fedor Rossed2f94a2023-10-16 18:16:14 +0200784#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
Simon Glass18422832024-08-22 07:55:00 -0600785#ifdef SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
Fedor Rossed2f94a2023-10-16 18:16:14 +0200786#define IMG_CNTN_SET1_OFFSET GENMASK(22, 19)
787unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
788 unsigned long raw_sect)
789{
790 u32 val, offset;
791
792 if (fuse_read(2, 1, &val)) {
793 debug("Error reading fuse!\n");
794 return raw_sect;
795 }
796
797 val = FIELD_GET(IMG_CNTN_SET1_OFFSET, val);
798 if (val > 10) {
799 debug("Secondary image boot disabled!\n");
800 return raw_sect;
801 }
802
803 if (val == 0)
804 offset = SZ_4M;
805 else if (val == 1)
806 offset = SZ_2M;
807 else if (val == 2)
808 offset = SZ_1M;
809 else /* flash.bin offset = 1 MiB * 2^n */
810 offset = SZ_1M << val;
811
812 offset /= 512;
813 offset -= CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET;
814
815 if (imx8m_detect_secondary_image_boot())
816 raw_sect += offset;
817
818 return raw_sect;
819}
Simon Glass18422832024-08-22 07:55:00 -0600820#endif /* SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION */
Fedor Rossed2f94a2023-10-16 18:16:14 +0200821#endif
822
Peng Faneae4de22018-01-10 13:20:37 +0800823bool is_usb_boot(void)
824{
825 return get_boot_device() == USB_BOOT;
826}
827
828#ifdef CONFIG_OF_SYSTEM_SETUP
Peng Fan435dc122020-07-09 14:06:49 +0800829bool check_fdt_new_path(void *blob)
830{
831 const char *soc_path = "/soc@0";
832 int nodeoff;
833
834 nodeoff = fdt_path_offset(blob, soc_path);
835 if (nodeoff < 0)
836 return false;
837
838 return true;
839}
840
841static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
842{
843 int i = 0;
844 int rc;
845 int nodeoff;
846 const char *status = "disabled";
847
848 for (i = 0; i < size_array; i++) {
849 nodeoff = fdt_path_offset(blob, nodes_path[i]);
850 if (nodeoff < 0)
851 continue; /* Not found, skip it */
852
Rasmus Villemoes8ab149a2023-05-22 11:27:28 +0200853 debug("Found %s node\n", nodes_path[i]);
Peng Fan435dc122020-07-09 14:06:49 +0800854
855add_status:
856 rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
857 if (rc) {
858 if (rc == -FDT_ERR_NOSPACE) {
859 rc = fdt_increase_size(blob, 512);
860 if (!rc)
861 goto add_status;
862 }
863 printf("Unable to update property %s:%s, err=%s\n",
864 nodes_path[i], "status", fdt_strerror(rc));
865 } else {
866 printf("Modify %s:%s disabled\n",
867 nodes_path[i], "status");
868 }
869 }
870
871 return 0;
872}
873
874#ifdef CONFIG_IMX8MQ
875bool check_dcss_fused(void)
876{
877 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
878 struct fuse_bank *bank = &ocotp->bank[1];
879 struct fuse_bank1_regs *fuse =
880 (struct fuse_bank1_regs *)bank->fuse_regs;
881 u32 value = readl(&fuse->tester4);
882
883 if (value & 0x4000000)
884 return true;
885
886 return false;
887}
888
889static int disable_mipi_dsi_nodes(void *blob)
890{
891 static const char * const nodes_path[] = {
892 "/mipi_dsi@30A00000",
893 "/mipi_dsi_bridge@30A00000",
894 "/dsi_phy@30A00300",
895 "/soc@0/bus@30800000/mipi_dsi@30a00000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800896 "/soc@0/bus@30800000/dphy@30a00300",
897 "/soc@0/bus@30800000/mipi-dsi@30a00000",
Peng Fan435dc122020-07-09 14:06:49 +0800898 };
899
900 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
901}
902
903static int disable_dcss_nodes(void *blob)
904{
905 static const char * const nodes_path[] = {
906 "/dcss@0x32e00000",
907 "/dcss@32e00000",
908 "/hdmi@32c00000",
909 "/hdmi_cec@32c33800",
910 "/hdmi_drm@32c00000",
911 "/display-subsystem",
912 "/sound-hdmi",
913 "/sound-hdmi-arc",
914 "/soc@0/bus@32c00000/display-controller@32e00000",
915 "/soc@0/bus@32c00000/hdmi@32c00000",
916 };
917
918 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
919}
920
921static int check_mipi_dsi_nodes(void *blob)
922{
923 static const char * const lcdif_path[] = {
924 "/lcdif@30320000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800925 "/soc@0/bus@30000000/lcdif@30320000",
926 "/soc@0/bus@30000000/lcd-controller@30320000"
Peng Fan435dc122020-07-09 14:06:49 +0800927 };
928 static const char * const mipi_dsi_path[] = {
929 "/mipi_dsi@30A00000",
930 "/soc@0/bus@30800000/mipi_dsi@30a00000"
931 };
932 static const char * const lcdif_ep_path[] = {
933 "/lcdif@30320000/port@0/mipi-dsi-endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800934 "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
935 "/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
Peng Fan435dc122020-07-09 14:06:49 +0800936 };
937 static const char * const mipi_dsi_ep_path[] = {
938 "/mipi_dsi@30A00000/port@1/endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800939 "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
940 "/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
Peng Fan435dc122020-07-09 14:06:49 +0800941 };
942
943 int lookup_node;
944 int nodeoff;
945 bool new_path = check_fdt_new_path(blob);
946 int i = new_path ? 1 : 0;
947
948 nodeoff = fdt_path_offset(blob, lcdif_path[i]);
949 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
950 /*
951 * If can't find lcdif node or lcdif node is disabled,
952 * then disable all mipi dsi, since they only can input
953 * from DCSS
954 */
955 return disable_mipi_dsi_nodes(blob);
956 }
957
958 nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
959 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
960 return 0;
961
962 nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
963 if (nodeoff < 0) {
964 /*
965 * If can't find lcdif endpoint, then disable all mipi dsi,
966 * since they only can input from DCSS
967 */
968 return disable_mipi_dsi_nodes(blob);
969 }
970
971 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
972 nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
973
974 if (nodeoff > 0 && nodeoff == lookup_node)
975 return 0;
976
977 return disable_mipi_dsi_nodes(blob);
978}
979#endif
980
981int disable_vpu_nodes(void *blob)
982{
983 static const char * const nodes_path_8mq[] = {
984 "/vpu@38300000",
Vitor Soares6dd07732024-03-15 14:44:25 +0000985 "/soc@0/vpu@38300000",
986 "/soc@0/video-codec@38300000",
987 "/soc@0/video-codec@38310000",
988 "/soc@0/blk-ctrl@38320000",
Peng Fan435dc122020-07-09 14:06:49 +0800989 };
990
991 static const char * const nodes_path_8mm[] = {
992 "/vpu_g1@38300000",
993 "/vpu_g2@38310000",
Vitor Soares6dd07732024-03-15 14:44:25 +0000994 "/vpu_h1@38320000",
995 "/soc@0/video-codec@38300000",
996 "/soc@0/video-codec@38310000",
997 "/soc@0/blk-ctrl@38330000",
Peng Fan435dc122020-07-09 14:06:49 +0800998 };
999
1000 static const char * const nodes_path_8mp[] = {
1001 "/vpu_g1@38300000",
1002 "/vpu_g2@38310000",
Vitor Soares6dd07732024-03-15 14:44:25 +00001003 "/vpu_vc8000e@38320000",
1004 "/soc@0/video-codec@38300000",
1005 "/soc@0/video-codec@38310000",
1006 "/soc@0/blk-ctrl@38330000",
Peng Fan435dc122020-07-09 14:06:49 +08001007 };
1008
1009 if (is_imx8mq())
1010 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
1011 else if (is_imx8mm())
1012 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
1013 else if (is_imx8mp())
1014 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1015 else
1016 return -EPERM;
1017}
1018
Ye Liee337ce2021-03-19 15:57:09 +08001019#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1020static int low_drive_gpu_freq(void *blob)
1021{
1022 static const char *nodes_path_8mn[] = {
1023 "/gpu@38000000",
1024 "/soc@0/gpu@38000000"
1025 };
1026
1027 int nodeoff, cnt, i;
1028 u32 assignedclks[7];
1029
1030 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
1031 if (nodeoff < 0)
1032 return nodeoff;
1033
1034 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
1035 if (cnt < 0)
1036 return cnt;
1037
1038 if (cnt != 7)
1039 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
Heinrich Schuchardt72c891f2023-04-18 01:37:21 +02001040 if (cnt < 2)
1041 return -1;
Ye Liee337ce2021-03-19 15:57:09 +08001042
1043 assignedclks[cnt - 1] = 200000000;
1044 assignedclks[cnt - 2] = 200000000;
1045
1046 for (i = 0; i < cnt; i++) {
1047 debug("<%u>, ", assignedclks[i]);
1048 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
1049 }
1050 debug("\n");
1051
1052 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
1053}
1054#endif
1055
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001056static bool check_remote_endpoint(void *blob, const char *ep1, const char *ep2)
1057{
1058 int lookup_node;
1059 int nodeoff;
1060
1061 nodeoff = fdt_path_offset(blob, ep1);
1062 if (nodeoff) {
1063 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
1064 nodeoff = fdt_path_offset(blob, ep2);
1065
1066 if (nodeoff > 0 && nodeoff == lookup_node)
1067 return true;
1068 }
1069
1070 return false;
1071}
1072
1073int disable_dsi_lcdif_nodes(void *blob)
1074{
1075 int ret;
1076
1077 static const char * const dsi_path_8mp[] = {
1078 "/soc@0/bus@32c00000/mipi_dsi@32e60000"
1079 };
1080
1081 static const char * const lcdif_path_8mp[] = {
1082 "/soc@0/bus@32c00000/lcd-controller@32e80000"
1083 };
1084
1085 static const char * const lcdif_ep_path_8mp[] = {
1086 "/soc@0/bus@32c00000/lcd-controller@32e80000/port@0/endpoint"
1087 };
1088 static const char * const dsi_ep_path_8mp[] = {
1089 "/soc@0/bus@32c00000/mipi_dsi@32e60000/port@0/endpoint"
1090 };
1091
1092 ret = disable_fdt_nodes(blob, dsi_path_8mp, ARRAY_SIZE(dsi_path_8mp));
1093 if (ret)
1094 return ret;
1095
1096 if (check_remote_endpoint(blob, dsi_ep_path_8mp[0], lcdif_ep_path_8mp[0])) {
1097 /* Disable lcdif node */
1098 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1099 }
1100
1101 return 0;
1102}
1103
1104int disable_lvds_lcdif_nodes(void *blob)
1105{
1106 int ret, i;
1107
1108 static const char * const ldb_path_8mp[] = {
1109 "/soc@0/bus@32c00000/ldb@32ec005c",
1110 "/soc@0/bus@32c00000/phy@32ec0128"
1111 };
1112
1113 static const char * const lcdif_path_8mp[] = {
1114 "/soc@0/bus@32c00000/lcd-controller@32e90000"
1115 };
1116
1117 static const char * const lcdif_ep_path_8mp[] = {
1118 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@0",
1119 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@1"
1120 };
1121 static const char * const ldb_ep_path_8mp[] = {
1122 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@0/port@0/endpoint",
1123 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@1/port@0/endpoint"
1124 };
1125
1126 ret = disable_fdt_nodes(blob, ldb_path_8mp, ARRAY_SIZE(ldb_path_8mp));
1127 if (ret)
1128 return ret;
1129
1130 for (i = 0; i < ARRAY_SIZE(ldb_ep_path_8mp); i++) {
1131 if (check_remote_endpoint(blob, ldb_ep_path_8mp[i], lcdif_ep_path_8mp[i])) {
1132 /* Disable lcdif node */
1133 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1134 }
1135 }
1136
1137 return 0;
1138}
1139
Peng Fan435dc122020-07-09 14:06:49 +08001140int disable_gpu_nodes(void *blob)
1141{
1142 static const char * const nodes_path_8mn[] = {
Peng Fan7d4195c2021-03-19 15:57:13 +08001143 "/gpu@38000000",
1144 "/soc@/gpu@38000000"
Peng Fan435dc122020-07-09 14:06:49 +08001145 };
1146
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001147 static const char * const nodes_path_8mp[] = {
1148 "/gpu3d@38000000",
1149 "/gpu2d@38008000"
1150 };
1151
1152 if (is_imx8mp())
1153 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1154 else
1155 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
Peng Fan435dc122020-07-09 14:06:49 +08001156}
1157
1158int disable_npu_nodes(void *blob)
1159{
1160 static const char * const nodes_path_8mp[] = {
Vitor Soares6dd07732024-03-15 14:44:25 +00001161 "/vipsi@38500000",
1162 "/soc@0/npu@38500000",
Peng Fan435dc122020-07-09 14:06:49 +08001163 };
1164
1165 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1166}
1167
1168int disable_isp_nodes(void *blob)
1169{
1170 static const char * const nodes_path_8mp[] = {
1171 "/soc@0/bus@32c00000/camera/isp@32e10000",
1172 "/soc@0/bus@32c00000/camera/isp@32e20000"
1173 };
1174
1175 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1176}
1177
1178int disable_dsp_nodes(void *blob)
1179{
1180 static const char * const nodes_path_8mp[] = {
1181 "/dsp@3b6e8000"
1182 };
1183
1184 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1185}
1186
Peng Fana08bc872022-04-07 15:55:54 +08001187static int cleanup_nodes_for_efi(void *blob)
1188{
Peng Fan1585b202022-04-07 15:55:55 +08001189 static const char * const path[][2] = {
1190 { "/soc@0/bus@32c00000/usb@32e40000", "extcon" },
1191 { "/soc@0/bus@32c00000/usb@32e50000", "extcon" },
1192 { "/soc@0/bus@30800000/ethernet@30be0000", "phy-reset-gpios" },
1193 { "/soc@0/bus@30800000/ethernet@30bf0000", "phy-reset-gpios" }
1194 };
Peng Fana08bc872022-04-07 15:55:54 +08001195 int nodeoff, i, rc;
1196
Peng Fan1585b202022-04-07 15:55:55 +08001197 for (i = 0; i < ARRAY_SIZE(path); i++) {
1198 nodeoff = fdt_path_offset(blob, path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001199 if (nodeoff < 0)
1200 continue; /* Not found, skip it */
Peng Fan1585b202022-04-07 15:55:55 +08001201 debug("Found %s node\n", path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001202
Peng Fan1585b202022-04-07 15:55:55 +08001203 rc = fdt_delprop(blob, nodeoff, path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001204 if (rc == -FDT_ERR_NOTFOUND)
1205 continue;
1206 if (rc) {
1207 printf("Unable to update property %s:%s, err=%s\n",
Peng Fan1585b202022-04-07 15:55:55 +08001208 path[i][0], path[i][1], fdt_strerror(rc));
Peng Fana08bc872022-04-07 15:55:54 +08001209 return rc;
1210 }
1211
Peng Fan1585b202022-04-07 15:55:55 +08001212 printf("Remove %s:%s\n", path[i][0], path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001213 }
1214
1215 return 0;
1216}
Peng Fana08bc872022-04-07 15:55:54 +08001217
Tim Harvey709ace82023-08-24 12:05:17 -07001218#define OPTEE_SHM_SIZE 0x00400000
1219static int ft_add_optee_node(void *fdt, struct bd_info *bd)
1220{
1221 struct fdt_memory carveout;
1222 const char *path, *subpath;
1223 phys_addr_t optee_start;
1224 size_t optee_size;
1225 int offs;
1226 int ret;
1227
1228 /*
1229 * No TEE space allocated indicating no TEE running, so no
1230 * need to add optee node in dts
1231 */
1232 if (!rom_pointer[1])
1233 return 0;
1234
1235 optee_start = (phys_addr_t)rom_pointer[0];
1236 optee_size = rom_pointer[1] - OPTEE_SHM_SIZE;
1237
1238 offs = fdt_increase_size(fdt, 512);
1239 if (offs) {
1240 printf("No Space for dtb\n");
1241 return 1;
1242 }
1243
1244 path = "/firmware";
1245 offs = fdt_path_offset(fdt, path);
1246 if (offs < 0) {
1247 path = "/";
1248 offs = fdt_path_offset(fdt, path);
1249
1250 if (offs < 0) {
1251 printf("Could not find root node.\n");
1252 return offs;
1253 }
1254
1255 subpath = "firmware";
1256 offs = fdt_add_subnode(fdt, offs, subpath);
1257 if (offs < 0) {
1258 printf("Could not create %s node.\n", subpath);
1259 return offs;
1260 }
1261 }
1262
1263 subpath = "optee";
1264 offs = fdt_add_subnode(fdt, offs, subpath);
1265 if (offs < 0) {
1266 printf("Could not create %s node.\n", subpath);
1267 return offs;
1268 }
1269
1270 fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz");
1271 fdt_setprop_string(fdt, offs, "method", "smc");
1272
1273 carveout.start = optee_start,
1274 carveout.end = optee_start + optee_size - 1,
1275 ret = fdtdec_add_reserved_memory(fdt, "optee_core", &carveout, NULL, 0,
1276 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1277 if (ret < 0) {
1278 printf("Could not create optee_core node.\n");
1279 return ret;
1280 }
1281
1282 carveout.start = optee_start + optee_size;
1283 carveout.end = optee_start + optee_size + OPTEE_SHM_SIZE - 1;
1284 ret = fdtdec_add_reserved_memory(fdt, "optee_shm", &carveout, NULL, 0,
1285 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1286 if (ret < 0) {
1287 printf("Could not create optee_shm node.\n");
1288 return ret;
1289 }
1290
1291 return 0;
1292}
1293
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001294int ft_system_setup(void *blob, struct bd_info *bd)
Peng Faneae4de22018-01-10 13:20:37 +08001295{
Peng Fan35fdfcf2024-09-19 12:01:31 +08001296 static const char * const nodes_path[] = {
1297 "/cpus/cpu@0",
1298 "/cpus/cpu@1",
1299 "/cpus/cpu@2",
1300 "/cpus/cpu@3",
1301 };
1302
Peng Fan435dc122020-07-09 14:06:49 +08001303#ifdef CONFIG_IMX8MQ
Peng Faneae4de22018-01-10 13:20:37 +08001304 int i = 0;
1305 int rc;
1306 int nodeoff;
1307
Peng Fan435dc122020-07-09 14:06:49 +08001308 if (get_boot_device() == USB_BOOT) {
1309 disable_dcss_nodes(blob);
1310
1311 bool new_path = check_fdt_new_path(blob);
1312 int v = new_path ? 1 : 0;
1313 static const char * const usb_dwc3_path[] = {
1314 "/usb@38100000/dwc3",
1315 "/soc@0/usb@38100000"
1316 };
1317
1318 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1319 if (nodeoff >= 0) {
1320 const char *speed = "high-speed";
1321
Rasmus Villemoes8ab149a2023-05-22 11:27:28 +02001322 debug("Found %s node\n", usb_dwc3_path[v]);
Peng Fan435dc122020-07-09 14:06:49 +08001323
1324usb_modify_speed:
1325
1326 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1327 if (rc) {
1328 if (rc == -FDT_ERR_NOSPACE) {
1329 rc = fdt_increase_size(blob, 512);
1330 if (!rc)
1331 goto usb_modify_speed;
1332 }
1333 printf("Unable to set property %s:%s, err=%s\n",
1334 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1335 } else {
1336 printf("Modify %s:%s = %s\n",
1337 usb_dwc3_path[v], "maximum-speed", speed);
1338 }
1339 } else {
1340 printf("Can't found %s node\n", usb_dwc3_path[v]);
1341 }
1342 }
1343
Peng Faneae4de22018-01-10 13:20:37 +08001344 /* Disable the CPU idle for A0 chip since the HW does not support it */
1345 if (is_soc_rev(CHIP_REV_1_0)) {
Peng Faneae4de22018-01-10 13:20:37 +08001346 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1347 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1348 if (nodeoff < 0)
1349 continue; /* Not found, skip it */
1350
Marek Vasute2e7a772020-04-24 21:37:33 +02001351 debug("Found %s node\n", nodes_path[i]);
Peng Faneae4de22018-01-10 13:20:37 +08001352
1353 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasute2e7a772020-04-24 21:37:33 +02001354 if (rc == -FDT_ERR_NOTFOUND)
1355 continue;
Peng Faneae4de22018-01-10 13:20:37 +08001356 if (rc) {
1357 printf("Unable to update property %s:%s, err=%s\n",
1358 nodes_path[i], "status", fdt_strerror(rc));
1359 return rc;
1360 }
1361
Marek Vasute2e7a772020-04-24 21:37:33 +02001362 debug("Remove %s:%s\n", nodes_path[i],
Peng Faneae4de22018-01-10 13:20:37 +08001363 "cpu-idle-states");
1364 }
1365 }
1366
Peng Fan435dc122020-07-09 14:06:49 +08001367 if (is_imx8mql()) {
1368 disable_vpu_nodes(blob);
1369 if (check_dcss_fused()) {
1370 printf("DCSS is fused\n");
1371 disable_dcss_nodes(blob);
1372 check_mipi_dsi_nodes(blob);
1373 }
1374 }
1375
1376 if (is_imx8md())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001377 disable_cpu_nodes(blob, nodes_path, 2, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001378
1379#elif defined(CONFIG_IMX8MM)
1380 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1381 disable_vpu_nodes(blob);
1382
1383 if (is_imx8mmd() || is_imx8mmdl())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001384 disable_cpu_nodes(blob, nodes_path, 2, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001385 else if (is_imx8mms() || is_imx8mmsl())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001386 disable_cpu_nodes(blob, nodes_path, 3, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001387
1388#elif defined(CONFIG_IMX8MN)
1389 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1390 disable_gpu_nodes(blob);
Ye Liee337ce2021-03-19 15:57:09 +08001391#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1392 else {
1393 int ldm_gpu = low_drive_gpu_freq(blob);
1394
1395 if (ldm_gpu < 0)
1396 printf("Update GPU node assigned-clock-rates failed\n");
1397 else
1398 printf("Update GPU node assigned-clock-rates ok\n");
1399 }
1400#endif
Peng Fan435dc122020-07-09 14:06:49 +08001401
Ye Li715180e2021-03-19 15:57:11 +08001402 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001403 disable_cpu_nodes(blob, nodes_path, 2, 4);
Ye Li715180e2021-03-19 15:57:11 +08001404 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001405 disable_cpu_nodes(blob, nodes_path, 3, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001406
1407#elif defined(CONFIG_IMX8MP)
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001408 if (is_imx8mpul()) {
1409 /* Disable GPU */
1410 disable_gpu_nodes(blob);
1411
1412 /* Disable DSI */
1413 disable_dsi_lcdif_nodes(blob);
1414
1415 /* Disable LVDS */
1416 disable_lvds_lcdif_nodes(blob);
1417 }
1418
1419 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001420 disable_vpu_nodes(blob);
1421
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001422 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001423 disable_npu_nodes(blob);
1424
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001425 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001426 disable_isp_nodes(blob);
1427
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001428 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001429 disable_dsp_nodes(blob);
1430
1431 if (is_imx8mpd())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001432 disable_cpu_nodes(blob, nodes_path, 2, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001433#endif
1434
Peng Fan1585b202022-04-07 15:55:55 +08001435 cleanup_nodes_for_efi(blob);
Andrejs Cainikovs2f3491c2022-05-27 15:20:42 +02001436
1437 if (fixup_thermal_trips(blob, "cpu-thermal"))
1438 printf("Failed to update cpu-thermal trip(s)");
1439 if (IS_ENABLED(CONFIG_IMX8MP) &&
1440 fixup_thermal_trips(blob, "soc-thermal"))
1441 printf("Failed to update soc-thermal trip(s)");
1442
Tim Harvey709ace82023-08-24 12:05:17 -07001443 return ft_add_optee_node(blob, bd);
Peng Faneae4de22018-01-10 13:20:37 +08001444}
1445#endif
1446
Marek Vasut64dc4de2020-04-29 15:04:21 +02001447#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler6f14d5f2020-12-15 16:47:52 +01001448void reset_cpu(void)
Peng Faneae4de22018-01-10 13:20:37 +08001449{
Claudius Heinee73f3942020-04-29 15:04:23 +02001450 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Faneae4de22018-01-10 13:20:37 +08001451
Ye Li54a915a2019-12-09 00:47:18 -08001452 /* Clear WDA to trigger WDOG_B immediately */
1453 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fan24290d92019-08-27 06:25:41 +00001454
Ye Li54a915a2019-12-09 00:47:18 -08001455 while (1) {
1456 /*
Harald Seilerec0c4472020-04-29 15:04:22 +02001457 * spin for .5 seconds before reset
Ye Li54a915a2019-12-09 00:47:18 -08001458 */
1459 }
Peng Faneae4de22018-01-10 13:20:37 +08001460}
Peng Fan24290d92019-08-27 06:25:41 +00001461#endif
Peng Fan5760d8d2020-04-22 10:51:13 +08001462
1463#if defined(CONFIG_ARCH_MISC_INIT)
Peng Fan5760d8d2020-04-22 10:51:13 +08001464int arch_misc_init(void)
1465{
Gaurav Jain81113a02022-03-24 11:50:27 +05301466 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1467 struct udevice *dev;
1468 int ret;
1469
1470 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1471 if (ret)
Ye Liec346892022-05-11 13:56:20 +05301472 printf("Failed to initialize caam_jr: %d\n", ret);
Gaurav Jain81113a02022-03-24 11:50:27 +05301473 }
Peng Fan5760d8d2020-04-22 10:51:13 +08001474
1475 return 0;
1476}
1477#endif
Ye Li325cd012020-05-03 22:19:52 +08001478
Simon Glass85ed77d2024-09-29 19:49:46 -06001479#if defined(CONFIG_XPL_BUILD)
Peng Fana35215d2020-07-09 13:39:26 +08001480#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1481bool serror_need_skip = true;
1482
Sean Anderson2d755492022-03-22 17:17:35 -04001483void do_error(struct pt_regs *pt_regs)
Peng Fana35215d2020-07-09 13:39:26 +08001484{
1485 /*
1486 * If stack is still in ROM reserved OCRAM not switch to SPL,
1487 * it is the ROM SError
1488 */
1489 ulong sp;
1490
1491 asm volatile("mov %0, sp" : "=r"(sp) : );
1492
1493 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1494 /* Check for ERR050342, imx8mq HDCP enabled parts */
1495 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1496 serror_need_skip = false;
1497 return; /* Do nothing skip the SError in ROM */
1498 }
1499
1500 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1501 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1502 serror_need_skip = false;
1503 return; /* Do nothing skip the SError in ROM */
1504 }
1505 }
1506
1507 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -04001508 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fana35215d2020-07-09 13:39:26 +08001509 show_regs(pt_regs);
1510 panic("Resetting CPU ...\n");
1511}
1512#endif
1513#endif
Ye Li0513f362019-07-15 01:16:46 -07001514
1515#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
Marek Vasut765b5802022-04-06 02:21:34 +02001516enum env_location arch_env_get_location(enum env_operation op, int prio)
Ye Li0513f362019-07-15 01:16:46 -07001517{
1518 enum boot_device dev = get_boot_device();
Ye Li0513f362019-07-15 01:16:46 -07001519
1520 if (prio)
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001521 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001522
1523 switch (dev) {
Fabio Estevam9be6daf2022-04-21 15:05:23 -03001524 case USB_BOOT:
1525 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1526 return ENVL_SPI_FLASH;
1527 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1528 return ENVL_NAND;
1529 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1530 return ENVL_MMC;
1531 if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
1532 return ENVL_NOWHERE;
1533 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001534 case QSPI_BOOT:
Marek Vasut31b3bc42022-03-25 18:59:28 +01001535 case SPI_NOR_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001536 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1537 return ENVL_SPI_FLASH;
1538 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001539 case NAND_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001540 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1541 return ENVL_NAND;
1542 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001543 case SD1_BOOT:
1544 case SD2_BOOT:
1545 case SD3_BOOT:
1546 case MMC1_BOOT:
1547 case MMC2_BOOT:
1548 case MMC3_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001549 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1550 return ENVL_MMC;
1551 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1552 return ENVL_EXT4;
1553 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1554 return ENVL_FAT;
1555 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001556 default:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001557 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001558 }
Ye Li0513f362019-07-15 01:16:46 -07001559}
1560
Ye Li0513f362019-07-15 01:16:46 -07001561#endif
Peng Fanf19e0e52022-04-29 16:03:14 +08001562
1563#ifdef CONFIG_IMX_BOOTAUX
1564const struct rproc_att hostmap[] = {
1565 /* aux core , host core, size */
1566 { 0x00000000, 0x007e0000, 0x00020000 },
1567 /* OCRAM_S */
1568 { 0x00180000, 0x00180000, 0x00008000 },
1569 /* OCRAM */
1570 { 0x00900000, 0x00900000, 0x00020000 },
1571 /* OCRAM */
1572 { 0x00920000, 0x00920000, 0x00020000 },
1573 /* QSPI Code - alias */
1574 { 0x08000000, 0x08000000, 0x08000000 },
1575 /* DDR (Code) - alias */
1576 { 0x10000000, 0x80000000, 0x0FFE0000 },
1577 /* TCML */
1578 { 0x1FFE0000, 0x007E0000, 0x00040000 },
1579 /* OCRAM_S */
1580 { 0x20180000, 0x00180000, 0x00008000 },
1581 /* OCRAM */
1582 { 0x20200000, 0x00900000, 0x00040000 },
1583 /* DDR (Data) */
1584 { 0x40000000, 0x40000000, 0x80000000 },
1585 { /* sentinel */ }
1586};
Marek Vasutddc59352022-12-13 05:46:07 +01001587
1588const struct rproc_att *imx_bootaux_get_hostmap(void)
1589{
1590 return hostmap;
1591}
Peng Fanf19e0e52022-04-29 16:03:14 +08001592#endif