blob: be38ca52885027831cefbc57af66872956b1b06b [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Peng Faneae4de22018-01-10 13:20:37 +08002/*
Gaurav Jain81113a02022-03-24 11:50:27 +05303 * Copyright 2017-2019, 2021 NXP
Peng Faneae4de22018-01-10 13:20:37 +08004 *
5 * Peng Fan <peng.fan@nxp.com>
Peng Faneae4de22018-01-10 13:20:37 +08006 */
7
Tom Rinidec7ea02024-05-20 13:35:03 -06008#include <config.h>
Simon Glass1d91ba72019-11-14 12:57:37 -07009#include <cpu_func.h>
Simon Glassfc557362022-03-04 08:43:05 -070010#include <event.h>
Simon Glass97589732020-05-10 11:40:02 -060011#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Peng Faneae4de22018-01-10 13:20:37 +080013#include <asm/arch/imx-regs.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060014#include <asm/global_data.h>
Peng Faneae4de22018-01-10 13:20:37 +080015#include <asm/io.h>
16#include <asm/arch/clock.h>
17#include <asm/arch/sys_proto.h>
18#include <asm/mach-imx/hab.h>
19#include <asm/mach-imx/boot_mode.h>
20#include <asm/mach-imx/syscounter.h>
Peng Fana35215d2020-07-09 13:39:26 +080021#include <asm/ptrace.h>
Peng Faneae4de22018-01-10 13:20:37 +080022#include <asm/armv8/mmu.h>
Peng Fanc98e0322019-08-27 06:25:58 +000023#include <dm/uclass.h>
Gaurav Jain81113a02022-03-24 11:50:27 +053024#include <dm/device.h>
Peng Fana35215d2020-07-09 13:39:26 +080025#include <efi_loader.h>
Ye Li0513f362019-07-15 01:16:46 -070026#include <env.h>
27#include <env_internal.h>
Peng Faneae4de22018-01-10 13:20:37 +080028#include <errno.h>
29#include <fdt_support.h>
30#include <fsl_wdog.h>
Fedor Rossed2f94a2023-10-16 18:16:14 +020031#include <fuse.h>
Peng Faneae4de22018-01-10 13:20:37 +080032#include <imx_sip.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060033#include <linux/bitops.h>
Fedor Rossed2f94a2023-10-16 18:16:14 +020034#include <linux/bitfield.h>
Peng Faneae4de22018-01-10 13:20:37 +080035
36DECLARE_GLOBAL_DATA_PTR;
37
Stefano Babicf8b509b2019-09-20 08:47:53 +020038#if defined(CONFIG_IMX_HAB)
Peng Faneae4de22018-01-10 13:20:37 +080039struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
40 .bank = 1,
41 .word = 3,
42};
43#endif
44
45int timer_init(void)
46{
47#ifdef CONFIG_SPL_BUILD
48 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
49 unsigned long freq = readl(&sctr->cntfid0);
50
51 /* Update with accurate clock frequency */
52 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
53
54 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
55 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
56#endif
57
58 gd->arch.tbl = 0;
59 gd->arch.tbu = 0;
60
61 return 0;
62}
63
64void enable_tzc380(void)
65{
66 struct iomuxc_gpr_base_regs *gpr =
67 (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
68
69 /* Enable TZASC and lock setting */
70 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN);
71 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010072
73 /*
74 * According to TRM, TZASC_ID_SWAP_BYPASS should be set in
75 * order to avoid AXI Bus errors when GPU is in use
76 */
Peng Fanda7a16c2022-04-29 16:18:49 +080077 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010078
79 /*
80 * imx8mn and imx8mp implements the lock bit for
81 * TZASC_ID_SWAP_BYPASS, enable it to lock settings
82 */
Peng Fanda7a16c2022-04-29 16:18:49 +080083 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS_LOCK);
Andrey Zhizhikin7c2d23a2022-01-24 21:48:09 +010084
Ye Li4c97c462019-08-27 06:25:34 +000085 /*
86 * set Region 0 attribute to allow secure and non-secure
87 * read/write permission. Found some masters like usb dwc3
88 * controllers can't work with secure memory.
89 */
90 writel(0xf0000000, TZASC_BASE_ADDR + 0x108);
Peng Faneae4de22018-01-10 13:20:37 +080091}
92
93void set_wdog_reset(struct wdog_regs *wdog)
94{
95 /*
96 * Output WDOG_B signal to reset external pmic or POR_B decided by
97 * the board design. Without external reset, the peripherals/DDR/
98 * PMIC are not reset, that may cause system working abnormal.
99 * WDZST bit is write-once only bit. Align this bit in kernel,
100 * otherwise kernel code will have no chance to set this bit.
101 */
102 setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK);
103}
104
Marek Vasut003969b2022-12-22 01:46:40 +0100105#ifdef CONFIG_ARMV8_PSCI
106#define PTE_MAP_NS PTE_BLOCK_NS
107#else
108#define PTE_MAP_NS 0
109#endif
110
Peng Faneae4de22018-01-10 13:20:37 +0800111static struct mm_region imx8m_mem_map[] = {
112 {
113 /* ROM */
114 .virt = 0x0UL,
115 .phys = 0x0UL,
116 .size = 0x100000UL,
117 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
118 PTE_BLOCK_OUTER_SHARE
119 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100120 /* CAAM */
121 .virt = 0x100000UL,
122 .phys = 0x100000UL,
123 .size = 0x8000UL,
124 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
125 PTE_BLOCK_NON_SHARE |
126 PTE_BLOCK_PXN | PTE_BLOCK_UXN
127 }, {
Marek Vasutb1738e02021-02-25 21:52:26 +0100128 /* OCRAM_S */
129 .virt = 0x180000UL,
130 .phys = 0x180000UL,
131 .size = 0x8000UL,
132 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100133 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Marek Vasutb1738e02021-02-25 21:52:26 +0100134 }, {
Gary Bisson5c72a452018-11-14 17:55:28 +0100135 /* TCM */
136 .virt = 0x7C0000UL,
137 .phys = 0x7C0000UL,
138 .size = 0x80000UL,
139 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
140 PTE_BLOCK_NON_SHARE |
Marek Vasut003969b2022-12-22 01:46:40 +0100141 PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_MAP_NS
Gary Bisson5c72a452018-11-14 17:55:28 +0100142 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800143 /* OCRAM */
144 .virt = 0x900000UL,
145 .phys = 0x900000UL,
146 .size = 0x200000UL,
147 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100148 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Faneae4de22018-01-10 13:20:37 +0800149 }, {
150 /* AIPS */
151 .virt = 0xB00000UL,
152 .phys = 0xB00000UL,
153 .size = 0x3f500000UL,
154 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
155 PTE_BLOCK_NON_SHARE |
156 PTE_BLOCK_PXN | PTE_BLOCK_UXN
157 }, {
158 /* DRAM1 */
159 .virt = 0x40000000UL,
160 .phys = 0x40000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000161 .size = PHYS_SDRAM_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800162 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100163 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fanb749b5e2019-08-27 06:25:27 +0000164#ifdef PHYS_SDRAM_2_SIZE
Peng Faneae4de22018-01-10 13:20:37 +0800165 }, {
166 /* DRAM2 */
167 .virt = 0x100000000UL,
168 .phys = 0x100000000UL,
Peng Fanb749b5e2019-08-27 06:25:27 +0000169 .size = PHYS_SDRAM_2_SIZE,
Peng Faneae4de22018-01-10 13:20:37 +0800170 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut003969b2022-12-22 01:46:40 +0100171 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fanb749b5e2019-08-27 06:25:27 +0000172#endif
Peng Faneae4de22018-01-10 13:20:37 +0800173 }, {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800174 /* empty entrie to split table entry 5 if needed when TEEs are used */
175 0,
176 }, {
Peng Faneae4de22018-01-10 13:20:37 +0800177 /* List terminator */
178 0,
179 }
180};
181
182struct mm_region *mem_map = imx8m_mem_map;
183
Marek Vasute48aac02021-02-27 14:59:00 +0100184static unsigned int imx8m_find_dram_entry_in_mem_map(void)
185{
186 int i;
187
188 for (i = 0; i < ARRAY_SIZE(imx8m_mem_map); i++)
Tom Rinibb4dd962022-11-16 13:10:37 -0500189 if (imx8m_mem_map[i].phys == CFG_SYS_SDRAM_BASE)
Marek Vasute48aac02021-02-27 14:59:00 +0100190 return i;
191
192 hang(); /* Entry not found, this must never happen. */
193}
194
Peng Fanb749b5e2019-08-27 06:25:27 +0000195void enable_caches(void)
196{
Ye Li453bfcb2022-04-07 15:55:56 +0800197 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
198 * If OPTEE does not run, still update the MMU table according to dram banks structure
199 * to set correct dram size from board_phys_sdram_size
200 */
201 int i = 0;
202 /*
203 * please make sure that entry initial value matches
204 * imx8m_mem_map for DRAM1
205 */
206 int entry = imx8m_find_dram_entry_in_mem_map();
207 u64 attrs = imx8m_mem_map[entry].attrs;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800208
Ye Li453bfcb2022-04-07 15:55:56 +0800209 while (i < CONFIG_NR_DRAM_BANKS &&
210 entry < ARRAY_SIZE(imx8m_mem_map)) {
211 if (gd->bd->bi_dram[i].start == 0)
212 break;
213 imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start;
214 imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start;
215 imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size;
216 imx8m_mem_map[entry].attrs = attrs;
217 debug("Added memory mapping (%d): %llx %llx\n", entry,
218 imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size);
219 i++; entry++;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800220 }
Peng Fanb749b5e2019-08-27 06:25:27 +0000221
222 icache_enable();
223 dcache_enable();
224}
225
Peng Fanfa35c3d2020-07-09 15:26:06 +0800226__weak int board_phys_sdram_size(phys_size_t *size)
227{
228 if (!size)
229 return -EINVAL;
230
231 *size = PHYS_SDRAM_SIZE;
Ye Li453bfcb2022-04-07 15:55:56 +0800232
233#ifdef PHYS_SDRAM_2_SIZE
234 *size += PHYS_SDRAM_2_SIZE;
235#endif
Peng Fanfa35c3d2020-07-09 15:26:06 +0800236 return 0;
237}
238
239int dram_init(void)
240{
241 phys_size_t sdram_size;
242 int ret;
243
244 ret = board_phys_sdram_size(&sdram_size);
245 if (ret)
246 return ret;
247
248 /* rom_pointer[1] contains the size of TEE occupies */
Elena Popa65c9edb2023-08-08 14:58:26 +0300249 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_SPL_BUILD) && rom_pointer[1])
Peng Fanfa35c3d2020-07-09 15:26:06 +0800250 gd->ram_size = sdram_size - rom_pointer[1];
251 else
252 gd->ram_size = sdram_size;
253
Peng Fanfa35c3d2020-07-09 15:26:06 +0800254 return 0;
255}
256
257int dram_init_banksize(void)
258{
259 int bank = 0;
260 int ret;
261 phys_size_t sdram_size;
Ye Li453bfcb2022-04-07 15:55:56 +0800262 phys_size_t sdram_b1_size, sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800263
264 ret = board_phys_sdram_size(&sdram_size);
265 if (ret)
266 return ret;
267
Ye Li453bfcb2022-04-07 15:55:56 +0800268 /* Bank 1 can't cross over 4GB space */
269 if (sdram_size > 0xc0000000) {
270 sdram_b1_size = 0xc0000000;
271 sdram_b2_size = sdram_size - 0xc0000000;
272 } else {
273 sdram_b1_size = sdram_size;
274 sdram_b2_size = 0;
275 }
276
Peng Fanfa35c3d2020-07-09 15:26:06 +0800277 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
Elena Popa65c9edb2023-08-08 14:58:26 +0300278 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_SPL_BUILD) && rom_pointer[1]) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800279 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
280 phys_size_t optee_size = (size_t)rom_pointer[1];
281
282 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
Ye Li453bfcb2022-04-07 15:55:56 +0800283 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
Peng Fanfa35c3d2020-07-09 15:26:06 +0800284 if (++bank >= CONFIG_NR_DRAM_BANKS) {
285 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
286 return -1;
287 }
288
289 gd->bd->bi_dram[bank].start = optee_start + optee_size;
290 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
Ye Li453bfcb2022-04-07 15:55:56 +0800291 sdram_b1_size - gd->bd->bi_dram[bank].start;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800292 }
293 } else {
Ye Li453bfcb2022-04-07 15:55:56 +0800294 gd->bd->bi_dram[bank].size = sdram_b1_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800295 }
296
Ye Li453bfcb2022-04-07 15:55:56 +0800297 if (sdram_b2_size) {
298 if (++bank >= CONFIG_NR_DRAM_BANKS) {
299 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
300 return -1;
301 }
302 gd->bd->bi_dram[bank].start = 0x100000000UL;
303 gd->bd->bi_dram[bank].size = sdram_b2_size;
Peng Fanfa35c3d2020-07-09 15:26:06 +0800304 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800305
306 return 0;
307}
308
309phys_size_t get_effective_memsize(void)
310{
Ye Li453bfcb2022-04-07 15:55:56 +0800311 int ret;
312 phys_size_t sdram_size;
313 phys_size_t sdram_b1_size;
314 ret = board_phys_sdram_size(&sdram_size);
315 if (!ret) {
316 /* Bank 1 can't cross over 4GB space */
317 if (sdram_size > 0xc0000000) {
318 sdram_b1_size = 0xc0000000;
319 } else {
320 sdram_b1_size = sdram_size;
321 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800322
Elena Popa65c9edb2023-08-08 14:58:26 +0300323 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && !IS_ENABLED(CONFIG_SPL_BUILD) &&
324 rom_pointer[1]) {
Ye Li453bfcb2022-04-07 15:55:56 +0800325 /* We will relocate u-boot to Top of dram1. Tee position has two cases:
326 * 1. At the top of dram1, Then return the size removed optee size.
327 * 2. In the middle of dram1, return the size of dram1.
328 */
329 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
330 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
331 }
332
333 return sdram_b1_size;
334 } else {
335 return PHYS_SDRAM_SIZE;
336 }
Peng Fanfa35c3d2020-07-09 15:26:06 +0800337}
338
Heinrich Schuchardt51a9aac2023-08-12 20:16:58 +0200339phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Frieder Schrempf159879e2021-06-07 14:36:44 +0200340{
Marek Vasutdcbbf782022-04-14 15:51:46 +0200341 ulong top_addr;
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800342
Frieder Schrempf159879e2021-06-07 14:36:44 +0200343 /*
344 * Some IPs have their accessible address space restricted by
345 * the interconnect. Let's make sure U-Boot only ever uses the
346 * space below the 4G address boundary (which is 3GiB big),
347 * even when the effective available memory is bigger.
348 */
Marek Vasutdcbbf782022-04-14 15:51:46 +0200349 top_addr = clamp_val((u64)PHYS_SDRAM + gd->ram_size, 0, 0xffffffff);
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800350
351 /*
352 * rom_pointer[0] stores the TEE memory start address.
353 * rom_pointer[1] stores the size TEE uses.
354 * We need to reserve the memory region for TEE.
355 */
Marek Vasut9ca966e2022-12-22 01:46:38 +0100356 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && rom_pointer[0] &&
357 rom_pointer[1] && top_addr > rom_pointer[0])
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800358 top_addr = rom_pointer[0];
Frieder Schrempf159879e2021-06-07 14:36:44 +0200359
Ying-Chun Liu (PaulLiu)ed55caf2021-08-23 10:43:06 +0800360 return top_addr;
Frieder Schrempf159879e2021-06-07 14:36:44 +0200361}
362
Peng Fan1caffdf2019-08-27 06:25:17 +0000363static u32 get_cpu_variant_type(u32 type)
364{
365 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
366 struct fuse_bank *bank = &ocotp->bank[1];
367 struct fuse_bank1_regs *fuse =
368 (struct fuse_bank1_regs *)bank->fuse_regs;
369
370 u32 value = readl(&fuse->tester4);
371
Peng Fan67815082020-02-05 17:34:54 +0800372 if (type == MXC_CPU_IMX8MQ) {
373 if ((value & 0x3) == 0x2)
374 return MXC_CPU_IMX8MD;
375 else if (value & 0x200000)
376 return MXC_CPU_IMX8MQL;
377
378 } else if (type == MXC_CPU_IMX8MM) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000379 switch (value & 0x3) {
380 case 2:
381 if (value & 0x1c0000)
382 return MXC_CPU_IMX8MMDL;
383 else
384 return MXC_CPU_IMX8MMD;
385 case 3:
386 if (value & 0x1c0000)
387 return MXC_CPU_IMX8MMSL;
388 else
389 return MXC_CPU_IMX8MMS;
390 default:
391 if (value & 0x1c0000)
392 return MXC_CPU_IMX8MML;
393 break;
394 }
Peng Fan1a07d912020-02-05 17:39:27 +0800395 } else if (type == MXC_CPU_IMX8MN) {
396 switch (value & 0x3) {
397 case 2:
Ye Li715180e2021-03-19 15:57:11 +0800398 if (value & 0x1000000) {
399 if (value & 0x10000000) /* MIPI DSI */
400 return MXC_CPU_IMX8MNUD;
401 else
402 return MXC_CPU_IMX8MNDL;
403 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800404 return MXC_CPU_IMX8MND;
Ye Li715180e2021-03-19 15:57:11 +0800405 }
Peng Fan1a07d912020-02-05 17:39:27 +0800406 case 3:
Ye Li715180e2021-03-19 15:57:11 +0800407 if (value & 0x1000000) {
408 if (value & 0x10000000) /* MIPI DSI */
409 return MXC_CPU_IMX8MNUS;
410 else
411 return MXC_CPU_IMX8MNSL;
412 } else {
Peng Fan1a07d912020-02-05 17:39:27 +0800413 return MXC_CPU_IMX8MNS;
Ye Li715180e2021-03-19 15:57:11 +0800414 }
Peng Fan1a07d912020-02-05 17:39:27 +0800415 default:
Ye Li715180e2021-03-19 15:57:11 +0800416 if (value & 0x1000000) {
417 if (value & 0x10000000) /* MIPI DSI */
418 return MXC_CPU_IMX8MNUQ;
419 else
420 return MXC_CPU_IMX8MNL;
421 }
Peng Fan1a07d912020-02-05 17:39:27 +0800422 break;
423 }
Ye Lid2d754f2020-04-20 20:12:54 -0700424 } else if (type == MXC_CPU_IMX8MP) {
425 u32 value0 = readl(&fuse->tester3);
426 u32 flag = 0;
427
428 if ((value0 & 0xc0000) == 0x80000)
429 return MXC_CPU_IMX8MPD;
430
431 /* vpu disabled */
432 if ((value0 & 0x43000000) == 0x43000000)
433 flag = 1;
434
435 /* npu disabled*/
436 if ((value & 0x8) == 0x8)
Peng Fan0386e7f2022-04-07 15:55:52 +0800437 flag |= BIT(1);
Ye Lid2d754f2020-04-20 20:12:54 -0700438
439 /* isp disabled */
440 if ((value & 0x3) == 0x3)
Peng Fan0386e7f2022-04-07 15:55:52 +0800441 flag |= BIT(2);
442
443 /* gpu disabled */
444 if ((value & 0xc0) == 0xc0)
445 flag |= BIT(3);
446
447 /* lvds disabled */
448 if ((value & 0x180000) == 0x180000)
449 flag |= BIT(4);
450
451 /* mipi dsi disabled */
452 if ((value & 0x60000) == 0x60000)
453 flag |= BIT(5);
Ye Lid2d754f2020-04-20 20:12:54 -0700454
455 switch (flag) {
Peng Fan0386e7f2022-04-07 15:55:52 +0800456 case 0x3f:
457 return MXC_CPU_IMX8MPUL;
Ye Lid2d754f2020-04-20 20:12:54 -0700458 case 7:
459 return MXC_CPU_IMX8MPL;
Ye Lid2d754f2020-04-20 20:12:54 -0700460 case 2:
461 return MXC_CPU_IMX8MP6;
Ye Lid2d754f2020-04-20 20:12:54 -0700462 default:
463 break;
464 }
465
Peng Fan1caffdf2019-08-27 06:25:17 +0000466 }
467
468 return type;
469}
470
Peng Faneae4de22018-01-10 13:20:37 +0800471u32 get_cpu_rev(void)
472{
473 struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
474 u32 reg = readl(&ana_pll->digprog);
475 u32 type = (reg >> 16) & 0xff;
Peng Fan1caffdf2019-08-27 06:25:17 +0000476 u32 major_low = (reg >> 8) & 0xff;
Peng Faneae4de22018-01-10 13:20:37 +0800477 u32 rom_version;
478
479 reg &= 0xff;
480
Peng Fan69cec072019-12-27 10:14:02 +0800481 /* iMX8MP */
482 if (major_low == 0x43) {
Ye Lid2d754f2020-04-20 20:12:54 -0700483 type = get_cpu_variant_type(MXC_CPU_IMX8MP);
Peng Fan69cec072019-12-27 10:14:02 +0800484 } else if (major_low == 0x42) {
485 /* iMX8MN */
Peng Fan1a07d912020-02-05 17:39:27 +0800486 type = get_cpu_variant_type(MXC_CPU_IMX8MN);
Peng Fan5d2f2062019-06-27 17:23:49 +0800487 } else if (major_low == 0x41) {
Peng Fan1caffdf2019-08-27 06:25:17 +0000488 type = get_cpu_variant_type(MXC_CPU_IMX8MM);
489 } else {
490 if (reg == CHIP_REV_1_0) {
491 /*
Peng Fanc23fbdd2019-10-16 10:24:17 +0000492 * For B0 chip, the DIGPROG is not updated,
493 * it is still TO1.0. we have to check ROM
494 * version or OCOTP_READ_FUSE_DATA.
495 * 0xff0055aa is magic number for B1.
Peng Fan1caffdf2019-08-27 06:25:17 +0000496 */
Peng Fanc23fbdd2019-10-16 10:24:17 +0000497 if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
Ye Lic963ed12021-03-19 15:57:16 +0800498 /*
499 * B2 uses same DIGPROG and OCOTP_READ_FUSE_DATA value with B1,
500 * so have to check ROM to distinguish them
501 */
502 rom_version = readl((void __iomem *)ROM_VERSION_B0);
503 rom_version &= 0xff;
504 if (rom_version == CHIP_REV_2_2)
505 reg = CHIP_REV_2_2;
506 else
507 reg = CHIP_REV_2_1;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000508 } else {
509 rom_version =
510 readl((void __iomem *)ROM_VERSION_A0);
511 if (rom_version != CHIP_REV_1_0) {
512 rom_version = readl((void __iomem *)ROM_VERSION_B0);
Patrick Wildtd4a78b92019-11-19 09:42:06 +0100513 rom_version &= 0xff;
Peng Fanc23fbdd2019-10-16 10:24:17 +0000514 if (rom_version == CHIP_REV_2_0)
515 reg = CHIP_REV_2_0;
516 }
Peng Fan1caffdf2019-08-27 06:25:17 +0000517 }
Peng Faneae4de22018-01-10 13:20:37 +0800518 }
Peng Fan67815082020-02-05 17:34:54 +0800519
520 type = get_cpu_variant_type(type);
Peng Faneae4de22018-01-10 13:20:37 +0800521 }
522
523 return (type << 12) | reg;
524}
525
526static void imx_set_wdog_powerdown(bool enable)
527{
528 struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
529 struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
530 struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
531
532 /* Write to the PDE (Power Down Enable) bit */
533 writew(enable, &wdog1->wmcr);
534 writew(enable, &wdog2->wmcr);
535 writew(enable, &wdog3->wmcr);
536}
537
Simon Glassb8357c12023-08-21 21:16:56 -0600538static int imx8m_check_clock(void)
Peng Fanc98e0322019-08-27 06:25:58 +0000539{
540 struct udevice *dev;
541 int ret;
542
Peng Fan3c073342019-10-16 03:01:51 +0000543 if (CONFIG_IS_ENABLED(CLK)) {
544 ret = uclass_get_device_by_name(UCLASS_CLK,
545 "clock-controller@30380000",
546 &dev);
547 if (ret < 0) {
548 printf("Failed to find clock node. Check device tree\n");
549 return ret;
550 }
Peng Fanc98e0322019-08-27 06:25:58 +0000551 }
552
553 return 0;
554}
Simon Glassb8357c12023-08-21 21:16:56 -0600555EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, imx8m_check_clock);
Peng Fanc98e0322019-08-27 06:25:58 +0000556
Marek Vasutf7b184e2022-09-19 21:37:07 +0200557static void imx8m_setup_snvs(void)
558{
559 /* Enable SNVS clock */
560 clock_enable(CCGR_SNVS, 1);
561 /* Initialize glitch detect */
562 writel(SNVS_LPPGDR_INIT, SNVS_BASE_ADDR + SNVS_LPLVDR);
563 /* Clear interrupt status */
564 writel(0xffffffff, SNVS_BASE_ADDR + SNVS_LPSR);
565}
566
Marek Vasut829858a2022-12-22 01:46:42 +0100567static void imx8m_setup_csu_tzasc(void)
568{
569 const uintptr_t tzasc_base[4] = {
570 0x301f0000, 0x301f0000, 0x301f0000, 0x301f0000
571 };
572 int i, j;
573
574 if (!IS_ENABLED(CONFIG_ARMV8_PSCI))
575 return;
576
577 /* CSU */
578 for (i = 0; i < 64; i++)
579 writel(0x00ff00ff, (void *)CSU_BASE_ADDR + (4 * i));
580
581 /* TZASC */
582 for (j = 0; j < 4; j++) {
583 writel(0x77777777, (void *)(tzasc_base[j]));
584 writel(0x77777777, (void *)(tzasc_base[j]) + 0x4);
585 for (i = 0; i <= 0x10; i += 4)
586 writel(0, (void *)(tzasc_base[j]) + 0x40 + i);
587 }
588}
589
Peng Faneae4de22018-01-10 13:20:37 +0800590int arch_cpu_init(void)
591{
Peng Fanc0b30d72019-04-17 09:41:16 +0000592 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
Marek Vasut3ea500a2022-04-13 00:41:52 +0200593
594#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
595 icache_enable();
596#endif
597
Peng Faneae4de22018-01-10 13:20:37 +0800598 /*
Peng Fand0ca2892019-08-27 06:25:37 +0000599 * ROM might disable clock for SCTR,
600 * enable the clock before timer_init.
601 */
602 if (IS_ENABLED(CONFIG_SPL_BUILD))
603 clock_enable(CCGR_SCTR, 1);
604 /*
Peng Faneae4de22018-01-10 13:20:37 +0800605 * Init timer at very early state, because sscg pll setting
606 * will use it
607 */
608 timer_init();
609
610 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
611 clock_init();
612 imx_set_wdog_powerdown(false);
Peng Fan9cf2aa32020-07-09 13:52:41 +0800613
614 if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
615 is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
Ye Li715180e2021-03-19 15:57:11 +0800616 is_imx8mnsl() || is_imx8mpd() || is_imx8mnud() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800617 /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
618 struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
619 struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
620 struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0);
621 struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR;
622
623 writel(0x1, &pgc_core2->pgcr);
624 writel(0x1, &pgc_core3->pgcr);
Ye Li715180e2021-03-19 15:57:11 +0800625 if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) {
Peng Fan9cf2aa32020-07-09 13:52:41 +0800626 writel(0x1, &pgc_core1->pgcr);
627 writel(0xE, &gpc->cpu_pgc_dn_trg);
628 } else {
629 writel(0xC, &gpc->cpu_pgc_dn_trg);
630 }
631 }
Peng Faneae4de22018-01-10 13:20:37 +0800632 }
633
Peng Fanc0b30d72019-04-17 09:41:16 +0000634 if (is_imx8mq()) {
635 clock_enable(CCGR_OCOTP, 1);
636 if (readl(&ocotp->ctrl) & 0x200)
637 writel(0x200, &ocotp->ctrl_clr);
638 }
639
Marek Vasutf7b184e2022-09-19 21:37:07 +0200640 imx8m_setup_snvs();
641
Marek Vasut829858a2022-12-22 01:46:42 +0100642 imx8m_setup_csu_tzasc();
643
Peng Faneae4de22018-01-10 13:20:37 +0800644 return 0;
645}
646
Peng Fanc9823b02019-09-16 03:09:36 +0000647#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
648struct rom_api *g_rom_api = (struct rom_api *)0x980;
Peng Fanc9823b02019-09-16 03:09:36 +0000649#endif
650
Marek Vasut520ded02021-07-03 04:55:33 +0200651#if defined(CONFIG_IMX8M)
652#include <spl.h>
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200653int imx8m_detect_secondary_image_boot(void)
Marek Vasut520ded02021-07-03 04:55:33 +0200654{
655 u32 *rom_log_addr = (u32 *)0x9e0;
656 u32 *rom_log;
657 u8 event_id;
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200658 int i, boot_secondary = 0;
Marek Vasut520ded02021-07-03 04:55:33 +0200659
660 /* If the ROM event log pointer is not valid. */
661 if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 ||
662 *rom_log_addr & 0x3)
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200663 return -EINVAL;
Marek Vasut520ded02021-07-03 04:55:33 +0200664
665 /* Parse the ROM event ID version 2 log */
666 rom_log = (u32 *)(uintptr_t)(*rom_log_addr);
667 for (i = 0; i < 128; i++) {
668 event_id = rom_log[i] >> 24;
669 switch (event_id) {
670 case 0x00: /* End of list */
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200671 return boot_secondary;
Marek Vasut520ded02021-07-03 04:55:33 +0200672 /* Log entries with 1 parameter, skip 1 */
673 case 0x80: /* Start to perform the device initialization */
674 case 0x81: /* The boot device initialization completes */
Fedor Ross7e02ff62022-04-14 18:36:23 +0200675 case 0x82: /* Starts to execute boot device driver pre-config */
Marek Vasut520ded02021-07-03 04:55:33 +0200676 case 0x8f: /* The boot device initialization fails */
677 case 0x90: /* Start to read data from boot device */
678 case 0x91: /* Reading data from boot device completes */
679 case 0x9f: /* Reading data from boot device fails */
680 i += 1;
681 continue;
682 /* Log entries with 2 parameters, skip 2 */
683 case 0xa0: /* Image authentication result */
684 case 0xc0: /* Jump to the boot image soon */
685 i += 2;
686 continue;
687 /* Boot from the secondary boot image */
688 case 0x51:
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200689 boot_secondary = 1;
Marek Vasut520ded02021-07-03 04:55:33 +0200690 continue;
691 default:
692 continue;
693 }
694 }
695
Fedor Ross5bc5f0e2023-10-16 18:16:13 +0200696 return boot_secondary;
697}
698
699int spl_mmc_emmc_boot_partition(struct mmc *mmc)
700{
701 int part, ret;
702
703 part = default_spl_mmc_emmc_boot_partition(mmc);
704 if (part == 0)
705 return part;
706
707 ret = imx8m_detect_secondary_image_boot();
708 if (ret < 0) {
709 printf("Could not get boot partition! Using %d\n", part);
710 return part;
711 }
712
713 if (ret == 1) {
714 /*
715 * Swap the eMMC boot partitions in case there was a
716 * fallback event (i.e. primary image was corrupted
717 * and that corruption was recognized by the BootROM),
718 * so the SPL loads the rest of the U-Boot from the
719 * correct eMMC boot partition, since the BootROM
720 * leaves the boot partition set to the corrupted one.
721 */
722 if (part == 1)
723 part = 2;
724 else if (part == 2)
725 part = 1;
726 }
727
Marek Vasut520ded02021-07-03 04:55:33 +0200728 return part;
729}
Fedor Rossc0b94842023-10-16 18:16:15 +0200730
731int boot_mode_getprisec(void)
732{
733 return !!imx8m_detect_secondary_image_boot();
734}
Marek Vasut520ded02021-07-03 04:55:33 +0200735#endif
736
Fedor Rossed2f94a2023-10-16 18:16:14 +0200737#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
738#define IMG_CNTN_SET1_OFFSET GENMASK(22, 19)
739unsigned long arch_spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
740 unsigned long raw_sect)
741{
742 u32 val, offset;
743
744 if (fuse_read(2, 1, &val)) {
745 debug("Error reading fuse!\n");
746 return raw_sect;
747 }
748
749 val = FIELD_GET(IMG_CNTN_SET1_OFFSET, val);
750 if (val > 10) {
751 debug("Secondary image boot disabled!\n");
752 return raw_sect;
753 }
754
755 if (val == 0)
756 offset = SZ_4M;
757 else if (val == 1)
758 offset = SZ_2M;
759 else if (val == 2)
760 offset = SZ_1M;
761 else /* flash.bin offset = 1 MiB * 2^n */
762 offset = SZ_1M << val;
763
764 offset /= 512;
765 offset -= CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET;
766
767 if (imx8m_detect_secondary_image_boot())
768 raw_sect += offset;
769
770 return raw_sect;
771}
772#endif
773
Peng Faneae4de22018-01-10 13:20:37 +0800774bool is_usb_boot(void)
775{
776 return get_boot_device() == USB_BOOT;
777}
778
779#ifdef CONFIG_OF_SYSTEM_SETUP
Peng Fan435dc122020-07-09 14:06:49 +0800780bool check_fdt_new_path(void *blob)
781{
782 const char *soc_path = "/soc@0";
783 int nodeoff;
784
785 nodeoff = fdt_path_offset(blob, soc_path);
786 if (nodeoff < 0)
787 return false;
788
789 return true;
790}
791
792static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
793{
794 int i = 0;
795 int rc;
796 int nodeoff;
797 const char *status = "disabled";
798
799 for (i = 0; i < size_array; i++) {
800 nodeoff = fdt_path_offset(blob, nodes_path[i]);
801 if (nodeoff < 0)
802 continue; /* Not found, skip it */
803
Rasmus Villemoes8ab149a2023-05-22 11:27:28 +0200804 debug("Found %s node\n", nodes_path[i]);
Peng Fan435dc122020-07-09 14:06:49 +0800805
806add_status:
807 rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
808 if (rc) {
809 if (rc == -FDT_ERR_NOSPACE) {
810 rc = fdt_increase_size(blob, 512);
811 if (!rc)
812 goto add_status;
813 }
814 printf("Unable to update property %s:%s, err=%s\n",
815 nodes_path[i], "status", fdt_strerror(rc));
816 } else {
817 printf("Modify %s:%s disabled\n",
818 nodes_path[i], "status");
819 }
820 }
821
822 return 0;
823}
824
825#ifdef CONFIG_IMX8MQ
826bool check_dcss_fused(void)
827{
828 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
829 struct fuse_bank *bank = &ocotp->bank[1];
830 struct fuse_bank1_regs *fuse =
831 (struct fuse_bank1_regs *)bank->fuse_regs;
832 u32 value = readl(&fuse->tester4);
833
834 if (value & 0x4000000)
835 return true;
836
837 return false;
838}
839
840static int disable_mipi_dsi_nodes(void *blob)
841{
842 static const char * const nodes_path[] = {
843 "/mipi_dsi@30A00000",
844 "/mipi_dsi_bridge@30A00000",
845 "/dsi_phy@30A00300",
846 "/soc@0/bus@30800000/mipi_dsi@30a00000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800847 "/soc@0/bus@30800000/dphy@30a00300",
848 "/soc@0/bus@30800000/mipi-dsi@30a00000",
Peng Fan435dc122020-07-09 14:06:49 +0800849 };
850
851 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
852}
853
854static int disable_dcss_nodes(void *blob)
855{
856 static const char * const nodes_path[] = {
857 "/dcss@0x32e00000",
858 "/dcss@32e00000",
859 "/hdmi@32c00000",
860 "/hdmi_cec@32c33800",
861 "/hdmi_drm@32c00000",
862 "/display-subsystem",
863 "/sound-hdmi",
864 "/sound-hdmi-arc",
865 "/soc@0/bus@32c00000/display-controller@32e00000",
866 "/soc@0/bus@32c00000/hdmi@32c00000",
867 };
868
869 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
870}
871
872static int check_mipi_dsi_nodes(void *blob)
873{
874 static const char * const lcdif_path[] = {
875 "/lcdif@30320000",
Peng Fan7d4195c2021-03-19 15:57:13 +0800876 "/soc@0/bus@30000000/lcdif@30320000",
877 "/soc@0/bus@30000000/lcd-controller@30320000"
Peng Fan435dc122020-07-09 14:06:49 +0800878 };
879 static const char * const mipi_dsi_path[] = {
880 "/mipi_dsi@30A00000",
881 "/soc@0/bus@30800000/mipi_dsi@30a00000"
882 };
883 static const char * const lcdif_ep_path[] = {
884 "/lcdif@30320000/port@0/mipi-dsi-endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800885 "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
886 "/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
Peng Fan435dc122020-07-09 14:06:49 +0800887 };
888 static const char * const mipi_dsi_ep_path[] = {
889 "/mipi_dsi@30A00000/port@1/endpoint",
Peng Fan7d4195c2021-03-19 15:57:13 +0800890 "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
891 "/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
Peng Fan435dc122020-07-09 14:06:49 +0800892 };
893
894 int lookup_node;
895 int nodeoff;
896 bool new_path = check_fdt_new_path(blob);
897 int i = new_path ? 1 : 0;
898
899 nodeoff = fdt_path_offset(blob, lcdif_path[i]);
900 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
901 /*
902 * If can't find lcdif node or lcdif node is disabled,
903 * then disable all mipi dsi, since they only can input
904 * from DCSS
905 */
906 return disable_mipi_dsi_nodes(blob);
907 }
908
909 nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
910 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
911 return 0;
912
913 nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
914 if (nodeoff < 0) {
915 /*
916 * If can't find lcdif endpoint, then disable all mipi dsi,
917 * since they only can input from DCSS
918 */
919 return disable_mipi_dsi_nodes(blob);
920 }
921
922 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
923 nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
924
925 if (nodeoff > 0 && nodeoff == lookup_node)
926 return 0;
927
928 return disable_mipi_dsi_nodes(blob);
929}
930#endif
931
932int disable_vpu_nodes(void *blob)
933{
934 static const char * const nodes_path_8mq[] = {
935 "/vpu@38300000",
Vitor Soares6dd07732024-03-15 14:44:25 +0000936 "/soc@0/vpu@38300000",
937 "/soc@0/video-codec@38300000",
938 "/soc@0/video-codec@38310000",
939 "/soc@0/blk-ctrl@38320000",
Peng Fan435dc122020-07-09 14:06:49 +0800940 };
941
942 static const char * const nodes_path_8mm[] = {
943 "/vpu_g1@38300000",
944 "/vpu_g2@38310000",
Vitor Soares6dd07732024-03-15 14:44:25 +0000945 "/vpu_h1@38320000",
946 "/soc@0/video-codec@38300000",
947 "/soc@0/video-codec@38310000",
948 "/soc@0/blk-ctrl@38330000",
Peng Fan435dc122020-07-09 14:06:49 +0800949 };
950
951 static const char * const nodes_path_8mp[] = {
952 "/vpu_g1@38300000",
953 "/vpu_g2@38310000",
Vitor Soares6dd07732024-03-15 14:44:25 +0000954 "/vpu_vc8000e@38320000",
955 "/soc@0/video-codec@38300000",
956 "/soc@0/video-codec@38310000",
957 "/soc@0/blk-ctrl@38330000",
Peng Fan435dc122020-07-09 14:06:49 +0800958 };
959
960 if (is_imx8mq())
961 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
962 else if (is_imx8mm())
963 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
964 else if (is_imx8mp())
965 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
966 else
967 return -EPERM;
968}
969
Ye Liee337ce2021-03-19 15:57:09 +0800970#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
971static int low_drive_gpu_freq(void *blob)
972{
973 static const char *nodes_path_8mn[] = {
974 "/gpu@38000000",
975 "/soc@0/gpu@38000000"
976 };
977
978 int nodeoff, cnt, i;
979 u32 assignedclks[7];
980
981 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
982 if (nodeoff < 0)
983 return nodeoff;
984
985 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
986 if (cnt < 0)
987 return cnt;
988
989 if (cnt != 7)
990 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
Heinrich Schuchardt72c891f2023-04-18 01:37:21 +0200991 if (cnt < 2)
992 return -1;
Ye Liee337ce2021-03-19 15:57:09 +0800993
994 assignedclks[cnt - 1] = 200000000;
995 assignedclks[cnt - 2] = 200000000;
996
997 for (i = 0; i < cnt; i++) {
998 debug("<%u>, ", assignedclks[i]);
999 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
1000 }
1001 debug("\n");
1002
1003 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
1004}
1005#endif
1006
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001007static bool check_remote_endpoint(void *blob, const char *ep1, const char *ep2)
1008{
1009 int lookup_node;
1010 int nodeoff;
1011
1012 nodeoff = fdt_path_offset(blob, ep1);
1013 if (nodeoff) {
1014 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
1015 nodeoff = fdt_path_offset(blob, ep2);
1016
1017 if (nodeoff > 0 && nodeoff == lookup_node)
1018 return true;
1019 }
1020
1021 return false;
1022}
1023
1024int disable_dsi_lcdif_nodes(void *blob)
1025{
1026 int ret;
1027
1028 static const char * const dsi_path_8mp[] = {
1029 "/soc@0/bus@32c00000/mipi_dsi@32e60000"
1030 };
1031
1032 static const char * const lcdif_path_8mp[] = {
1033 "/soc@0/bus@32c00000/lcd-controller@32e80000"
1034 };
1035
1036 static const char * const lcdif_ep_path_8mp[] = {
1037 "/soc@0/bus@32c00000/lcd-controller@32e80000/port@0/endpoint"
1038 };
1039 static const char * const dsi_ep_path_8mp[] = {
1040 "/soc@0/bus@32c00000/mipi_dsi@32e60000/port@0/endpoint"
1041 };
1042
1043 ret = disable_fdt_nodes(blob, dsi_path_8mp, ARRAY_SIZE(dsi_path_8mp));
1044 if (ret)
1045 return ret;
1046
1047 if (check_remote_endpoint(blob, dsi_ep_path_8mp[0], lcdif_ep_path_8mp[0])) {
1048 /* Disable lcdif node */
1049 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1050 }
1051
1052 return 0;
1053}
1054
1055int disable_lvds_lcdif_nodes(void *blob)
1056{
1057 int ret, i;
1058
1059 static const char * const ldb_path_8mp[] = {
1060 "/soc@0/bus@32c00000/ldb@32ec005c",
1061 "/soc@0/bus@32c00000/phy@32ec0128"
1062 };
1063
1064 static const char * const lcdif_path_8mp[] = {
1065 "/soc@0/bus@32c00000/lcd-controller@32e90000"
1066 };
1067
1068 static const char * const lcdif_ep_path_8mp[] = {
1069 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@0",
1070 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@1"
1071 };
1072 static const char * const ldb_ep_path_8mp[] = {
1073 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@0/port@0/endpoint",
1074 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@1/port@0/endpoint"
1075 };
1076
1077 ret = disable_fdt_nodes(blob, ldb_path_8mp, ARRAY_SIZE(ldb_path_8mp));
1078 if (ret)
1079 return ret;
1080
1081 for (i = 0; i < ARRAY_SIZE(ldb_ep_path_8mp); i++) {
1082 if (check_remote_endpoint(blob, ldb_ep_path_8mp[i], lcdif_ep_path_8mp[i])) {
1083 /* Disable lcdif node */
1084 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1085 }
1086 }
1087
1088 return 0;
1089}
1090
Peng Fan435dc122020-07-09 14:06:49 +08001091int disable_gpu_nodes(void *blob)
1092{
1093 static const char * const nodes_path_8mn[] = {
Peng Fan7d4195c2021-03-19 15:57:13 +08001094 "/gpu@38000000",
1095 "/soc@/gpu@38000000"
Peng Fan435dc122020-07-09 14:06:49 +08001096 };
1097
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001098 static const char * const nodes_path_8mp[] = {
1099 "/gpu3d@38000000",
1100 "/gpu2d@38008000"
1101 };
1102
1103 if (is_imx8mp())
1104 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1105 else
1106 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
Peng Fan435dc122020-07-09 14:06:49 +08001107}
1108
1109int disable_npu_nodes(void *blob)
1110{
1111 static const char * const nodes_path_8mp[] = {
Vitor Soares6dd07732024-03-15 14:44:25 +00001112 "/vipsi@38500000",
1113 "/soc@0/npu@38500000",
Peng Fan435dc122020-07-09 14:06:49 +08001114 };
1115
1116 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1117}
1118
1119int disable_isp_nodes(void *blob)
1120{
1121 static const char * const nodes_path_8mp[] = {
1122 "/soc@0/bus@32c00000/camera/isp@32e10000",
1123 "/soc@0/bus@32c00000/camera/isp@32e20000"
1124 };
1125
1126 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1127}
1128
1129int disable_dsp_nodes(void *blob)
1130{
1131 static const char * const nodes_path_8mp[] = {
1132 "/dsp@3b6e8000"
1133 };
1134
1135 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1136}
1137
Ye Li26517af2021-03-19 15:57:12 +08001138static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores)
1139{
1140 static const char * const thermal_path[] = {
1141 "/thermal-zones/cpu-thermal/cooling-maps/map0"
1142 };
1143
1144 int nodeoff, cnt, i, ret, j;
1145 u32 cooling_dev[12];
1146
1147 for (i = 0; i < ARRAY_SIZE(thermal_path); i++) {
1148 nodeoff = fdt_path_offset(blob, thermal_path[i]);
1149 if (nodeoff < 0)
1150 continue; /* Not found, skip it */
1151
1152 cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 12);
1153 if (cnt < 0)
1154 continue;
1155
1156 if (cnt != 12)
1157 printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt);
1158
1159 for (j = 0; j < cnt; j++)
1160 cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]);
1161
1162 ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev,
1163 sizeof(u32) * (12 - disabled_cores * 3));
1164 if (ret < 0) {
1165 printf("Warning: %s, cooling-device setprop failed %d\n",
1166 thermal_path[i], ret);
1167 continue;
1168 }
1169
1170 printf("Update node %s, cooling-device prop\n", thermal_path[i]);
1171 }
1172}
1173
1174static void disable_pmu_cpu_nodes(void *blob, u32 disabled_cores)
1175{
1176 static const char * const pmu_path[] = {
1177 "/pmu"
1178 };
1179
1180 int nodeoff, cnt, i, ret, j;
1181 u32 irq_affinity[4];
1182
1183 for (i = 0; i < ARRAY_SIZE(pmu_path); i++) {
1184 nodeoff = fdt_path_offset(blob, pmu_path[i]);
1185 if (nodeoff < 0)
1186 continue; /* Not found, skip it */
1187
1188 cnt = fdtdec_get_int_array_count(blob, nodeoff, "interrupt-affinity",
1189 irq_affinity, 4);
1190 if (cnt < 0)
1191 continue;
1192
1193 if (cnt != 4)
1194 printf("Warning: %s, interrupt-affinity count %d\n", pmu_path[i], cnt);
1195
1196 for (j = 0; j < cnt; j++)
1197 irq_affinity[j] = cpu_to_fdt32(irq_affinity[j]);
1198
1199 ret = fdt_setprop(blob, nodeoff, "interrupt-affinity", &irq_affinity,
1200 sizeof(u32) * (4 - disabled_cores));
1201 if (ret < 0) {
1202 printf("Warning: %s, interrupt-affinity setprop failed %d\n",
1203 pmu_path[i], ret);
1204 continue;
1205 }
1206
1207 printf("Update node %s, interrupt-affinity prop\n", pmu_path[i]);
1208 }
1209}
1210
Peng Fan435dc122020-07-09 14:06:49 +08001211static int disable_cpu_nodes(void *blob, u32 disabled_cores)
1212{
1213 static const char * const nodes_path[] = {
1214 "/cpus/cpu@1",
1215 "/cpus/cpu@2",
1216 "/cpus/cpu@3",
1217 };
1218 u32 i = 0;
1219 int rc;
1220 int nodeoff;
1221
1222 if (disabled_cores > 3)
1223 return -EINVAL;
1224
1225 i = 3 - disabled_cores;
1226
1227 for (; i < 3; i++) {
1228 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1229 if (nodeoff < 0)
1230 continue; /* Not found, skip it */
1231
1232 debug("Found %s node\n", nodes_path[i]);
1233
1234 rc = fdt_del_node(blob, nodeoff);
1235 if (rc < 0) {
1236 printf("Unable to delete node %s, err=%s\n",
1237 nodes_path[i], fdt_strerror(rc));
1238 } else {
1239 printf("Delete node %s\n", nodes_path[i]);
1240 }
1241 }
1242
Ye Li26517af2021-03-19 15:57:12 +08001243 disable_thermal_cpu_nodes(blob, disabled_cores);
1244 disable_pmu_cpu_nodes(blob, disabled_cores);
1245
Peng Fan435dc122020-07-09 14:06:49 +08001246 return 0;
1247}
1248
Peng Fana08bc872022-04-07 15:55:54 +08001249static int cleanup_nodes_for_efi(void *blob)
1250{
Peng Fan1585b202022-04-07 15:55:55 +08001251 static const char * const path[][2] = {
1252 { "/soc@0/bus@32c00000/usb@32e40000", "extcon" },
1253 { "/soc@0/bus@32c00000/usb@32e50000", "extcon" },
1254 { "/soc@0/bus@30800000/ethernet@30be0000", "phy-reset-gpios" },
1255 { "/soc@0/bus@30800000/ethernet@30bf0000", "phy-reset-gpios" }
1256 };
Peng Fana08bc872022-04-07 15:55:54 +08001257 int nodeoff, i, rc;
1258
Peng Fan1585b202022-04-07 15:55:55 +08001259 for (i = 0; i < ARRAY_SIZE(path); i++) {
1260 nodeoff = fdt_path_offset(blob, path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001261 if (nodeoff < 0)
1262 continue; /* Not found, skip it */
Peng Fan1585b202022-04-07 15:55:55 +08001263 debug("Found %s node\n", path[i][0]);
Peng Fana08bc872022-04-07 15:55:54 +08001264
Peng Fan1585b202022-04-07 15:55:55 +08001265 rc = fdt_delprop(blob, nodeoff, path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001266 if (rc == -FDT_ERR_NOTFOUND)
1267 continue;
1268 if (rc) {
1269 printf("Unable to update property %s:%s, err=%s\n",
Peng Fan1585b202022-04-07 15:55:55 +08001270 path[i][0], path[i][1], fdt_strerror(rc));
Peng Fana08bc872022-04-07 15:55:54 +08001271 return rc;
1272 }
1273
Peng Fan1585b202022-04-07 15:55:55 +08001274 printf("Remove %s:%s\n", path[i][0], path[i][1]);
Peng Fana08bc872022-04-07 15:55:54 +08001275 }
1276
1277 return 0;
1278}
Peng Fana08bc872022-04-07 15:55:54 +08001279
Andrejs Cainikovs2f3491c2022-05-27 15:20:42 +02001280static int fixup_thermal_trips(void *blob, const char *name)
1281{
1282 int minc, maxc;
1283 int node, trip;
1284
1285 node = fdt_path_offset(blob, "/thermal-zones");
1286 if (node < 0)
1287 return node;
1288
1289 node = fdt_subnode_offset(blob, node, name);
1290 if (node < 0)
1291 return node;
1292
1293 node = fdt_subnode_offset(blob, node, "trips");
1294 if (node < 0)
1295 return node;
1296
1297 get_cpu_temp_grade(&minc, &maxc);
1298
1299 fdt_for_each_subnode(trip, blob, node) {
1300 const char *type;
1301 int temp, ret;
1302
1303 type = fdt_getprop(blob, trip, "type", NULL);
1304 if (!type)
1305 continue;
1306
1307 temp = 0;
1308 if (!strcmp(type, "critical"))
1309 temp = 1000 * maxc;
1310 else if (!strcmp(type, "passive"))
1311 temp = 1000 * (maxc - 10);
1312 if (temp) {
1313 ret = fdt_setprop_u32(blob, trip, "temperature", temp);
1314 if (ret)
1315 return ret;
1316 }
1317 }
1318
1319 return 0;
1320}
1321
Tim Harvey709ace82023-08-24 12:05:17 -07001322#define OPTEE_SHM_SIZE 0x00400000
1323static int ft_add_optee_node(void *fdt, struct bd_info *bd)
1324{
1325 struct fdt_memory carveout;
1326 const char *path, *subpath;
1327 phys_addr_t optee_start;
1328 size_t optee_size;
1329 int offs;
1330 int ret;
1331
1332 /*
1333 * No TEE space allocated indicating no TEE running, so no
1334 * need to add optee node in dts
1335 */
1336 if (!rom_pointer[1])
1337 return 0;
1338
1339 optee_start = (phys_addr_t)rom_pointer[0];
1340 optee_size = rom_pointer[1] - OPTEE_SHM_SIZE;
1341
1342 offs = fdt_increase_size(fdt, 512);
1343 if (offs) {
1344 printf("No Space for dtb\n");
1345 return 1;
1346 }
1347
1348 path = "/firmware";
1349 offs = fdt_path_offset(fdt, path);
1350 if (offs < 0) {
1351 path = "/";
1352 offs = fdt_path_offset(fdt, path);
1353
1354 if (offs < 0) {
1355 printf("Could not find root node.\n");
1356 return offs;
1357 }
1358
1359 subpath = "firmware";
1360 offs = fdt_add_subnode(fdt, offs, subpath);
1361 if (offs < 0) {
1362 printf("Could not create %s node.\n", subpath);
1363 return offs;
1364 }
1365 }
1366
1367 subpath = "optee";
1368 offs = fdt_add_subnode(fdt, offs, subpath);
1369 if (offs < 0) {
1370 printf("Could not create %s node.\n", subpath);
1371 return offs;
1372 }
1373
1374 fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz");
1375 fdt_setprop_string(fdt, offs, "method", "smc");
1376
1377 carveout.start = optee_start,
1378 carveout.end = optee_start + optee_size - 1,
1379 ret = fdtdec_add_reserved_memory(fdt, "optee_core", &carveout, NULL, 0,
1380 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1381 if (ret < 0) {
1382 printf("Could not create optee_core node.\n");
1383 return ret;
1384 }
1385
1386 carveout.start = optee_start + optee_size;
1387 carveout.end = optee_start + optee_size + OPTEE_SHM_SIZE - 1;
1388 ret = fdtdec_add_reserved_memory(fdt, "optee_shm", &carveout, NULL, 0,
1389 NULL, FDTDEC_RESERVED_MEMORY_NO_MAP);
1390 if (ret < 0) {
1391 printf("Could not create optee_shm node.\n");
1392 return ret;
1393 }
1394
1395 return 0;
1396}
1397
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +09001398int ft_system_setup(void *blob, struct bd_info *bd)
Peng Faneae4de22018-01-10 13:20:37 +08001399{
Peng Fan435dc122020-07-09 14:06:49 +08001400#ifdef CONFIG_IMX8MQ
Peng Faneae4de22018-01-10 13:20:37 +08001401 int i = 0;
1402 int rc;
1403 int nodeoff;
1404
Peng Fan435dc122020-07-09 14:06:49 +08001405 if (get_boot_device() == USB_BOOT) {
1406 disable_dcss_nodes(blob);
1407
1408 bool new_path = check_fdt_new_path(blob);
1409 int v = new_path ? 1 : 0;
1410 static const char * const usb_dwc3_path[] = {
1411 "/usb@38100000/dwc3",
1412 "/soc@0/usb@38100000"
1413 };
1414
1415 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1416 if (nodeoff >= 0) {
1417 const char *speed = "high-speed";
1418
Rasmus Villemoes8ab149a2023-05-22 11:27:28 +02001419 debug("Found %s node\n", usb_dwc3_path[v]);
Peng Fan435dc122020-07-09 14:06:49 +08001420
1421usb_modify_speed:
1422
1423 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1424 if (rc) {
1425 if (rc == -FDT_ERR_NOSPACE) {
1426 rc = fdt_increase_size(blob, 512);
1427 if (!rc)
1428 goto usb_modify_speed;
1429 }
1430 printf("Unable to set property %s:%s, err=%s\n",
1431 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1432 } else {
1433 printf("Modify %s:%s = %s\n",
1434 usb_dwc3_path[v], "maximum-speed", speed);
1435 }
1436 } else {
1437 printf("Can't found %s node\n", usb_dwc3_path[v]);
1438 }
1439 }
1440
Peng Faneae4de22018-01-10 13:20:37 +08001441 /* Disable the CPU idle for A0 chip since the HW does not support it */
1442 if (is_soc_rev(CHIP_REV_1_0)) {
1443 static const char * const nodes_path[] = {
1444 "/cpus/cpu@0",
1445 "/cpus/cpu@1",
1446 "/cpus/cpu@2",
1447 "/cpus/cpu@3",
1448 };
1449
1450 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1451 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1452 if (nodeoff < 0)
1453 continue; /* Not found, skip it */
1454
Marek Vasute2e7a772020-04-24 21:37:33 +02001455 debug("Found %s node\n", nodes_path[i]);
Peng Faneae4de22018-01-10 13:20:37 +08001456
1457 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasute2e7a772020-04-24 21:37:33 +02001458 if (rc == -FDT_ERR_NOTFOUND)
1459 continue;
Peng Faneae4de22018-01-10 13:20:37 +08001460 if (rc) {
1461 printf("Unable to update property %s:%s, err=%s\n",
1462 nodes_path[i], "status", fdt_strerror(rc));
1463 return rc;
1464 }
1465
Marek Vasute2e7a772020-04-24 21:37:33 +02001466 debug("Remove %s:%s\n", nodes_path[i],
Peng Faneae4de22018-01-10 13:20:37 +08001467 "cpu-idle-states");
1468 }
1469 }
1470
Peng Fan435dc122020-07-09 14:06:49 +08001471 if (is_imx8mql()) {
1472 disable_vpu_nodes(blob);
1473 if (check_dcss_fused()) {
1474 printf("DCSS is fused\n");
1475 disable_dcss_nodes(blob);
1476 check_mipi_dsi_nodes(blob);
1477 }
1478 }
1479
1480 if (is_imx8md())
1481 disable_cpu_nodes(blob, 2);
1482
1483#elif defined(CONFIG_IMX8MM)
1484 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1485 disable_vpu_nodes(blob);
1486
1487 if (is_imx8mmd() || is_imx8mmdl())
1488 disable_cpu_nodes(blob, 2);
1489 else if (is_imx8mms() || is_imx8mmsl())
1490 disable_cpu_nodes(blob, 3);
1491
1492#elif defined(CONFIG_IMX8MN)
1493 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1494 disable_gpu_nodes(blob);
Ye Liee337ce2021-03-19 15:57:09 +08001495#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1496 else {
1497 int ldm_gpu = low_drive_gpu_freq(blob);
1498
1499 if (ldm_gpu < 0)
1500 printf("Update GPU node assigned-clock-rates failed\n");
1501 else
1502 printf("Update GPU node assigned-clock-rates ok\n");
1503 }
1504#endif
Peng Fan435dc122020-07-09 14:06:49 +08001505
Ye Li715180e2021-03-19 15:57:11 +08001506 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan435dc122020-07-09 14:06:49 +08001507 disable_cpu_nodes(blob, 2);
Ye Li715180e2021-03-19 15:57:11 +08001508 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan435dc122020-07-09 14:06:49 +08001509 disable_cpu_nodes(blob, 3);
1510
1511#elif defined(CONFIG_IMX8MP)
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001512 if (is_imx8mpul()) {
1513 /* Disable GPU */
1514 disable_gpu_nodes(blob);
1515
1516 /* Disable DSI */
1517 disable_dsi_lcdif_nodes(blob);
1518
1519 /* Disable LVDS */
1520 disable_lvds_lcdif_nodes(blob);
1521 }
1522
1523 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001524 disable_vpu_nodes(blob);
1525
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001526 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001527 disable_npu_nodes(blob);
1528
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001529 if (is_imx8mpul() || is_imx8mpl())
Peng Fan435dc122020-07-09 14:06:49 +08001530 disable_isp_nodes(blob);
1531
Peng Fanf5f9b8e2022-04-07 15:55:53 +08001532 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan435dc122020-07-09 14:06:49 +08001533 disable_dsp_nodes(blob);
1534
1535 if (is_imx8mpd())
1536 disable_cpu_nodes(blob, 2);
1537#endif
1538
Peng Fan1585b202022-04-07 15:55:55 +08001539 cleanup_nodes_for_efi(blob);
Andrejs Cainikovs2f3491c2022-05-27 15:20:42 +02001540
1541 if (fixup_thermal_trips(blob, "cpu-thermal"))
1542 printf("Failed to update cpu-thermal trip(s)");
1543 if (IS_ENABLED(CONFIG_IMX8MP) &&
1544 fixup_thermal_trips(blob, "soc-thermal"))
1545 printf("Failed to update soc-thermal trip(s)");
1546
Tim Harvey709ace82023-08-24 12:05:17 -07001547 return ft_add_optee_node(blob, bd);
Peng Faneae4de22018-01-10 13:20:37 +08001548}
1549#endif
1550
Marek Vasut64dc4de2020-04-29 15:04:21 +02001551#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler6f14d5f2020-12-15 16:47:52 +01001552void reset_cpu(void)
Peng Faneae4de22018-01-10 13:20:37 +08001553{
Claudius Heinee73f3942020-04-29 15:04:23 +02001554 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Faneae4de22018-01-10 13:20:37 +08001555
Ye Li54a915a2019-12-09 00:47:18 -08001556 /* Clear WDA to trigger WDOG_B immediately */
1557 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fan24290d92019-08-27 06:25:41 +00001558
Ye Li54a915a2019-12-09 00:47:18 -08001559 while (1) {
1560 /*
Harald Seilerec0c4472020-04-29 15:04:22 +02001561 * spin for .5 seconds before reset
Ye Li54a915a2019-12-09 00:47:18 -08001562 */
1563 }
Peng Faneae4de22018-01-10 13:20:37 +08001564}
Peng Fan24290d92019-08-27 06:25:41 +00001565#endif
Peng Fan5760d8d2020-04-22 10:51:13 +08001566
1567#if defined(CONFIG_ARCH_MISC_INIT)
Peng Fan5760d8d2020-04-22 10:51:13 +08001568int arch_misc_init(void)
1569{
Gaurav Jain81113a02022-03-24 11:50:27 +05301570 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1571 struct udevice *dev;
1572 int ret;
1573
1574 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1575 if (ret)
Ye Liec346892022-05-11 13:56:20 +05301576 printf("Failed to initialize caam_jr: %d\n", ret);
Gaurav Jain81113a02022-03-24 11:50:27 +05301577 }
Peng Fan5760d8d2020-04-22 10:51:13 +08001578
1579 return 0;
1580}
1581#endif
Ye Li325cd012020-05-03 22:19:52 +08001582
Peng Fana35215d2020-07-09 13:39:26 +08001583#if defined(CONFIG_SPL_BUILD)
1584#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1585bool serror_need_skip = true;
1586
Sean Anderson2d755492022-03-22 17:17:35 -04001587void do_error(struct pt_regs *pt_regs)
Peng Fana35215d2020-07-09 13:39:26 +08001588{
1589 /*
1590 * If stack is still in ROM reserved OCRAM not switch to SPL,
1591 * it is the ROM SError
1592 */
1593 ulong sp;
1594
1595 asm volatile("mov %0, sp" : "=r"(sp) : );
1596
1597 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1598 /* Check for ERR050342, imx8mq HDCP enabled parts */
1599 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1600 serror_need_skip = false;
1601 return; /* Do nothing skip the SError in ROM */
1602 }
1603
1604 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1605 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1606 serror_need_skip = false;
1607 return; /* Do nothing skip the SError in ROM */
1608 }
1609 }
1610
1611 efi_restore_gd();
Sean Anderson2d755492022-03-22 17:17:35 -04001612 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fana35215d2020-07-09 13:39:26 +08001613 show_regs(pt_regs);
1614 panic("Resetting CPU ...\n");
1615}
1616#endif
1617#endif
Ye Li0513f362019-07-15 01:16:46 -07001618
1619#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
Marek Vasut765b5802022-04-06 02:21:34 +02001620enum env_location arch_env_get_location(enum env_operation op, int prio)
Ye Li0513f362019-07-15 01:16:46 -07001621{
1622 enum boot_device dev = get_boot_device();
Ye Li0513f362019-07-15 01:16:46 -07001623
1624 if (prio)
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001625 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001626
1627 switch (dev) {
Fabio Estevam9be6daf2022-04-21 15:05:23 -03001628 case USB_BOOT:
1629 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1630 return ENVL_SPI_FLASH;
1631 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1632 return ENVL_NAND;
1633 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1634 return ENVL_MMC;
1635 if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
1636 return ENVL_NOWHERE;
1637 return ENVL_UNKNOWN;
Ye Li0513f362019-07-15 01:16:46 -07001638 case QSPI_BOOT:
Marek Vasut31b3bc42022-03-25 18:59:28 +01001639 case SPI_NOR_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001640 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1641 return ENVL_SPI_FLASH;
1642 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001643 case NAND_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001644 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1645 return ENVL_NAND;
1646 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001647 case SD1_BOOT:
1648 case SD2_BOOT:
1649 case SD3_BOOT:
1650 case MMC1_BOOT:
1651 case MMC2_BOOT:
1652 case MMC3_BOOT:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001653 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1654 return ENVL_MMC;
1655 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1656 return ENVL_EXT4;
1657 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1658 return ENVL_FAT;
1659 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001660 default:
Ricardo Salveti1daf63f2021-10-20 16:16:26 -03001661 return ENVL_NOWHERE;
Ye Li0513f362019-07-15 01:16:46 -07001662 }
Ye Li0513f362019-07-15 01:16:46 -07001663}
1664
Ye Li0513f362019-07-15 01:16:46 -07001665#endif
Peng Fanf19e0e52022-04-29 16:03:14 +08001666
1667#ifdef CONFIG_IMX_BOOTAUX
1668const struct rproc_att hostmap[] = {
1669 /* aux core , host core, size */
1670 { 0x00000000, 0x007e0000, 0x00020000 },
1671 /* OCRAM_S */
1672 { 0x00180000, 0x00180000, 0x00008000 },
1673 /* OCRAM */
1674 { 0x00900000, 0x00900000, 0x00020000 },
1675 /* OCRAM */
1676 { 0x00920000, 0x00920000, 0x00020000 },
1677 /* QSPI Code - alias */
1678 { 0x08000000, 0x08000000, 0x08000000 },
1679 /* DDR (Code) - alias */
1680 { 0x10000000, 0x80000000, 0x0FFE0000 },
1681 /* TCML */
1682 { 0x1FFE0000, 0x007E0000, 0x00040000 },
1683 /* OCRAM_S */
1684 { 0x20180000, 0x00180000, 0x00008000 },
1685 /* OCRAM */
1686 { 0x20200000, 0x00900000, 0x00040000 },
1687 /* DDR (Data) */
1688 { 0x40000000, 0x40000000, 0x80000000 },
1689 { /* sentinel */ }
1690};
Marek Vasutddc59352022-12-13 05:46:07 +01001691
1692const struct rproc_att *imx_bootaux_get_hostmap(void)
1693{
1694 return hostmap;
1695}
Peng Fanf19e0e52022-04-29 16:03:14 +08001696#endif