blob: 5293cb85e56628f1f17f2894d4ebae640579de2a [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{
48#ifdef CONFIG_SPL_BUILD
49 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 */
Elena Popa65c9edb2023-08-08 14:58:26 +0300258 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_SPL_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;
Elena Popa65c9edb2023-08-08 14:58:26 +0300287 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_SPL_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
Elena Popa65c9edb2023-08-08 14:58:26 +0300332 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_SPL_BUILD) &&
333 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
615 if (IS_ENABLED(CONFIG_SPL_BUILD))
616 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 */
649 if (IS_ENABLED(CONFIG_SPL_BUILD))
650 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
657 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
658 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",
Vitor Soares003810a2024-10-01 17:01:52 +01001007 "/soc@0/blk-ctl@38330000",
Peng Fan435dc122020-07-09 14:06:49 +08001008 };
1009
1010 if (is_imx8mq())
1011 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
1012 else if (is_imx8mm())
1013 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
1014 else if (is_imx8mp())
1015 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1016 else
1017 return -EPERM;
1018}
1019
Ye Liee337ce2021-03-19 15:57:09 +08001020#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1021static int low_drive_gpu_freq(void *blob)
1022{
1023 static const char *nodes_path_8mn[] = {
1024 "/gpu@38000000",
1025 "/soc@0/gpu@38000000"
1026 };
1027
1028 int nodeoff, cnt, i;
1029 u32 assignedclks[7];
1030
1031 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
1032 if (nodeoff < 0)
1033 return nodeoff;
1034
1035 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
1036 if (cnt < 0)
1037 return cnt;
1038
1039 if (cnt != 7)
1040 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
Heinrich Schuchardt72c891f2023-04-18 01:37:21 +02001041 if (cnt < 2)
1042 return -1;
Ye Liee337ce2021-03-19 15:57:09 +08001043
1044 assignedclks[cnt - 1] = 200000000;
1045 assignedclks[cnt - 2] = 200000000;
1046
1047 for (i = 0; i < cnt; i++) {
1048 debug("<%u>, ", assignedclks[i]);
1049 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
1050 }
1051 debug("\n");
1052
1053 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
1054}
1055#endif
1056
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001057static bool check_remote_endpoint(void *blob, const char *ep1, const char *ep2)
1058{
1059 int lookup_node;
1060 int nodeoff;
1061
1062 nodeoff = fdt_path_offset(blob, ep1);
1063 if (nodeoff) {
1064 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
1065 nodeoff = fdt_path_offset(blob, ep2);
1066
1067 if (nodeoff > 0 && nodeoff == lookup_node)
1068 return true;
1069 }
1070
1071 return false;
1072}
1073
1074int disable_dsi_lcdif_nodes(void *blob)
1075{
1076 int ret;
1077
1078 static const char * const dsi_path_8mp[] = {
1079 "/soc@0/bus@32c00000/mipi_dsi@32e60000"
1080 };
1081
1082 static const char * const lcdif_path_8mp[] = {
1083 "/soc@0/bus@32c00000/lcd-controller@32e80000"
1084 };
1085
1086 static const char * const lcdif_ep_path_8mp[] = {
1087 "/soc@0/bus@32c00000/lcd-controller@32e80000/port@0/endpoint"
1088 };
1089 static const char * const dsi_ep_path_8mp[] = {
1090 "/soc@0/bus@32c00000/mipi_dsi@32e60000/port@0/endpoint"
1091 };
1092
1093 ret = disable_fdt_nodes(blob, dsi_path_8mp, ARRAY_SIZE(dsi_path_8mp));
1094 if (ret)
1095 return ret;
1096
1097 if (check_remote_endpoint(blob, dsi_ep_path_8mp[0], lcdif_ep_path_8mp[0])) {
1098 /* Disable lcdif node */
1099 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1100 }
1101
1102 return 0;
1103}
1104
1105int disable_lvds_lcdif_nodes(void *blob)
1106{
1107 int ret, i;
1108
1109 static const char * const ldb_path_8mp[] = {
1110 "/soc@0/bus@32c00000/ldb@32ec005c",
1111 "/soc@0/bus@32c00000/phy@32ec0128"
1112 };
1113
1114 static const char * const lcdif_path_8mp[] = {
1115 "/soc@0/bus@32c00000/lcd-controller@32e90000"
1116 };
1117
1118 static const char * const lcdif_ep_path_8mp[] = {
1119 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@0",
1120 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@1"
1121 };
1122 static const char * const ldb_ep_path_8mp[] = {
1123 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@0/port@0/endpoint",
1124 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@1/port@0/endpoint"
1125 };
1126
1127 ret = disable_fdt_nodes(blob, ldb_path_8mp, ARRAY_SIZE(ldb_path_8mp));
1128 if (ret)
1129 return ret;
1130
1131 for (i = 0; i < ARRAY_SIZE(ldb_ep_path_8mp); i++) {
1132 if (check_remote_endpoint(blob, ldb_ep_path_8mp[i], lcdif_ep_path_8mp[i])) {
1133 /* Disable lcdif node */
1134 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1135 }
1136 }
1137
1138 return 0;
1139}
1140
Peng Fan435dc122020-07-09 14:06:49 +08001141int disable_gpu_nodes(void *blob)
1142{
1143 static const char * const nodes_path_8mn[] = {
Peng Fan7d4195c2021-03-19 15:57:13 +08001144 "/gpu@38000000",
1145 "/soc@/gpu@38000000"
Peng Fan435dc122020-07-09 14:06:49 +08001146 };
1147
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001148 static const char * const nodes_path_8mp[] = {
1149 "/gpu3d@38000000",
1150 "/gpu2d@38008000"
1151 };
1152
1153 if (is_imx8mp())
1154 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1155 else
1156 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
Peng Fan435dc122020-07-09 14:06:49 +08001157}
1158
1159int disable_npu_nodes(void *blob)
1160{
1161 static const char * const nodes_path_8mp[] = {
Vitor Soares6dd07732024-03-15 14:44:25 +00001162 "/vipsi@38500000",
1163 "/soc@0/npu@38500000",
Peng Fan435dc122020-07-09 14:06:49 +08001164 };
1165
1166 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1167}
1168
1169int disable_isp_nodes(void *blob)
1170{
1171 static const char * const nodes_path_8mp[] = {
1172 "/soc@0/bus@32c00000/camera/isp@32e10000",
1173 "/soc@0/bus@32c00000/camera/isp@32e20000"
1174 };
1175
1176 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1177}
1178
1179int disable_dsp_nodes(void *blob)
1180{
1181 static const char * const nodes_path_8mp[] = {
1182 "/dsp@3b6e8000"
1183 };
1184
1185 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1186}
1187
Peng Fana08bc872022-04-07 15:55:54 +08001188static int cleanup_nodes_for_efi(void *blob)
1189{
Peng Fan1585b202022-04-07 15:55:55 +08001190 static const char * const path[][2] = {
1191 { "/soc@0/bus@32c00000/usb@32e40000", "extcon" },
1192 { "/soc@0/bus@32c00000/usb@32e50000", "extcon" },
1193 { "/soc@0/bus@30800000/ethernet@30be0000", "phy-reset-gpios" },
1194 { "/soc@0/bus@30800000/ethernet@30bf0000", "phy-reset-gpios" }
1195 };
Peng Fana08bc872022-04-07 15:55:54 +08001196 int nodeoff, i, rc;
1197
Peng Fan1585b202022-04-07 15:55:55 +08001198 for (i = 0; i < ARRAY_SIZE(path); i++) {
1199 nodeoff = fdt_path_offset(blob, path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001200 if (nodeoff < 0)
1201 continue; /* Not found, skip it */
Peng Fan1585b202022-04-07 15:55:55 +08001202 debug("Found %s node\n", path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001203
Peng Fan1585b202022-04-07 15:55:55 +08001204 rc = fdt_delprop(blob, nodeoff, path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001205 if (rc == -FDT_ERR_NOTFOUND)
1206 continue;
1207 if (rc) {
1208 printf("Unable to update property %s:%s, err=%s\n",
Peng Fan1585b202022-04-07 15:55:55 +08001209 path[i][0], path[i][1], fdt_strerror(rc));
Peng Fana08bc872022-04-07 15:55:54 +08001210 return rc;
1211 }
1212
Peng Fan1585b202022-04-07 15:55:55 +08001213 printf("Remove %s:%s\n", path[i][0], path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001214 }
1215
1216 return 0;
1217}
Peng Fana08bc872022-04-07 15:55:54 +08001218
Tim Harvey709ace82023-08-24 12:05:17 -07001219#define OPTEE_SHM_SIZE 0x00400000
1220static int ft_add_optee_node(void *fdt, struct bd_info *bd)
1221{
1222 struct fdt_memory carveout;
1223 const char *path, *subpath;
1224 phys_addr_t optee_start;
1225 size_t optee_size;
1226 int offs;
1227 int ret;
1228
1229 /*
1230 * No TEE space allocated indicating no TEE running, so no
1231 * need to add optee node in dts
1232 */
1233 if (!rom_pointer[1])
1234 return 0;
1235
1236 optee_start = (phys_addr_t)rom_pointer[0];
1237 optee_size = rom_pointer[1] - OPTEE_SHM_SIZE;
1238
1239 offs = fdt_increase_size(fdt, 512);
1240 if (offs) {
1241 printf("No Space for dtb\n");
1242 return 1;
1243 }
1244
1245 path = "/firmware";
1246 offs = fdt_path_offset(fdt, path);
1247 if (offs < 0) {
1248 path = "/";
1249 offs = fdt_path_offset(fdt, path);
1250
1251 if (offs < 0) {
1252 printf("Could not find root node.\n");
1253 return offs;
1254 }
1255
1256 subpath = "firmware";
1257 offs = fdt_add_subnode(fdt, offs, subpath);
1258 if (offs < 0) {
1259 printf("Could not create %s node.\n", subpath);
1260 return offs;
1261 }
1262 }
1263
1264 subpath = "optee";
1265 offs = fdt_add_subnode(fdt, offs, subpath);
1266 if (offs < 0) {
1267 printf("Could not create %s node.\n", subpath);
1268 return offs;
1269 }
1270
1271 fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz");
1272 fdt_setprop_string(fdt, offs, "method", "smc");
1273
1274 carveout.start = optee_start,
1275 carveout.end = optee_start + optee_size - 1,
1276 ret = fdtdec_add_reserved_memory(fdt, "optee_core", &carveout, NULL, 0,
1277 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1278 if (ret < 0) {
1279 printf("Could not create optee_core node.\n");
1280 return ret;
1281 }
1282
1283 carveout.start = optee_start + optee_size;
1284 carveout.end = optee_start + optee_size + OPTEE_SHM_SIZE - 1;
1285 ret = fdtdec_add_reserved_memory(fdt, "optee_shm", &carveout, NULL, 0,
1286 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1287 if (ret < 0) {
1288 printf("Could not create optee_shm node.\n");
1289 return ret;
1290 }
1291
1292 return 0;
1293}
1294
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001295int ft_system_setup(void *blob, struct bd_info *bd)
Peng Faneae4de22018-01-10 13:20:37 +08001296{
Peng Fan35fdfcf2024-09-19 12:01:31 +08001297 static const char * const nodes_path[] = {
1298 "/cpus/cpu@0",
1299 "/cpus/cpu@1",
1300 "/cpus/cpu@2",
1301 "/cpus/cpu@3",
1302 };
1303
Peng Fan435dc122020-07-09 14:06:49 +08001304#ifdef CONFIG_IMX8MQ
Peng Faneae4de22018-01-10 13:20:37 +08001305 int i = 0;
1306 int rc;
1307 int nodeoff;
1308
Peng Fan435dc122020-07-09 14:06:49 +08001309 if (get_boot_device() == USB_BOOT) {
1310 disable_dcss_nodes(blob);
1311
1312 bool new_path = check_fdt_new_path(blob);
1313 int v = new_path ? 1 : 0;
1314 static const char * const usb_dwc3_path[] = {
1315 "/usb@38100000/dwc3",
1316 "/soc@0/usb@38100000"
1317 };
1318
1319 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1320 if (nodeoff >= 0) {
1321 const char *speed = "high-speed";
1322
Rasmus Villemoes8ab149a2023-05-22 11:27:28 +02001323 debug("Found %s node\n", usb_dwc3_path[v]);
Peng Fan435dc122020-07-09 14:06:49 +08001324
1325usb_modify_speed:
1326
1327 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1328 if (rc) {
1329 if (rc == -FDT_ERR_NOSPACE) {
1330 rc = fdt_increase_size(blob, 512);
1331 if (!rc)
1332 goto usb_modify_speed;
1333 }
1334 printf("Unable to set property %s:%s, err=%s\n",
1335 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1336 } else {
1337 printf("Modify %s:%s = %s\n",
1338 usb_dwc3_path[v], "maximum-speed", speed);
1339 }
1340 } else {
1341 printf("Can't found %s node\n", usb_dwc3_path[v]);
1342 }
1343 }
1344
Peng Faneae4de22018-01-10 13:20:37 +08001345 /* Disable the CPU idle for A0 chip since the HW does not support it */
1346 if (is_soc_rev(CHIP_REV_1_0)) {
Peng Faneae4de22018-01-10 13:20:37 +08001347 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1348 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1349 if (nodeoff < 0)
1350 continue; /* Not found, skip it */
1351
Marek Vasute2e7a772020-04-24 21:37:33 +02001352 debug("Found %s node\n", nodes_path[i]);
Peng Faneae4de22018-01-10 13:20:37 +08001353
1354 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasute2e7a772020-04-24 21:37:33 +02001355 if (rc == -FDT_ERR_NOTFOUND)
1356 continue;
Peng Faneae4de22018-01-10 13:20:37 +08001357 if (rc) {
1358 printf("Unable to update property %s:%s, err=%s\n",
1359 nodes_path[i], "status", fdt_strerror(rc));
1360 return rc;
1361 }
1362
Marek Vasute2e7a772020-04-24 21:37:33 +02001363 debug("Remove %s:%s\n", nodes_path[i],
Peng Faneae4de22018-01-10 13:20:37 +08001364 "cpu-idle-states");
1365 }
1366 }
1367
Peng Fan435dc122020-07-09 14:06:49 +08001368 if (is_imx8mql()) {
1369 disable_vpu_nodes(blob);
1370 if (check_dcss_fused()) {
1371 printf("DCSS is fused\n");
1372 disable_dcss_nodes(blob);
1373 check_mipi_dsi_nodes(blob);
1374 }
1375 }
1376
1377 if (is_imx8md())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001378 disable_cpu_nodes(blob, nodes_path, 2, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001379
1380#elif defined(CONFIG_IMX8MM)
1381 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1382 disable_vpu_nodes(blob);
1383
1384 if (is_imx8mmd() || is_imx8mmdl())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001385 disable_cpu_nodes(blob, nodes_path, 2, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001386 else if (is_imx8mms() || is_imx8mmsl())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001387 disable_cpu_nodes(blob, nodes_path, 3, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001388
1389#elif defined(CONFIG_IMX8MN)
1390 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1391 disable_gpu_nodes(blob);
Ye Liee337ce2021-03-19 15:57:09 +08001392#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1393 else {
1394 int ldm_gpu = low_drive_gpu_freq(blob);
1395
1396 if (ldm_gpu < 0)
1397 printf("Update GPU node assigned-clock-rates failed\n");
1398 else
1399 printf("Update GPU node assigned-clock-rates ok\n");
1400 }
1401#endif
Peng Fan435dc122020-07-09 14:06:49 +08001402
Ye Li715180e2021-03-19 15:57:11 +08001403 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001404 disable_cpu_nodes(blob, nodes_path, 2, 4);
Ye Li715180e2021-03-19 15:57:11 +08001405 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001406 disable_cpu_nodes(blob, nodes_path, 3, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001407
1408#elif defined(CONFIG_IMX8MP)
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001409 if (is_imx8mpul()) {
1410 /* Disable GPU */
1411 disable_gpu_nodes(blob);
1412
1413 /* Disable DSI */
1414 disable_dsi_lcdif_nodes(blob);
1415
1416 /* Disable LVDS */
1417 disable_lvds_lcdif_nodes(blob);
1418 }
1419
1420 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001421 disable_vpu_nodes(blob);
1422
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001423 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001424 disable_npu_nodes(blob);
1425
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001426 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001427 disable_isp_nodes(blob);
1428
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001429 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001430 disable_dsp_nodes(blob);
1431
1432 if (is_imx8mpd())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001433 disable_cpu_nodes(blob, nodes_path, 2, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001434#endif
1435
Peng Fan1585b202022-04-07 15:55:55 +08001436 cleanup_nodes_for_efi(blob);
Andrejs Cainikovs2f3491c2022-05-27 15:20:42 +02001437
1438 if (fixup_thermal_trips(blob, "cpu-thermal"))
1439 printf("Failed to update cpu-thermal trip(s)");
1440 if (IS_ENABLED(CONFIG_IMX8MP) &&
1441 fixup_thermal_trips(blob, "soc-thermal"))
1442 printf("Failed to update soc-thermal trip(s)");
1443
Tim Harvey709ace82023-08-24 12:05:17 -07001444 return ft_add_optee_node(blob, bd);
Peng Faneae4de22018-01-10 13:20:37 +08001445}
1446#endif
1447
Marek Vasut64dc4de2020-04-29 15:04:21 +02001448#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler6f14d5f2020-12-15 16:47:52 +01001449void reset_cpu(void)
Peng Faneae4de22018-01-10 13:20:37 +08001450{
Claudius Heinee73f3942020-04-29 15:04:23 +02001451 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Faneae4de22018-01-10 13:20:37 +08001452
Ye Li54a915a2019-12-09 00:47:18 -08001453 /* Clear WDA to trigger WDOG_B immediately */
1454 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fan24290d92019-08-27 06:25:41 +00001455
Ye Li54a915a2019-12-09 00:47:18 -08001456 while (1) {
1457 /*
Harald Seilerec0c4472020-04-29 15:04:22 +02001458 * spin for .5 seconds before reset
Ye Li54a915a2019-12-09 00:47:18 -08001459 */
1460 }
Peng Faneae4de22018-01-10 13:20:37 +08001461}
Peng Fan24290d92019-08-27 06:25:41 +00001462#endif
Peng Fan5760d8d2020-04-22 10:51:13 +08001463
1464#if defined(CONFIG_ARCH_MISC_INIT)
Peng Fan5760d8d2020-04-22 10:51:13 +08001465int arch_misc_init(void)
1466{
Gaurav Jain81113a02022-03-24 11:50:27 +05301467 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1468 struct udevice *dev;
1469 int ret;
1470
1471 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1472 if (ret)
Ye Liec346892022-05-11 13:56:20 +05301473 printf("Failed to initialize caam_jr: %d\n", ret);
Gaurav Jain81113a02022-03-24 11:50:27 +05301474 }
Peng Fan5760d8d2020-04-22 10:51:13 +08001475
1476 return 0;
1477}
1478#endif
Ye Li325cd012020-05-03 22:19:52 +08001479
Peng Fana35215d2020-07-09 13:39:26 +08001480#if defined(CONFIG_SPL_BUILD)
1481#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1482bool serror_need_skip = true;
1483
Sean Anderson2d755492022-03-22 17:17:35 -04001484void do_error(struct pt_regs *pt_regs)
Peng Fana35215d2020-07-09 13:39:26 +08001485{
1486 /*
1487 * If stack is still in ROM reserved OCRAM not switch to SPL,
1488 * it is the ROM SError
1489 */
1490 ulong sp;
1491
1492 asm volatile("mov %0, sp" : "=r"(sp) : );
1493
1494 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1495 /* Check for ERR050342, imx8mq HDCP enabled parts */
1496 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1497 serror_need_skip = false;
1498 return; /* Do nothing skip the SError in ROM */
1499 }
1500
1501 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1502 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1503 serror_need_skip = false;
1504 return; /* Do nothing skip the SError in ROM */
1505 }
1506 }
1507
1508 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -04001509 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fana35215d2020-07-09 13:39:26 +08001510 show_regs(pt_regs);
1511 panic("Resetting CPU ...\n");
1512}
1513#endif
1514#endif
Ye Li0513f362019-07-15 01:16:46 -07001515
1516#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
Marek Vasut765b5802022-04-06 02:21:34 +02001517enum env_location arch_env_get_location(enum env_operation op, int prio)
Ye Li0513f362019-07-15 01:16:46 -07001518{
1519 enum boot_device dev = get_boot_device();
Ye Li0513f362019-07-15 01:16:46 -07001520
1521 if (prio)
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001522 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001523
1524 switch (dev) {
Fabio Estevam9be6daf2022-04-21 15:05:23 -03001525 case USB_BOOT:
1526 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1527 return ENVL_SPI_FLASH;
1528 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1529 return ENVL_NAND;
1530 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1531 return ENVL_MMC;
1532 if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
1533 return ENVL_NOWHERE;
1534 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001535 case QSPI_BOOT:
Marek Vasut31b3bc42022-03-25 18:59:28 +01001536 case SPI_NOR_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001537 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1538 return ENVL_SPI_FLASH;
1539 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001540 case NAND_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001541 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1542 return ENVL_NAND;
1543 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001544 case SD1_BOOT:
1545 case SD2_BOOT:
1546 case SD3_BOOT:
1547 case MMC1_BOOT:
1548 case MMC2_BOOT:
1549 case MMC3_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001550 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1551 return ENVL_MMC;
1552 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1553 return ENVL_EXT4;
1554 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1555 return ENVL_FAT;
1556 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001557 default:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001558 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001559 }
Ye Li0513f362019-07-15 01:16:46 -07001560}
1561
Ye Li0513f362019-07-15 01:16:46 -07001562#endif
Peng Fanf19e0e52022-04-29 16:03:14 +08001563
1564#ifdef CONFIG_IMX_BOOTAUX
1565const struct rproc_att hostmap[] = {
1566 /* aux core , host core, size */
1567 { 0x00000000, 0x007e0000, 0x00020000 },
1568 /* OCRAM_S */
1569 { 0x00180000, 0x00180000, 0x00008000 },
1570 /* OCRAM */
1571 { 0x00900000, 0x00900000, 0x00020000 },
1572 /* OCRAM */
1573 { 0x00920000, 0x00920000, 0x00020000 },
1574 /* QSPI Code - alias */
1575 { 0x08000000, 0x08000000, 0x08000000 },
1576 /* DDR (Code) - alias */
1577 { 0x10000000, 0x80000000, 0x0FFE0000 },
1578 /* TCML */
1579 { 0x1FFE0000, 0x007E0000, 0x00040000 },
1580 /* OCRAM_S */
1581 { 0x20180000, 0x00180000, 0x00008000 },
1582 /* OCRAM */
1583 { 0x20200000, 0x00900000, 0x00040000 },
1584 /* DDR (Data) */
1585 { 0x40000000, 0x40000000, 0x80000000 },
1586 { /* sentinel */ }
1587};
Marek Vasutddc59352022-12-13 05:46:07 +01001588
1589const struct rproc_att *imx_bootaux_get_hostmap(void)
1590{
1591 return hostmap;
1592}
Peng Fanf19e0e52022-04-29 16:03:14 +08001593#endif