blob: 805e1a6fb7e847b751bec2aca410a4c219495957 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Peng Faneae4de22018-01-10 13:20:37 +08002/*
Gaurav Jain81113a02022-03-24 11:50:27 +05303 * Copyright 2017-2019, 2021 NXP
Peng Faneae4de22018-01-10 13:20:37 +08004 *
5 * Peng Fan <peng.fan@nxp.com>
Peng Faneae4de22018-01-10 13:20:37 +08006 */
7
8#include <common.h>
Simon Glass1d91ba72019-11-14 12:57:37 -07009#include <cpu_func.h>
Simon Glassfc557362022-03-04 08:43:05 -070010#include <event.h>
Simon Glass97589732020-05-10 11:40:02 -060011#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Peng Faneae4de22018-01-10 13:20:37 +080013#include <asm/arch/imx-regs.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060014#include <asm/global_data.h>
Peng Faneae4de22018-01-10 13:20:37 +080015#include <asm/io.h>
16#include <asm/arch/clock.h>
17#include <asm/arch/sys_proto.h>
18#include <asm/mach-imx/hab.h>
19#include <asm/mach-imx/boot_mode.h>
20#include <asm/mach-imx/syscounter.h>
Peng Fana35215d2020-07-09 13:39:26 +080021#include <asm/ptrace.h>
Peng Faneae4de22018-01-10 13:20:37 +080022#include <asm/armv8/mmu.h>
Peng Fanc98e0322019-08-27 06:25:58 +000023#include <dm/uclass.h>
Gaurav Jain81113a02022-03-24 11:50:27 +053024#include <dm/device.h>
Peng Fana35215d2020-07-09 13:39:26 +080025#include <efi_loader.h>
Ye Li0513f362019-07-15 01:16:46 -070026#include <env.h>
27#include <env_internal.h>
Peng Faneae4de22018-01-10 13:20:37 +080028#include <errno.h>
29#include <fdt_support.h>
30#include <fsl_wdog.h>
31#include <imx_sip.h>
Peng Fan45d843a2020-05-11 15:14:04 +080032#include <linux/arm-smccc.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060033#include <linux/bitops.h>
Peng Faneae4de22018-01-10 13:20:37 +080034
35DECLARE_GLOBAL_DATA_PTR;
36
Stefano Babicf8b509b2019-09-20 08:47:53 +020037#if defined(CONFIG_IMX_HAB)
Peng Faneae4de22018-01-10 13:20:37 +080038struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
39 .bank = 1,
40 .word = 3,
41};
42#endif
43
44int timer_init(void)
45{
46#ifdef CONFIG_SPL_BUILD
47 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
48 unsigned long freq = readl(&sctr->cntfid0);
49
50 /* Update with accurate clock frequency */
51 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
52
53 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
54 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
55#endif
56
57 gd->arch.tbl = 0;
58 gd->arch.tbu = 0;
59
60 return 0;
61}
62
63void enable_tzc380(void)
64{
65 struct iomuxc_gpr_base_regs *gpr =
66 (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
67
68 /* Enable TZASC and lock setting */
69 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN);
70 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010071
72 /*
73 * According to TRM, TZASC_ID_SWAP_BYPASS should be set in
74 * order to avoid AXI Bus errors when GPU is in use
75 */
Peng Fanc0e47fc2019-12-27 10:19:42 +080076 if (is_imx8mm() || is_imx8mn() || is_imx8mp())
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010077 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS);
78
79 /*
80 * imx8mn and imx8mp implements the lock bit for
81 * TZASC_ID_SWAP_BYPASS, enable it to lock settings
82 */
83 if (is_imx8mn() || is_imx8mp())
84 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS_LOCK);
85
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
106static struct mm_region imx8m_mem_map[] = {
107 {
108 /* ROM */
109 .virt = 0x0UL,
110 .phys = 0x0UL,
111 .size = 0x100000UL,
112 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
113 PTE_BLOCK_OUTER_SHARE
114 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100115 /* CAAM */
116 .virt = 0x100000UL,
117 .phys = 0x100000UL,
118 .size = 0x8000UL,
119 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
120 PTE_BLOCK_NON_SHARE |
121 PTE_BLOCK_PXN | PTE_BLOCK_UXN
122 }, {
Marek Vasutb1738e02021-02-25 21:52:26 +0100123 /* OCRAM_S */
124 .virt = 0x180000UL,
125 .phys = 0x180000UL,
126 .size = 0x8000UL,
127 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
128 PTE_BLOCK_OUTER_SHARE
129 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100130 /* TCM */
131 .virt = 0x7C0000UL,
132 .phys = 0x7C0000UL,
133 .size = 0x80000UL,
134 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
135 PTE_BLOCK_NON_SHARE |
136 PTE_BLOCK_PXN | PTE_BLOCK_UXN
137 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800138 /* OCRAM */
139 .virt = 0x900000UL,
140 .phys = 0x900000UL,
141 .size = 0x200000UL,
142 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
143 PTE_BLOCK_OUTER_SHARE
144 }, {
145 /* AIPS */
146 .virt = 0xB00000UL,
147 .phys = 0xB00000UL,
148 .size = 0x3f500000UL,
149 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
150 PTE_BLOCK_NON_SHARE |
151 PTE_BLOCK_PXN | PTE_BLOCK_UXN
152 }, {
153 /* DRAM1 */
154 .virt = 0x40000000UL,
155 .phys = 0x40000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000156 .size = PHYS_SDRAM_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800157 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
158 PTE_BLOCK_OUTER_SHARE
Peng Fanb749b5e2019-08-27 06:25:27 +0000159#ifdef PHYS_SDRAM_2_SIZE
Peng Faneae4de22018-01-10 13:20:37 +0800160 }, {
161 /* DRAM2 */
162 .virt = 0x100000000UL,
163 .phys = 0x100000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000164 .size = PHYS_SDRAM_2_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800165 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
166 PTE_BLOCK_OUTER_SHARE
Peng Fanb749b5e2019-08-27 06:25:27 +0000167#endif
Peng Faneae4de22018-01-10 13:20:37 +0800168 }, {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800169 /* empty entrie to split table entry 5 if needed when TEEs are used */
170 0,
171 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800172 /* List terminator */
173 0,
174 }
175};
176
177struct mm_region *mem_map = imx8m_mem_map;
178
Marek Vasute48aac02021-02-27 14:59:00 +0100179static unsigned int imx8m_find_dram_entry_in_mem_map(void)
180{
181 int i;
182
183 for (i = 0; i < ARRAY_SIZE(imx8m_mem_map); i++)
184 if (imx8m_mem_map[i].phys == CONFIG_SYS_SDRAM_BASE)
185 return i;
186
187 hang(); /* Entry not found, this must never happen. */
188}
189
Peng Fanb749b5e2019-08-27 06:25:27 +0000190void enable_caches(void)
191{
Peng Fanfa35c3d2020-07-09 15:26:06 +0800192 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch */
193 if (rom_pointer[1]) {
194 /*
195 * TEE are loaded, So the ddr bank structures
196 * have been modified update mmu table accordingly
197 */
198 int i = 0;
199 /*
200 * please make sure that entry initial value matches
201 * imx8m_mem_map for DRAM1
202 */
Marek Vasute48aac02021-02-27 14:59:00 +0100203 int entry = imx8m_find_dram_entry_in_mem_map();
Peng Fanfa35c3d2020-07-09 15:26:06 +0800204 u64 attrs = imx8m_mem_map[entry].attrs;
205
Marek Vasute48aac02021-02-27 14:59:00 +0100206 while (i < CONFIG_NR_DRAM_BANKS &&
207 entry < ARRAY_SIZE(imx8m_mem_map)) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800208 if (gd->bd->bi_dram[i].start == 0)
209 break;
210 imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start;
211 imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start;
212 imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size;
213 imx8m_mem_map[entry].attrs = attrs;
214 debug("Added memory mapping (%d): %llx %llx\n", entry,
215 imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size);
216 i++; entry++;
217 }
218 }
Peng Fanb749b5e2019-08-27 06:25:27 +0000219
220 icache_enable();
221 dcache_enable();
222}
223
Peng Fanfa35c3d2020-07-09 15:26:06 +0800224__weak int board_phys_sdram_size(phys_size_t *size)
225{
226 if (!size)
227 return -EINVAL;
228
229 *size = PHYS_SDRAM_SIZE;
230 return 0;
231}
232
233int dram_init(void)
234{
Marek Vasute48aac02021-02-27 14:59:00 +0100235 unsigned int entry = imx8m_find_dram_entry_in_mem_map();
Peng Fanfa35c3d2020-07-09 15:26:06 +0800236 phys_size_t sdram_size;
237 int ret;
238
239 ret = board_phys_sdram_size(&sdram_size);
240 if (ret)
241 return ret;
242
243 /* rom_pointer[1] contains the size of TEE occupies */
244 if (rom_pointer[1])
245 gd->ram_size = sdram_size - rom_pointer[1];
246 else
247 gd->ram_size = sdram_size;
248
Tim Harvey32927bc2020-09-25 08:08:35 -0700249 /* also update the SDRAM size in the mem_map used externally */
Marek Vasute48aac02021-02-27 14:59:00 +0100250 imx8m_mem_map[entry].size = sdram_size;
Tim Harvey32927bc2020-09-25 08:08:35 -0700251
Peng Fanfa35c3d2020-07-09 15:26:06 +0800252#ifdef PHYS_SDRAM_2_SIZE
253 gd->ram_size += PHYS_SDRAM_2_SIZE;
254#endif
255
256 return 0;
257}
258
259int dram_init_banksize(void)
260{
261 int bank = 0;
262 int ret;
263 phys_size_t sdram_size;
264
265 ret = board_phys_sdram_size(&sdram_size);
266 if (ret)
267 return ret;
268
269 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
270 if (rom_pointer[1]) {
271 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
272 phys_size_t optee_size = (size_t)rom_pointer[1];
273
274 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
275 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_size)) {
276 if (++bank >= CONFIG_NR_DRAM_BANKS) {
277 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
278 return -1;
279 }
280
281 gd->bd->bi_dram[bank].start = optee_start + optee_size;
282 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
283 sdram_size - gd->bd->bi_dram[bank].start;
284 }
285 } else {
286 gd->bd->bi_dram[bank].size = sdram_size;
287 }
288
289#ifdef PHYS_SDRAM_2_SIZE
290 if (++bank >= CONFIG_NR_DRAM_BANKS) {
291 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
292 return -1;
293 }
294 gd->bd->bi_dram[bank].start = PHYS_SDRAM_2;
295 gd->bd->bi_dram[bank].size = PHYS_SDRAM_2_SIZE;
296#endif
297
298 return 0;
299}
300
301phys_size_t get_effective_memsize(void)
302{
303 /* return the first bank as effective memory */
304 if (rom_pointer[1])
305 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
306
307#ifdef PHYS_SDRAM_2_SIZE
308 return gd->ram_size - PHYS_SDRAM_2_SIZE;
309#else
310 return gd->ram_size;
311#endif
312}
313
Frieder Schrempf159879e2021-06-07 14:36:44 +0200314ulong board_get_usable_ram_top(ulong total_size)
315{
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800316 ulong top_addr = PHYS_SDRAM + gd->ram_size;
317
Frieder Schrempf159879e2021-06-07 14:36:44 +0200318 /*
319 * Some IPs have their accessible address space restricted by
320 * the interconnect. Let's make sure U-Boot only ever uses the
321 * space below the 4G address boundary (which is 3GiB big),
322 * even when the effective available memory is bigger.
323 */
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800324 if (top_addr > 0x80000000)
325 top_addr = 0x80000000;
326
327 /*
328 * rom_pointer[0] stores the TEE memory start address.
329 * rom_pointer[1] stores the size TEE uses.
330 * We need to reserve the memory region for TEE.
331 */
332 if (rom_pointer[0] && rom_pointer[1] && top_addr > rom_pointer[0])
333 top_addr = rom_pointer[0];
Frieder Schrempf159879e2021-06-07 14:36:44 +0200334
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800335 return top_addr;
Frieder Schrempf159879e2021-06-07 14:36:44 +0200336}
337
Peng Fan1caffdf2019-08-27 06:25:17 +0000338static u32 get_cpu_variant_type(u32 type)
339{
340 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
341 struct fuse_bank *bank = &ocotp->bank[1];
342 struct fuse_bank1_regs *fuse =
343 (struct fuse_bank1_regs *)bank->fuse_regs;
344
345 u32 value = readl(&fuse->tester4);
346
Peng Fan67815082020-02-05 17:34:54 +0800347 if (type == MXC_CPU_IMX8MQ) {
348 if ((value & 0x3) == 0x2)
349 return MXC_CPU_IMX8MD;
350 else if (value & 0x200000)
351 return MXC_CPU_IMX8MQL;
352
353 } else if (type == MXC_CPU_IMX8MM) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000354 switch (value & 0x3) {
355 case 2:
356 if (value & 0x1c0000)
357 return MXC_CPU_IMX8MMDL;
358 else
359 return MXC_CPU_IMX8MMD;
360 case 3:
361 if (value & 0x1c0000)
362 return MXC_CPU_IMX8MMSL;
363 else
364 return MXC_CPU_IMX8MMS;
365 default:
366 if (value & 0x1c0000)
367 return MXC_CPU_IMX8MML;
368 break;
369 }
Peng Fan1a07d912020-02-05 17:39:27 +0800370 } else if (type == MXC_CPU_IMX8MN) {
371 switch (value & 0x3) {
372 case 2:
Ye Li715180e2021-03-19 15:57:11 +0800373 if (value & 0x1000000) {
374 if (value & 0x10000000) /* MIPI DSI */
375 return MXC_CPU_IMX8MNUD;
376 else
377 return MXC_CPU_IMX8MNDL;
378 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800379 return MXC_CPU_IMX8MND;
Ye Li715180e2021-03-19 15:57:11 +0800380 }
Peng Fan1a07d912020-02-05 17:39:27 +0800381 case 3:
Ye Li715180e2021-03-19 15:57:11 +0800382 if (value & 0x1000000) {
383 if (value & 0x10000000) /* MIPI DSI */
384 return MXC_CPU_IMX8MNUS;
385 else
386 return MXC_CPU_IMX8MNSL;
387 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800388 return MXC_CPU_IMX8MNS;
Ye Li715180e2021-03-19 15:57:11 +0800389 }
Peng Fan1a07d912020-02-05 17:39:27 +0800390 default:
Ye Li715180e2021-03-19 15:57:11 +0800391 if (value & 0x1000000) {
392 if (value & 0x10000000) /* MIPI DSI */
393 return MXC_CPU_IMX8MNUQ;
394 else
395 return MXC_CPU_IMX8MNL;
396 }
Peng Fan1a07d912020-02-05 17:39:27 +0800397 break;
398 }
Ye Lid2d754f2020-04-20 20:12:54 -0700399 } else if (type == MXC_CPU_IMX8MP) {
400 u32 value0 = readl(&fuse->tester3);
401 u32 flag = 0;
402
403 if ((value0 & 0xc0000) == 0x80000)
404 return MXC_CPU_IMX8MPD;
405
406 /* vpu disabled */
407 if ((value0 & 0x43000000) == 0x43000000)
408 flag = 1;
409
410 /* npu disabled*/
411 if ((value & 0x8) == 0x8)
412 flag |= (1 << 1);
413
414 /* isp disabled */
415 if ((value & 0x3) == 0x3)
416 flag |= (1 << 2);
417
418 switch (flag) {
419 case 7:
420 return MXC_CPU_IMX8MPL;
Ye Lid2d754f2020-04-20 20:12:54 -0700421 case 2:
422 return MXC_CPU_IMX8MP6;
Ye Lid2d754f2020-04-20 20:12:54 -0700423 default:
424 break;
425 }
426
Peng Fan1caffdf2019-08-27 06:25:17 +0000427 }
428
429 return type;
430}
431
Peng Faneae4de22018-01-10 13:20:37 +0800432u32 get_cpu_rev(void)
433{
434 struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
435 u32 reg = readl(&ana_pll->digprog);
436 u32 type = (reg >> 16) & 0xff;
Peng Fan1caffdf2019-08-27 06:25:17 +0000437 u32 major_low = (reg >> 8) & 0xff;
Peng Faneae4de22018-01-10 13:20:37 +0800438 u32 rom_version;
439
440 reg &= 0xff;
441
Peng Fan69cec072019-12-27 10:14:02 +0800442 /* iMX8MP */
443 if (major_low == 0x43) {
Ye Lid2d754f2020-04-20 20:12:54 -0700444 type = get_cpu_variant_type(MXC_CPU_IMX8MP);
Peng Fan69cec072019-12-27 10:14:02 +0800445 } else if (major_low == 0x42) {
446 /* iMX8MN */
Peng Fan1a07d912020-02-05 17:39:27 +0800447 type = get_cpu_variant_type(MXC_CPU_IMX8MN);
Peng Fan5d2f2062019-06-27 17:23:49 +0800448 } else if (major_low == 0x41) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000449 type = get_cpu_variant_type(MXC_CPU_IMX8MM);
450 } else {
451 if (reg == CHIP_REV_1_0) {
452 /*
Peng Fanc23fbdd2019-10-16 10:24:17 +0000453 * For B0 chip, the DIGPROG is not updated,
454 * it is still TO1.0. we have to check ROM
455 * version or OCOTP_READ_FUSE_DATA.
456 * 0xff0055aa is magic number for B1.
Peng Fan1caffdf2019-08-27 06:25:17 +0000457 */
Peng Fanc23fbdd2019-10-16 10:24:17 +0000458 if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
Ye Lic963ed12021-03-19 15:57:16 +0800459 /*
460 * B2 uses same DIGPROG and OCOTP_READ_FUSE_DATA value with B1,
461 * so have to check ROM to distinguish them
462 */
463 rom_version = readl((void __iomem *)ROM_VERSION_B0);
464 rom_version &= 0xff;
465 if (rom_version == CHIP_REV_2_2)
466 reg = CHIP_REV_2_2;
467 else
468 reg = CHIP_REV_2_1;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000469 } else {
470 rom_version =
471 readl((void __iomem *)ROM_VERSION_A0);
472 if (rom_version != CHIP_REV_1_0) {
473 rom_version = readl((void __iomem *)ROM_VERSION_B0);
Patrick Wildtd4a78b92019-11-19 09:42:06 +0100474 rom_version &= 0xff;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000475 if (rom_version == CHIP_REV_2_0)
476 reg = CHIP_REV_2_0;
477 }
Peng Fan1caffdf2019-08-27 06:25:17 +0000478 }
Peng Faneae4de22018-01-10 13:20:37 +0800479 }
Peng Fan67815082020-02-05 17:34:54 +0800480
481 type = get_cpu_variant_type(type);
Peng Faneae4de22018-01-10 13:20:37 +0800482 }
483
484 return (type << 12) | reg;
485}
486
487static void imx_set_wdog_powerdown(bool enable)
488{
489 struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
490 struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
491 struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
492
493 /* Write to the PDE (Power Down Enable) bit */
494 writew(enable, &wdog1->wmcr);
495 writew(enable, &wdog2->wmcr);
496 writew(enable, &wdog3->wmcr);
497}
498
Simon Glassfc557362022-03-04 08:43:05 -0700499static int imx8m_check_clock(void *ctx, struct event *event)
Peng Fanc98e0322019-08-27 06:25:58 +0000500{
501 struct udevice *dev;
502 int ret;
503
Peng Fan3c073342019-10-16 03:01:51 +0000504 if (CONFIG_IS_ENABLED(CLK)) {
505 ret = uclass_get_device_by_name(UCLASS_CLK,
506 "clock-controller@30380000",
507 &dev);
508 if (ret < 0) {
509 printf("Failed to find clock node. Check device tree\n");
510 return ret;
511 }
Peng Fanc98e0322019-08-27 06:25:58 +0000512 }
513
514 return 0;
515}
Simon Glassfc557362022-03-04 08:43:05 -0700516EVENT_SPY(EVT_DM_POST_INIT, imx8m_check_clock);
Peng Fanc98e0322019-08-27 06:25:58 +0000517
Peng Faneae4de22018-01-10 13:20:37 +0800518int arch_cpu_init(void)
519{
Peng Fanc0b30d72019-04-17 09:41:16 +0000520 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
Peng Faneae4de22018-01-10 13:20:37 +0800521 /*
Peng Fand0ca2892019-08-27 06:25:37 +0000522 * ROM might disable clock for SCTR,
523 * enable the clock before timer_init.
524 */
525 if (IS_ENABLED(CONFIG_SPL_BUILD))
526 clock_enable(CCGR_SCTR, 1);
527 /*
Peng Faneae4de22018-01-10 13:20:37 +0800528 * Init timer at very early state, because sscg pll setting
529 * will use it
530 */
531 timer_init();
532
533 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
534 clock_init();
535 imx_set_wdog_powerdown(false);
Peng Fan9cf2aa32020-07-09 13:52:41 +0800536
537 if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
538 is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
Ye Li715180e2021-03-19 15:57:11 +0800539 is_imx8mnsl() || is_imx8mpd() || is_imx8mnud() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800540 /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
541 struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
542 struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
543 struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0);
544 struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR;
545
546 writel(0x1, &pgc_core2->pgcr);
547 writel(0x1, &pgc_core3->pgcr);
Ye Li715180e2021-03-19 15:57:11 +0800548 if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800549 writel(0x1, &pgc_core1->pgcr);
550 writel(0xE, &gpc->cpu_pgc_dn_trg);
551 } else {
552 writel(0xC, &gpc->cpu_pgc_dn_trg);
553 }
554 }
Peng Faneae4de22018-01-10 13:20:37 +0800555 }
556
Peng Fanc0b30d72019-04-17 09:41:16 +0000557 if (is_imx8mq()) {
558 clock_enable(CCGR_OCOTP, 1);
559 if (readl(&ocotp->ctrl) & 0x200)
560 writel(0x200, &ocotp->ctrl_clr);
561 }
562
Peng Faneae4de22018-01-10 13:20:37 +0800563 return 0;
564}
565
Peng Fanc9823b02019-09-16 03:09:36 +0000566#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
567struct rom_api *g_rom_api = (struct rom_api *)0x980;
568
569enum boot_device get_boot_device(void)
570{
571 volatile gd_t *pgd = gd;
572 int ret;
573 u32 boot;
574 u16 boot_type;
575 u8 boot_instance;
576 enum boot_device boot_dev = SD1_BOOT;
577
578 ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
579 ((uintptr_t)&boot) ^ QUERY_BT_DEV);
Marek Behúna8cf1552021-05-20 13:24:10 +0200580 set_gd(pgd);
Peng Fanc9823b02019-09-16 03:09:36 +0000581
582 if (ret != ROM_API_OKAY) {
583 puts("ROMAPI: failure at query_boot_info\n");
584 return -1;
585 }
586
587 boot_type = boot >> 16;
588 boot_instance = (boot >> 8) & 0xff;
589
590 switch (boot_type) {
591 case BT_DEV_TYPE_SD:
592 boot_dev = boot_instance + SD1_BOOT;
593 break;
594 case BT_DEV_TYPE_MMC:
595 boot_dev = boot_instance + MMC1_BOOT;
596 break;
597 case BT_DEV_TYPE_NAND:
598 boot_dev = NAND_BOOT;
599 break;
600 case BT_DEV_TYPE_FLEXSPINOR:
601 boot_dev = QSPI_BOOT;
602 break;
Marek Vasut31b3bc42022-03-25 18:59:28 +0100603 case BT_DEV_TYPE_SPI_NOR:
604 boot_dev = SPI_NOR_BOOT;
605 break;
Peng Fanc9823b02019-09-16 03:09:36 +0000606 case BT_DEV_TYPE_USB:
607 boot_dev = USB_BOOT;
608 break;
609 default:
610 break;
611 }
612
613 return boot_dev;
614}
615#endif
616
Marek Vasut520ded02021-07-03 04:55:33 +0200617#if defined(CONFIG_IMX8M)
618#include <spl.h>
619int spl_mmc_emmc_boot_partition(struct mmc *mmc)
620{
621 u32 *rom_log_addr = (u32 *)0x9e0;
622 u32 *rom_log;
623 u8 event_id;
624 int i, part;
625
626 part = default_spl_mmc_emmc_boot_partition(mmc);
627
628 /* If the ROM event log pointer is not valid. */
629 if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 ||
630 *rom_log_addr & 0x3)
631 return part;
632
633 /* Parse the ROM event ID version 2 log */
634 rom_log = (u32 *)(uintptr_t)(*rom_log_addr);
635 for (i = 0; i < 128; i++) {
636 event_id = rom_log[i] >> 24;
637 switch (event_id) {
638 case 0x00: /* End of list */
639 return part;
640 /* Log entries with 1 parameter, skip 1 */
641 case 0x80: /* Start to perform the device initialization */
642 case 0x81: /* The boot device initialization completes */
643 case 0x8f: /* The boot device initialization fails */
644 case 0x90: /* Start to read data from boot device */
645 case 0x91: /* Reading data from boot device completes */
646 case 0x9f: /* Reading data from boot device fails */
647 i += 1;
648 continue;
649 /* Log entries with 2 parameters, skip 2 */
650 case 0xa0: /* Image authentication result */
651 case 0xc0: /* Jump to the boot image soon */
652 i += 2;
653 continue;
654 /* Boot from the secondary boot image */
655 case 0x51:
656 /*
657 * Swap the eMMC boot partitions in case there was a
658 * fallback event (i.e. primary image was corrupted
659 * and that corruption was recognized by the BootROM),
660 * so the SPL loads the rest of the U-Boot from the
661 * correct eMMC boot partition, since the BootROM
662 * leaves the boot partition set to the corrupted one.
663 */
664 if (part == 1)
665 part = 2;
666 else if (part == 2)
667 part = 1;
668 continue;
669 default:
670 continue;
671 }
672 }
673
674 return part;
675}
676#endif
677
Peng Faneae4de22018-01-10 13:20:37 +0800678bool is_usb_boot(void)
679{
680 return get_boot_device() == USB_BOOT;
681}
682
683#ifdef CONFIG_OF_SYSTEM_SETUP
Peng Fan435dc122020-07-09 14:06:49 +0800684bool check_fdt_new_path(void *blob)
685{
686 const char *soc_path = "/soc@0";
687 int nodeoff;
688
689 nodeoff = fdt_path_offset(blob, soc_path);
690 if (nodeoff < 0)
691 return false;
692
693 return true;
694}
695
696static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
697{
698 int i = 0;
699 int rc;
700 int nodeoff;
701 const char *status = "disabled";
702
703 for (i = 0; i < size_array; i++) {
704 nodeoff = fdt_path_offset(blob, nodes_path[i]);
705 if (nodeoff < 0)
706 continue; /* Not found, skip it */
707
708 printf("Found %s node\n", nodes_path[i]);
709
710add_status:
711 rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
712 if (rc) {
713 if (rc == -FDT_ERR_NOSPACE) {
714 rc = fdt_increase_size(blob, 512);
715 if (!rc)
716 goto add_status;
717 }
718 printf("Unable to update property %s:%s, err=%s\n",
719 nodes_path[i], "status", fdt_strerror(rc));
720 } else {
721 printf("Modify %s:%s disabled\n",
722 nodes_path[i], "status");
723 }
724 }
725
726 return 0;
727}
728
729#ifdef CONFIG_IMX8MQ
730bool check_dcss_fused(void)
731{
732 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
733 struct fuse_bank *bank = &ocotp->bank[1];
734 struct fuse_bank1_regs *fuse =
735 (struct fuse_bank1_regs *)bank->fuse_regs;
736 u32 value = readl(&fuse->tester4);
737
738 if (value & 0x4000000)
739 return true;
740
741 return false;
742}
743
744static int disable_mipi_dsi_nodes(void *blob)
745{
746 static const char * const nodes_path[] = {
747 "/mipi_dsi@30A00000",
748 "/mipi_dsi_bridge@30A00000",
749 "/dsi_phy@30A00300",
750 "/soc@0/bus@30800000/mipi_dsi@30a00000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800751 "/soc@0/bus@30800000/dphy@30a00300",
752 "/soc@0/bus@30800000/mipi-dsi@30a00000",
Peng Fan435dc122020-07-09 14:06:49 +0800753 };
754
755 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
756}
757
758static int disable_dcss_nodes(void *blob)
759{
760 static const char * const nodes_path[] = {
761 "/dcss@0x32e00000",
762 "/dcss@32e00000",
763 "/hdmi@32c00000",
764 "/hdmi_cec@32c33800",
765 "/hdmi_drm@32c00000",
766 "/display-subsystem",
767 "/sound-hdmi",
768 "/sound-hdmi-arc",
769 "/soc@0/bus@32c00000/display-controller@32e00000",
770 "/soc@0/bus@32c00000/hdmi@32c00000",
771 };
772
773 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
774}
775
776static int check_mipi_dsi_nodes(void *blob)
777{
778 static const char * const lcdif_path[] = {
779 "/lcdif@30320000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800780 "/soc@0/bus@30000000/lcdif@30320000",
781 "/soc@0/bus@30000000/lcd-controller@30320000"
Peng Fan435dc122020-07-09 14:06:49 +0800782 };
783 static const char * const mipi_dsi_path[] = {
784 "/mipi_dsi@30A00000",
785 "/soc@0/bus@30800000/mipi_dsi@30a00000"
786 };
787 static const char * const lcdif_ep_path[] = {
788 "/lcdif@30320000/port@0/mipi-dsi-endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800789 "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
790 "/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
Peng Fan435dc122020-07-09 14:06:49 +0800791 };
792 static const char * const mipi_dsi_ep_path[] = {
793 "/mipi_dsi@30A00000/port@1/endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800794 "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
795 "/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
Peng Fan435dc122020-07-09 14:06:49 +0800796 };
797
798 int lookup_node;
799 int nodeoff;
800 bool new_path = check_fdt_new_path(blob);
801 int i = new_path ? 1 : 0;
802
803 nodeoff = fdt_path_offset(blob, lcdif_path[i]);
804 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
805 /*
806 * If can't find lcdif node or lcdif node is disabled,
807 * then disable all mipi dsi, since they only can input
808 * from DCSS
809 */
810 return disable_mipi_dsi_nodes(blob);
811 }
812
813 nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
814 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
815 return 0;
816
817 nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
818 if (nodeoff < 0) {
819 /*
820 * If can't find lcdif endpoint, then disable all mipi dsi,
821 * since they only can input from DCSS
822 */
823 return disable_mipi_dsi_nodes(blob);
824 }
825
826 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
827 nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
828
829 if (nodeoff > 0 && nodeoff == lookup_node)
830 return 0;
831
832 return disable_mipi_dsi_nodes(blob);
833}
834#endif
835
836int disable_vpu_nodes(void *blob)
837{
838 static const char * const nodes_path_8mq[] = {
839 "/vpu@38300000",
840 "/soc@0/vpu@38300000"
841 };
842
843 static const char * const nodes_path_8mm[] = {
844 "/vpu_g1@38300000",
845 "/vpu_g2@38310000",
846 "/vpu_h1@38320000"
847 };
848
849 static const char * const nodes_path_8mp[] = {
850 "/vpu_g1@38300000",
851 "/vpu_g2@38310000",
852 "/vpu_vc8000e@38320000"
853 };
854
855 if (is_imx8mq())
856 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
857 else if (is_imx8mm())
858 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
859 else if (is_imx8mp())
860 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
861 else
862 return -EPERM;
863}
864
Ye Liee337ce2021-03-19 15:57:09 +0800865#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
866static int low_drive_gpu_freq(void *blob)
867{
868 static const char *nodes_path_8mn[] = {
869 "/gpu@38000000",
870 "/soc@0/gpu@38000000"
871 };
872
873 int nodeoff, cnt, i;
874 u32 assignedclks[7];
875
876 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
877 if (nodeoff < 0)
878 return nodeoff;
879
880 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
881 if (cnt < 0)
882 return cnt;
883
884 if (cnt != 7)
885 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
886
887 assignedclks[cnt - 1] = 200000000;
888 assignedclks[cnt - 2] = 200000000;
889
890 for (i = 0; i < cnt; i++) {
891 debug("<%u>, ", assignedclks[i]);
892 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
893 }
894 debug("\n");
895
896 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
897}
898#endif
899
Peng Fan435dc122020-07-09 14:06:49 +0800900int disable_gpu_nodes(void *blob)
901{
902 static const char * const nodes_path_8mn[] = {
Peng Fan7d4195c2021-03-19 15:57:13 +0800903 "/gpu@38000000",
904 "/soc@/gpu@38000000"
Peng Fan435dc122020-07-09 14:06:49 +0800905 };
906
907 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
908}
909
910int disable_npu_nodes(void *blob)
911{
912 static const char * const nodes_path_8mp[] = {
913 "/vipsi@38500000"
914 };
915
916 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
917}
918
919int disable_isp_nodes(void *blob)
920{
921 static const char * const nodes_path_8mp[] = {
922 "/soc@0/bus@32c00000/camera/isp@32e10000",
923 "/soc@0/bus@32c00000/camera/isp@32e20000"
924 };
925
926 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
927}
928
929int disable_dsp_nodes(void *blob)
930{
931 static const char * const nodes_path_8mp[] = {
932 "/dsp@3b6e8000"
933 };
934
935 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
936}
937
Ye Li26517af2021-03-19 15:57:12 +0800938static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores)
939{
940 static const char * const thermal_path[] = {
941 "/thermal-zones/cpu-thermal/cooling-maps/map0"
942 };
943
944 int nodeoff, cnt, i, ret, j;
945 u32 cooling_dev[12];
946
947 for (i = 0; i < ARRAY_SIZE(thermal_path); i++) {
948 nodeoff = fdt_path_offset(blob, thermal_path[i]);
949 if (nodeoff < 0)
950 continue; /* Not found, skip it */
951
952 cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 12);
953 if (cnt < 0)
954 continue;
955
956 if (cnt != 12)
957 printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt);
958
959 for (j = 0; j < cnt; j++)
960 cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]);
961
962 ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev,
963 sizeof(u32) * (12 - disabled_cores * 3));
964 if (ret < 0) {
965 printf("Warning: %s, cooling-device setprop failed %d\n",
966 thermal_path[i], ret);
967 continue;
968 }
969
970 printf("Update node %s, cooling-device prop\n", thermal_path[i]);
971 }
972}
973
974static void disable_pmu_cpu_nodes(void *blob, u32 disabled_cores)
975{
976 static const char * const pmu_path[] = {
977 "/pmu"
978 };
979
980 int nodeoff, cnt, i, ret, j;
981 u32 irq_affinity[4];
982
983 for (i = 0; i < ARRAY_SIZE(pmu_path); i++) {
984 nodeoff = fdt_path_offset(blob, pmu_path[i]);
985 if (nodeoff < 0)
986 continue; /* Not found, skip it */
987
988 cnt = fdtdec_get_int_array_count(blob, nodeoff, "interrupt-affinity",
989 irq_affinity, 4);
990 if (cnt < 0)
991 continue;
992
993 if (cnt != 4)
994 printf("Warning: %s, interrupt-affinity count %d\n", pmu_path[i], cnt);
995
996 for (j = 0; j < cnt; j++)
997 irq_affinity[j] = cpu_to_fdt32(irq_affinity[j]);
998
999 ret = fdt_setprop(blob, nodeoff, "interrupt-affinity", &irq_affinity,
1000 sizeof(u32) * (4 - disabled_cores));
1001 if (ret < 0) {
1002 printf("Warning: %s, interrupt-affinity setprop failed %d\n",
1003 pmu_path[i], ret);
1004 continue;
1005 }
1006
1007 printf("Update node %s, interrupt-affinity prop\n", pmu_path[i]);
1008 }
1009}
1010
Peng Fan435dc122020-07-09 14:06:49 +08001011static int disable_cpu_nodes(void *blob, u32 disabled_cores)
1012{
1013 static const char * const nodes_path[] = {
1014 "/cpus/cpu@1",
1015 "/cpus/cpu@2",
1016 "/cpus/cpu@3",
1017 };
1018 u32 i = 0;
1019 int rc;
1020 int nodeoff;
1021
1022 if (disabled_cores > 3)
1023 return -EINVAL;
1024
1025 i = 3 - disabled_cores;
1026
1027 for (; i < 3; i++) {
1028 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1029 if (nodeoff < 0)
1030 continue; /* Not found, skip it */
1031
1032 debug("Found %s node\n", nodes_path[i]);
1033
1034 rc = fdt_del_node(blob, nodeoff);
1035 if (rc < 0) {
1036 printf("Unable to delete node %s, err=%s\n",
1037 nodes_path[i], fdt_strerror(rc));
1038 } else {
1039 printf("Delete node %s\n", nodes_path[i]);
1040 }
1041 }
1042
Ye Li26517af2021-03-19 15:57:12 +08001043 disable_thermal_cpu_nodes(blob, disabled_cores);
1044 disable_pmu_cpu_nodes(blob, disabled_cores);
1045
Peng Fan435dc122020-07-09 14:06:49 +08001046 return 0;
1047}
1048
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001049int ft_system_setup(void *blob, struct bd_info *bd)
Peng Faneae4de22018-01-10 13:20:37 +08001050{
Peng Fan435dc122020-07-09 14:06:49 +08001051#ifdef CONFIG_IMX8MQ
Peng Faneae4de22018-01-10 13:20:37 +08001052 int i = 0;
1053 int rc;
1054 int nodeoff;
1055
Peng Fan435dc122020-07-09 14:06:49 +08001056 if (get_boot_device() == USB_BOOT) {
1057 disable_dcss_nodes(blob);
1058
1059 bool new_path = check_fdt_new_path(blob);
1060 int v = new_path ? 1 : 0;
1061 static const char * const usb_dwc3_path[] = {
1062 "/usb@38100000/dwc3",
1063 "/soc@0/usb@38100000"
1064 };
1065
1066 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1067 if (nodeoff >= 0) {
1068 const char *speed = "high-speed";
1069
1070 printf("Found %s node\n", usb_dwc3_path[v]);
1071
1072usb_modify_speed:
1073
1074 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1075 if (rc) {
1076 if (rc == -FDT_ERR_NOSPACE) {
1077 rc = fdt_increase_size(blob, 512);
1078 if (!rc)
1079 goto usb_modify_speed;
1080 }
1081 printf("Unable to set property %s:%s, err=%s\n",
1082 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1083 } else {
1084 printf("Modify %s:%s = %s\n",
1085 usb_dwc3_path[v], "maximum-speed", speed);
1086 }
1087 } else {
1088 printf("Can't found %s node\n", usb_dwc3_path[v]);
1089 }
1090 }
1091
Peng Faneae4de22018-01-10 13:20:37 +08001092 /* Disable the CPU idle for A0 chip since the HW does not support it */
1093 if (is_soc_rev(CHIP_REV_1_0)) {
1094 static const char * const nodes_path[] = {
1095 "/cpus/cpu@0",
1096 "/cpus/cpu@1",
1097 "/cpus/cpu@2",
1098 "/cpus/cpu@3",
1099 };
1100
1101 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1102 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1103 if (nodeoff < 0)
1104 continue; /* Not found, skip it */
1105
Marek Vasute2e7a772020-04-24 21:37:33 +02001106 debug("Found %s node\n", nodes_path[i]);
Peng Faneae4de22018-01-10 13:20:37 +08001107
1108 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasute2e7a772020-04-24 21:37:33 +02001109 if (rc == -FDT_ERR_NOTFOUND)
1110 continue;
Peng Faneae4de22018-01-10 13:20:37 +08001111 if (rc) {
1112 printf("Unable to update property %s:%s, err=%s\n",
1113 nodes_path[i], "status", fdt_strerror(rc));
1114 return rc;
1115 }
1116
Marek Vasute2e7a772020-04-24 21:37:33 +02001117 debug("Remove %s:%s\n", nodes_path[i],
Peng Faneae4de22018-01-10 13:20:37 +08001118 "cpu-idle-states");
1119 }
1120 }
1121
Peng Fan435dc122020-07-09 14:06:49 +08001122 if (is_imx8mql()) {
1123 disable_vpu_nodes(blob);
1124 if (check_dcss_fused()) {
1125 printf("DCSS is fused\n");
1126 disable_dcss_nodes(blob);
1127 check_mipi_dsi_nodes(blob);
1128 }
1129 }
1130
1131 if (is_imx8md())
1132 disable_cpu_nodes(blob, 2);
1133
1134#elif defined(CONFIG_IMX8MM)
1135 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1136 disable_vpu_nodes(blob);
1137
1138 if (is_imx8mmd() || is_imx8mmdl())
1139 disable_cpu_nodes(blob, 2);
1140 else if (is_imx8mms() || is_imx8mmsl())
1141 disable_cpu_nodes(blob, 3);
1142
1143#elif defined(CONFIG_IMX8MN)
1144 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1145 disable_gpu_nodes(blob);
Ye Liee337ce2021-03-19 15:57:09 +08001146#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1147 else {
1148 int ldm_gpu = low_drive_gpu_freq(blob);
1149
1150 if (ldm_gpu < 0)
1151 printf("Update GPU node assigned-clock-rates failed\n");
1152 else
1153 printf("Update GPU node assigned-clock-rates ok\n");
1154 }
1155#endif
Peng Fan435dc122020-07-09 14:06:49 +08001156
Ye Li715180e2021-03-19 15:57:11 +08001157 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan435dc122020-07-09 14:06:49 +08001158 disable_cpu_nodes(blob, 2);
Ye Li715180e2021-03-19 15:57:11 +08001159 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan435dc122020-07-09 14:06:49 +08001160 disable_cpu_nodes(blob, 3);
1161
1162#elif defined(CONFIG_IMX8MP)
Peng Fan8a472a22020-09-16 15:17:22 +08001163 if (is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001164 disable_vpu_nodes(blob);
1165
Peng Fan8a472a22020-09-16 15:17:22 +08001166 if (is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001167 disable_npu_nodes(blob);
1168
Peng Fan8a472a22020-09-16 15:17:22 +08001169 if (is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001170 disable_isp_nodes(blob);
1171
Peng Fan8a472a22020-09-16 15:17:22 +08001172 if (is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001173 disable_dsp_nodes(blob);
1174
1175 if (is_imx8mpd())
1176 disable_cpu_nodes(blob, 2);
1177#endif
1178
Peng Faneae4de22018-01-10 13:20:37 +08001179 return 0;
1180}
1181#endif
1182
Marek Vasut64dc4de2020-04-29 15:04:21 +02001183#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler6f14d5f2020-12-15 16:47:52 +01001184void reset_cpu(void)
Peng Faneae4de22018-01-10 13:20:37 +08001185{
Claudius Heinee73f3942020-04-29 15:04:23 +02001186 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Faneae4de22018-01-10 13:20:37 +08001187
Ye Li54a915a2019-12-09 00:47:18 -08001188 /* Clear WDA to trigger WDOG_B immediately */
1189 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fan24290d92019-08-27 06:25:41 +00001190
Ye Li54a915a2019-12-09 00:47:18 -08001191 while (1) {
1192 /*
Harald Seilerec0c4472020-04-29 15:04:22 +02001193 * spin for .5 seconds before reset
Ye Li54a915a2019-12-09 00:47:18 -08001194 */
1195 }
Peng Faneae4de22018-01-10 13:20:37 +08001196}
Peng Fan24290d92019-08-27 06:25:41 +00001197#endif
Peng Fan5760d8d2020-04-22 10:51:13 +08001198
1199#if defined(CONFIG_ARCH_MISC_INIT)
1200static void acquire_buildinfo(void)
1201{
1202 u64 atf_commit = 0;
Peng Fan45d843a2020-05-11 15:14:04 +08001203 struct arm_smccc_res res;
Peng Fan5760d8d2020-04-22 10:51:13 +08001204
1205 /* Get ARM Trusted Firmware commit id */
Peng Fan45d843a2020-05-11 15:14:04 +08001206 arm_smccc_smc(IMX_SIP_BUILDINFO, IMX_SIP_BUILDINFO_GET_COMMITHASH,
Fabio Estevam31e410f2020-07-17 16:36:54 -03001207 0, 0, 0, 0, 0, 0, &res);
Peng Fan45d843a2020-05-11 15:14:04 +08001208 atf_commit = res.a0;
Peng Fan5760d8d2020-04-22 10:51:13 +08001209 if (atf_commit == 0xffffffff) {
1210 debug("ATF does not support build info\n");
1211 atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */
1212 }
1213
1214 printf("\n BuildInfo:\n - ATF %s\n\n", (char *)&atf_commit);
1215}
1216
1217int arch_misc_init(void)
1218{
Gaurav Jain81113a02022-03-24 11:50:27 +05301219 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1220 struct udevice *dev;
1221 int ret;
1222
1223 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1224 if (ret)
1225 printf("Failed to initialize %s: %d\n", dev->name, ret);
1226 }
Peng Fan5760d8d2020-04-22 10:51:13 +08001227 acquire_buildinfo();
1228
1229 return 0;
1230}
1231#endif
Ye Li325cd012020-05-03 22:19:52 +08001232
1233void imx_tmu_arch_init(void *reg_base)
1234{
Ye Lia00f2f02020-05-03 22:19:53 +08001235 if (is_imx8mm() || is_imx8mn()) {
Ye Li325cd012020-05-03 22:19:52 +08001236 /* Load TCALIV and TASR from fuses */
1237 struct ocotp_regs *ocotp =
1238 (struct ocotp_regs *)OCOTP_BASE_ADDR;
1239 struct fuse_bank *bank = &ocotp->bank[3];
1240 struct fuse_bank3_regs *fuse =
1241 (struct fuse_bank3_regs *)bank->fuse_regs;
1242
1243 u32 tca_rt, tca_hr, tca_en;
1244 u32 buf_vref, buf_slope;
1245
1246 tca_rt = fuse->ana0 & 0xFF;
1247 tca_hr = (fuse->ana0 & 0xFF00) >> 8;
1248 tca_en = (fuse->ana0 & 0x2000000) >> 25;
1249
1250 buf_vref = (fuse->ana0 & 0x1F00000) >> 20;
1251 buf_slope = (fuse->ana0 & 0xF0000) >> 16;
1252
1253 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1254 writel((tca_en << 31) | (tca_hr << 16) | tca_rt,
1255 (ulong)reg_base + 0x30);
1256 }
Ye Li41a20252020-05-03 22:19:54 +08001257#ifdef CONFIG_IMX8MP
1258 /* Load TCALIV0/1/m40 and TRIM from fuses */
1259 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
1260 struct fuse_bank *bank = &ocotp->bank[38];
1261 struct fuse_bank38_regs *fuse =
1262 (struct fuse_bank38_regs *)bank->fuse_regs;
1263 struct fuse_bank *bank2 = &ocotp->bank[39];
1264 struct fuse_bank39_regs *fuse2 =
1265 (struct fuse_bank39_regs *)bank2->fuse_regs;
1266 u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr;
1267 u32 reg;
1268 u32 tca40[2], tca25[2], tca105[2];
1269
1270 /* For blank sample */
1271 if (!fuse->ana_trim2 && !fuse->ana_trim3 &&
1272 !fuse->ana_trim4 && !fuse2->ana_trim5) {
1273 /* Use a default 25C binary codes */
1274 tca25[0] = 1596;
Ye Lid756ca02020-05-03 22:19:55 +08001275 tca25[1] = 1596;
Ye Li41a20252020-05-03 22:19:54 +08001276 writel(tca25[0], (ulong)reg_base + 0x30);
Ye Lid756ca02020-05-03 22:19:55 +08001277 writel(tca25[1], (ulong)reg_base + 0x34);
Ye Li41a20252020-05-03 22:19:54 +08001278 return;
1279 }
1280
1281 buf_vref = (fuse->ana_trim2 & 0xc0) >> 6;
1282 buf_slope = (fuse->ana_trim2 & 0xF00) >> 8;
1283 bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12;
1284 bgr = (fuse->ana_trim2 & 0xF0000) >> 16;
1285 vlsb = (fuse->ana_trim2 & 0xF00000) >> 20;
1286 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1287
1288 reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7);
1289 writel(reg, (ulong)reg_base + 0x3c);
1290
1291 tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16;
1292 tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28;
1293 tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4);
1294 tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8;
1295 tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20;
1296 tca25[1] = fuse2->ana_trim5 & 0xFFF;
1297 tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12;
1298
1299 /* use 25c for 1p calibration */
1300 writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30);
1301 writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34);
1302 writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38);
1303#endif
Ye Li325cd012020-05-03 22:19:52 +08001304}
Peng Fana35215d2020-07-09 13:39:26 +08001305
1306#if defined(CONFIG_SPL_BUILD)
1307#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1308bool serror_need_skip = true;
1309
Sean Anderson2d755492022-03-22 17:17:35 -04001310void do_error(struct pt_regs *pt_regs)
Peng Fana35215d2020-07-09 13:39:26 +08001311{
1312 /*
1313 * If stack is still in ROM reserved OCRAM not switch to SPL,
1314 * it is the ROM SError
1315 */
1316 ulong sp;
1317
1318 asm volatile("mov %0, sp" : "=r"(sp) : );
1319
1320 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1321 /* Check for ERR050342, imx8mq HDCP enabled parts */
1322 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1323 serror_need_skip = false;
1324 return; /* Do nothing skip the SError in ROM */
1325 }
1326
1327 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1328 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1329 serror_need_skip = false;
1330 return; /* Do nothing skip the SError in ROM */
1331 }
1332 }
1333
1334 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -04001335 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fana35215d2020-07-09 13:39:26 +08001336 show_regs(pt_regs);
1337 panic("Resetting CPU ...\n");
1338}
1339#endif
1340#endif
Ye Li0513f362019-07-15 01:16:46 -07001341
1342#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
1343enum env_location env_get_location(enum env_operation op, int prio)
1344{
1345 enum boot_device dev = get_boot_device();
Ye Li0513f362019-07-15 01:16:46 -07001346
1347 if (prio)
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001348 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001349
1350 switch (dev) {
Ye Li0513f362019-07-15 01:16:46 -07001351 case QSPI_BOOT:
Marek Vasut31b3bc42022-03-25 18:59:28 +01001352 case SPI_NOR_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001353 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1354 return ENVL_SPI_FLASH;
1355 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001356 case NAND_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001357 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1358 return ENVL_NAND;
1359 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001360 case SD1_BOOT:
1361 case SD2_BOOT:
1362 case SD3_BOOT:
1363 case MMC1_BOOT:
1364 case MMC2_BOOT:
1365 case MMC3_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001366 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1367 return ENVL_MMC;
1368 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1369 return ENVL_EXT4;
1370 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1371 return ENVL_FAT;
1372 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001373 default:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001374 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001375 }
Ye Li0513f362019-07-15 01:16:46 -07001376}
1377
Ye Li0513f362019-07-15 01:16:46 -07001378#endif