blob: 4baeea6527a191e366d49f4fb6c0586f4d5ff69a [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;
603 case BT_DEV_TYPE_USB:
604 boot_dev = USB_BOOT;
605 break;
606 default:
607 break;
608 }
609
610 return boot_dev;
611}
612#endif
613
Marek Vasut520ded02021-07-03 04:55:33 +0200614#if defined(CONFIG_IMX8M)
615#include <spl.h>
616int spl_mmc_emmc_boot_partition(struct mmc *mmc)
617{
618 u32 *rom_log_addr = (u32 *)0x9e0;
619 u32 *rom_log;
620 u8 event_id;
621 int i, part;
622
623 part = default_spl_mmc_emmc_boot_partition(mmc);
624
625 /* If the ROM event log pointer is not valid. */
626 if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 ||
627 *rom_log_addr & 0x3)
628 return part;
629
630 /* Parse the ROM event ID version 2 log */
631 rom_log = (u32 *)(uintptr_t)(*rom_log_addr);
632 for (i = 0; i < 128; i++) {
633 event_id = rom_log[i] >> 24;
634 switch (event_id) {
635 case 0x00: /* End of list */
636 return part;
637 /* Log entries with 1 parameter, skip 1 */
638 case 0x80: /* Start to perform the device initialization */
639 case 0x81: /* The boot device initialization completes */
640 case 0x8f: /* The boot device initialization fails */
641 case 0x90: /* Start to read data from boot device */
642 case 0x91: /* Reading data from boot device completes */
643 case 0x9f: /* Reading data from boot device fails */
644 i += 1;
645 continue;
646 /* Log entries with 2 parameters, skip 2 */
647 case 0xa0: /* Image authentication result */
648 case 0xc0: /* Jump to the boot image soon */
649 i += 2;
650 continue;
651 /* Boot from the secondary boot image */
652 case 0x51:
653 /*
654 * Swap the eMMC boot partitions in case there was a
655 * fallback event (i.e. primary image was corrupted
656 * and that corruption was recognized by the BootROM),
657 * so the SPL loads the rest of the U-Boot from the
658 * correct eMMC boot partition, since the BootROM
659 * leaves the boot partition set to the corrupted one.
660 */
661 if (part == 1)
662 part = 2;
663 else if (part == 2)
664 part = 1;
665 continue;
666 default:
667 continue;
668 }
669 }
670
671 return part;
672}
673#endif
674
Peng Faneae4de22018-01-10 13:20:37 +0800675bool is_usb_boot(void)
676{
677 return get_boot_device() == USB_BOOT;
678}
679
680#ifdef CONFIG_OF_SYSTEM_SETUP
Peng Fan435dc122020-07-09 14:06:49 +0800681bool check_fdt_new_path(void *blob)
682{
683 const char *soc_path = "/soc@0";
684 int nodeoff;
685
686 nodeoff = fdt_path_offset(blob, soc_path);
687 if (nodeoff < 0)
688 return false;
689
690 return true;
691}
692
693static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
694{
695 int i = 0;
696 int rc;
697 int nodeoff;
698 const char *status = "disabled";
699
700 for (i = 0; i < size_array; i++) {
701 nodeoff = fdt_path_offset(blob, nodes_path[i]);
702 if (nodeoff < 0)
703 continue; /* Not found, skip it */
704
705 printf("Found %s node\n", nodes_path[i]);
706
707add_status:
708 rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
709 if (rc) {
710 if (rc == -FDT_ERR_NOSPACE) {
711 rc = fdt_increase_size(blob, 512);
712 if (!rc)
713 goto add_status;
714 }
715 printf("Unable to update property %s:%s, err=%s\n",
716 nodes_path[i], "status", fdt_strerror(rc));
717 } else {
718 printf("Modify %s:%s disabled\n",
719 nodes_path[i], "status");
720 }
721 }
722
723 return 0;
724}
725
726#ifdef CONFIG_IMX8MQ
727bool check_dcss_fused(void)
728{
729 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
730 struct fuse_bank *bank = &ocotp->bank[1];
731 struct fuse_bank1_regs *fuse =
732 (struct fuse_bank1_regs *)bank->fuse_regs;
733 u32 value = readl(&fuse->tester4);
734
735 if (value & 0x4000000)
736 return true;
737
738 return false;
739}
740
741static int disable_mipi_dsi_nodes(void *blob)
742{
743 static const char * const nodes_path[] = {
744 "/mipi_dsi@30A00000",
745 "/mipi_dsi_bridge@30A00000",
746 "/dsi_phy@30A00300",
747 "/soc@0/bus@30800000/mipi_dsi@30a00000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800748 "/soc@0/bus@30800000/dphy@30a00300",
749 "/soc@0/bus@30800000/mipi-dsi@30a00000",
Peng Fan435dc122020-07-09 14:06:49 +0800750 };
751
752 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
753}
754
755static int disable_dcss_nodes(void *blob)
756{
757 static const char * const nodes_path[] = {
758 "/dcss@0x32e00000",
759 "/dcss@32e00000",
760 "/hdmi@32c00000",
761 "/hdmi_cec@32c33800",
762 "/hdmi_drm@32c00000",
763 "/display-subsystem",
764 "/sound-hdmi",
765 "/sound-hdmi-arc",
766 "/soc@0/bus@32c00000/display-controller@32e00000",
767 "/soc@0/bus@32c00000/hdmi@32c00000",
768 };
769
770 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
771}
772
773static int check_mipi_dsi_nodes(void *blob)
774{
775 static const char * const lcdif_path[] = {
776 "/lcdif@30320000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800777 "/soc@0/bus@30000000/lcdif@30320000",
778 "/soc@0/bus@30000000/lcd-controller@30320000"
Peng Fan435dc122020-07-09 14:06:49 +0800779 };
780 static const char * const mipi_dsi_path[] = {
781 "/mipi_dsi@30A00000",
782 "/soc@0/bus@30800000/mipi_dsi@30a00000"
783 };
784 static const char * const lcdif_ep_path[] = {
785 "/lcdif@30320000/port@0/mipi-dsi-endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800786 "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
787 "/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
Peng Fan435dc122020-07-09 14:06:49 +0800788 };
789 static const char * const mipi_dsi_ep_path[] = {
790 "/mipi_dsi@30A00000/port@1/endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800791 "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
792 "/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
Peng Fan435dc122020-07-09 14:06:49 +0800793 };
794
795 int lookup_node;
796 int nodeoff;
797 bool new_path = check_fdt_new_path(blob);
798 int i = new_path ? 1 : 0;
799
800 nodeoff = fdt_path_offset(blob, lcdif_path[i]);
801 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
802 /*
803 * If can't find lcdif node or lcdif node is disabled,
804 * then disable all mipi dsi, since they only can input
805 * from DCSS
806 */
807 return disable_mipi_dsi_nodes(blob);
808 }
809
810 nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
811 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
812 return 0;
813
814 nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
815 if (nodeoff < 0) {
816 /*
817 * If can't find lcdif endpoint, then disable all mipi dsi,
818 * since they only can input from DCSS
819 */
820 return disable_mipi_dsi_nodes(blob);
821 }
822
823 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
824 nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
825
826 if (nodeoff > 0 && nodeoff == lookup_node)
827 return 0;
828
829 return disable_mipi_dsi_nodes(blob);
830}
831#endif
832
833int disable_vpu_nodes(void *blob)
834{
835 static const char * const nodes_path_8mq[] = {
836 "/vpu@38300000",
837 "/soc@0/vpu@38300000"
838 };
839
840 static const char * const nodes_path_8mm[] = {
841 "/vpu_g1@38300000",
842 "/vpu_g2@38310000",
843 "/vpu_h1@38320000"
844 };
845
846 static const char * const nodes_path_8mp[] = {
847 "/vpu_g1@38300000",
848 "/vpu_g2@38310000",
849 "/vpu_vc8000e@38320000"
850 };
851
852 if (is_imx8mq())
853 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
854 else if (is_imx8mm())
855 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
856 else if (is_imx8mp())
857 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
858 else
859 return -EPERM;
860}
861
Ye Liee337ce2021-03-19 15:57:09 +0800862#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
863static int low_drive_gpu_freq(void *blob)
864{
865 static const char *nodes_path_8mn[] = {
866 "/gpu@38000000",
867 "/soc@0/gpu@38000000"
868 };
869
870 int nodeoff, cnt, i;
871 u32 assignedclks[7];
872
873 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
874 if (nodeoff < 0)
875 return nodeoff;
876
877 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
878 if (cnt < 0)
879 return cnt;
880
881 if (cnt != 7)
882 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
883
884 assignedclks[cnt - 1] = 200000000;
885 assignedclks[cnt - 2] = 200000000;
886
887 for (i = 0; i < cnt; i++) {
888 debug("<%u>, ", assignedclks[i]);
889 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
890 }
891 debug("\n");
892
893 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
894}
895#endif
896
Peng Fan435dc122020-07-09 14:06:49 +0800897int disable_gpu_nodes(void *blob)
898{
899 static const char * const nodes_path_8mn[] = {
Peng Fan7d4195c2021-03-19 15:57:13 +0800900 "/gpu@38000000",
901 "/soc@/gpu@38000000"
Peng Fan435dc122020-07-09 14:06:49 +0800902 };
903
904 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
905}
906
907int disable_npu_nodes(void *blob)
908{
909 static const char * const nodes_path_8mp[] = {
910 "/vipsi@38500000"
911 };
912
913 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
914}
915
916int disable_isp_nodes(void *blob)
917{
918 static const char * const nodes_path_8mp[] = {
919 "/soc@0/bus@32c00000/camera/isp@32e10000",
920 "/soc@0/bus@32c00000/camera/isp@32e20000"
921 };
922
923 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
924}
925
926int disable_dsp_nodes(void *blob)
927{
928 static const char * const nodes_path_8mp[] = {
929 "/dsp@3b6e8000"
930 };
931
932 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
933}
934
Ye Li26517af2021-03-19 15:57:12 +0800935static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores)
936{
937 static const char * const thermal_path[] = {
938 "/thermal-zones/cpu-thermal/cooling-maps/map0"
939 };
940
941 int nodeoff, cnt, i, ret, j;
942 u32 cooling_dev[12];
943
944 for (i = 0; i < ARRAY_SIZE(thermal_path); i++) {
945 nodeoff = fdt_path_offset(blob, thermal_path[i]);
946 if (nodeoff < 0)
947 continue; /* Not found, skip it */
948
949 cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 12);
950 if (cnt < 0)
951 continue;
952
953 if (cnt != 12)
954 printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt);
955
956 for (j = 0; j < cnt; j++)
957 cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]);
958
959 ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev,
960 sizeof(u32) * (12 - disabled_cores * 3));
961 if (ret < 0) {
962 printf("Warning: %s, cooling-device setprop failed %d\n",
963 thermal_path[i], ret);
964 continue;
965 }
966
967 printf("Update node %s, cooling-device prop\n", thermal_path[i]);
968 }
969}
970
971static void disable_pmu_cpu_nodes(void *blob, u32 disabled_cores)
972{
973 static const char * const pmu_path[] = {
974 "/pmu"
975 };
976
977 int nodeoff, cnt, i, ret, j;
978 u32 irq_affinity[4];
979
980 for (i = 0; i < ARRAY_SIZE(pmu_path); i++) {
981 nodeoff = fdt_path_offset(blob, pmu_path[i]);
982 if (nodeoff < 0)
983 continue; /* Not found, skip it */
984
985 cnt = fdtdec_get_int_array_count(blob, nodeoff, "interrupt-affinity",
986 irq_affinity, 4);
987 if (cnt < 0)
988 continue;
989
990 if (cnt != 4)
991 printf("Warning: %s, interrupt-affinity count %d\n", pmu_path[i], cnt);
992
993 for (j = 0; j < cnt; j++)
994 irq_affinity[j] = cpu_to_fdt32(irq_affinity[j]);
995
996 ret = fdt_setprop(blob, nodeoff, "interrupt-affinity", &irq_affinity,
997 sizeof(u32) * (4 - disabled_cores));
998 if (ret < 0) {
999 printf("Warning: %s, interrupt-affinity setprop failed %d\n",
1000 pmu_path[i], ret);
1001 continue;
1002 }
1003
1004 printf("Update node %s, interrupt-affinity prop\n", pmu_path[i]);
1005 }
1006}
1007
Peng Fan435dc122020-07-09 14:06:49 +08001008static int disable_cpu_nodes(void *blob, u32 disabled_cores)
1009{
1010 static const char * const nodes_path[] = {
1011 "/cpus/cpu@1",
1012 "/cpus/cpu@2",
1013 "/cpus/cpu@3",
1014 };
1015 u32 i = 0;
1016 int rc;
1017 int nodeoff;
1018
1019 if (disabled_cores > 3)
1020 return -EINVAL;
1021
1022 i = 3 - disabled_cores;
1023
1024 for (; i < 3; i++) {
1025 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1026 if (nodeoff < 0)
1027 continue; /* Not found, skip it */
1028
1029 debug("Found %s node\n", nodes_path[i]);
1030
1031 rc = fdt_del_node(blob, nodeoff);
1032 if (rc < 0) {
1033 printf("Unable to delete node %s, err=%s\n",
1034 nodes_path[i], fdt_strerror(rc));
1035 } else {
1036 printf("Delete node %s\n", nodes_path[i]);
1037 }
1038 }
1039
Ye Li26517af2021-03-19 15:57:12 +08001040 disable_thermal_cpu_nodes(blob, disabled_cores);
1041 disable_pmu_cpu_nodes(blob, disabled_cores);
1042
Peng Fan435dc122020-07-09 14:06:49 +08001043 return 0;
1044}
1045
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001046int ft_system_setup(void *blob, struct bd_info *bd)
Peng Faneae4de22018-01-10 13:20:37 +08001047{
Peng Fan435dc122020-07-09 14:06:49 +08001048#ifdef CONFIG_IMX8MQ
Peng Faneae4de22018-01-10 13:20:37 +08001049 int i = 0;
1050 int rc;
1051 int nodeoff;
1052
Peng Fan435dc122020-07-09 14:06:49 +08001053 if (get_boot_device() == USB_BOOT) {
1054 disable_dcss_nodes(blob);
1055
1056 bool new_path = check_fdt_new_path(blob);
1057 int v = new_path ? 1 : 0;
1058 static const char * const usb_dwc3_path[] = {
1059 "/usb@38100000/dwc3",
1060 "/soc@0/usb@38100000"
1061 };
1062
1063 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1064 if (nodeoff >= 0) {
1065 const char *speed = "high-speed";
1066
1067 printf("Found %s node\n", usb_dwc3_path[v]);
1068
1069usb_modify_speed:
1070
1071 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1072 if (rc) {
1073 if (rc == -FDT_ERR_NOSPACE) {
1074 rc = fdt_increase_size(blob, 512);
1075 if (!rc)
1076 goto usb_modify_speed;
1077 }
1078 printf("Unable to set property %s:%s, err=%s\n",
1079 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1080 } else {
1081 printf("Modify %s:%s = %s\n",
1082 usb_dwc3_path[v], "maximum-speed", speed);
1083 }
1084 } else {
1085 printf("Can't found %s node\n", usb_dwc3_path[v]);
1086 }
1087 }
1088
Peng Faneae4de22018-01-10 13:20:37 +08001089 /* Disable the CPU idle for A0 chip since the HW does not support it */
1090 if (is_soc_rev(CHIP_REV_1_0)) {
1091 static const char * const nodes_path[] = {
1092 "/cpus/cpu@0",
1093 "/cpus/cpu@1",
1094 "/cpus/cpu@2",
1095 "/cpus/cpu@3",
1096 };
1097
1098 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1099 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1100 if (nodeoff < 0)
1101 continue; /* Not found, skip it */
1102
Marek Vasute2e7a772020-04-24 21:37:33 +02001103 debug("Found %s node\n", nodes_path[i]);
Peng Faneae4de22018-01-10 13:20:37 +08001104
1105 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasute2e7a772020-04-24 21:37:33 +02001106 if (rc == -FDT_ERR_NOTFOUND)
1107 continue;
Peng Faneae4de22018-01-10 13:20:37 +08001108 if (rc) {
1109 printf("Unable to update property %s:%s, err=%s\n",
1110 nodes_path[i], "status", fdt_strerror(rc));
1111 return rc;
1112 }
1113
Marek Vasute2e7a772020-04-24 21:37:33 +02001114 debug("Remove %s:%s\n", nodes_path[i],
Peng Faneae4de22018-01-10 13:20:37 +08001115 "cpu-idle-states");
1116 }
1117 }
1118
Peng Fan435dc122020-07-09 14:06:49 +08001119 if (is_imx8mql()) {
1120 disable_vpu_nodes(blob);
1121 if (check_dcss_fused()) {
1122 printf("DCSS is fused\n");
1123 disable_dcss_nodes(blob);
1124 check_mipi_dsi_nodes(blob);
1125 }
1126 }
1127
1128 if (is_imx8md())
1129 disable_cpu_nodes(blob, 2);
1130
1131#elif defined(CONFIG_IMX8MM)
1132 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1133 disable_vpu_nodes(blob);
1134
1135 if (is_imx8mmd() || is_imx8mmdl())
1136 disable_cpu_nodes(blob, 2);
1137 else if (is_imx8mms() || is_imx8mmsl())
1138 disable_cpu_nodes(blob, 3);
1139
1140#elif defined(CONFIG_IMX8MN)
1141 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1142 disable_gpu_nodes(blob);
Ye Liee337ce2021-03-19 15:57:09 +08001143#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1144 else {
1145 int ldm_gpu = low_drive_gpu_freq(blob);
1146
1147 if (ldm_gpu < 0)
1148 printf("Update GPU node assigned-clock-rates failed\n");
1149 else
1150 printf("Update GPU node assigned-clock-rates ok\n");
1151 }
1152#endif
Peng Fan435dc122020-07-09 14:06:49 +08001153
Ye Li715180e2021-03-19 15:57:11 +08001154 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan435dc122020-07-09 14:06:49 +08001155 disable_cpu_nodes(blob, 2);
Ye Li715180e2021-03-19 15:57:11 +08001156 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan435dc122020-07-09 14:06:49 +08001157 disable_cpu_nodes(blob, 3);
1158
1159#elif defined(CONFIG_IMX8MP)
Peng Fan8a472a22020-09-16 15:17:22 +08001160 if (is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001161 disable_vpu_nodes(blob);
1162
Peng Fan8a472a22020-09-16 15:17:22 +08001163 if (is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001164 disable_npu_nodes(blob);
1165
Peng Fan8a472a22020-09-16 15:17:22 +08001166 if (is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001167 disable_isp_nodes(blob);
1168
Peng Fan8a472a22020-09-16 15:17:22 +08001169 if (is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001170 disable_dsp_nodes(blob);
1171
1172 if (is_imx8mpd())
1173 disable_cpu_nodes(blob, 2);
1174#endif
1175
Peng Faneae4de22018-01-10 13:20:37 +08001176 return 0;
1177}
1178#endif
1179
Marek Vasut64dc4de2020-04-29 15:04:21 +02001180#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler6f14d5f2020-12-15 16:47:52 +01001181void reset_cpu(void)
Peng Faneae4de22018-01-10 13:20:37 +08001182{
Claudius Heinee73f3942020-04-29 15:04:23 +02001183 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Faneae4de22018-01-10 13:20:37 +08001184
Ye Li54a915a2019-12-09 00:47:18 -08001185 /* Clear WDA to trigger WDOG_B immediately */
1186 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fan24290d92019-08-27 06:25:41 +00001187
Ye Li54a915a2019-12-09 00:47:18 -08001188 while (1) {
1189 /*
Harald Seilerec0c4472020-04-29 15:04:22 +02001190 * spin for .5 seconds before reset
Ye Li54a915a2019-12-09 00:47:18 -08001191 */
1192 }
Peng Faneae4de22018-01-10 13:20:37 +08001193}
Peng Fan24290d92019-08-27 06:25:41 +00001194#endif
Peng Fan5760d8d2020-04-22 10:51:13 +08001195
1196#if defined(CONFIG_ARCH_MISC_INIT)
1197static void acquire_buildinfo(void)
1198{
1199 u64 atf_commit = 0;
Peng Fan45d843a2020-05-11 15:14:04 +08001200 struct arm_smccc_res res;
Peng Fan5760d8d2020-04-22 10:51:13 +08001201
1202 /* Get ARM Trusted Firmware commit id */
Peng Fan45d843a2020-05-11 15:14:04 +08001203 arm_smccc_smc(IMX_SIP_BUILDINFO, IMX_SIP_BUILDINFO_GET_COMMITHASH,
Fabio Estevam31e410f2020-07-17 16:36:54 -03001204 0, 0, 0, 0, 0, 0, &res);
Peng Fan45d843a2020-05-11 15:14:04 +08001205 atf_commit = res.a0;
Peng Fan5760d8d2020-04-22 10:51:13 +08001206 if (atf_commit == 0xffffffff) {
1207 debug("ATF does not support build info\n");
1208 atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */
1209 }
1210
1211 printf("\n BuildInfo:\n - ATF %s\n\n", (char *)&atf_commit);
1212}
1213
1214int arch_misc_init(void)
1215{
Gaurav Jain81113a02022-03-24 11:50:27 +05301216 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1217 struct udevice *dev;
1218 int ret;
1219
1220 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1221 if (ret)
1222 printf("Failed to initialize %s: %d\n", dev->name, ret);
1223 }
Peng Fan5760d8d2020-04-22 10:51:13 +08001224 acquire_buildinfo();
1225
1226 return 0;
1227}
1228#endif
Ye Li325cd012020-05-03 22:19:52 +08001229
1230void imx_tmu_arch_init(void *reg_base)
1231{
Ye Lia00f2f02020-05-03 22:19:53 +08001232 if (is_imx8mm() || is_imx8mn()) {
Ye Li325cd012020-05-03 22:19:52 +08001233 /* Load TCALIV and TASR from fuses */
1234 struct ocotp_regs *ocotp =
1235 (struct ocotp_regs *)OCOTP_BASE_ADDR;
1236 struct fuse_bank *bank = &ocotp->bank[3];
1237 struct fuse_bank3_regs *fuse =
1238 (struct fuse_bank3_regs *)bank->fuse_regs;
1239
1240 u32 tca_rt, tca_hr, tca_en;
1241 u32 buf_vref, buf_slope;
1242
1243 tca_rt = fuse->ana0 & 0xFF;
1244 tca_hr = (fuse->ana0 & 0xFF00) >> 8;
1245 tca_en = (fuse->ana0 & 0x2000000) >> 25;
1246
1247 buf_vref = (fuse->ana0 & 0x1F00000) >> 20;
1248 buf_slope = (fuse->ana0 & 0xF0000) >> 16;
1249
1250 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1251 writel((tca_en << 31) | (tca_hr << 16) | tca_rt,
1252 (ulong)reg_base + 0x30);
1253 }
Ye Li41a20252020-05-03 22:19:54 +08001254#ifdef CONFIG_IMX8MP
1255 /* Load TCALIV0/1/m40 and TRIM from fuses */
1256 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
1257 struct fuse_bank *bank = &ocotp->bank[38];
1258 struct fuse_bank38_regs *fuse =
1259 (struct fuse_bank38_regs *)bank->fuse_regs;
1260 struct fuse_bank *bank2 = &ocotp->bank[39];
1261 struct fuse_bank39_regs *fuse2 =
1262 (struct fuse_bank39_regs *)bank2->fuse_regs;
1263 u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr;
1264 u32 reg;
1265 u32 tca40[2], tca25[2], tca105[2];
1266
1267 /* For blank sample */
1268 if (!fuse->ana_trim2 && !fuse->ana_trim3 &&
1269 !fuse->ana_trim4 && !fuse2->ana_trim5) {
1270 /* Use a default 25C binary codes */
1271 tca25[0] = 1596;
Ye Lid756ca02020-05-03 22:19:55 +08001272 tca25[1] = 1596;
Ye Li41a20252020-05-03 22:19:54 +08001273 writel(tca25[0], (ulong)reg_base + 0x30);
Ye Lid756ca02020-05-03 22:19:55 +08001274 writel(tca25[1], (ulong)reg_base + 0x34);
Ye Li41a20252020-05-03 22:19:54 +08001275 return;
1276 }
1277
1278 buf_vref = (fuse->ana_trim2 & 0xc0) >> 6;
1279 buf_slope = (fuse->ana_trim2 & 0xF00) >> 8;
1280 bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12;
1281 bgr = (fuse->ana_trim2 & 0xF0000) >> 16;
1282 vlsb = (fuse->ana_trim2 & 0xF00000) >> 20;
1283 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1284
1285 reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7);
1286 writel(reg, (ulong)reg_base + 0x3c);
1287
1288 tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16;
1289 tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28;
1290 tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4);
1291 tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8;
1292 tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20;
1293 tca25[1] = fuse2->ana_trim5 & 0xFFF;
1294 tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12;
1295
1296 /* use 25c for 1p calibration */
1297 writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30);
1298 writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34);
1299 writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38);
1300#endif
Ye Li325cd012020-05-03 22:19:52 +08001301}
Peng Fana35215d2020-07-09 13:39:26 +08001302
1303#if defined(CONFIG_SPL_BUILD)
1304#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1305bool serror_need_skip = true;
1306
Sean Anderson2d755492022-03-22 17:17:35 -04001307void do_error(struct pt_regs *pt_regs)
Peng Fana35215d2020-07-09 13:39:26 +08001308{
1309 /*
1310 * If stack is still in ROM reserved OCRAM not switch to SPL,
1311 * it is the ROM SError
1312 */
1313 ulong sp;
1314
1315 asm volatile("mov %0, sp" : "=r"(sp) : );
1316
1317 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1318 /* Check for ERR050342, imx8mq HDCP enabled parts */
1319 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1320 serror_need_skip = false;
1321 return; /* Do nothing skip the SError in ROM */
1322 }
1323
1324 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1325 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1326 serror_need_skip = false;
1327 return; /* Do nothing skip the SError in ROM */
1328 }
1329 }
1330
1331 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -04001332 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fana35215d2020-07-09 13:39:26 +08001333 show_regs(pt_regs);
1334 panic("Resetting CPU ...\n");
1335}
1336#endif
1337#endif
Ye Li0513f362019-07-15 01:16:46 -07001338
1339#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
1340enum env_location env_get_location(enum env_operation op, int prio)
1341{
1342 enum boot_device dev = get_boot_device();
Ye Li0513f362019-07-15 01:16:46 -07001343
1344 if (prio)
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001345 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001346
1347 switch (dev) {
Ye Li0513f362019-07-15 01:16:46 -07001348 case QSPI_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001349 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1350 return ENVL_SPI_FLASH;
1351 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001352 case NAND_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001353 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1354 return ENVL_NAND;
1355 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001356 case SD1_BOOT:
1357 case SD2_BOOT:
1358 case SD3_BOOT:
1359 case MMC1_BOOT:
1360 case MMC2_BOOT:
1361 case MMC3_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001362 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1363 return ENVL_MMC;
1364 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1365 return ENVL_EXT4;
1366 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1367 return ENVL_FAT;
1368 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001369 default:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001370 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001371 }
Ye Li0513f362019-07-15 01:16:46 -07001372}
1373
Ye Li0513f362019-07-15 01:16:46 -07001374#endif