blob: 9588b8b28bf2c5fafa18d62c036cbf71231a37fa [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
Ian Ray38dfa082024-11-08 16:03:55 +020037#include "../snvs.h"
38
Peng Faneae4de22018-01-10 13:20:37 +080039DECLARE_GLOBAL_DATA_PTR;
40
Stefano Babicf8b509b2019-09-20 08:47:53 +020041#if defined(CONFIG_IMX_HAB)
Paul Geurtsdf0f95a2024-11-01 09:49:20 +010042struct imx_fuse const imx_sec_config_fuse = {
Peng Faneae4de22018-01-10 13:20:37 +080043 .bank = 1,
44 .word = 3,
45};
Paul Geurtsfea40042024-11-01 09:49:21 +010046
47struct imx_fuse const imx_field_return_fuse = {
48 .bank = 8,
49 .word = 3,
50};
Peng Faneae4de22018-01-10 13:20:37 +080051#endif
52
53int timer_init(void)
54{
Simon Glass85ed77d2024-09-29 19:49:46 -060055#ifdef CONFIG_XPL_BUILD
Peng Faneae4de22018-01-10 13:20:37 +080056 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
57 unsigned long freq = readl(&sctr->cntfid0);
58
59 /* Update with accurate clock frequency */
60 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
61
62 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
63 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
64#endif
65
66 gd->arch.tbl = 0;
67 gd->arch.tbu = 0;
68
69 return 0;
70}
71
72void enable_tzc380(void)
73{
74 struct iomuxc_gpr_base_regs *gpr =
75 (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
76
77 /* Enable TZASC and lock setting */
78 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN);
79 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010080
81 /*
82 * According to TRM, TZASC_ID_SWAP_BYPASS should be set in
83 * order to avoid AXI Bus errors when GPU is in use
84 */
Peng Fanda7a16c2022-04-29 16:18:49 +080085 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010086
87 /*
88 * imx8mn and imx8mp implements the lock bit for
89 * TZASC_ID_SWAP_BYPASS, enable it to lock settings
90 */
Peng Fanda7a16c2022-04-29 16:18:49 +080091 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS_LOCK);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010092
Ye Li4c97c462019-08-27 06:25:34 +000093 /*
94 * set Region 0 attribute to allow secure and non-secure
95 * read/write permission. Found some masters like usb dwc3
96 * controllers can't work with secure memory.
97 */
98 writel(0xf0000000, TZASC_BASE_ADDR + 0x108);
Peng Faneae4de22018-01-10 13:20:37 +080099}
100
101void set_wdog_reset(struct wdog_regs *wdog)
102{
103 /*
104 * Output WDOG_B signal to reset external pmic or POR_B decided by
105 * the board design. Without external reset, the peripherals/DDR/
106 * PMIC are not reset, that may cause system working abnormal.
107 * WDZST bit is write-once only bit. Align this bit in kernel,
108 * otherwise kernel code will have no chance to set this bit.
109 */
110 setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK);
111}
112
Marek Vasut003969b2022-12-22 01:46:40 +0100113#ifdef CONFIG_ARMV8_PSCI
114#define PTE_MAP_NS PTE_BLOCK_NS
115#else
116#define PTE_MAP_NS 0
117#endif
118
Peng Faneae4de22018-01-10 13:20:37 +0800119static struct mm_region imx8m_mem_map[] = {
120 {
121 /* ROM */
122 .virt = 0x0UL,
123 .phys = 0x0UL,
124 .size = 0x100000UL,
125 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
126 PTE_BLOCK_OUTER_SHARE
127 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100128 /* CAAM */
129 .virt = 0x100000UL,
130 .phys = 0x100000UL,
131 .size = 0x8000UL,
132 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
133 PTE_BLOCK_NON_SHARE |
134 PTE_BLOCK_PXN | PTE_BLOCK_UXN
135 }, {
Marek Vasutb1738e02021-02-25 21:52:26 +0100136 /* OCRAM_S */
137 .virt = 0x180000UL,
138 .phys = 0x180000UL,
139 .size = 0x8000UL,
140 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100141 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Marek Vasutb1738e02021-02-25 21:52:26 +0100142 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100143 /* TCM */
144 .virt = 0x7C0000UL,
145 .phys = 0x7C0000UL,
146 .size = 0x80000UL,
147 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
148 PTE_BLOCK_NON_SHARE |
Marek Vasut003969b2022-12-22 01:46:40 +0100149 PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_MAP_NS
Gary Bisson5c72a452018-11-14 17:55:28 +0100150 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800151 /* OCRAM */
152 .virt = 0x900000UL,
153 .phys = 0x900000UL,
154 .size = 0x200000UL,
155 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100156 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Faneae4de22018-01-10 13:20:37 +0800157 }, {
158 /* AIPS */
159 .virt = 0xB00000UL,
160 .phys = 0xB00000UL,
161 .size = 0x3f500000UL,
162 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
163 PTE_BLOCK_NON_SHARE |
164 PTE_BLOCK_PXN | PTE_BLOCK_UXN
165 }, {
166 /* DRAM1 */
167 .virt = 0x40000000UL,
168 .phys = 0x40000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000169 .size = PHYS_SDRAM_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800170 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100171 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fanb749b5e2019-08-27 06:25:27 +0000172#ifdef PHYS_SDRAM_2_SIZE
Peng Faneae4de22018-01-10 13:20:37 +0800173 }, {
174 /* DRAM2 */
175 .virt = 0x100000000UL,
176 .phys = 0x100000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000177 .size = PHYS_SDRAM_2_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800178 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100179 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fanb749b5e2019-08-27 06:25:27 +0000180#endif
Peng Faneae4de22018-01-10 13:20:37 +0800181 }, {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800182 /* empty entrie to split table entry 5 if needed when TEEs are used */
183 0,
184 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800185 /* List terminator */
186 0,
187 }
188};
189
190struct mm_region *mem_map = imx8m_mem_map;
191
Marek Vasute48aac02021-02-27 14:59:00 +0100192static unsigned int imx8m_find_dram_entry_in_mem_map(void)
193{
194 int i;
195
196 for (i = 0; i < ARRAY_SIZE(imx8m_mem_map); i++)
Tom Rinibb4dd962022-11-16 13:10:37 -0500197 if (imx8m_mem_map[i].phys == CFG_SYS_SDRAM_BASE)
Marek Vasute48aac02021-02-27 14:59:00 +0100198 return i;
199
200 hang(); /* Entry not found, this must never happen. */
201}
202
Peng Fanb749b5e2019-08-27 06:25:27 +0000203void enable_caches(void)
204{
Ye Li453bfcb2022-04-07 15:55:56 +0800205 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
206 * If OPTEE does not run, still update the MMU table according to dram banks structure
207 * to set correct dram size from board_phys_sdram_size
208 */
209 int i = 0;
210 /*
211 * please make sure that entry initial value matches
212 * imx8m_mem_map for DRAM1
213 */
214 int entry = imx8m_find_dram_entry_in_mem_map();
215 u64 attrs = imx8m_mem_map[entry].attrs;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800216
Marek Vasut9ce353d2024-09-05 17:35:00 +0200217 /* Deactivate the data cache, possibly enabled in arch_cpu_init() */
218 dcache_disable();
219 /*
220 * Force the call of setup_all_pgtables() in mmu_setup() by clearing tlb_fillptr
221 * to update the TLB location udpated in board_f.c::reserve_mmu
222 */
223 gd->arch.tlb_fillptr = 0;
224
Ye Li453bfcb2022-04-07 15:55:56 +0800225 while (i < CONFIG_NR_DRAM_BANKS &&
226 entry < ARRAY_SIZE(imx8m_mem_map)) {
227 if (gd->bd->bi_dram[i].start == 0)
228 break;
229 imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start;
230 imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start;
231 imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size;
232 imx8m_mem_map[entry].attrs = attrs;
233 debug("Added memory mapping (%d): %llx %llx\n", entry,
234 imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size);
235 i++; entry++;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800236 }
Peng Fanb749b5e2019-08-27 06:25:27 +0000237
238 icache_enable();
239 dcache_enable();
240}
241
Peng Fanfa35c3d2020-07-09 15:26:06 +0800242__weak int board_phys_sdram_size(phys_size_t *size)
243{
244 if (!size)
245 return -EINVAL;
246
247 *size = PHYS_SDRAM_SIZE;
Ye Li453bfcb2022-04-07 15:55:56 +0800248
249#ifdef PHYS_SDRAM_2_SIZE
250 *size += PHYS_SDRAM_2_SIZE;
251#endif
Peng Fanfa35c3d2020-07-09 15:26:06 +0800252 return 0;
253}
254
255int dram_init(void)
256{
257 phys_size_t sdram_size;
258 int ret;
259
260 ret = board_phys_sdram_size(&sdram_size);
261 if (ret)
262 return ret;
263
264 /* rom_pointer[1] contains the size of TEE occupies */
Simon Glass85ed77d2024-09-29 19:49:46 -0600265 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_XPL_BUILD) && rom_pointer[1])
Peng Fanfa35c3d2020-07-09 15:26:06 +0800266 gd->ram_size = sdram_size - rom_pointer[1];
267 else
268 gd->ram_size = sdram_size;
269
Peng Fanfa35c3d2020-07-09 15:26:06 +0800270 return 0;
271}
272
273int dram_init_banksize(void)
274{
275 int bank = 0;
276 int ret;
277 phys_size_t sdram_size;
Ye Li453bfcb2022-04-07 15:55:56 +0800278 phys_size_t sdram_b1_size, sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800279
280 ret = board_phys_sdram_size(&sdram_size);
281 if (ret)
282 return ret;
283
Ye Li453bfcb2022-04-07 15:55:56 +0800284 /* Bank 1 can't cross over 4GB space */
285 if (sdram_size > 0xc0000000) {
286 sdram_b1_size = 0xc0000000;
287 sdram_b2_size = sdram_size - 0xc0000000;
288 } else {
289 sdram_b1_size = sdram_size;
290 sdram_b2_size = 0;
291 }
292
Peng Fanfa35c3d2020-07-09 15:26:06 +0800293 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
Simon Glass85ed77d2024-09-29 19:49:46 -0600294 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_XPL_BUILD) && rom_pointer[1]) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800295 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
296 phys_size_t optee_size = (size_t)rom_pointer[1];
297
298 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
Ye Li453bfcb2022-04-07 15:55:56 +0800299 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800300 if (++bank >= CONFIG_NR_DRAM_BANKS) {
301 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
302 return -1;
303 }
304
305 gd->bd->bi_dram[bank].start = optee_start + optee_size;
306 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
Ye Li453bfcb2022-04-07 15:55:56 +0800307 sdram_b1_size - gd->bd->bi_dram[bank].start;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800308 }
309 } else {
Ye Li453bfcb2022-04-07 15:55:56 +0800310 gd->bd->bi_dram[bank].size = sdram_b1_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800311 }
312
Ye Li453bfcb2022-04-07 15:55:56 +0800313 if (sdram_b2_size) {
314 if (++bank >= CONFIG_NR_DRAM_BANKS) {
315 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
316 return -1;
317 }
318 gd->bd->bi_dram[bank].start = 0x100000000UL;
319 gd->bd->bi_dram[bank].size = sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800320 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800321
322 return 0;
323}
324
325phys_size_t get_effective_memsize(void)
326{
Ye Li453bfcb2022-04-07 15:55:56 +0800327 int ret;
328 phys_size_t sdram_size;
329 phys_size_t sdram_b1_size;
330 ret = board_phys_sdram_size(&sdram_size);
331 if (!ret) {
332 /* Bank 1 can't cross over 4GB space */
333 if (sdram_size > 0xc0000000) {
334 sdram_b1_size = 0xc0000000;
335 } else {
336 sdram_b1_size = sdram_size;
337 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800338
Simon Glass85ed77d2024-09-29 19:49:46 -0600339 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_XPL_BUILD) &&
Elena Popa65c9edb2023-08-08 14:58:26 +0300340 rom_pointer[1]) {
Ye Li453bfcb2022-04-07 15:55:56 +0800341 /* We will relocate u-boot to Top of dram1. Tee position has two cases:
342 * 1. At the top of dram1, Then return the size removed optee size.
343 * 2. In the middle of dram1, return the size of dram1.
344 */
345 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
346 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
347 }
348
349 return sdram_b1_size;
350 } else {
351 return PHYS_SDRAM_SIZE;
352 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800353}
354
Heinrich Schuchardt51a9aac2023-08-12 20:16:58 +0200355phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Frieder Schrempf159879e2021-06-07 14:36:44 +0200356{
Marek Vasutdcbbf782022-04-14 15:51:46 +0200357 ulong top_addr;
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800358
Frieder Schrempf159879e2021-06-07 14:36:44 +0200359 /*
360 * Some IPs have their accessible address space restricted by
361 * the interconnect. Let's make sure U-Boot only ever uses the
362 * space below the 4G address boundary (which is 3GiB big),
363 * even when the effective available memory is bigger.
364 */
Marek Vasutdcbbf782022-04-14 15:51:46 +0200365 top_addr = clamp_val((u64)PHYS_SDRAM + gd->ram_size, 0, 0xffffffff);
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800366
367 /*
368 * rom_pointer[0] stores the TEE memory start address.
369 * rom_pointer[1] stores the size TEE uses.
370 * We need to reserve the memory region for TEE.
371 */
Marek Vasut9ca966e2022-12-22 01:46:38 +0100372 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && rom_pointer[0] &&
373 rom_pointer[1] && top_addr > rom_pointer[0])
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800374 top_addr = rom_pointer[0];
Frieder Schrempf159879e2021-06-07 14:36:44 +0200375
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800376 return top_addr;
Frieder Schrempf159879e2021-06-07 14:36:44 +0200377}
378
Peng Fan1caffdf2019-08-27 06:25:17 +0000379static u32 get_cpu_variant_type(u32 type)
380{
381 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
382 struct fuse_bank *bank = &ocotp->bank[1];
383 struct fuse_bank1_regs *fuse =
384 (struct fuse_bank1_regs *)bank->fuse_regs;
385
386 u32 value = readl(&fuse->tester4);
387
Peng Fan67815082020-02-05 17:34:54 +0800388 if (type == MXC_CPU_IMX8MQ) {
389 if ((value & 0x3) == 0x2)
390 return MXC_CPU_IMX8MD;
391 else if (value & 0x200000)
392 return MXC_CPU_IMX8MQL;
393
394 } else if (type == MXC_CPU_IMX8MM) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000395 switch (value & 0x3) {
396 case 2:
397 if (value & 0x1c0000)
398 return MXC_CPU_IMX8MMDL;
399 else
400 return MXC_CPU_IMX8MMD;
401 case 3:
402 if (value & 0x1c0000)
403 return MXC_CPU_IMX8MMSL;
404 else
405 return MXC_CPU_IMX8MMS;
406 default:
407 if (value & 0x1c0000)
408 return MXC_CPU_IMX8MML;
409 break;
410 }
Peng Fan1a07d912020-02-05 17:39:27 +0800411 } else if (type == MXC_CPU_IMX8MN) {
412 switch (value & 0x3) {
413 case 2:
Ye Li715180e2021-03-19 15:57:11 +0800414 if (value & 0x1000000) {
415 if (value & 0x10000000) /* MIPI DSI */
416 return MXC_CPU_IMX8MNUD;
417 else
418 return MXC_CPU_IMX8MNDL;
419 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800420 return MXC_CPU_IMX8MND;
Ye Li715180e2021-03-19 15:57:11 +0800421 }
Peng Fan1a07d912020-02-05 17:39:27 +0800422 case 3:
Ye Li715180e2021-03-19 15:57:11 +0800423 if (value & 0x1000000) {
424 if (value & 0x10000000) /* MIPI DSI */
425 return MXC_CPU_IMX8MNUS;
426 else
427 return MXC_CPU_IMX8MNSL;
428 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800429 return MXC_CPU_IMX8MNS;
Ye Li715180e2021-03-19 15:57:11 +0800430 }
Peng Fan1a07d912020-02-05 17:39:27 +0800431 default:
Ye Li715180e2021-03-19 15:57:11 +0800432 if (value & 0x1000000) {
433 if (value & 0x10000000) /* MIPI DSI */
434 return MXC_CPU_IMX8MNUQ;
435 else
436 return MXC_CPU_IMX8MNL;
437 }
Peng Fan1a07d912020-02-05 17:39:27 +0800438 break;
439 }
Ye Lid2d754f2020-04-20 20:12:54 -0700440 } else if (type == MXC_CPU_IMX8MP) {
441 u32 value0 = readl(&fuse->tester3);
442 u32 flag = 0;
443
444 if ((value0 & 0xc0000) == 0x80000)
445 return MXC_CPU_IMX8MPD;
446
447 /* vpu disabled */
448 if ((value0 & 0x43000000) == 0x43000000)
449 flag = 1;
450
451 /* npu disabled*/
452 if ((value & 0x8) == 0x8)
Peng Fan0386e7f2022-04-07 15:55:52 +0800453 flag |= BIT(1);
Ye Lid2d754f2020-04-20 20:12:54 -0700454
455 /* isp disabled */
456 if ((value & 0x3) == 0x3)
Peng Fan0386e7f2022-04-07 15:55:52 +0800457 flag |= BIT(2);
458
459 /* gpu disabled */
460 if ((value & 0xc0) == 0xc0)
461 flag |= BIT(3);
462
463 /* lvds disabled */
464 if ((value & 0x180000) == 0x180000)
465 flag |= BIT(4);
466
467 /* mipi dsi disabled */
468 if ((value & 0x60000) == 0x60000)
469 flag |= BIT(5);
Ye Lid2d754f2020-04-20 20:12:54 -0700470
471 switch (flag) {
Peng Fan0386e7f2022-04-07 15:55:52 +0800472 case 0x3f:
473 return MXC_CPU_IMX8MPUL;
Ye Lid2d754f2020-04-20 20:12:54 -0700474 case 7:
475 return MXC_CPU_IMX8MPL;
Ye Lid2d754f2020-04-20 20:12:54 -0700476 case 2:
477 return MXC_CPU_IMX8MP6;
Ye Lid2d754f2020-04-20 20:12:54 -0700478 default:
479 break;
480 }
481
Peng Fan1caffdf2019-08-27 06:25:17 +0000482 }
483
484 return type;
485}
486
Peng Faneae4de22018-01-10 13:20:37 +0800487u32 get_cpu_rev(void)
488{
489 struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
490 u32 reg = readl(&ana_pll->digprog);
491 u32 type = (reg >> 16) & 0xff;
Peng Fan1caffdf2019-08-27 06:25:17 +0000492 u32 major_low = (reg >> 8) & 0xff;
Peng Faneae4de22018-01-10 13:20:37 +0800493 u32 rom_version;
494
495 reg &= 0xff;
496
Peng Fan69cec072019-12-27 10:14:02 +0800497 /* iMX8MP */
498 if (major_low == 0x43) {
Ye Lid2d754f2020-04-20 20:12:54 -0700499 type = get_cpu_variant_type(MXC_CPU_IMX8MP);
Peng Fan69cec072019-12-27 10:14:02 +0800500 } else if (major_low == 0x42) {
501 /* iMX8MN */
Peng Fan1a07d912020-02-05 17:39:27 +0800502 type = get_cpu_variant_type(MXC_CPU_IMX8MN);
Peng Fan5d2f2062019-06-27 17:23:49 +0800503 } else if (major_low == 0x41) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000504 type = get_cpu_variant_type(MXC_CPU_IMX8MM);
505 } else {
506 if (reg == CHIP_REV_1_0) {
507 /*
Peng Fanc23fbdd2019-10-16 10:24:17 +0000508 * For B0 chip, the DIGPROG is not updated,
509 * it is still TO1.0. we have to check ROM
510 * version or OCOTP_READ_FUSE_DATA.
511 * 0xff0055aa is magic number for B1.
Peng Fan1caffdf2019-08-27 06:25:17 +0000512 */
Peng Fanc23fbdd2019-10-16 10:24:17 +0000513 if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
Ye Lic963ed12021-03-19 15:57:16 +0800514 /*
515 * B2 uses same DIGPROG and OCOTP_READ_FUSE_DATA value with B1,
516 * so have to check ROM to distinguish them
517 */
518 rom_version = readl((void __iomem *)ROM_VERSION_B0);
519 rom_version &= 0xff;
520 if (rom_version == CHIP_REV_2_2)
521 reg = CHIP_REV_2_2;
522 else
523 reg = CHIP_REV_2_1;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000524 } else {
525 rom_version =
526 readl((void __iomem *)ROM_VERSION_A0);
527 if (rom_version != CHIP_REV_1_0) {
528 rom_version = readl((void __iomem *)ROM_VERSION_B0);
Patrick Wildtd4a78b92019-11-19 09:42:06 +0100529 rom_version &= 0xff;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000530 if (rom_version == CHIP_REV_2_0)
531 reg = CHIP_REV_2_0;
532 }
Peng Fan1caffdf2019-08-27 06:25:17 +0000533 }
Peng Faneae4de22018-01-10 13:20:37 +0800534 }
Peng Fan67815082020-02-05 17:34:54 +0800535
536 type = get_cpu_variant_type(type);
Peng Faneae4de22018-01-10 13:20:37 +0800537 }
538
539 return (type << 12) | reg;
540}
541
542static void imx_set_wdog_powerdown(bool enable)
543{
544 struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
545 struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
546 struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
547
548 /* Write to the PDE (Power Down Enable) bit */
549 writew(enable, &wdog1->wmcr);
550 writew(enable, &wdog2->wmcr);
551 writew(enable, &wdog3->wmcr);
552}
553
Simon Glassb8357c12023-08-21 21:16:56 -0600554static int imx8m_check_clock(void)
Peng Fanc98e0322019-08-27 06:25:58 +0000555{
556 struct udevice *dev;
557 int ret;
558
Peng Fan3c073342019-10-16 03:01:51 +0000559 if (CONFIG_IS_ENABLED(CLK)) {
560 ret = uclass_get_device_by_name(UCLASS_CLK,
561 "clock-controller@30380000",
562 &dev);
563 if (ret < 0) {
564 printf("Failed to find clock node. Check device tree\n");
565 return ret;
566 }
Peng Fanc98e0322019-08-27 06:25:58 +0000567 }
568
569 return 0;
570}
Simon Glassb8357c12023-08-21 21:16:56 -0600571EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, imx8m_check_clock);
Peng Fanc98e0322019-08-27 06:25:58 +0000572
Marek Vasutf7b184e2022-09-19 21:37:07 +0200573static void imx8m_setup_snvs(void)
574{
575 /* Enable SNVS clock */
576 clock_enable(CCGR_SNVS, 1);
577 /* Initialize glitch detect */
578 writel(SNVS_LPPGDR_INIT, SNVS_BASE_ADDR + SNVS_LPLVDR);
579 /* Clear interrupt status */
580 writel(0xffffffff, SNVS_BASE_ADDR + SNVS_LPSR);
Ian Ray38dfa082024-11-08 16:03:55 +0200581
582 init_snvs();
Marek Vasutf7b184e2022-09-19 21:37:07 +0200583}
584
Marek Vasut829858a2022-12-22 01:46:42 +0100585static void imx8m_setup_csu_tzasc(void)
586{
587 const uintptr_t tzasc_base[4] = {
588 0x301f0000, 0x301f0000, 0x301f0000, 0x301f0000
589 };
590 int i, j;
591
592 if (!IS_ENABLED(CONFIG_ARMV8_PSCI))
593 return;
594
595 /* CSU */
596 for (i = 0; i < 64; i++)
597 writel(0x00ff00ff, (void *)CSU_BASE_ADDR + (4 * i));
598
599 /* TZASC */
600 for (j = 0; j < 4; j++) {
601 writel(0x77777777, (void *)(tzasc_base[j]));
602 writel(0x77777777, (void *)(tzasc_base[j]) + 0x4);
603 for (i = 0; i <= 0x10; i += 4)
604 writel(0, (void *)(tzasc_base[j]) + 0x40 + i);
605 }
606}
607
Marek Vasut9ce353d2024-09-05 17:35:00 +0200608/*
609 * Place early TLB into the .data section so that it will not
610 * get cleared, use 16 kiB alignment.
611 */
612#define EARLY_TLB_SIZE SZ_64K
613u8 early_tlb[EARLY_TLB_SIZE] __section(".data") __aligned(0x4000);
614
615/*
616 * Initialize the MMU and activate cache in U-Boot pre-reloc stage
617 * MMU/TLB is updated in enable_caches() for U-Boot after relocation
618 */
619static void early_enable_caches(void)
620{
621 phys_size_t sdram_size;
622 int entry, ret;
623
Simon Glass85ed77d2024-09-29 19:49:46 -0600624 if (IS_ENABLED(CONFIG_XPL_BUILD))
Marek Vasut9ce353d2024-09-05 17:35:00 +0200625 return;
626
627 if (CONFIG_IS_ENABLED(SYS_ICACHE_OFF) || CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
628 return;
629
630 /* Use maximum available DRAM size in first bank. */
631 ret = board_phys_sdram_size(&sdram_size);
632 if (ret)
633 return;
634
635 entry = imx8m_find_dram_entry_in_mem_map();
636 imx8m_mem_map[entry].size = max(sdram_size, (phys_size_t)0xc0000000);
637
638 gd->arch.tlb_size = EARLY_TLB_SIZE;
639 gd->arch.tlb_addr = (unsigned long)&early_tlb;
640
641 /* Enable MMU (default configuration) */
642 dcache_enable();
643}
644
Peng Faneae4de22018-01-10 13:20:37 +0800645int arch_cpu_init(void)
646{
Peng Fanc0b30d72019-04-17 09:41:16 +0000647 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
Marek Vasut3ea500a2022-04-13 00:41:52 +0200648
649#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
650 icache_enable();
Marek Vasut9ce353d2024-09-05 17:35:00 +0200651 early_enable_caches();
Marek Vasut3ea500a2022-04-13 00:41:52 +0200652#endif
653
Peng Faneae4de22018-01-10 13:20:37 +0800654 /*
Peng Fand0ca2892019-08-27 06:25:37 +0000655 * ROM might disable clock for SCTR,
656 * enable the clock before timer_init.
657 */
Simon Glass85ed77d2024-09-29 19:49:46 -0600658 if (IS_ENABLED(CONFIG_XPL_BUILD))
Peng Fand0ca2892019-08-27 06:25:37 +0000659 clock_enable(CCGR_SCTR, 1);
660 /*
Peng Faneae4de22018-01-10 13:20:37 +0800661 * Init timer at very early state, because sscg pll setting
662 * will use it
663 */
664 timer_init();
665
Simon Glass85ed77d2024-09-29 19:49:46 -0600666 if (IS_ENABLED(CONFIG_XPL_BUILD)) {
Peng Faneae4de22018-01-10 13:20:37 +0800667 clock_init();
668 imx_set_wdog_powerdown(false);
Peng Fan9cf2aa32020-07-09 13:52:41 +0800669
670 if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
671 is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
Ye Li715180e2021-03-19 15:57:11 +0800672 is_imx8mnsl() || is_imx8mpd() || is_imx8mnud() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800673 /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
674 struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
675 struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
676 struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0);
677 struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR;
678
679 writel(0x1, &pgc_core2->pgcr);
680 writel(0x1, &pgc_core3->pgcr);
Ye Li715180e2021-03-19 15:57:11 +0800681 if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800682 writel(0x1, &pgc_core1->pgcr);
683 writel(0xE, &gpc->cpu_pgc_dn_trg);
684 } else {
685 writel(0xC, &gpc->cpu_pgc_dn_trg);
686 }
687 }
Peng Faneae4de22018-01-10 13:20:37 +0800688 }
689
Peng Fanc0b30d72019-04-17 09:41:16 +0000690 if (is_imx8mq()) {
691 clock_enable(CCGR_OCOTP, 1);
692 if (readl(&ocotp->ctrl) & 0x200)
693 writel(0x200, &ocotp->ctrl_clr);
694 }
695
Marek Vasutf7b184e2022-09-19 21:37:07 +0200696 imx8m_setup_snvs();
697
Marek Vasut829858a2022-12-22 01:46:42 +0100698 imx8m_setup_csu_tzasc();
699
Peng Faneae4de22018-01-10 13:20:37 +0800700 return 0;
701}
702
Peng Fanc9823b02019-09-16 03:09:36 +0000703#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
704struct rom_api *g_rom_api = (struct rom_api *)0x980;
Peng Fanc9823b02019-09-16 03:09:36 +0000705#endif
706
Marek Vasut520ded02021-07-03 04:55:33 +0200707#if defined(CONFIG_IMX8M)
708#include <spl.h>
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200709int imx8m_detect_secondary_image_boot(void)
Marek Vasut520ded02021-07-03 04:55:33 +0200710{
711 u32 *rom_log_addr = (u32 *)0x9e0;
712 u32 *rom_log;
713 u8 event_id;
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200714 int i, boot_secondary = 0;
Marek Vasut520ded02021-07-03 04:55:33 +0200715
716 /* If the ROM event log pointer is not valid. */
717 if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 ||
718 *rom_log_addr & 0x3)
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200719 return -EINVAL;
Marek Vasut520ded02021-07-03 04:55:33 +0200720
721 /* Parse the ROM event ID version 2 log */
722 rom_log = (u32 *)(uintptr_t)(*rom_log_addr);
723 for (i = 0; i < 128; i++) {
724 event_id = rom_log[i] >> 24;
725 switch (event_id) {
726 case 0x00: /* End of list */
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200727 return boot_secondary;
Marek Vasut520ded02021-07-03 04:55:33 +0200728 /* Log entries with 1 parameter, skip 1 */
729 case 0x80: /* Start to perform the device initialization */
730 case 0x81: /* The boot device initialization completes */
Fedor Ross7e02ff62022-04-14 18:36:23 +0200731 case 0x82: /* Starts to execute boot device driver pre-config */
Marek Vasut520ded02021-07-03 04:55:33 +0200732 case 0x8f: /* The boot device initialization fails */
733 case 0x90: /* Start to read data from boot device */
734 case 0x91: /* Reading data from boot device completes */
735 case 0x9f: /* Reading data from boot device fails */
736 i += 1;
737 continue;
738 /* Log entries with 2 parameters, skip 2 */
739 case 0xa0: /* Image authentication result */
740 case 0xc0: /* Jump to the boot image soon */
741 i += 2;
742 continue;
743 /* Boot from the secondary boot image */
744 case 0x51:
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200745 boot_secondary = 1;
Marek Vasut520ded02021-07-03 04:55:33 +0200746 continue;
747 default:
748 continue;
749 }
750 }
751
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200752 return boot_secondary;
753}
754
755int spl_mmc_emmc_boot_partition(struct mmc *mmc)
756{
757 int part, ret;
758
759 part = default_spl_mmc_emmc_boot_partition(mmc);
760 if (part == 0)
761 return part;
762
763 ret = imx8m_detect_secondary_image_boot();
764 if (ret < 0) {
765 printf("Could not get boot partition! Using %d\n", part);
766 return part;
767 }
768
769 if (ret == 1) {
770 /*
771 * Swap the eMMC boot partitions in case there was a
772 * fallback event (i.e. primary image was corrupted
773 * and that corruption was recognized by the BootROM),
774 * so the SPL loads the rest of the U-Boot from the
775 * correct eMMC boot partition, since the BootROM
776 * leaves the boot partition set to the corrupted one.
777 */
778 if (part == 1)
779 part = 2;
780 else if (part == 2)
781 part = 1;
782 }
783
Marek Vasut520ded02021-07-03 04:55:33 +0200784 return part;
785}
Fedor Rossc0b94842023-10-16 18:16:15 +0200786
787int boot_mode_getprisec(void)
788{
789 return !!imx8m_detect_secondary_image_boot();
790}
Marek Vasut520ded02021-07-03 04:55:33 +0200791#endif
792
Fedor Rossed2f94a2023-10-16 18:16:14 +0200793#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
Simon Glass18422832024-08-22 07:55:00 -0600794#ifdef SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
Fedor Rossed2f94a2023-10-16 18:16:14 +0200795#define IMG_CNTN_SET1_OFFSET GENMASK(22, 19)
796unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
797 unsigned long raw_sect)
798{
799 u32 val, offset;
800
801 if (fuse_read(2, 1, &val)) {
802 debug("Error reading fuse!\n");
803 return raw_sect;
804 }
805
806 val = FIELD_GET(IMG_CNTN_SET1_OFFSET, val);
807 if (val > 10) {
808 debug("Secondary image boot disabled!\n");
809 return raw_sect;
810 }
811
812 if (val == 0)
813 offset = SZ_4M;
814 else if (val == 1)
815 offset = SZ_2M;
816 else if (val == 2)
817 offset = SZ_1M;
818 else /* flash.bin offset = 1 MiB * 2^n */
819 offset = SZ_1M << val;
820
821 offset /= 512;
822 offset -= CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET;
823
824 if (imx8m_detect_secondary_image_boot())
825 raw_sect += offset;
826
827 return raw_sect;
828}
Simon Glass18422832024-08-22 07:55:00 -0600829#endif /* SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION */
Fedor Rossed2f94a2023-10-16 18:16:14 +0200830#endif
831
Peng Faneae4de22018-01-10 13:20:37 +0800832bool is_usb_boot(void)
833{
834 return get_boot_device() == USB_BOOT;
835}
836
837#ifdef CONFIG_OF_SYSTEM_SETUP
Peng Fan435dc122020-07-09 14:06:49 +0800838bool check_fdt_new_path(void *blob)
839{
840 const char *soc_path = "/soc@0";
841 int nodeoff;
842
843 nodeoff = fdt_path_offset(blob, soc_path);
844 if (nodeoff < 0)
845 return false;
846
847 return true;
848}
849
850static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
851{
852 int i = 0;
853 int rc;
854 int nodeoff;
855 const char *status = "disabled";
856
857 for (i = 0; i < size_array; i++) {
858 nodeoff = fdt_path_offset(blob, nodes_path[i]);
859 if (nodeoff < 0)
860 continue; /* Not found, skip it */
861
Rasmus Villemoes8ab149a2023-05-22 11:27:28 +0200862 debug("Found %s node\n", nodes_path[i]);
Peng Fan435dc122020-07-09 14:06:49 +0800863
864add_status:
865 rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
866 if (rc) {
867 if (rc == -FDT_ERR_NOSPACE) {
868 rc = fdt_increase_size(blob, 512);
869 if (!rc)
870 goto add_status;
871 }
872 printf("Unable to update property %s:%s, err=%s\n",
873 nodes_path[i], "status", fdt_strerror(rc));
874 } else {
875 printf("Modify %s:%s disabled\n",
876 nodes_path[i], "status");
877 }
878 }
879
880 return 0;
881}
882
883#ifdef CONFIG_IMX8MQ
884bool check_dcss_fused(void)
885{
886 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
887 struct fuse_bank *bank = &ocotp->bank[1];
888 struct fuse_bank1_regs *fuse =
889 (struct fuse_bank1_regs *)bank->fuse_regs;
890 u32 value = readl(&fuse->tester4);
891
892 if (value & 0x4000000)
893 return true;
894
895 return false;
896}
897
898static int disable_mipi_dsi_nodes(void *blob)
899{
900 static const char * const nodes_path[] = {
901 "/mipi_dsi@30A00000",
902 "/mipi_dsi_bridge@30A00000",
903 "/dsi_phy@30A00300",
904 "/soc@0/bus@30800000/mipi_dsi@30a00000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800905 "/soc@0/bus@30800000/dphy@30a00300",
906 "/soc@0/bus@30800000/mipi-dsi@30a00000",
Peng Fan435dc122020-07-09 14:06:49 +0800907 };
908
909 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
910}
911
912static int disable_dcss_nodes(void *blob)
913{
914 static const char * const nodes_path[] = {
915 "/dcss@0x32e00000",
916 "/dcss@32e00000",
917 "/hdmi@32c00000",
918 "/hdmi_cec@32c33800",
919 "/hdmi_drm@32c00000",
920 "/display-subsystem",
921 "/sound-hdmi",
922 "/sound-hdmi-arc",
923 "/soc@0/bus@32c00000/display-controller@32e00000",
924 "/soc@0/bus@32c00000/hdmi@32c00000",
925 };
926
927 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
928}
929
930static int check_mipi_dsi_nodes(void *blob)
931{
932 static const char * const lcdif_path[] = {
933 "/lcdif@30320000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800934 "/soc@0/bus@30000000/lcdif@30320000",
935 "/soc@0/bus@30000000/lcd-controller@30320000"
Peng Fan435dc122020-07-09 14:06:49 +0800936 };
937 static const char * const mipi_dsi_path[] = {
938 "/mipi_dsi@30A00000",
939 "/soc@0/bus@30800000/mipi_dsi@30a00000"
940 };
941 static const char * const lcdif_ep_path[] = {
942 "/lcdif@30320000/port@0/mipi-dsi-endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800943 "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
944 "/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
Peng Fan435dc122020-07-09 14:06:49 +0800945 };
946 static const char * const mipi_dsi_ep_path[] = {
947 "/mipi_dsi@30A00000/port@1/endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800948 "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
949 "/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
Peng Fan435dc122020-07-09 14:06:49 +0800950 };
951
952 int lookup_node;
953 int nodeoff;
954 bool new_path = check_fdt_new_path(blob);
955 int i = new_path ? 1 : 0;
956
957 nodeoff = fdt_path_offset(blob, lcdif_path[i]);
958 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
959 /*
960 * If can't find lcdif node or lcdif node is disabled,
961 * then disable all mipi dsi, since they only can input
962 * from DCSS
963 */
964 return disable_mipi_dsi_nodes(blob);
965 }
966
967 nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
968 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
969 return 0;
970
971 nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
972 if (nodeoff < 0) {
973 /*
974 * If can't find lcdif endpoint, then disable all mipi dsi,
975 * since they only can input from DCSS
976 */
977 return disable_mipi_dsi_nodes(blob);
978 }
979
980 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
981 nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
982
983 if (nodeoff > 0 && nodeoff == lookup_node)
984 return 0;
985
986 return disable_mipi_dsi_nodes(blob);
987}
988#endif
989
990int disable_vpu_nodes(void *blob)
991{
992 static const char * const nodes_path_8mq[] = {
993 "/vpu@38300000",
Vitor Soares6dd07732024-03-15 14:44:25 +0000994 "/soc@0/vpu@38300000",
995 "/soc@0/video-codec@38300000",
996 "/soc@0/video-codec@38310000",
997 "/soc@0/blk-ctrl@38320000",
Peng Fan435dc122020-07-09 14:06:49 +0800998 };
999
1000 static const char * const nodes_path_8mm[] = {
1001 "/vpu_g1@38300000",
1002 "/vpu_g2@38310000",
Vitor Soares6dd07732024-03-15 14:44:25 +00001003 "/vpu_h1@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 static const char * const nodes_path_8mp[] = {
1010 "/vpu_g1@38300000",
1011 "/vpu_g2@38310000",
Vitor Soares6dd07732024-03-15 14:44:25 +00001012 "/vpu_vc8000e@38320000",
1013 "/soc@0/video-codec@38300000",
1014 "/soc@0/video-codec@38310000",
1015 "/soc@0/blk-ctrl@38330000",
Vitor Soares003810a2024-10-01 17:01:52 +01001016 "/soc@0/blk-ctl@38330000",
Peng Fan435dc122020-07-09 14:06:49 +08001017 };
1018
1019 if (is_imx8mq())
1020 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
1021 else if (is_imx8mm())
1022 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
1023 else if (is_imx8mp())
1024 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1025 else
1026 return -EPERM;
1027}
1028
Ye Liee337ce2021-03-19 15:57:09 +08001029#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1030static int low_drive_gpu_freq(void *blob)
1031{
1032 static const char *nodes_path_8mn[] = {
1033 "/gpu@38000000",
1034 "/soc@0/gpu@38000000"
1035 };
1036
1037 int nodeoff, cnt, i;
1038 u32 assignedclks[7];
1039
1040 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
1041 if (nodeoff < 0)
1042 return nodeoff;
1043
1044 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
1045 if (cnt < 0)
1046 return cnt;
1047
1048 if (cnt != 7)
1049 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
Heinrich Schuchardt72c891f2023-04-18 01:37:21 +02001050 if (cnt < 2)
1051 return -1;
Ye Liee337ce2021-03-19 15:57:09 +08001052
1053 assignedclks[cnt - 1] = 200000000;
1054 assignedclks[cnt - 2] = 200000000;
1055
1056 for (i = 0; i < cnt; i++) {
1057 debug("<%u>, ", assignedclks[i]);
1058 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
1059 }
1060 debug("\n");
1061
1062 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
1063}
1064#endif
1065
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001066static bool check_remote_endpoint(void *blob, const char *ep1, const char *ep2)
1067{
1068 int lookup_node;
1069 int nodeoff;
1070
1071 nodeoff = fdt_path_offset(blob, ep1);
1072 if (nodeoff) {
1073 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
1074 nodeoff = fdt_path_offset(blob, ep2);
1075
1076 if (nodeoff > 0 && nodeoff == lookup_node)
1077 return true;
1078 }
1079
1080 return false;
1081}
1082
1083int disable_dsi_lcdif_nodes(void *blob)
1084{
1085 int ret;
1086
1087 static const char * const dsi_path_8mp[] = {
1088 "/soc@0/bus@32c00000/mipi_dsi@32e60000"
1089 };
1090
1091 static const char * const lcdif_path_8mp[] = {
1092 "/soc@0/bus@32c00000/lcd-controller@32e80000"
1093 };
1094
1095 static const char * const lcdif_ep_path_8mp[] = {
1096 "/soc@0/bus@32c00000/lcd-controller@32e80000/port@0/endpoint"
1097 };
1098 static const char * const dsi_ep_path_8mp[] = {
1099 "/soc@0/bus@32c00000/mipi_dsi@32e60000/port@0/endpoint"
1100 };
1101
1102 ret = disable_fdt_nodes(blob, dsi_path_8mp, ARRAY_SIZE(dsi_path_8mp));
1103 if (ret)
1104 return ret;
1105
1106 if (check_remote_endpoint(blob, dsi_ep_path_8mp[0], lcdif_ep_path_8mp[0])) {
1107 /* Disable lcdif node */
1108 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1109 }
1110
1111 return 0;
1112}
1113
1114int disable_lvds_lcdif_nodes(void *blob)
1115{
1116 int ret, i;
1117
1118 static const char * const ldb_path_8mp[] = {
1119 "/soc@0/bus@32c00000/ldb@32ec005c",
1120 "/soc@0/bus@32c00000/phy@32ec0128"
1121 };
1122
1123 static const char * const lcdif_path_8mp[] = {
1124 "/soc@0/bus@32c00000/lcd-controller@32e90000"
1125 };
1126
1127 static const char * const lcdif_ep_path_8mp[] = {
1128 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@0",
1129 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@1"
1130 };
1131 static const char * const ldb_ep_path_8mp[] = {
1132 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@0/port@0/endpoint",
1133 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@1/port@0/endpoint"
1134 };
1135
1136 ret = disable_fdt_nodes(blob, ldb_path_8mp, ARRAY_SIZE(ldb_path_8mp));
1137 if (ret)
1138 return ret;
1139
1140 for (i = 0; i < ARRAY_SIZE(ldb_ep_path_8mp); i++) {
1141 if (check_remote_endpoint(blob, ldb_ep_path_8mp[i], lcdif_ep_path_8mp[i])) {
1142 /* Disable lcdif node */
1143 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1144 }
1145 }
1146
1147 return 0;
1148}
1149
Peng Fan435dc122020-07-09 14:06:49 +08001150int disable_gpu_nodes(void *blob)
1151{
1152 static const char * const nodes_path_8mn[] = {
Peng Fan7d4195c2021-03-19 15:57:13 +08001153 "/gpu@38000000",
1154 "/soc@/gpu@38000000"
Peng Fan435dc122020-07-09 14:06:49 +08001155 };
1156
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001157 static const char * const nodes_path_8mp[] = {
1158 "/gpu3d@38000000",
1159 "/gpu2d@38008000"
1160 };
1161
1162 if (is_imx8mp())
1163 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1164 else
1165 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
Peng Fan435dc122020-07-09 14:06:49 +08001166}
1167
1168int disable_npu_nodes(void *blob)
1169{
1170 static const char * const nodes_path_8mp[] = {
Vitor Soares6dd07732024-03-15 14:44:25 +00001171 "/vipsi@38500000",
1172 "/soc@0/npu@38500000",
Peng Fan435dc122020-07-09 14:06:49 +08001173 };
1174
1175 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1176}
1177
1178int disable_isp_nodes(void *blob)
1179{
1180 static const char * const nodes_path_8mp[] = {
1181 "/soc@0/bus@32c00000/camera/isp@32e10000",
1182 "/soc@0/bus@32c00000/camera/isp@32e20000"
1183 };
1184
1185 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1186}
1187
1188int disable_dsp_nodes(void *blob)
1189{
1190 static const char * const nodes_path_8mp[] = {
1191 "/dsp@3b6e8000"
1192 };
1193
1194 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1195}
1196
Peng Fana08bc872022-04-07 15:55:54 +08001197static int cleanup_nodes_for_efi(void *blob)
1198{
Peng Fan1585b202022-04-07 15:55:55 +08001199 static const char * const path[][2] = {
1200 { "/soc@0/bus@32c00000/usb@32e40000", "extcon" },
1201 { "/soc@0/bus@32c00000/usb@32e50000", "extcon" },
1202 { "/soc@0/bus@30800000/ethernet@30be0000", "phy-reset-gpios" },
1203 { "/soc@0/bus@30800000/ethernet@30bf0000", "phy-reset-gpios" }
1204 };
Peng Fana08bc872022-04-07 15:55:54 +08001205 int nodeoff, i, rc;
1206
Peng Fan1585b202022-04-07 15:55:55 +08001207 for (i = 0; i < ARRAY_SIZE(path); i++) {
1208 nodeoff = fdt_path_offset(blob, path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001209 if (nodeoff < 0)
1210 continue; /* Not found, skip it */
Peng Fan1585b202022-04-07 15:55:55 +08001211 debug("Found %s node\n", path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001212
Peng Fan1585b202022-04-07 15:55:55 +08001213 rc = fdt_delprop(blob, nodeoff, path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001214 if (rc == -FDT_ERR_NOTFOUND)
1215 continue;
1216 if (rc) {
1217 printf("Unable to update property %s:%s, err=%s\n",
Peng Fan1585b202022-04-07 15:55:55 +08001218 path[i][0], path[i][1], fdt_strerror(rc));
Peng Fana08bc872022-04-07 15:55:54 +08001219 return rc;
1220 }
1221
Peng Fan1585b202022-04-07 15:55:55 +08001222 printf("Remove %s:%s\n", path[i][0], path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001223 }
1224
1225 return 0;
1226}
Peng Fana08bc872022-04-07 15:55:54 +08001227
Tim Harvey709ace82023-08-24 12:05:17 -07001228#define OPTEE_SHM_SIZE 0x00400000
1229static int ft_add_optee_node(void *fdt, struct bd_info *bd)
1230{
1231 struct fdt_memory carveout;
1232 const char *path, *subpath;
1233 phys_addr_t optee_start;
1234 size_t optee_size;
1235 int offs;
1236 int ret;
1237
1238 /*
1239 * No TEE space allocated indicating no TEE running, so no
1240 * need to add optee node in dts
1241 */
1242 if (!rom_pointer[1])
1243 return 0;
1244
1245 optee_start = (phys_addr_t)rom_pointer[0];
1246 optee_size = rom_pointer[1] - OPTEE_SHM_SIZE;
1247
1248 offs = fdt_increase_size(fdt, 512);
1249 if (offs) {
1250 printf("No Space for dtb\n");
1251 return 1;
1252 }
1253
1254 path = "/firmware";
1255 offs = fdt_path_offset(fdt, path);
1256 if (offs < 0) {
1257 path = "/";
1258 offs = fdt_path_offset(fdt, path);
1259
1260 if (offs < 0) {
1261 printf("Could not find root node.\n");
1262 return offs;
1263 }
1264
1265 subpath = "firmware";
1266 offs = fdt_add_subnode(fdt, offs, subpath);
1267 if (offs < 0) {
1268 printf("Could not create %s node.\n", subpath);
1269 return offs;
1270 }
1271 }
1272
1273 subpath = "optee";
1274 offs = fdt_add_subnode(fdt, offs, subpath);
1275 if (offs < 0) {
1276 printf("Could not create %s node.\n", subpath);
1277 return offs;
1278 }
1279
1280 fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz");
1281 fdt_setprop_string(fdt, offs, "method", "smc");
1282
1283 carveout.start = optee_start,
1284 carveout.end = optee_start + optee_size - 1,
1285 ret = fdtdec_add_reserved_memory(fdt, "optee_core", &carveout, NULL, 0,
1286 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1287 if (ret < 0) {
1288 printf("Could not create optee_core node.\n");
1289 return ret;
1290 }
1291
1292 carveout.start = optee_start + optee_size;
1293 carveout.end = optee_start + optee_size + OPTEE_SHM_SIZE - 1;
1294 ret = fdtdec_add_reserved_memory(fdt, "optee_shm", &carveout, NULL, 0,
1295 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1296 if (ret < 0) {
1297 printf("Could not create optee_shm node.\n");
1298 return ret;
1299 }
1300
1301 return 0;
1302}
1303
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001304int ft_system_setup(void *blob, struct bd_info *bd)
Peng Faneae4de22018-01-10 13:20:37 +08001305{
Peng Fan35fdfcf2024-09-19 12:01:31 +08001306 static const char * const nodes_path[] = {
1307 "/cpus/cpu@0",
1308 "/cpus/cpu@1",
1309 "/cpus/cpu@2",
1310 "/cpus/cpu@3",
1311 };
1312
Peng Fan435dc122020-07-09 14:06:49 +08001313#ifdef CONFIG_IMX8MQ
Peng Faneae4de22018-01-10 13:20:37 +08001314 int i = 0;
1315 int rc;
1316 int nodeoff;
1317
Peng Fan435dc122020-07-09 14:06:49 +08001318 if (get_boot_device() == USB_BOOT) {
1319 disable_dcss_nodes(blob);
1320
1321 bool new_path = check_fdt_new_path(blob);
1322 int v = new_path ? 1 : 0;
1323 static const char * const usb_dwc3_path[] = {
1324 "/usb@38100000/dwc3",
1325 "/soc@0/usb@38100000"
1326 };
1327
1328 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1329 if (nodeoff >= 0) {
1330 const char *speed = "high-speed";
1331
Rasmus Villemoes8ab149a2023-05-22 11:27:28 +02001332 debug("Found %s node\n", usb_dwc3_path[v]);
Peng Fan435dc122020-07-09 14:06:49 +08001333
1334usb_modify_speed:
1335
1336 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1337 if (rc) {
1338 if (rc == -FDT_ERR_NOSPACE) {
1339 rc = fdt_increase_size(blob, 512);
1340 if (!rc)
1341 goto usb_modify_speed;
1342 }
1343 printf("Unable to set property %s:%s, err=%s\n",
1344 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1345 } else {
1346 printf("Modify %s:%s = %s\n",
1347 usb_dwc3_path[v], "maximum-speed", speed);
1348 }
1349 } else {
1350 printf("Can't found %s node\n", usb_dwc3_path[v]);
1351 }
1352 }
1353
Peng Faneae4de22018-01-10 13:20:37 +08001354 /* Disable the CPU idle for A0 chip since the HW does not support it */
1355 if (is_soc_rev(CHIP_REV_1_0)) {
Peng Faneae4de22018-01-10 13:20:37 +08001356 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1357 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1358 if (nodeoff < 0)
1359 continue; /* Not found, skip it */
1360
Marek Vasute2e7a772020-04-24 21:37:33 +02001361 debug("Found %s node\n", nodes_path[i]);
Peng Faneae4de22018-01-10 13:20:37 +08001362
1363 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasute2e7a772020-04-24 21:37:33 +02001364 if (rc == -FDT_ERR_NOTFOUND)
1365 continue;
Peng Faneae4de22018-01-10 13:20:37 +08001366 if (rc) {
1367 printf("Unable to update property %s:%s, err=%s\n",
1368 nodes_path[i], "status", fdt_strerror(rc));
1369 return rc;
1370 }
1371
Marek Vasute2e7a772020-04-24 21:37:33 +02001372 debug("Remove %s:%s\n", nodes_path[i],
Peng Faneae4de22018-01-10 13:20:37 +08001373 "cpu-idle-states");
1374 }
1375 }
1376
Peng Fan435dc122020-07-09 14:06:49 +08001377 if (is_imx8mql()) {
1378 disable_vpu_nodes(blob);
1379 if (check_dcss_fused()) {
1380 printf("DCSS is fused\n");
1381 disable_dcss_nodes(blob);
1382 check_mipi_dsi_nodes(blob);
1383 }
1384 }
1385
1386 if (is_imx8md())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001387 disable_cpu_nodes(blob, nodes_path, 2, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001388
1389#elif defined(CONFIG_IMX8MM)
1390 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1391 disable_vpu_nodes(blob);
1392
1393 if (is_imx8mmd() || is_imx8mmdl())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001394 disable_cpu_nodes(blob, nodes_path, 2, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001395 else if (is_imx8mms() || is_imx8mmsl())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001396 disable_cpu_nodes(blob, nodes_path, 3, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001397
1398#elif defined(CONFIG_IMX8MN)
1399 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1400 disable_gpu_nodes(blob);
Ye Liee337ce2021-03-19 15:57:09 +08001401#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1402 else {
1403 int ldm_gpu = low_drive_gpu_freq(blob);
1404
1405 if (ldm_gpu < 0)
1406 printf("Update GPU node assigned-clock-rates failed\n");
1407 else
1408 printf("Update GPU node assigned-clock-rates ok\n");
1409 }
1410#endif
Peng Fan435dc122020-07-09 14:06:49 +08001411
Ye Li715180e2021-03-19 15:57:11 +08001412 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001413 disable_cpu_nodes(blob, nodes_path, 2, 4);
Ye Li715180e2021-03-19 15:57:11 +08001414 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001415 disable_cpu_nodes(blob, nodes_path, 3, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001416
1417#elif defined(CONFIG_IMX8MP)
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001418 if (is_imx8mpul()) {
1419 /* Disable GPU */
1420 disable_gpu_nodes(blob);
1421
1422 /* Disable DSI */
1423 disable_dsi_lcdif_nodes(blob);
1424
1425 /* Disable LVDS */
1426 disable_lvds_lcdif_nodes(blob);
1427 }
1428
1429 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001430 disable_vpu_nodes(blob);
1431
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001432 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001433 disable_npu_nodes(blob);
1434
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001435 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001436 disable_isp_nodes(blob);
1437
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001438 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001439 disable_dsp_nodes(blob);
1440
1441 if (is_imx8mpd())
Peng Fan35fdfcf2024-09-19 12:01:31 +08001442 disable_cpu_nodes(blob, nodes_path, 2, 4);
Peng Fan435dc122020-07-09 14:06:49 +08001443#endif
1444
Peng Fan1585b202022-04-07 15:55:55 +08001445 cleanup_nodes_for_efi(blob);
Andrejs Cainikovs2f3491c2022-05-27 15:20:42 +02001446
1447 if (fixup_thermal_trips(blob, "cpu-thermal"))
1448 printf("Failed to update cpu-thermal trip(s)");
1449 if (IS_ENABLED(CONFIG_IMX8MP) &&
1450 fixup_thermal_trips(blob, "soc-thermal"))
1451 printf("Failed to update soc-thermal trip(s)");
1452
Tim Harvey709ace82023-08-24 12:05:17 -07001453 return ft_add_optee_node(blob, bd);
Peng Faneae4de22018-01-10 13:20:37 +08001454}
1455#endif
1456
Marek Vasut64dc4de2020-04-29 15:04:21 +02001457#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler6f14d5f2020-12-15 16:47:52 +01001458void reset_cpu(void)
Peng Faneae4de22018-01-10 13:20:37 +08001459{
Claudius Heinee73f3942020-04-29 15:04:23 +02001460 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Faneae4de22018-01-10 13:20:37 +08001461
Ye Li54a915a2019-12-09 00:47:18 -08001462 /* Clear WDA to trigger WDOG_B immediately */
1463 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fan24290d92019-08-27 06:25:41 +00001464
Ye Li54a915a2019-12-09 00:47:18 -08001465 while (1) {
1466 /*
Harald Seilerec0c4472020-04-29 15:04:22 +02001467 * spin for .5 seconds before reset
Ye Li54a915a2019-12-09 00:47:18 -08001468 */
1469 }
Peng Faneae4de22018-01-10 13:20:37 +08001470}
Peng Fan24290d92019-08-27 06:25:41 +00001471#endif
Peng Fan5760d8d2020-04-22 10:51:13 +08001472
1473#if defined(CONFIG_ARCH_MISC_INIT)
Peng Fan5760d8d2020-04-22 10:51:13 +08001474int arch_misc_init(void)
1475{
Gaurav Jain81113a02022-03-24 11:50:27 +05301476 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1477 struct udevice *dev;
1478 int ret;
1479
1480 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1481 if (ret)
Ye Liec346892022-05-11 13:56:20 +05301482 printf("Failed to initialize caam_jr: %d\n", ret);
Gaurav Jain81113a02022-03-24 11:50:27 +05301483 }
Peng Fan5760d8d2020-04-22 10:51:13 +08001484
1485 return 0;
1486}
1487#endif
Ye Li325cd012020-05-03 22:19:52 +08001488
Simon Glass85ed77d2024-09-29 19:49:46 -06001489#if defined(CONFIG_XPL_BUILD)
Peng Fana35215d2020-07-09 13:39:26 +08001490#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1491bool serror_need_skip = true;
1492
Sean Anderson2d755492022-03-22 17:17:35 -04001493void do_error(struct pt_regs *pt_regs)
Peng Fana35215d2020-07-09 13:39:26 +08001494{
1495 /*
1496 * If stack is still in ROM reserved OCRAM not switch to SPL,
1497 * it is the ROM SError
1498 */
1499 ulong sp;
1500
1501 asm volatile("mov %0, sp" : "=r"(sp) : );
1502
1503 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1504 /* Check for ERR050342, imx8mq HDCP enabled parts */
1505 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1506 serror_need_skip = false;
1507 return; /* Do nothing skip the SError in ROM */
1508 }
1509
1510 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1511 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1512 serror_need_skip = false;
1513 return; /* Do nothing skip the SError in ROM */
1514 }
1515 }
1516
1517 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -04001518 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fana35215d2020-07-09 13:39:26 +08001519 show_regs(pt_regs);
1520 panic("Resetting CPU ...\n");
1521}
1522#endif
1523#endif
Ye Li0513f362019-07-15 01:16:46 -07001524
1525#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
Marek Vasut765b5802022-04-06 02:21:34 +02001526enum env_location arch_env_get_location(enum env_operation op, int prio)
Ye Li0513f362019-07-15 01:16:46 -07001527{
1528 enum boot_device dev = get_boot_device();
Ye Li0513f362019-07-15 01:16:46 -07001529
1530 if (prio)
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001531 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001532
1533 switch (dev) {
Fabio Estevam9be6daf2022-04-21 15:05:23 -03001534 case USB_BOOT:
1535 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1536 return ENVL_SPI_FLASH;
1537 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1538 return ENVL_NAND;
1539 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1540 return ENVL_MMC;
1541 if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
1542 return ENVL_NOWHERE;
1543 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001544 case QSPI_BOOT:
Marek Vasut31b3bc42022-03-25 18:59:28 +01001545 case SPI_NOR_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001546 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1547 return ENVL_SPI_FLASH;
1548 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001549 case NAND_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001550 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1551 return ENVL_NAND;
1552 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001553 case SD1_BOOT:
1554 case SD2_BOOT:
1555 case SD3_BOOT:
1556 case MMC1_BOOT:
1557 case MMC2_BOOT:
1558 case MMC3_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001559 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1560 return ENVL_MMC;
1561 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1562 return ENVL_EXT4;
1563 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1564 return ENVL_FAT;
1565 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001566 default:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001567 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001568 }
Ye Li0513f362019-07-15 01:16:46 -07001569}
1570
Ye Li0513f362019-07-15 01:16:46 -07001571#endif
Peng Fanf19e0e52022-04-29 16:03:14 +08001572
1573#ifdef CONFIG_IMX_BOOTAUX
1574const struct rproc_att hostmap[] = {
1575 /* aux core , host core, size */
1576 { 0x00000000, 0x007e0000, 0x00020000 },
1577 /* OCRAM_S */
1578 { 0x00180000, 0x00180000, 0x00008000 },
1579 /* OCRAM */
1580 { 0x00900000, 0x00900000, 0x00020000 },
1581 /* OCRAM */
1582 { 0x00920000, 0x00920000, 0x00020000 },
1583 /* QSPI Code - alias */
1584 { 0x08000000, 0x08000000, 0x08000000 },
1585 /* DDR (Code) - alias */
1586 { 0x10000000, 0x80000000, 0x0FFE0000 },
1587 /* TCML */
1588 { 0x1FFE0000, 0x007E0000, 0x00040000 },
1589 /* OCRAM_S */
1590 { 0x20180000, 0x00180000, 0x00008000 },
1591 /* OCRAM */
1592 { 0x20200000, 0x00900000, 0x00040000 },
1593 /* DDR (Data) */
1594 { 0x40000000, 0x40000000, 0x80000000 },
1595 { /* sentinel */ }
1596};
Marek Vasutddc59352022-12-13 05:46:07 +01001597
1598const struct rproc_att *imx_bootaux_get_hostmap(void)
1599{
1600 return hostmap;
1601}
Peng Fanf19e0e52022-04-29 16:03:14 +08001602#endif